Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/nes-containers.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-04 15:53:02 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-04 15:53:02 +0300
commitee11aae7f78810c4e002e26b03754a46d0a18ddd (patch)
treef3e9dbd43ab59e69cb1b1a9e2f92f6bc7eecf563
parentc02d5efa89d71092675d73744e76e9aeb518d813 (diff)
Nullable types
-rw-r--r--FdsBlockDiskInfo.cs10
-rw-r--r--FdsBlockFileAmount.cs2
-rw-r--r--FdsBlockFileData.cs22
-rw-r--r--FdsBlockFileHeader.cs4
-rw-r--r--FdsDiskFile.cs8
-rw-r--r--NesContainers.csproj3
-rw-r--r--NesFile.cs12
-rw-r--r--UnifFile.cs159
8 files changed, 99 insertions, 121 deletions
diff --git a/FdsBlockDiskInfo.cs b/FdsBlockDiskInfo.cs
index 9f91957..5a893ef 100644
--- a/FdsBlockDiskInfo.cs
+++ b/FdsBlockDiskInfo.cs
@@ -653,7 +653,7 @@ namespace com.clusterrr.Famicom.Containers
public Company LicenseeCode { get => (Company)manufacturerCode; set => manufacturerCode = (byte)value; }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
- byte[] gameName;
+ byte[] gameName = Encoding.ASCII.GetBytes("---");
/// <summary>
/// 3-letter ASCII code per game (e.g. ZEL for The Legend of Zelda)
/// </summary>
@@ -718,7 +718,7 @@ namespace com.clusterrr.Famicom.Containers
readonly byte unknown06 = 0xFF;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
- byte[] manufacturingDate;
+ byte[] manufacturingDate = { 0, 0, 0 };
/// <summary>
/// Manufacturing date
/// </summary>
@@ -769,10 +769,10 @@ namespace com.clusterrr.Famicom.Containers
readonly ushort unknown09 = 0x0200;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
// Speculative: some kind of game information representation?
- readonly byte[] unknown10;
+ readonly byte[] unknown10 = { 0, 0, 0, 0, 0 };
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
- byte[] rewrittenDate;
+ byte[] rewrittenDate = { 0, 0, 0 };
/// <summary>
/// "Rewritten disk" date. It's speculated this refers to the date the disk was formatted and rewritten by something like a Disk Writer kiosk.
/// In the case of an original (non-copied) disk, this should be the same as Manufacturing date
@@ -881,7 +881,7 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Return raw data
+ /// Returns raw data
/// </summary>
/// <returns>Data</returns>
public byte[] ToBytes()
diff --git a/FdsBlockFileAmount.cs b/FdsBlockFileAmount.cs
index 868b22e..54be4cf 100644
--- a/FdsBlockFileAmount.cs
+++ b/FdsBlockFileAmount.cs
@@ -48,7 +48,7 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Return raw data
+ /// Returns raw data
/// </summary>
/// <returns>Data</returns>
public byte[] ToBytes() => new byte[] { blockType, fileAmount };
diff --git a/FdsBlockFileData.cs b/FdsBlockFileData.cs
index 8ec31b4..9ce46f5 100644
--- a/FdsBlockFileData.cs
+++ b/FdsBlockFileData.cs
@@ -30,16 +30,6 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Set by dumper. True when checksum is ok
- /// </summary>
- public bool CrcOk { get; set; } = true;
-
- /// <summary>
- /// Set by dumper. True when "end of head" flag was meet during dumping
- /// </summary>
- public bool EndOfHeadMeet { get; set; } = false;
-
- /// <summary>
/// Length of the block
/// </summary>
public uint Length => (uint)(data.Length + 1);
@@ -63,18 +53,10 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Return raw data
+ /// Returns raw data
/// </summary>
/// <returns>Data</returns>
- public byte[] ToBytes()
- {
- var result = new List<byte>
- {
- blockType
- };
- result.AddRange(Data);
- return result.ToArray();
- }
+ public byte[] ToBytes() => Enumerable.Concat<byte>(new[] { blockType }, data).ToArray();
/// <summary>
/// String representation
diff --git a/FdsBlockFileHeader.cs b/FdsBlockFileHeader.cs
index ee0233c..a884a87 100644
--- a/FdsBlockFileHeader.cs
+++ b/FdsBlockFileHeader.cs
@@ -57,7 +57,7 @@ namespace com.clusterrr.Famicom.Containers
public byte FileIndicateCode { get => fileIndicateCode; set => fileIndicateCode = value; }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
- private byte[] fileName;
+ private byte[] fileName = Encoding.ASCII.GetBytes("FILENAME");
/// <summary>
/// Filename
/// </summary>
@@ -122,7 +122,7 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Return raw data
+ /// Returns raw data
/// </summary>
/// <returns>Data</returns>
public byte[] ToBytes()
diff --git a/FdsDiskFile.cs b/FdsDiskFile.cs
index c3c2e53..88e3dce 100644
--- a/FdsDiskFile.cs
+++ b/FdsDiskFile.cs
@@ -62,8 +62,8 @@ namespace com.clusterrr.Famicom.Containers
/// <param name="dataBlock">File data block</param>
public FdsDiskFile(FdsBlockFileHeader headerBlock, FdsBlockFileData dataBlock)
{
- this.HeaderBlock = headerBlock;
- this.DataBlock = dataBlock;
+ this.headerBlock = headerBlock;
+ this.dataBlock = dataBlock;
headerBlock.FileSize = (ushort)dataBlock.Data.Count();
}
@@ -72,8 +72,8 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public FdsDiskFile()
{
- this.HeaderBlock = new FdsBlockFileHeader();
- this.DataBlock = new FdsBlockFileData();
+ this.headerBlock = new FdsBlockFileHeader();
+ this.dataBlock = new FdsBlockFileData();
HeaderBlock.FileSize = (ushort)DataBlock.Data.Count();
}
diff --git a/NesContainers.csproj b/NesContainers.csproj
index b8ea4c0..fbc4df3 100644
--- a/NesContainers.csproj
+++ b/NesContainers.csproj
@@ -4,12 +4,13 @@
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>NesContainers</AssemblyName>
<RootNamespace>com.clusterrr.Famicom.Containers</RootNamespace>
- <LangVersion>7.3</LangVersion>
+ <LangVersion>11</LangVersion>
<DebugType>embedded</DebugType>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DocumentationFile>NesContainers.xml</DocumentationFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
diff --git a/NesFile.cs b/NesFile.cs
index 06dc837..042b7ec 100644
--- a/NesFile.cs
+++ b/NesFile.cs
@@ -22,17 +22,17 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// CHR data (can be null if none)
/// </summary>
- public IEnumerable<byte> CHR
+ public IEnumerable<byte>? CHR
{
- get => Array.AsReadOnly(chr);
+ get => chr.Length == 0 ? null : Array.AsReadOnly(chr);
set => chr = (value ?? new byte[0]).ToArray();
}
/// <summary>
/// Trainer (can be null if none)
/// </summary>
- public IEnumerable<byte> Trainer
+ public IEnumerable<byte>? Trainer
{
- get => Array.AsReadOnly(trainer);
+ get => trainer.Length == 0 ? null : Array.AsReadOnly(trainer);
set
{
if (value != null && value.Count() != 0 && value.Count() != 512)
@@ -43,9 +43,9 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// Miscellaneous ROM (NES 2.0 only, can be null if none)
/// </summary>
- public IEnumerable<byte> MiscellaneousROM
+ public IEnumerable<byte>? MiscellaneousROM
{
- get => Array.AsReadOnly(miscellaneousROM);
+ get => miscellaneousROM.Length == 0 ? null : Array.AsReadOnly(miscellaneousROM);
set => miscellaneousROM = (value ?? new byte[0]).ToArray();
}
/// <summary>
diff --git a/UnifFile.cs b/UnifFile.cs
index 921edec..e1d9bad 100644
--- a/UnifFile.cs
+++ b/UnifFile.cs
@@ -5,6 +5,7 @@ using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
+using System.Xml.Linq;
namespace com.clusterrr.Famicom.Containers
{
@@ -16,7 +17,7 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// UNIF fields
/// </summary>
- private Dictionary<string, byte[]> fields = new Dictionary<string, byte[]>();
+ private Dictionary<string, byte[]?> fields = new Dictionary<string, byte[]?>();
/// <summary>
/// UNIF version
@@ -28,11 +29,12 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
/// <param name="key">UNIF data block key</param>
/// <returns></returns>
- public IEnumerable<byte> this[string key]
+ public IEnumerable<byte>? this[string key]
{
get
{
if (key.Length != 4) throw new ArgumentException("UNIF data block key must be 4 characters long");
+ if (!fields.ContainsKey(key)) return null;
return Array.AsReadOnly(fields[key]);
}
set
@@ -82,7 +84,7 @@ namespace com.clusterrr.Famicom.Containers
pos += 4;
var fieldData = new byte[length];
Array.Copy(data, pos, fieldData, 0, length);
- fields[type] = fieldData;
+ this[type] = fieldData;
pos += length;
}
}
@@ -124,15 +126,16 @@ namespace com.clusterrr.Famicom.Containers
header[7] = (byte)((Version >> 24) & 0xFF);
data.AddRange(header);
- foreach (var name in fields.Keys)
+ foreach (var kv in this)
{
- data.AddRange(Encoding.UTF8.GetBytes(name));
- int len = fields[name].Length;
+ data.AddRange(Encoding.UTF8.GetBytes(kv.Key));
+ var v = kv.Value.ToArray();
+ int len = v.Length;
data.Add((byte)(len & 0xFF));
data.Add((byte)((len >> 8) & 0xFF));
data.Add((byte)((len >> 16) & 0xFF));
data.Add((byte)((len >> 24) & 0xFF));
- data.AddRange(fields[name]);
+ data.AddRange(v);
}
return data.ToArray();
}
@@ -148,8 +151,9 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
/// <param name="text">Input text</param>
/// <returns>Output byte[] array</returns>
- private static byte[] StringToUTF8N(string text)
+ private static byte[]? StringToUTF8N(string? text)
{
+ if (text == null) return null;
var str = Encoding.UTF8.GetBytes(text);
var result = new byte[str.Length + 1];
Array.Copy(str, result, str.Length);
@@ -163,8 +167,9 @@ namespace com.clusterrr.Famicom.Containers
/// <param name="maxLength">Maximum number of bytes to parse</param>
/// <param name="offset">Start offset</param>
/// <returns></returns>
- private static string UTF8NToString(byte[] data, int maxLength = int.MaxValue, int offset = 0)
+ private static string? UTF8NToString(byte[]? data, int maxLength = int.MaxValue, int offset = 0)
{
+ if (data == null || data.Length == 0) return null;
int length = 0;
while ((data[length + offset] != 0) && (length + offset < data.Length) && (length + offset < maxLength))
length++;
@@ -174,108 +179,97 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// Mapper name
/// </summary>
- public string Mapper
+ public string? Mapper
{
- get
- {
- if (fields.ContainsKey("MAPR"))
- return UTF8NToString(fields["MAPR"]);
- else
- return null;
- }
- set
- {
- fields["MAPR"] = StringToUTF8N(value);
- }
+ get => UTF8NToString(fields["MAPR"]);
+ set => fields["MAPR"] = value == null ? null : StringToUTF8N(value);
}
/// <summary>
/// The dumper name
/// </summary>
///
- public string DumperName
+ public string? DumperName
{
- get
- {
- if (!fields.ContainsKey("DINF"))
- return null;
- return UTF8NToString(fields["DINF"], 100);
- }
+ get => UTF8NToString(fields["DINF"], 100);
set
{
- if (!fields.ContainsKey("DINF"))
- fields["DINF"] = new byte[204];
+ if (this["DINF"] == null)
+ this["DINF"] = new byte[204];
+ var data = this["DINF"].ToArray();
for (int i = 0; i < 100; i++)
- fields["DINF"][i] = 0;
- var name = StringToUTF8N(value);
- Array.Copy(name, 0, fields["DINF"], 0, Math.Min(100, name.Length));
+ data[i] = 0;
+ if (value != null)
+ {
+ var name = StringToUTF8N(value);
+ Array.Copy(name, 0, data, 0, Math.Min(100, name!.Length));
+ }
+ this["DINF"] = data;
}
}
/// <summary>
/// The name of the dumping software or mechanism
/// </summary>
- public string DumpingSoftware
+ public string? DumpingSoftware
{
- get
- {
- if (!fields.ContainsKey("DINF"))
- return null;
- return UTF8NToString(fields["DINF"], 100, 104);
- }
+ get => UTF8NToString(fields["DINF"], 100, 104);
set
{
- if (!fields.ContainsKey("DINF"))
- fields["DINF"] = new byte[204];
+ if (this["DINF"] == null)
+ this["DINF"] = new byte[204];
+ var data = this["DINF"].ToArray();
for (int i = 104; i < 104 + 100; i++)
- fields["DINF"][i] = 0;
- var name = StringToUTF8N(value);
- Array.Copy(name, 0, fields["DINF"], 104, Math.Min(100, name.Length));
+ data[i] = 0;
+ if (value != null)
+ {
+ var name = StringToUTF8N(value);
+ Array.Copy(name, 0, fields["DINF"], 104, Math.Min(100, name!.Length));
+ }
+ this["DINF"] = data;
}
}
/// <summary>
/// Date of the dump
/// </summary>
- public DateTime DumpDate
+ public DateTime? DumpDate
{
get
{
+ var data = this["DINF"]?.ToArray();
+ if (data == null) return null;
if (!fields.ContainsKey("DINF"))
return new DateTime();
return new DateTime(
- year: fields["DINF"][102] | (fields["DINF"][103] << 8),
- month: fields["DINF"][101],
- day: fields["DINF"][100]
+ year: data[102] | (data[103] << 8),
+ month: data[101],
+ day: data[100]
);
}
set
{
- if (!fields.ContainsKey("DINF"))
- fields["DINF"] = new byte[204];
- fields["DINF"][100] = (byte)value.Day;
- fields["DINF"][101] = (byte)value.Month;
- fields["DINF"][102] = (byte)(value.Year & 0xFF);
- fields["DINF"][103] = (byte)(value.Year >> 8);
+ if (this["DINF"] == null)
+ this["DINF"] = new byte[204];
+ if (value != null)
+ {
+ var data = this["DINF"].ToArray();
+ data[100] = (byte)value.Value.Day;
+ data[101] = (byte)value.Value.Month;
+ data[102] = (byte)(value.Value.Year & 0xFF);
+ data[103] = (byte)(value.Value.Year >> 8);
+ this["DINF"] = data;
+ }
}
}
/// <summary>
/// Name of the game
/// </summary>
- public string GameName
+ public string? GameName
{
- get
- {
- if (fields.ContainsKey("NAME"))
- return UTF8NToString(fields["NAME"]);
- else
- return null;
- }
- set
- {
- fields["NAME"] = StringToUTF8N(value);
- }
+ get => UTF8NToString(this["NAME"]?.ToArray());
+ set => this["NAME"] = StringToUTF8N(value);
}
/// <summary>
@@ -285,14 +279,15 @@ namespace com.clusterrr.Famicom.Containers
{
get
{
- if (fields.ContainsKey("TVCI") && fields["TVCI"].Length > 0)
- return (NesFile.Timing)fields["TVCI"][0];
+ var data = this["TVCI"];
+ if (data != null && data.Any())
+ return (NesFile.Timing)data.First();
else
return NesFile.Timing.Ntsc;
}
set
{
- fields["TVCI"] = new byte[] { (byte)value };
+ this["TVCI"] = new byte[] { (byte)value };
}
}
@@ -303,8 +298,8 @@ namespace com.clusterrr.Famicom.Containers
{
get
{
- if (fields.ContainsKey("CTRL") && fields["CTRL"].Length > 0)
- return (Controller)fields["CTRL"][0];
+ if (this["CTRL"]?.Any() == true)
+ return (Controller)this["CTRL"].First();
else
return Controller.None;
}
@@ -321,8 +316,8 @@ namespace com.clusterrr.Famicom.Containers
{
get
{
- if (fields.ContainsKey("BATR") && fields["BATR"].Length > 0)
- return fields["BATR"][0] != 0;
+ if (this["BATR"]?.Any() == true)
+ return this["BATR"].First() != 0;
else
return false;
}
@@ -339,8 +334,8 @@ namespace com.clusterrr.Famicom.Containers
{
get
{
- if (fields.ContainsKey("MIRR") && fields["MIRR"].Length > 0)
- return (MirroringType)fields["MIRR"][0];
+ if (this["MIRR"]?.Any() == true)
+ return (MirroringType)fields["MIRR"].First();
else
return MirroringType.Unknown;
}
@@ -355,10 +350,10 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public void CalculateAndStoreCRCs()
{
- foreach (var key in fields.Keys.Where(k => k.StartsWith("PRG")))
+ foreach (var kv in this.Where(kv => kv.Key.StartsWith("PRG")))
{
- var num = key[3];
- var crc32 = Crc32Calculator.CalculateCRC32(fields[key]);
+ var num = kv.Key[3];
+ var crc32 = Crc32Calculator.CalculateCRC32(kv.Value.ToArray());
fields[$"PCK{num}"] = new byte[] {
(byte)(crc32 & 0xFF),
(byte)((crc32 >> 8) & 0xFF),
@@ -366,10 +361,10 @@ namespace com.clusterrr.Famicom.Containers
(byte)((crc32 >> 24) & 0xFF)
};
}
- foreach (var key in fields.Keys.Where(k => k.StartsWith("CHR")))
+ foreach (var kv in this.Where(kv => kv.Key.StartsWith("CHR")))
{
- var num = key[3];
- var crc32 = Crc32Calculator.CalculateCRC32(fields[key]);
+ var num = kv.Key[3];
+ var crc32 = Crc32Calculator.CalculateCRC32(kv.Value.ToArray());
fields[$"CCK{num}"] = new byte[] {
(byte)(crc32 & 0xFF),
(byte)((crc32 >> 8) & 0xFF),