Compare commits

...

63 Commits
1.1.3 ... 1.4.3

Author SHA1 Message Date
Matt Nadareski
fc5374108c Bump version 2024-04-02 16:15:29 -04:00
Matt Nadareski
15452ded52 Use new IO extension 2024-04-02 16:12:08 -04:00
Matt Nadareski
49c6c4412b Update SabreTools.IO 2024-04-02 16:10:58 -04:00
Matt Nadareski
cfc53f66a8 Fix cuesheet serialization 2024-04-02 15:30:43 -04:00
Matt Nadareski
ec1fb7247c Add file serializers for all stream variants 2024-04-02 14:28:30 -04:00
Matt Nadareski
54b1eef8ae Better handle version 3 CFB files, probably (fixes #3) 2024-04-02 12:54:54 -04:00
Matt Nadareski
f448314309 Add file serializer for CFB 2024-04-02 12:45:31 -04:00
Matt Nadareski
c4e8debb15 Detect invalid dialog item counts (fixes #5) 2024-04-02 12:35:14 -04:00
Matt Nadareski
822839c813 Add file serializers for executable types 2024-04-02 12:06:56 -04:00
Matt Nadareski
27d36a11ca Add skeleton test executable 2024-04-02 11:56:27 -04:00
Matt Nadareski
92d9ca932d Move library code to subfolder 2024-04-02 11:51:39 -04:00
Deterous
69e1f5ff0b De/Serialize XboxOne/XSX catalog.js files (#6)
* Add JSON/catalog.js logic

* Proper json deserialize

* Update packages

* Catalog is UTF-16 LE, make BaseJsonFile encoding independent

* Bump version, use ST.Models 1.4.1

* Implement JsonFile as interface with UTF8 as default

* typo
2024-04-02 08:46:12 -07:00
Matt Nadareski
d265c14841 Bump version 2024-03-25 14:25:28 -04:00
Matt Nadareski
1148245226 Surface NE/LE/PE methods for other library use 2024-03-24 21:09:12 -04:00
Matt Nadareski
f53d9f94e6 Break if StringFileInfo child is total size 0 2024-03-22 23:46:05 -04:00
Matt Nadareski
4e3d832834 Ensure Listrom serializes to the correct model type 2024-03-19 15:47:13 -04:00
Matt Nadareski
0713dfafb2 Bump version 2024-03-12 16:35:45 -04:00
Matt Nadareski
c0d4f403c3 Update IO package 2024-03-12 16:34:32 -04:00
Matt Nadareski
5ed79166cf Update Models library 2024-03-12 16:29:05 -04:00
Matt Nadareski
17030cfb9f Fix Listxml type key issues 2024-03-12 12:58:27 -04:00
Matt Nadareski
530fa69d3c Fix OpenMSX cross-model serialization keys 2024-03-12 00:46:46 -04:00
Matt Nadareski
7a5956f599 Fix capitalization in RomCenter INI stream serializer 2024-03-11 23:08:10 -04:00
Matt Nadareski
5562768509 Fix separated value cross-model serialization 2024-03-11 22:47:38 -04:00
Matt Nadareski
aa538df229 All doctype overloads to take nullable objects 2024-03-11 22:31:40 -04:00
Matt Nadareski
b7b22cba32 Fix AttractMode writing 2024-03-11 14:52:32 -04:00
Matt Nadareski
fc489125d9 Fix serialization problem for listrom 2024-03-10 00:39:23 -05:00
Matt Nadareski
036589473d Fix serialziation problem for archive.org 2024-03-10 00:36:31 -05:00
Matt Nadareski
432ce85f89 Bump version 2024-03-05 11:16:22 -05:00
Matt Nadareski
438e8067eb Update SabreTools.IO 2024-03-05 11:12:59 -05:00
Matt Nadareski
9715507aaf Add nuget package and PR workflows 2024-02-27 19:17:20 -05:00
Matt Nadareski
b745d4b9f6 Update copyright year 2024-01-30 13:39:23 -05:00
Matt Nadareski
4271bd86b3 Bump version 2024-01-26 09:57:09 -05:00
Matt Nadareski
88de4be27b Fix too-long string values 2024-01-26 01:23:33 -05:00
Matt Nadareski
33905165f7 Bump version 2024-01-05 21:57:50 -05:00
Deterous
83ec3b6950 Update CueSheet.Deserializer.cs (#2)
* Update CueSheet.Deserializer.cs

Don't return null when cuesheet is not ended

* Explicitly deal with new track/file cases
2024-01-02 17:51:27 -08:00
Matt Nadareski
9b5d51884c Use more lenient file reading 2023-12-13 15:45:40 -05:00
Matt Nadareski
aaa6422921 Bump version 2023-11-21 21:11:24 -05:00
Matt Nadareski
f24b88031b Address some suggestions 2023-11-21 21:10:43 -05:00
Matt Nadareski
edf9fed751 Support .NET Framework 2.0 2023-11-21 20:59:20 -05:00
Matt Nadareski
beca747943 Fix other data endpoint issues 2023-11-15 12:44:32 -05:00
Matt Nadareski
58e538eff6 Bump version 2023-11-15 12:41:21 -05:00
Matt Nadareski
4f04c8aa89 Fix end-of-data issue, add .NET 8 syntax 2023-11-15 12:34:57 -05:00
Matt Nadareski
d7c1e4e83a Support ancient .NET 2023-11-14 14:50:47 -05:00
Matt Nadareski
975eefdc61 Expand supported RIDs 2023-11-08 22:51:40 -05:00
Matt Nadareski
d8cd5854ce Enable latest language version 2023-11-07 23:30:26 -05:00
Matt Nadareski
0790fc93b6 Bump version 2023-10-25 15:34:38 -04:00
Matt Nadareski
7f6c128521 Update README 2023-10-25 15:04:22 -04:00
Matt Nadareski
87df6b3ebd Add IRD wrapper 2023-10-25 14:51:07 -04:00
Matt Nadareski
2ca7326074 Implement IRD serializers 2023-10-25 14:43:43 -04:00
Matt Nadareski
3b90af7b3a Split XgdInfo into two proper wrappers 2023-10-25 13:29:59 -04:00
Matt Nadareski
6eda2f2541 Update models, add XgdInfo extensions 2023-10-25 13:17:36 -04:00
Matt Nadareski
defe1c53aa Port a version of XgdInfo from MPF 2023-10-24 23:33:53 -04:00
Matt Nadareski
e5fe0a71ef Add Xbox string serialization 2023-10-24 23:24:17 -04:00
Matt Nadareski
83450f693f Make Strings namespace and move Xbox 2023-10-24 23:20:27 -04:00
Matt Nadareski
1f70e1f544 Remove unnecessary validation / methods from Xbox 2023-10-24 23:05:16 -04:00
Matt Nadareski
4bfc83d5d4 Make XMID consistent with XeMID 2023-10-24 21:50:26 -04:00
Matt Nadareski
7364661900 Add two X360 publishers 2023-10-24 21:43:21 -04:00
Matt Nadareski
1cafc4079d Make XeMID logic a bit clearer 2023-10-24 16:56:41 -04:00
Matt Nadareski
0d62cbd1e9 Add XGD4 PIC reading 2023-09-28 23:25:25 -04:00
Matt Nadareski
bf753262a5 Update Models version 2023-09-22 16:05:20 -04:00
Matt Nadareski
5510b5d19d Fix inconsistent access issue 2023-09-16 00:55:31 -04:00
Matt Nadareski
d0f0ade757 Bump version 2023-09-16 00:44:35 -04:00
Matt Nadareski
26b03d8256 Make some base functionality public 2023-09-16 00:15:44 -04:00
325 changed files with 3100 additions and 4466 deletions

43
.github/workflows/build_nupkg.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Nuget Pack
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Pack
run: dotnet pack
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: 'Nuget Package'
path: 'SabreTools.Serialization/bin/Release/*.nupkg'
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: 'SabreTools.Serialization/bin/Release/*.nupkg'
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

17
.github/workflows/check_pr.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Build
run: dotnet build

View File

@@ -1,32 +0,0 @@
using System.IO;
using SabreTools.Models.AttractMode;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class AttractMode : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path)
#else
public bool Serialize(MetadataFile? obj, string? path)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.AttractMode().Serialize(obj))
{
if (stream == null)
return false;
using (var fs = File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,39 +0,0 @@
using System.IO;
using SabreTools.Models.ClrMamePro;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class ClrMamePro : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path) => Serialize(obj, path, true);
#else
public bool Serialize(MetadataFile? obj, string? path) => Serialize(obj, path, true);
#endif
/// <inheritdoc cref="Serialize(MetadataFile, string)"/>
#if NET48
public bool Serialize(MetadataFile obj, string path, bool quotes)
#else
public bool Serialize(MetadataFile? obj, string? path, bool quotes)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.ClrMamePro().Serialize(obj, quotes))
{
if (stream == null)
return false;
using (var fs = File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
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;
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
using SabreTools.Models.DosCenter;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class DosCenter : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path)
#else
public bool Serialize(MetadataFile? obj, string? path)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.DosCenter().Serialize(obj))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
using SabreTools.Models.EverdriveSMDB;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class EverdriveSMDB : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path)
#else
public bool Serialize(MetadataFile? obj, string? path)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.EverdriveSMDB().Serialize(obj))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,37 +0,0 @@
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) => Serialize(obj, path, Hash.CRC);
#else
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, hash))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
using SabreTools.Models.Listrom;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class Listrom : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path)
#else
public bool Serialize(MetadataFile? obj, string? path)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.Listrom().Serialize(obj))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,21 +0,0 @@
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);
}
}
}
}

View File

@@ -1,31 +0,0 @@
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;
}
}
}
}
}

View File

@@ -1,31 +0,0 @@
using SabreTools.Models.RomCenter;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class RomCenter : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path)
#else
public bool Serialize(MetadataFile? obj, string? path)
#endif
{
if (string.IsNullOrWhiteSpace(path))
return false;
using (var stream = new Streams.RomCenter().Serialize(obj))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,38 +0,0 @@
using SabreTools.Models.SeparatedValue;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class SeparatedValue : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public bool Serialize(MetadataFile obj, string path) => Serialize(obj, path, ',');
#else
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, delim))
{
if (stream == null)
return false;
using (var fs = System.IO.File.OpenWrite(path))
{
stream.CopyTo(fs);
return true;
}
}
}
}
}

View File

@@ -1,216 +0,0 @@
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
}
}

View File

@@ -1,15 +0,0 @@
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
}
}

View File

@@ -1,275 +0,0 @@
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
}
}

View File

@@ -1,15 +0,0 @@
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
}
}

View File

@@ -20,6 +20,10 @@ This namespace comprises of serializers and deserializers that can convert to an
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.Strings`
This namespace comprises of serializers and deserializers that can convert to and from strings. 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.

View File

@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Serialization", "SabreTools.Serialization.csproj", "{5B688801-5F36-483E-B2E8-F219BA5923A2}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Serialization", "SabreTools.Serialization\SabreTools.Serialization.csproj", "{5B688801-5F36-483E-B2E8-F219BA5923A2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{F3DEE31A-4726-464C-A90C-C19D78F51898}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -18,5 +20,9 @@ Global
{5B688801-5F36-483E-B2E8-F219BA5923A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B688801-5F36-483E-B2E8-F219BA5923A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B688801-5F36-483E-B2E8-F219BA5923A2}.Release|Any CPU.Build.0 = Release|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class AACS : IByteSerializer<MediaKeyBlock>
{
/// <inheritdoc/>
#if NET48
public MediaKeyBlock Deserialize(byte[] data, int offset)
#else
public MediaKeyBlock? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class BDPlus : IByteSerializer<SVM>
{
/// <inheritdoc/>
#if NET48
public SVM Deserialize(byte[] data, int offset)
#else
public SVM? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class BFPK : IByteSerializer<Archive>
{
/// <inheritdoc/>
#if NET48
public Archive Deserialize(byte[] data, int offset)
#else
public Archive? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class BSP : IByteSerializer<Models.BSP.File>
{
/// <inheritdoc/>
#if NET48
public Models.BSP.File Deserialize(byte[] data, int offset)
#else
public Models.BSP.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class CFB : IByteSerializer<Binary>
{
/// <inheritdoc/>
#if NET48
public Binary Deserialize(byte[] data, int offset)
#else
public Binary? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class CIA : IByteSerializer<Models.N3DS.CIA>
{
/// <inheritdoc/>
#if NET48
public Models.N3DS.CIA Deserialize(byte[] data, int offset)
#else
public Models.N3DS.CIA? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class GCF : IByteSerializer<Models.GCF.File>
{
/// <inheritdoc/>
#if NET48
public Models.GCF.File Deserialize(byte[] data, int offset)
#else
public Models.GCF.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -0,0 +1,24 @@
using System.IO;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Bytes
{
public partial class IRD : IByteSerializer<Models.IRD.File>
{
/// <inheritdoc/>
public Models.IRD.File? Deserialize(byte[]? data, int offset)
{
// If the data is invalid
if (data == null)
return null;
// If the offset is out of bounds
if (offset < 0 || offset >= data.Length)
return null;
// Create a memory stream and parse that
MemoryStream dataStream = new MemoryStream(data, offset, data.Length - offset);
return new Streams.IRD().Deserialize(dataStream);
}
}
}

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.Bytes
public partial class InstallShieldCabinet : IByteSerializer<Cabinet>
{
/// <inheritdoc/>
#if NET48
public Cabinet Deserialize(byte[] data, int offset)
#else
public Cabinet? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class LinearExecutable : IByteSerializer<Executable>
{
/// <inheritdoc/>
#if NET48
public Executable Deserialize(byte[] data, int offset)
#else
public Executable? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class MSDOS : IByteSerializer<Executable>
{
/// <inheritdoc/>
#if NET48
public Executable Deserialize(byte[] data, int offset)
#else
public Executable? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.Bytes
public partial class MicrosoftCabinet : IByteSerializer<Cabinet>
{
/// <inheritdoc/>
#if NET48
public Cabinet Deserialize(byte[] data, int offset)
#else
public Cabinet? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class MoPaQ : IByteSerializer<Archive>
{
/// <inheritdoc/>
#if NET48
public Archive Deserialize(byte[] data, int offset)
#else
public Archive? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class N3DS : IByteSerializer<Cart>
{
/// <inheritdoc/>
#if NET48
public Cart Deserialize(byte[] data, int offset)
#else
public Cart? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class NCF : IByteSerializer<Models.NCF.File>
{
/// <inheritdoc/>
#if NET48
public Models.NCF.File Deserialize(byte[] data, int offset)
#else
public Models.NCF.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class NewExecutable : IByteSerializer<Executable>
{
/// <inheritdoc/>
#if NET48
public Executable Deserialize(byte[] data, int offset)
#else
public Executable? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class Nitro : IByteSerializer<Cart>
{
/// <inheritdoc/>
#if NET48
public Cart Deserialize(byte[] data, int offset)
#else
public Cart? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class PAK : IByteSerializer<Models.PAK.File>
{
/// <inheritdoc/>
#if NET48
public Models.PAK.File Deserialize(byte[] data, int offset)
#else
public Models.PAK.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class PFF : IByteSerializer<Archive>
{
/// <inheritdoc/>
#if NET48
public Archive Deserialize(byte[] data, int offset)
#else
public Archive? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class PlayJAudio : IByteSerializer<AudioFile>
{
/// <inheritdoc/>
#if NET48
public AudioFile Deserialize(byte[] data, int offset)
#else
public AudioFile? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class PlayJPlaylist : IByteSerializer<Playlist>
{
/// <inheritdoc/>
#if NET48
public Playlist Deserialize(byte[] data, int offset)
#else
public Playlist? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class PortableExecutable : IByteSerializer<Executable>
{
/// <inheritdoc/>
#if NET48
public Executable Deserialize(byte[] data, int offset)
#else
public Executable? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.Bytes
public partial class Quantum : IByteSerializer<Archive>
{
/// <inheritdoc/>
#if NET48
public Archive Deserialize(byte[] data, int offset)
#else
public Archive? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class SGA : IByteSerializer<Models.SGA.File>
{
/// <inheritdoc/>
#if NET48
public Models.SGA.File Deserialize(byte[] data, int offset)
#else
public Models.SGA.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class VBSP : IByteSerializer<Models.VBSP.File>
{
/// <inheritdoc/>
#if NET48
public Models.VBSP.File Deserialize(byte[] data, int offset)
#else
public Models.VBSP.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class VPK : IByteSerializer<Models.VPK.File>
{
/// <inheritdoc/>
#if NET48
public Models.VPK.File Deserialize(byte[] data, int offset)
#else
public Models.VPK.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class WAD : IByteSerializer<Models.WAD.File>
{
/// <inheritdoc/>
#if NET48
public Models.WAD.File Deserialize(byte[] data, int offset)
#else
public Models.WAD.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.Bytes
public partial class XZP : IByteSerializer<Models.XZP.File>
{
/// <inheritdoc/>
#if NET48
public Models.XZP.File Deserialize(byte[] data, int offset)
#else
public Models.XZP.File? Deserialize(byte[]? data, int offset)
#endif
{
// If the data is invalid
if (data == null)

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class ArchiveDotOrg : IModelSerializer<Models.ArchiveDotOrg.Files, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.ArchiveDotOrg.Files Deserialize(Models.Metadata.MetadataFile obj)
#else
public Models.ArchiveDotOrg.Files? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -38,7 +34,7 @@ namespace SabreTools.Serialization.CrossModel
{
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
if (roms == null)
return Array.Empty<File>();
return [];
return roms
.Where(r => r != null)

View File

@@ -6,15 +6,11 @@ namespace SabreTools.Serialization.CrossModel
public partial class ArchiveDotOrg : IModelSerializer<Models.ArchiveDotOrg.Files, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Models.ArchiveDotOrg.Files item)
#else
public Models.Metadata.MetadataFile? Serialize(Models.ArchiveDotOrg.Files? item)
#endif
{
if (item == null)
return null;
var metadataFile = new Models.Metadata.MetadataFile
{
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
@@ -47,27 +43,21 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.ArchiveDotOrg.File"/> to <cref="Models.Metadata.Machine"/>
/// </summary>
#if NET48
private static Models.Metadata.Machine ConvertMachineToInternalModel(Models.ArchiveDotOrg.File item)
#else
private static Models.Metadata.Machine ConvertMachineToInternalModel(Models.ArchiveDotOrg.File? item)
#endif
{
var machine = new Models.Metadata.Machine
{
[Models.Metadata.Machine.RomKey] = ConvertToInternalModel(item),
};
var machine = new Models.Metadata.Machine();
var rom = ConvertToInternalModel(item);
if (rom != null)
machine[Models.Metadata.Machine.RomKey] = new Models.Metadata.Rom[] { rom };
return machine;
}
/// <summary>
/// Convert from <cref="Models.ArchiveDotOrg.File"/> to <cref="Models.Metadata.Rom"/>
/// </summary>
#if NET48
private static Models.Metadata.Rom ConvertToInternalModel(Models.ArchiveDotOrg.File item)
#else
private static Models.Metadata.Rom? ConvertToInternalModel(Models.ArchiveDotOrg.File? item)
#endif
{
if (item == null)
return null;

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class AttractMode : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -51,7 +47,7 @@ namespace SabreTools.Serialization.CrossModel
{
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
if (roms == null || !roms.Any())
return Array.Empty<Row>();
return [];
return roms
.Where(r => r != null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class AttractMode : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -48,11 +44,7 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.AttractMode.Row"/> to <cref="Models.Metadata.Machine"/>
/// </summary>
#if NET48
private static Models.Metadata.Machine ConvertMachineToInternalModel(Row item)
#else
private static Models.Metadata.Machine? ConvertMachineToInternalModel(Row? item)
#endif
{
if (item == null)
return null;

View File

@@ -7,18 +7,10 @@ namespace SabreTools.Serialization.CrossModel
public partial class ClrMamePro : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj) => Deserialize(obj, false);
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj) => Deserialize(obj, false);
#endif
/// <inheritdoc cref="Deserialize(Models.Metadata.MetadataFile)"/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj, bool game)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj, bool game)
#endif
{
if (obj == null)
return null;
@@ -72,15 +64,7 @@ namespace SabreTools.Serialization.CrossModel
/// </summary>
private static GameBase ConvertMachineFromInternalModel(Models.Metadata.Machine item, bool game = false)
{
#if NET48
GameBase gameBase;
if (game)
gameBase = new Game();
else
gameBase = new Machine();
#else
GameBase gameBase = game ? new Models.ClrMamePro.Game() : new Models.ClrMamePro.Machine();
#endif
gameBase.Name = item.ReadString(Models.Metadata.Machine.NameKey);
gameBase.Description = item.ReadString(Models.Metadata.Machine.DescriptionKey);

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class ClrMamePro : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -62,11 +58,7 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.ClrMamePro.GameBase"/> to <cref="Models.Metadata.Machine"/>
/// </summary>
#if NET48
private static Models.Metadata.Machine ConvertMachineToInternalModel(GameBase item)
#else
private static Models.Metadata.Machine? ConvertMachineToInternalModel(GameBase? item)
#endif
{
if (item == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class DosCenter : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class DosCenter : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class EverdriveSMDB : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -38,7 +34,7 @@ namespace SabreTools.Serialization.CrossModel
{
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
if (roms == null || !roms.Any())
return Array.Empty<Row>();
return [];
return roms
.Where(r => r != null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class EverdriveSMDB : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -8,18 +8,10 @@ namespace SabreTools.Serialization.CrossModel
public partial class Hashfile : IModelSerializer<Models.Hashfile.Hashfile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Hashfile.Hashfile Deserialize(Models.Metadata.MetadataFile obj) => Deserialize(obj, Hash.CRC);
#else
public Models.Hashfile.Hashfile? Deserialize(Models.Metadata.MetadataFile? obj) => Deserialize(obj, Hash.CRC);
#endif
/// <inheritdoc/>
#if NET48
public Models.Hashfile.Hashfile Deserialize(Models.Metadata.MetadataFile obj, Hash hash)
#else
public Models.Hashfile.Hashfile? Deserialize(Models.Metadata.MetadataFile? obj, Hash hash)
#endif
{
if (obj == null)
return null;
@@ -81,11 +73,7 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.MetadataFile"/> to an array of <cref="Models.Hashfile.Hashfile"/>
/// </summary>
#if NET48
public static Models.Hashfile.Hashfile[] ConvertArrayFromInternalModel(Models.Metadata.MetadataFile item, Hash hash)
#else
public static Models.Hashfile.Hashfile[]? ConvertArrayFromInternalModel(Models.Metadata.MetadataFile? item, Hash hash)
#endif
{
if (item == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class Hashfile : IModelSerializer<Models.Hashfile.Hashfile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Models.Hashfile.Hashfile obj)
#else
public Models.Metadata.MetadataFile? Serialize(Models.Hashfile.Hashfile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class Listrom : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class Listrom : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -51,7 +47,7 @@ namespace SabreTools.Serialization.CrossModel
private static Models.Metadata.Machine ConvertMachineToInternalModel(Set item)
{
var machine = new Models.Metadata.Machine();
if (!string.IsNullOrWhiteSpace(item.Device))
if (!string.IsNullOrEmpty(item.Device))
{
machine[Models.Metadata.Machine.NameKey] = item.Device;
machine[Models.Metadata.Machine.IsDeviceKey] = "yes";
@@ -69,8 +65,8 @@ namespace SabreTools.Serialization.CrossModel
datItems.Add(ConvertToInternalModel(file));
}
machine[Models.Metadata.Machine.DiskKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "disk")?.ToArray();
machine[Models.Metadata.Machine.RomKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "rom")?.ToArray();
machine[Models.Metadata.Machine.DiskKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "disk").Select(d => d as Models.Metadata.Disk).ToArray();
machine[Models.Metadata.Machine.RomKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "rom").Select(d => d as Models.Metadata.Rom).ToArray();
}
return machine;
@@ -85,6 +81,7 @@ namespace SabreTools.Serialization.CrossModel
{
var disk = new Models.Metadata.Disk
{
[Models.Metadata.DatItem.TypeKey] = "disk",
[Models.Metadata.Disk.NameKey] = item.Name,
[Models.Metadata.Disk.MD5Key] = item.MD5,
[Models.Metadata.Disk.SHA1Key] = item.SHA1,
@@ -101,6 +98,7 @@ namespace SabreTools.Serialization.CrossModel
{
var rom = new Models.Metadata.Rom
{
[Models.Metadata.DatItem.TypeKey] = "rom",
[Models.Metadata.Rom.NameKey] = item.Name,
[Models.Metadata.Rom.SizeKey] = item.Size,
[Models.Metadata.Rom.CRCKey] = item.CRC,

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class Listxml : IModelSerializer<Mame, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Mame Deserialize(Models.Metadata.MetadataFile obj)
#else
public Mame? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -34,11 +30,7 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.Models.Metadata.MetadataFile"/> to <cref="Models.Listxml.Mame"/>
/// </summary>
#if NET48
private static Mame ConvertMameFromInternalModel(Models.Metadata.MetadataFile item)
#else
public static Mame? ConvertMameFromInternalModel(Models.Metadata.MetadataFile? item)
#endif
{
if (item == null)
return null;
@@ -316,7 +308,7 @@ namespace SabreTools.Serialization.CrossModel
{
Name = item.ReadString(Models.Metadata.Chip.NameKey),
Tag = item.ReadString(Models.Metadata.Chip.TagKey),
Type = item.ReadString(Models.Metadata.Chip.TypeKey),
Type = item.ReadString(Models.Metadata.Chip.ChipTypeKey),
SoundOnly = item.ReadString(Models.Metadata.Chip.SoundOnlyKey),
Clock = item.ReadString(Models.Metadata.Chip.ClockKey),
};
@@ -415,7 +407,7 @@ namespace SabreTools.Serialization.CrossModel
{
var control = new Control
{
Type = item.ReadString(Models.Metadata.Control.TypeKey),
Type = item.ReadString(Models.Metadata.Control.ControlTypeKey),
Player = item.ReadString(Models.Metadata.Control.PlayerKey),
Buttons = item.ReadString(Models.Metadata.Control.ButtonsKey),
ReqButtons = item.ReadString(Models.Metadata.Control.ReqButtonsKey),
@@ -438,7 +430,7 @@ namespace SabreTools.Serialization.CrossModel
{
var device = new Device
{
Type = item.ReadString(Models.Metadata.Device.TypeKey),
Type = item.ReadString(Models.Metadata.Device.DeviceTypeKey),
Tag = item.ReadString(Models.Metadata.Device.TagKey),
FixedImage = item.ReadString(Models.Metadata.Device.FixedImageKey),
Mandatory = item.ReadString(Models.Metadata.Device.MandatoryKey),
@@ -571,7 +563,7 @@ namespace SabreTools.Serialization.CrossModel
var display = new Display
{
Tag = item.ReadString(Models.Metadata.Display.TagKey),
Type = item.ReadString(Models.Metadata.Display.TypeKey),
Type = item.ReadString(Models.Metadata.Display.DisplayTypeKey),
Rotate = item.ReadString(Models.Metadata.Display.RotateKey),
FlipX = item.ReadString(Models.Metadata.Display.FlipXKey),
Width = item.ReadString(Models.Metadata.Display.WidthKey),
@@ -629,7 +621,7 @@ namespace SabreTools.Serialization.CrossModel
{
var feature = new Feature
{
Type = item.ReadString(Models.Metadata.Feature.TypeKey),
Type = item.ReadString(Models.Metadata.Feature.FeatureTypeKey),
Status = item.ReadString(Models.Metadata.Feature.StatusKey),
Overall = item.ReadString(Models.Metadata.Feature.OverallKey),
};

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class Listxml : IModelSerializer<Mame, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Mame item)
#else
public Models.Metadata.MetadataFile? Serialize(Mame? item)
#endif
{
if (item == null)
return null;
@@ -268,7 +264,7 @@ namespace SabreTools.Serialization.CrossModel
{
[Models.Metadata.Chip.NameKey] = item.Name,
[Models.Metadata.Chip.TagKey] = item.Tag,
[Models.Metadata.Chip.TypeKey] = item.Type,
[Models.Metadata.Chip.ChipTypeKey] = item.Type,
[Models.Metadata.Chip.SoundOnlyKey] = item.SoundOnly,
[Models.Metadata.Chip.ClockKey] = item.Clock,
};
@@ -363,7 +359,7 @@ namespace SabreTools.Serialization.CrossModel
{
var control = new Models.Metadata.Control
{
[Models.Metadata.Control.TypeKey] = item.Type,
[Models.Metadata.Control.ControlTypeKey] = item.Type,
[Models.Metadata.Control.PlayerKey] = item.Player,
[Models.Metadata.Control.ButtonsKey] = item.Buttons,
[Models.Metadata.Control.ReqButtonsKey] = item.ReqButtons,
@@ -386,7 +382,7 @@ namespace SabreTools.Serialization.CrossModel
{
var device = new Models.Metadata.Device
{
[Models.Metadata.Device.TypeKey] = item.Type,
[Models.Metadata.Device.DeviceTypeKey] = item.Type,
[Models.Metadata.Device.TagKey] = item.Tag,
[Models.Metadata.Device.FixedImageKey] = item.FixedImage,
[Models.Metadata.Device.MandatoryKey] = item.Mandatory,
@@ -513,7 +509,7 @@ namespace SabreTools.Serialization.CrossModel
var display = new Models.Metadata.Display
{
[Models.Metadata.Display.TagKey] = item.Tag,
[Models.Metadata.Display.TypeKey] = item.Type,
[Models.Metadata.Display.DisplayTypeKey] = item.Type,
[Models.Metadata.Display.RotateKey] = item.Rotate,
[Models.Metadata.Display.FlipXKey] = item.FlipX,
[Models.Metadata.Display.WidthKey] = item.Width,
@@ -571,7 +567,7 @@ namespace SabreTools.Serialization.CrossModel
{
var feature = new Models.Metadata.Feature
{
[Models.Metadata.Feature.TypeKey] = item.Type,
[Models.Metadata.Feature.FeatureTypeKey] = item.Type,
[Models.Metadata.Feature.StatusKey] = item.Status,
[Models.Metadata.Feature.OverallKey] = item.Overall,
};

View File

@@ -7,18 +7,10 @@ namespace SabreTools.Serialization.CrossModel
public partial class Logiqx : IModelSerializer<Datafile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Datafile Deserialize(Models.Metadata.MetadataFile obj) => Deserialize(obj, false);
#else
public Datafile? Deserialize(Models.Metadata.MetadataFile? obj) => Deserialize(obj, false);
#endif
/// <inheritdoc/>
#if NET48
public Datafile Deserialize(Models.Metadata.MetadataFile obj, bool game)
#else
public Datafile? Deserialize(Models.Metadata.MetadataFile? obj, bool game)
#endif
{
if (obj == null)
return null;
@@ -111,15 +103,7 @@ namespace SabreTools.Serialization.CrossModel
/// </summary>
private static GameBase ConvertMachineFromInternalModel(Models.Metadata.Machine item, bool game = false)
{
#if NET48
GameBase gameBase;
if (game)
gameBase = new Game();
else
gameBase = new Machine();
#else
GameBase gameBase = game ? new Game() : new Machine();
#endif
gameBase.Name = item.ReadString(Models.Metadata.Machine.NameKey);
gameBase.SourceFile = item.ReadString(Models.Metadata.Machine.SourceFileKey);

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
{
public partial class Logiqx : IModelSerializer<Datafile, Models.Metadata.MetadataFile>
{
#if NET48
public Models.Metadata.MetadataFile Serialize(Datafile item)
#else
public Models.Metadata.MetadataFile? Serialize(Datafile? item)
#endif
{
if (item == null)
return null;
@@ -26,9 +22,9 @@ namespace SabreTools.Serialization.CrossModel
if (item.Game != null && item.Game.Any())
{
machines.AddRange(item.Game
.Where(g => g != null)
.Select(ConvertMachineToInternalModel));
machines.AddRange(item.Game
.Where(g => g != null)
.Select(ConvertMachineToInternalModel));
}
if (item.Dir != null && item.Dir.Any())
@@ -108,7 +104,7 @@ namespace SabreTools.Serialization.CrossModel
private static Models.Metadata.Machine[] ConvertDirToInternalModel(Dir item)
{
if (item.Game == null || !item.Game.Any())
return Array.Empty<Models.Metadata.Machine>();
return [];
return item.Game
.Where(g => g != null)

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class M1 : IModelSerializer<Models.Listxml.M1, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Listxml.M1 Deserialize(Models.Metadata.MetadataFile obj)
#else
public Models.Listxml.M1? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -6,11 +6,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class M1 : IModelSerializer<Models.Listxml.M1, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Models.Listxml.M1 item)
#else
public Models.Metadata.MetadataFile? Serialize(Models.Listxml.M1? item)
#endif
{
if (item == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class OfflineList : IModelSerializer<Dat, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Dat Deserialize(Models.Metadata.MetadataFile obj)
#else
public Dat? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class OfflineList : IModelSerializer<Dat, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Dat item)
#else
public Models.Metadata.MetadataFile? Serialize(Dat? item)
#endif
{
if (item == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class OpenMSX : IModelSerializer<SoftwareDb, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public SoftwareDb Deserialize(Models.Metadata.MetadataFile obj)
#else
public SoftwareDb? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -104,7 +100,7 @@ namespace SabreTools.Serialization.CrossModel
var megaRom = new MegaRom
{
Start = item.ReadString(Models.Metadata.Rom.StartKey),
Type = item.ReadString(Models.Metadata.Rom.TypeKey),
Type = item.ReadString(Models.Metadata.Rom.OpenMSXType),
Hash = item.ReadString(Models.Metadata.Rom.SHA1Key),
Remark = item.ReadString(Models.Metadata.Rom.RemarkKey),
};
@@ -132,7 +128,7 @@ namespace SabreTools.Serialization.CrossModel
var rom = new Rom
{
Start = item.ReadString(Models.Metadata.Rom.StartKey),
Type = item.ReadString(Models.Metadata.Rom.TypeKey),
Type = item.ReadString(Models.Metadata.Rom.OpenMSXType),
Hash = item.ReadString(Models.Metadata.Rom.SHA1Key),
Remark = item.ReadString(Models.Metadata.Rom.RemarkKey),
};
@@ -147,7 +143,7 @@ namespace SabreTools.Serialization.CrossModel
var sccPlusCart = new SCCPlusCart
{
Start = item.ReadString(Models.Metadata.Rom.StartKey),
Type = item.ReadString(Models.Metadata.Rom.TypeKey),
Type = item.ReadString(Models.Metadata.Rom.OpenMSXType),
Hash = item.ReadString(Models.Metadata.Rom.SHA1Key),
Remark = item.ReadString(Models.Metadata.Rom.RemarkKey),
};

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class OpenMSX : IModelSerializer<SoftwareDb, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(SoftwareDb item)
#else
public Models.Metadata.MetadataFile? Serialize(SoftwareDb? item)
#endif
{
if (item == null)
return null;
@@ -122,7 +118,7 @@ namespace SabreTools.Serialization.CrossModel
var rom = new Models.Metadata.Rom
{
[Models.Metadata.Rom.StartKey] = item.Start,
[Models.Metadata.Rom.TypeKey] = item.Type,
[Models.Metadata.Rom.OpenMSXType] = item.Type,
[Models.Metadata.Rom.SHA1Key] = item.Hash,
[Models.Metadata.Rom.RemarkKey] = item.Remark,
};

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class RomCenter : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -95,7 +91,7 @@ namespace SabreTools.Serialization.CrossModel
{
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
if (roms == null)
return Array.Empty<Rom>();
return [];
return roms
.Where(r => r != null)

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class RomCenter : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -8,11 +8,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class SeparatedValue : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(Models.Metadata.MetadataFile obj)
#else
public MetadataFile? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -25,7 +21,7 @@ namespace SabreTools.Serialization.CrossModel
{
metadataFile.Row = machines
.Where(m => m != null)
.SelectMany(ConvertMachineFromInternalModel)
.SelectMany(m => ConvertMachineFromInternalModel(m, header))
.ToArray();
}
@@ -47,7 +43,7 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.Machine"/> to an array of <cref="Models.SeparatedValue.Row"/>
/// </summary>
private static Row[] ConvertMachineFromInternalModel(Models.Metadata.Machine item)
private static Row[] ConvertMachineFromInternalModel(Models.Metadata.Machine item, Models.Metadata.Header? header)
{
var rowItems = new List<Row>();
@@ -56,7 +52,7 @@ namespace SabreTools.Serialization.CrossModel
{
rowItems.AddRange(roms
.Where(r => r != null)
.Select(rom => ConvertFromInternalModel(rom, item)));
.Select(rom => ConvertFromInternalModel(rom, item, header)));
}
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
@@ -64,7 +60,7 @@ namespace SabreTools.Serialization.CrossModel
{
rowItems.AddRange(disks
.Where(d => d != null)
.Select(disk => ConvertFromInternalModel(disk, item)));
.Select(disk => ConvertFromInternalModel(disk, item, header)));
}
var media = item.Read<Models.Metadata.Media[]>(Models.Metadata.Machine.MediaKey);
@@ -72,7 +68,7 @@ namespace SabreTools.Serialization.CrossModel
{
rowItems.AddRange(media
.Where(m => m != null)
.Select(medium => ConvertFromInternalModel(medium, item)));
.Select(medium => ConvertFromInternalModel(medium, item, header)));
}
return rowItems.ToArray();
@@ -81,16 +77,26 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.Disk"/> to <cref="Models.SeparatedValue.Row"/>
/// </summary>
private static Row ConvertFromInternalModel(Models.Metadata.Disk item, Models.Metadata.Machine parent)
private static Row ConvertFromInternalModel(Models.Metadata.Disk item, Models.Metadata.Machine parent, Models.Metadata.Header? header)
{
var row = new Row
{
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve
InternalName = header?.ReadString(Models.Metadata.Header.NameKey),
Description = header?.ReadString(Models.Metadata.Header.DescriptionKey),
GameName = parent.ReadString(Models.Metadata.Machine.NameKey),
Description = parent.ReadString(Models.Metadata.Machine.DescriptionKey),
GameDescription = parent.ReadString(Models.Metadata.Machine.DescriptionKey),
Type = "disk",
RomName = null,
DiskName = item.ReadString(Models.Metadata.Disk.NameKey),
Size = null,
CRC = null,
MD5 = item.ReadString(Models.Metadata.Disk.MD5Key),
SHA1 = item.ReadString(Models.Metadata.Disk.SHA1Key),
SHA256 = null,
SHA384 = null,
SHA512 = null,
SpamSum = null,
Status = item.ReadString(Models.Metadata.Disk.StatusKey),
};
return row;
@@ -99,17 +105,25 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.Media"/> to <cref="Models.SeparatedValue.Row"/>
/// </summary>
private static Row ConvertFromInternalModel(Models.Metadata.Media item, Models.Metadata.Machine parent)
private static Row ConvertFromInternalModel(Models.Metadata.Media item, Models.Metadata.Machine parent, Models.Metadata.Header? header)
{
var row = new Row
{
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve
InternalName = header?.ReadString(Models.Metadata.Header.NameKey),
Description = header?.ReadString(Models.Metadata.Header.DescriptionKey),
GameName = parent.ReadString(Models.Metadata.Machine.NameKey),
Description = parent.ReadString(Models.Metadata.Machine.DescriptionKey),
GameDescription = parent.ReadString(Models.Metadata.Machine.DescriptionKey),
Type = "media",
RomName = null,
DiskName = item.ReadString(Models.Metadata.Media.NameKey),
Size = null,
CRC = null,
MD5 = item.ReadString(Models.Metadata.Media.MD5Key),
SHA1 = item.ReadString(Models.Metadata.Media.SHA1Key),
SHA256 = item.ReadString(Models.Metadata.Media.SHA256Key),
SHA384 = null,
SHA512 = null,
SpamSum = item.ReadString(Models.Metadata.Media.SpamSumKey),
};
return row;
@@ -118,14 +132,18 @@ namespace SabreTools.Serialization.CrossModel
/// <summary>
/// Convert from <cref="Models.Metadata.Rom"/> to <cref="Models.SeparatedValue.Row"/>
/// </summary>
private static Row ConvertFromInternalModel(Models.Metadata.Rom item, Models.Metadata.Machine parent)
private static Row ConvertFromInternalModel(Models.Metadata.Rom item, Models.Metadata.Machine parent, Models.Metadata.Header? header)
{
var row = new Row
{
GameName = parent?.ReadString(Models.Metadata.Machine.NameKey),
Description = parent?.ReadString(Models.Metadata.Machine.DescriptionKey),
FileName = header?.ReadString("FILENAME"), // TODO: Make this an actual key to retrieve
InternalName = header?.ReadString(Models.Metadata.Header.NameKey),
Description = header?.ReadString(Models.Metadata.Header.DescriptionKey),
GameName = parent.ReadString(Models.Metadata.Machine.NameKey),
GameDescription = parent.ReadString(Models.Metadata.Machine.DescriptionKey),
Type = "rom",
RomName = item.ReadString(Models.Metadata.Rom.NameKey),
DiskName = null,
Size = item.ReadString(Models.Metadata.Rom.SizeKey),
CRC = item.ReadString(Models.Metadata.Rom.CRCKey),
MD5 = item.ReadString(Models.Metadata.Rom.MD5Key),

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class SeparatedValue : IModelSerializer<MetadataFile, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(MetadataFile obj)
#else
public Models.Metadata.MetadataFile? Serialize(MetadataFile? obj)
#endif
{
if (obj == null)
return null;
@@ -78,53 +74,6 @@ namespace SabreTools.Serialization.CrossModel
return machine;
}
#if NET48
/// <summary>
/// Convert from <cref="Models.SeparatedValue.Row"/> to <cref="Models.Metadata.DatItem"/>
/// </summary>
private static Models.Metadata.DatItem ConvertToInternalModel(Row item)
{
switch (item.Type)
{
case "disk":
return new Models.Metadata.Disk
{
[Models.Metadata.Disk.NameKey] = item.DiskName,
[Models.Metadata.Disk.MD5Key] = item.MD5,
[Models.Metadata.Disk.SHA1Key] = item.SHA1,
[Models.Metadata.Disk.StatusKey] = item.Status,
};
case "media":
return new Models.Metadata.Media
{
[Models.Metadata.Media.NameKey] = item.DiskName,
[Models.Metadata.Media.MD5Key] = item.MD5,
[Models.Metadata.Media.SHA1Key] = item.SHA1,
[Models.Metadata.Media.SHA256Key] = item.SHA256,
[Models.Metadata.Media.SpamSumKey] = item.SpamSum,
};
case "rom":
return new Models.Metadata.Rom
{
[Models.Metadata.Rom.NameKey] = item.RomName,
[Models.Metadata.Rom.SizeKey] = item.Size,
[Models.Metadata.Rom.CRCKey] = item.CRC,
[Models.Metadata.Rom.MD5Key] = item.MD5,
[Models.Metadata.Rom.SHA1Key] = item.SHA1,
[Models.Metadata.Rom.SHA256Key] = item.SHA256,
[Models.Metadata.Rom.SHA384Key] = item.SHA384,
[Models.Metadata.Rom.SHA512Key] = item.SHA512,
[Models.Metadata.Rom.SpamSumKey] = item.SpamSum,
[Models.Metadata.Rom.StatusKey] = item.Status,
};
default:
return null;
}
}
#else
/// <summary>
/// Convert from <cref="Models.SeparatedValue.Row"/> to <cref="Models.Metadata.DatItem"/>
/// </summary>
@@ -163,6 +112,5 @@ namespace SabreTools.Serialization.CrossModel
_ => null,
};
}
#endif
}
}

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class SoftwareList : IModelSerializer<Models.SoftwareList.SoftwareList, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.SoftwareList.SoftwareList Deserialize(Models.Metadata.MetadataFile obj)
#else
public Models.SoftwareList.SoftwareList? Deserialize(Models.Metadata.MetadataFile? obj)
#endif
{
if (obj == null)
return null;

View File

@@ -7,11 +7,7 @@ namespace SabreTools.Serialization.CrossModel
public partial class SoftwareList : IModelSerializer<Models.SoftwareList.SoftwareList, Models.Metadata.MetadataFile>
{
/// <inheritdoc/>
#if NET48
public Models.Metadata.MetadataFile Serialize(Models.SoftwareList.SoftwareList item)
#else
public Models.Metadata.MetadataFile? Serialize(Models.SoftwareList.SoftwareList? item)
#endif
{
if (item == null)
return null;

View File

@@ -17,11 +17,7 @@ namespace SabreTools.Serialization
/// <param name="rva">Relative virtual address to convert</param>
/// <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, SectionHeader[] sections)
#else
public static uint ConvertVirtualAddress(this uint rva, SectionHeader?[]? sections)
#endif
{
// If we have an invalid section table, we can't do anything
if (sections == null || sections.Length == 0)
@@ -44,19 +40,11 @@ namespace SabreTools.Serialization
continue;
// If the section "starts" at 0, just skip it
#if NET48
if (sections[i].PointerToRawData == 0)
#else
if (sections[i]!.PointerToRawData == 0)
#endif
continue;
// Attempt to derive the physical address from the current section
#if NET48
var section = sections[i];
#else
var section = sections[i]!;
#endif
if (rva >= section.VirtualAddress && section.VirtualSize != 0 && rva <= section.VirtualAddress + section.VirtualSize)
return rva - section.VirtualAddress + section.PointerToRawData;
else if (rva >= section.VirtualAddress && section.SizeOfRawData != 0 && rva <= section.VirtualAddress + section.SizeOfRawData)
@@ -72,11 +60,7 @@ 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>
#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)
@@ -114,11 +98,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into overlay data</param>
/// <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 SecuROMAddD AsSecuROMAddD(this byte[] data, ref int offset)
#else
public static SecuROMAddD? AsSecuROMAddD(this byte[]? data, ref int offset)
#endif
{
// If we have data that's invalid, we can't do anything
if (data == null)
@@ -135,15 +115,15 @@ namespace SabreTools.Serialization
addD.EntryCount = data.ReadUInt32(ref offset);
addD.Version = data.ReadString(ref offset, Encoding.ASCII);
if (string.IsNullOrWhiteSpace(addD.Version))
if (string.IsNullOrEmpty(addD.Version))
offset = originalOffset + 0x10;
addD.Build = data.ReadBytes(ref offset, 4)?.Select(b => (char)b)?.ToArray();
// Distinguish between v1 and v2
int bytesToRead = 112; // v2
if (string.IsNullOrWhiteSpace(addD.Version)
|| addD.Version.StartsWith("3")
if (string.IsNullOrEmpty(addD.Version)
|| addD.Version!.StartsWith("3")
|| addD.Version.StartsWith("4.47"))
{
bytesToRead = 44;
@@ -181,11 +161,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a database</param>
/// <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 NB10ProgramDatabase AsNB10ProgramDatabase(this byte[] data, ref int offset)
#else
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)
@@ -211,11 +187,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a database</param>
/// <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 RSDSProgramDatabase AsRSDSProgramDatabase(this byte[] data, ref int offset)
#else
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)
@@ -247,11 +219,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a resource header</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled resource header on success, null on error</returns>
#if NET48
public static ResourceHeader AsResourceHeader(this byte[] data, ref int offset)
#else
public static ResourceHeader? AsResourceHeader(this byte[]? data, ref int offset)
#endif
{
// If we have data that's invalid, we can't do anything
if (data == null)
@@ -277,11 +245,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 AcceleratorTableEntry[] AsAcceleratorTableResource(this ResourceDataEntry entry)
#else
public static AcceleratorTableEntry[]? AsAcceleratorTableResource(this ResourceDataEntry? entry)
#endif
{
// If we have data that's invalid for this resource type, we can't do anything
if (entry?.Data == null || entry.Data.Length % 8 != 0)
@@ -317,11 +281,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 AssemblyManifest AsAssemblyManifest(this ResourceDataEntry entry)
#else
public static AssemblyManifest? AsAssemblyManifest(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -329,7 +289,7 @@ namespace SabreTools.Serialization
try
{
XmlSerializer serializer = new XmlSerializer(typeof(AssemblyManifest));
var serializer = new XmlSerializer(typeof(AssemblyManifest));
return serializer.Deserialize(new MemoryStream(entry.Data)) as AssemblyManifest;
}
catch
@@ -343,11 +303,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 DialogBoxResource AsDialogBox(this ResourceDataEntry entry)
#else
public static DialogBoxResource? AsDialogBox(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -402,7 +358,7 @@ namespace SabreTools.Serialization
dialogTemplateExtended.MenuResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -438,7 +394,7 @@ namespace SabreTools.Serialization
dialogTemplateExtended.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -469,7 +425,7 @@ namespace SabreTools.Serialization
dialogTemplateExtended.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -481,7 +437,11 @@ namespace SabreTools.Serialization
#region Point size and typeface
// Only if DS_SETFONT is set are the values here used
#if NET20 || NET35
if ((dialogTemplateExtended.Style & WindowStyles.DS_SETFONT) != 0)
#else
if (dialogTemplateExtended.Style.HasFlag(WindowStyles.DS_SETFONT))
#endif
{
dialogTemplateExtended.PointSize = entry.Data.ReadUInt16(ref offset);
dialogTemplateExtended.Weight = entry.Data.ReadUInt16(ref offset);
@@ -491,9 +451,9 @@ namespace SabreTools.Serialization
}
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
@@ -546,7 +506,7 @@ namespace SabreTools.Serialization
dialogItemTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -576,7 +536,7 @@ namespace SabreTools.Serialization
dialogItemTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -594,16 +554,20 @@ namespace SabreTools.Serialization
#endregion
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
dialogItemExtendedTemplates.Add(dialogItemTemplate);
// If we have an invalid item count
if (offset >= entry.Data.Length)
break;
}
dialogBoxResource.ExtendedDialogItemTemplates = dialogItemExtendedTemplates.ToArray();
dialogBoxResource.ExtendedDialogItemTemplates = [.. dialogItemExtendedTemplates];
#endregion
}
@@ -644,7 +608,7 @@ namespace SabreTools.Serialization
dialogTemplate.MenuResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -680,7 +644,7 @@ namespace SabreTools.Serialization
dialogTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -711,7 +675,7 @@ namespace SabreTools.Serialization
dialogTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -723,7 +687,11 @@ namespace SabreTools.Serialization
#region Point size and typeface
// Only if DS_SETFONT is set are the values here used
#if NET20 || NET35
if ((dialogTemplate.Style & WindowStyles.DS_SETFONT) != 0)
#else
if (dialogTemplate.Style.HasFlag(WindowStyles.DS_SETFONT))
#endif
{
dialogTemplate.PointSizeValue = entry.Data.ReadUInt16(ref offset);
@@ -732,9 +700,9 @@ namespace SabreTools.Serialization
}
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
@@ -786,7 +754,7 @@ namespace SabreTools.Serialization
dialogItemTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -816,7 +784,7 @@ namespace SabreTools.Serialization
dialogItemTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the WORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 2) != 0)
_ = entry.Data.ReadByte(ref offset);
@@ -834,16 +802,20 @@ namespace SabreTools.Serialization
#endregion
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
dialogItemTemplates.Add(dialogItemTemplate);
// If we have an invalid item count
if (offset >= entry.Data.Length)
break;
}
dialogBoxResource.DialogItemTemplates = dialogItemTemplates.ToArray();
dialogBoxResource.DialogItemTemplates = [.. dialogItemTemplates];
#endregion
}
@@ -856,11 +828,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 FontGroupHeader AsFontGroup(this ResourceDataEntry entry)
#else
public static FontGroupHeader? AsFontGroup(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -929,11 +897,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 MenuResource AsMenu(this ResourceDataEntry entry)
#else
public static MenuResource? AsMenu(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -981,9 +945,9 @@ namespace SabreTools.Serialization
extendedMenuItem.MenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
@@ -991,7 +955,7 @@ namespace SabreTools.Serialization
}
}
menuResource.ExtendedMenuItems = extendedMenuItems.ToArray();
menuResource.ExtendedMenuItems = [.. extendedMenuItems];
#endregion
}
@@ -1019,7 +983,11 @@ namespace SabreTools.Serialization
// Determine if this is a popup
int flagsOffset = offset;
var initialFlags = (MenuFlags)entry.Data.ReadUInt16(ref flagsOffset);
#if NET20 || NET35
if ((initialFlags & MenuFlags.MF_POPUP) != 0)
#else
if (initialFlags.HasFlag(MenuFlags.MF_POPUP))
#endif
{
menuItem.PopupItemType = (MenuFlags)entry.Data.ReadUInt32(ref offset);
menuItem.PopupState = (MenuFlags)entry.Data.ReadUInt32(ref offset);
@@ -1034,16 +1002,16 @@ namespace SabreTools.Serialization
}
// Align to the DWORD boundary if we're not at the end
if (offset != entry.Data.Length)
if (offset < entry.Data.Length)
{
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
_ = entry.Data.ReadByte(ref offset);
}
menuItems.Add(menuItem);
}
menuResource.MenuItems = menuItems.ToArray();
menuResource.MenuItems = [.. menuItems];
#endregion
}
@@ -1056,11 +1024,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 MessageResourceData AsMessageResourceData(this ResourceDataEntry entry)
#else
public static MessageResourceData? AsMessageResourceData(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -1089,17 +1053,13 @@ namespace SabreTools.Serialization
messageResourceBlocks.Add(messageResourceBlock);
}
messageResourceData.Blocks = messageResourceBlocks.ToArray();
messageResourceData.Blocks = [.. messageResourceBlocks];
}
// Message resource entries
if (messageResourceData.Blocks != null && messageResourceData.Blocks.Length != 0)
{
#if NET48
var messageResourceEntries = new Dictionary<uint, MessageResourceEntry>();
#else
var messageResourceEntries = new Dictionary<uint, MessageResourceEntry?>();
#endif
for (int i = 0; i < messageResourceData.Blocks.Length; i++)
{
@@ -1117,11 +1077,7 @@ namespace SabreTools.Serialization
messageResourceEntry.Flags = entry.Data.ReadUInt16(ref offset);
Encoding textEncoding = messageResourceEntry.Flags == 0x0001 ? Encoding.Unicode : Encoding.ASCII;
#if NET48
byte[] textArray = entry.Data.ReadBytes(ref offset, messageResourceEntry.Length - 4);
#else
byte[]? textArray = entry.Data.ReadBytes(ref offset, messageResourceEntry.Length - 4);
#endif
if (textArray != null)
messageResourceEntry.Text = textEncoding.GetString(textArray);
@@ -1140,11 +1096,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 ResourceDataEntry entry)
#else
public static Dictionary<int, string?>? AsStringTable(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -1154,11 +1106,7 @@ namespace SabreTools.Serialization
int offset = 0, stringIndex = 0;
// Create the output table
#if NET48
var stringTable = new Dictionary<int, string>();
#else
var stringTable = new Dictionary<int, string?>();
#endif
// Loop through and add
while (offset < entry.Data.Length)
@@ -1191,11 +1139,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <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 VersionInfo AsVersionInfo(this ResourceDataEntry entry)
#else
public static VersionInfo? AsVersionInfo(this ResourceDataEntry? entry)
#endif
{
// If we have an invalid entry, just skip
if (entry?.Data == null)
@@ -1214,7 +1158,7 @@ namespace SabreTools.Serialization
if (versionInfo.Key != "VS_VERSION_INFO")
return null;
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
versionInfo.Padding1 = entry.Data.ReadUInt16(ref offset);
// Read fixed file info
@@ -1240,7 +1184,7 @@ namespace SabreTools.Serialization
versionInfo.Value = fixedFileInfo;
}
while ((offset % 4) != 0)
while (offset < entry.Data.Length && (offset % 4) != 0)
versionInfo.Padding2 = entry.Data.ReadUInt16(ref offset);
// TODO: Make the following block a private helper method
@@ -1252,11 +1196,7 @@ namespace SabreTools.Serialization
int currentOffset = offset;
offset += 6;
#if NET48
string nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
#else
string? nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
#endif
offset = currentOffset;
if (nextKey == "StringFileInfo")
@@ -1278,11 +1218,7 @@ namespace SabreTools.Serialization
int currentOffset = offset;
offset += 6;
#if NET48
string nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
#else
string? nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
#endif
offset = currentOffset;
if (nextKey == "StringFileInfo")
@@ -1306,11 +1242,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a string file info</param>
/// <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 StringFileInfo AsStringFileInfo(byte[] data, ref int offset)
#else
private static StringFileInfo? AsStringFileInfo(byte[] data, ref int offset)
#endif
{
var stringFileInfo = new StringFileInfo();
@@ -1328,9 +1260,9 @@ namespace SabreTools.Serialization
}
// Align to the DWORD boundary if we're not at the end
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
stringFileInfo.Padding = data.ReadByte(ref offset);
}
@@ -1345,9 +1277,9 @@ namespace SabreTools.Serialization
stringTable.Key = data.ReadString(ref offset, Encoding.Unicode);
// Align to the DWORD boundary if we're not at the end
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
stringTable.Padding = data.ReadByte(ref offset);
}
@@ -1356,45 +1288,45 @@ namespace SabreTools.Serialization
{
var stringData = new StringData();
int dataStartOffset = offset;
stringData.Length = data.ReadUInt16(ref offset);
stringData.ValueLength = 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
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
stringData.Padding = data.ReadByte(ref offset);
}
if (stringData.ValueLength > 0)
{
#if NET48
byte[] valueBytes = data.ReadBytes(ref offset, stringData.ValueLength * sizeof(ushort));
#else
byte[]? valueBytes = data.ReadBytes(ref offset, stringData.ValueLength * sizeof(ushort));
#endif
int bytesReadable = Math.Min(stringData.ValueLength * sizeof(ushort), stringData.Length - (offset - dataStartOffset));
byte[]? valueBytes = data.ReadBytes(ref offset, bytesReadable);
if (valueBytes != null)
stringData.Value = Encoding.Unicode.GetString(valueBytes);
}
// Align to the DWORD boundary if we're not at the end
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
_ = data.ReadByte(ref offset);
}
stringTableChildren.Add(stringData);
if (stringData.Length == 0 && stringData.ValueLength == 0)
break;
}
stringTable.Children = stringTableChildren.ToArray();
stringTable.Children = [.. stringTableChildren];
stringFileInfoChildren.Add(stringTable);
}
stringFileInfo.Children = stringFileInfoChildren.ToArray();
stringFileInfo.Children = [.. stringFileInfoChildren];
return stringFileInfo;
}
@@ -1405,11 +1337,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a var file info</param>
/// <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 VarFileInfo AsVarFileInfo(byte[] data, ref int offset)
#else
private static VarFileInfo? AsVarFileInfo(byte[] data, ref int offset)
#endif
{
var varFileInfo = new VarFileInfo();
@@ -1424,9 +1352,9 @@ namespace SabreTools.Serialization
return null;
// Align to the DWORD boundary if we're not at the end
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
varFileInfo.Padding = data.ReadByte(ref offset);
}
@@ -1446,9 +1374,9 @@ namespace SabreTools.Serialization
}
// Align to the DWORD boundary if we're not at the end
if (offset != data.Length)
if (offset < data.Length)
{
while ((offset % 4) != 0)
while (offset < data.Length && (offset % 4) != 0)
varData.Padding = data.ReadByte(ref offset);
}
@@ -1462,12 +1390,12 @@ namespace SabreTools.Serialization
varDataValue.Add(languageAndCodeIdentifierPair);
}
varData.Value = varDataValue.ToArray();
varData.Value = [.. varDataValue];
varFileInfoChildren.Add(varData);
}
varFileInfo.Children = varFileInfoChildren.ToArray();
varFileInfo.Children = [.. varFileInfoChildren];
return varFileInfo;
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class AACS : IFileSerializer<Models.AACS.MediaKeyBlock>
{
/// <inheritdoc/>
public Models.AACS.MediaKeyBlock? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.AACS().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class AACS : IFileSerializer<Models.AACS.MediaKeyBlock>
{
/// <inheritdoc/>
public bool Serialize(Models.AACS.MediaKeyBlock? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.AACS().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -6,16 +6,10 @@ namespace SabreTools.Serialization.Files
public partial class AttractMode : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(string path)
#else
public MetadataFile? Deserialize(string? path)
#endif
{
using (var stream = PathProcessor.OpenStream(path))
{
return new Streams.AttractMode().Deserialize(stream);
}
using var stream = PathProcessor.OpenStream(path);
return new Streams.AttractMode().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
using SabreTools.Models.AttractMode;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class AttractMode : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
public bool Serialize(MetadataFile? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.AttractMode().Serialize(obj);
if (stream == null)
return false;
using var fs = File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BDPlus : IFileSerializer<Models.BDPlus.SVM>
{
/// <inheritdoc/>
public Models.BDPlus.SVM? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.BDPlus().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BDPlus : IFileSerializer<Models.BDPlus.SVM>
{
/// <inheritdoc/>
public bool Serialize(Models.BDPlus.SVM? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.BDPlus().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BFPK : IFileSerializer<Models.BFPK.Archive>
{
/// <inheritdoc/>
public Models.BFPK.Archive? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.BFPK().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BFPK : IFileSerializer<Models.BFPK.Archive>
{
/// <inheritdoc/>
public bool Serialize(Models.BFPK.Archive? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.BFPK().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BSP : IFileSerializer<Models.BSP.File>
{
/// <inheritdoc/>
public Models.BSP.File? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.BSP().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class BSP : IFileSerializer<Models.BSP.File>
{
/// <inheritdoc/>
public bool Serialize(Models.BSP.File? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.BSP().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class CFB : IFileSerializer<Models.CFB.Binary>
{
/// <inheritdoc/>
public Models.CFB.Binary? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.CFB().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class CFB : IFileSerializer<Models.CFB.Binary>
{
/// <inheritdoc/>
public bool Serialize(Models.CFB.Binary? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.CFB().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,14 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class CIA : IFileSerializer<Models.N3DS.CIA>
{
/// <inheritdoc/>
public Models.N3DS.CIA? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
return new Streams.CIA().Deserialize(stream);
}
}
}

View File

@@ -0,0 +1,22 @@
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Files
{
public partial class CIA : IFileSerializer<Models.N3DS.CIA>
{
/// <inheritdoc/>
public bool Serialize(Models.N3DS.CIA? obj, string? path)
{
if (string.IsNullOrEmpty(path))
return false;
using var stream = new Streams.CIA().Serialize(obj);
if (stream == null)
return false;
using var fs = System.IO.File.OpenWrite(path);
stream.CopyTo(fs);
return true;
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Text;
namespace SabreTools.Serialization.Files
{
public partial class Catalog : JsonFile<Models.Xbox.Catalog>
{
// Catalog.js file is a UTF-16 LE JSON
public new Models.Xbox.Catalog? Deserialize(string? path)
=> Deserialize(path, new UnicodeEncoding());
}
}

View File

@@ -0,0 +1,11 @@
using System.Text;
namespace SabreTools.Serialization.Files
{
public partial class Catalog : JsonFile<Models.Xbox.Catalog>
{
// Catalog.js file is a UTF-16 LE JSON
public new bool Serialize(Models.Xbox.Catalog? obj, string? path)
=> Serialize(obj, path, new UnicodeEncoding());
}
}

View File

@@ -6,23 +6,13 @@ namespace SabreTools.Serialization.Files
public partial class ClrMamePro : IFileSerializer<MetadataFile>
{
/// <inheritdoc/>
#if NET48
public MetadataFile Deserialize(string path) => Deserialize(path, true);
#else
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, quotes);
}
using var stream = PathProcessor.OpenStream(path);
return new Streams.ClrMamePro().Deserialize(stream, quotes);
}
}
}

Some files were not shown because too many files have changed in this diff Show More