diff --git a/SabreTools.Serialization/Extensions/NESCart.cs b/SabreTools.Serialization/Extensions/NESCart.cs
index 3be12544..b53e1e85 100644
--- a/SabreTools.Serialization/Extensions/NESCart.cs
+++ b/SabreTools.Serialization/Extensions/NESCart.cs
@@ -165,6 +165,34 @@ namespace SabreTools.Data.Extensions
};
}
+ ///
+ /// Convert a value to string
+ ///
+ public static string FromTVSystem(this TVSystem system)
+ {
+ return system switch
+ {
+ TVSystem.NTSC => "NTSC",
+ TVSystem.PAL => "PAL",
+ _ => $"Unknown {(byte)system}",
+ };
+ }
+
+ ///
+ /// Convert a value to string
+ ///
+ public static string FromTVSystemExtended(this TVSystemExtended system)
+ {
+ return system switch
+ {
+ TVSystemExtended.NTSC => "NTSC",
+ TVSystemExtended.DualCompatible1 => "Dual-compatible (0x01)",
+ TVSystemExtended.PAL => "PAL",
+ TVSystemExtended.DualCompatible3 => "Dual-compatible (0x03)",
+ _ => $"Unknown {(byte)system}",
+ };
+ }
+
///
/// Convert a value to string
///
diff --git a/SabreTools.Serialization/Models/NES/Enums.cs b/SabreTools.Serialization/Models/NES/Enums.cs
index aa97467a..f3b568cc 100644
--- a/SabreTools.Serialization/Models/NES/Enums.cs
+++ b/SabreTools.Serialization/Models/NES/Enums.cs
@@ -1,51 +1,5 @@
-using System;
-
namespace SabreTools.Data.Models.NES
{
- ///
- /// TV system, PRG-RAM presence (unofficial, rarely used extension)
- ///
- [Flags]
- public enum Flag10 : byte
- {
- #region Bits 0-1
-
- NTSC = 0b000000,
- DualCompatible1 = 0b000001,
- PAL = 0b000010,
- DualCompatible2 = 0b000011,
-
- #endregion
-
- #region Bit 4
-
- ///
- /// PRG RAM ($6000-$7FFF) present
- ///
- PRGRAMPresent = 0b000000,
-
- ///
- /// PRG RAM ($6000-$7FFF) not present
- ///
- PRGRAMNotPresent = 0b010000,
-
- #endregion
-
- #region Bit 5
-
- ///
- /// Board has no bus conflicts
- ///
- BoardHasNoBusConflicts = 0b000000,
-
- ///
- /// Board has bus conflicts
- ///
- BoardHasBusConflicts = 0b100000,
-
- #endregion
- }
-
///
/// Console Type
///
@@ -625,12 +579,25 @@ namespace SabreTools.Data.Models.NES
///
/// TV system (rarely used extension)
///
+ /// Byte 9
public enum TVSystem : byte
{
NTSC = 0x00,
PAL = 0x01,
}
+ ///
+ /// TV system with extended values
+ ///
+ /// Actually only 2 bits (bits 0-1 of flag 10)
+ public enum TVSystemExtended : byte
+ {
+ NTSC = 0x00,
+ DualCompatible1 = 0x01,
+ PAL = 0x02,
+ DualCompatible3 = 0x03,
+ }
+
///
/// Vs. Hardware Type
///
diff --git a/SabreTools.Serialization/Models/NES/Header1.cs b/SabreTools.Serialization/Models/NES/Header1.cs
index a2db94a4..72a78e26 100644
--- a/SabreTools.Serialization/Models/NES/Header1.cs
+++ b/SabreTools.Serialization/Models/NES/Header1.cs
@@ -36,14 +36,64 @@ namespace SabreTools.Data.Models.NES
///
public TVSystem TVSystem { get; set; }
+ #region Byte 10
+
///
- /// TV system, PRG-RAM presence (unofficial, rarely used extension)
+ /// TV system with extended values
///
///
+ /// Byte 10, Bits 0-1
+ ///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
///
- public Flag10 Flag10 { get; set; }
+ public TVSystemExtended TVSystemExtended { get; set; }
+
+ ///
+ /// Unknown reserved bits
+ ///
+ ///
+ /// Byte 10, Bits 2-3
+ ///
+ /// This byte is not part of the official specification, and relatively
+ /// few emulators honor it.
+ ///
+ public byte ReservedBits23 { get; set; }
+
+ ///
+ /// PRG RAM ($6000-$7FFF) present
+ ///
+ ///
+ /// Byte 10, Bit 4
+ ///
+ /// This byte is not part of the official specification, and relatively
+ /// few emulators honor it.
+ ///
+ public bool PRGRAMPresent { get; set; }
+
+ ///
+ /// Board has bus conflicts
+ ///
+ ///
+ /// Byte 10, Bit 5
+ ///
+ /// This byte is not part of the official specification, and relatively
+ /// few emulators honor it.
+ ///
+ public bool HasBusConflicts { get; set; }
+
+ ///
+ /// Unknown reserved bits
+ ///
+ ///
+ /// Byte 10, Bits 6-7
+ ///
+ /// This byte is not part of the official specification, and relatively
+ /// few emulators honor it.
+ ///
+ public byte ReservedBits67 { get; set; }
+
+ #endregion
///
/// Unused padding to align to 16 bytes
diff --git a/SabreTools.Serialization/Readers/NESCart.cs b/SabreTools.Serialization/Readers/NESCart.cs
index 4325857a..cc513d7b 100644
--- a/SabreTools.Serialization/Readers/NESCart.cs
+++ b/SabreTools.Serialization/Readers/NESCart.cs
@@ -93,17 +93,17 @@ namespace SabreTools.Serialization.Readers
byte prgRomSize = data.ReadByteValue();
byte chrRomSize = data.ReadByteValue();
- byte flag6 = data.ReadByteValue();
- NametableArrangement nametableArrangement = (NametableArrangement)(flag6 & 0x01);
- bool batteryBackedPrgRam = ((flag6 >> 1) & 0x01) != 0;
- bool trainerPresent = ((flag6 >> 2) & 0x01) != 0;
- bool alternativeNametableLayout = ((flag6 >> 3) & 0x01) != 0;
- byte mapperLowerNibble = (byte)(flag6 >> 4);
+ byte byte6 = data.ReadByteValue();
+ NametableArrangement nametableArrangement = (NametableArrangement)(byte6 & 0x01);
+ bool batteryBackedPrgRam = ((byte6 >> 1) & 0x01) != 0;
+ bool trainerPresent = ((byte6 >> 2) & 0x01) != 0;
+ bool alternativeNametableLayout = ((byte6 >> 3) & 0x01) != 0;
+ byte mapperLowerNibble = (byte)(byte6 >> 4);
- byte flag7 = data.ReadByteValue();
- ConsoleType consoleType = (ConsoleType)(flag7 & 0x03);
- bool nes20 = ((flag7 >> 2) & 0x02) == 0x02;
- byte mapperUpperNibble = (byte)(flag7 >> 4);
+ byte byte7 = data.ReadByteValue();
+ ConsoleType consoleType = (ConsoleType)(byte7 & 0x03);
+ bool nes20 = ((byte7 >> 2) & 0x02) == 0x02;
+ byte mapperUpperNibble = (byte)(byte7 >> 4);
// NES 2.0
if (nes20)
@@ -147,21 +147,29 @@ namespace SabreTools.Serialization.Readers
obj.PRGROMSize = prgRomSize;
obj.CHRROMSize = chrRomSize;
- // Flag 6
+ // Byte 6
obj.NametableArrangement = nametableArrangement;
obj.BatteryBackedPRGRAM = batteryBackedPrgRam;
obj.TrainerPresent = trainerPresent;
obj.AlternativeNametableLayout = alternativeNametableLayout;
obj.MapperLowerNibble = mapperLowerNibble;
- // Flag 7
+ // Byte 7
obj.ConsoleType = consoleType;
obj.NES20 = nes20;
obj.MapperUpperNibble = mapperUpperNibble;
obj.PRGRAMSize = data.ReadByteValue();
obj.TVSystem = (TVSystem)data.ReadByteValue();
- obj.Flag10 = (Flag10)data.ReadByteValue();
+
+ // Byte 10
+ byte byte10 = data.ReadByteValue();
+ obj.TVSystemExtended = (TVSystemExtended)(byte10 & 0x03);
+ obj.ReservedBits23 = (byte)((byte10 >> 2) & 0x03);
+ obj.PRGRAMPresent = ((byte10 >> 4) & 0x01) == 0x01;
+ obj.HasBusConflicts = ((byte10 >> 5) & 0x01) == 0x01;
+ obj.ReservedBits67 = (byte)((byte10 >> 6) & 0x03);
+
obj.Padding = data.ReadBytes(5);
return obj;
diff --git a/SabreTools.Serialization/Wrappers/NESCart.Printing.cs b/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
index d3418cc0..40a6eeed 100644
--- a/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
+++ b/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
@@ -91,7 +91,8 @@ namespace SabreTools.Serialization.Wrappers
builder.AppendLine(header1.PRGRAMSize, prefixString: " PRG-RAM size in 8KiB units");
// Byte 9
- builder.AppendLine($" TV system: {header1.TVSystem} (0x{header1.TVSystem:X})");
+ string tvSystem = header1.TVSystem.FromTVSystem();
+ builder.AppendLine(tvSystem, " TV system");
// Byte 10
#region Flag 10
@@ -99,46 +100,21 @@ namespace SabreTools.Serialization.Wrappers
builder.AppendLine(" Flag 10:");
// Bits 0-1
-#if NET20 || NET35
- if ((header1.Flag10 & Flag10.DualCompatible2) != 0)
-#else
- if (header1.Flag10.HasFlag(Flag10.DualCompatible2))
-#endif
- builder.AppendLine(" TV System: Dual-compatible");
-#if NET20 || NET35
- else if ((header1.Flag10 & Flag10.PAL) != 0)
-#else
- else if (header1.Flag10.HasFlag(Flag10.PAL))
-#endif
- builder.AppendLine(" TV System: PAL");
-#if NET20 || NET35
- else if ((header1.Flag10 & Flag10.DualCompatible1) != 0)
-#else
- else if (header1.Flag10.HasFlag(Flag10.DualCompatible1))
-#endif
- builder.AppendLine(" TV System: Dual-compatible");
- else
- builder.AppendLine(" TV System: NTSC");
+ string tvSystemExtended = header1.TVSystemExtended.FromTVSystemExtended();
+ builder.AppendLine(tvSystemExtended, " TV System Extended");
+
+ // Bits 2-3
+ builder.AppendLine(header1.ReservedBits23, " Reserved bits 1-2");
// Bit 4
-#if NET20 || NET35
- if ((header1.Flag10 & Flag10.PRGRAMNotPresent) != 0)
-#else
- if (header1.Flag10.HasFlag(Flag10.PRGRAMNotPresent))
-#endif
- builder.AppendLine(" PRG-RAM: Not present");
- else
- builder.AppendLine(" PRG-RAM: Present");
+ string prgRamPresent = header1.PRGRAMPresent ? "Present" : "Not present";
+ builder.AppendLine(prgRamPresent, " PRG-RAM");
// Bit 5
-#if NET20 || NET35
- if ((header1.Flag10 & Flag10.BoardHasBusConflicts) != 0)
-#else
- if (header1.Flag10.HasFlag(Flag10.BoardHasBusConflicts))
-#endif
- builder.AppendLine(" Has Bus Conflicts: True");
- else
- builder.AppendLine(" Has Bus Conflicts: False");
+ builder.AppendLine(header1.HasBusConflicts, " Has Bus Conflicts");
+
+ // Bits 6-7
+ builder.AppendLine(header1.ReservedBits67, " Reserved bits 6-7");
#endregion
diff --git a/SabreTools.Serialization/Wrappers/NESCart.cs b/SabreTools.Serialization/Wrappers/NESCart.cs
index f52e1164..d7046889 100644
--- a/SabreTools.Serialization/Wrappers/NESCart.cs
+++ b/SabreTools.Serialization/Wrappers/NESCart.cs
@@ -147,9 +147,7 @@ namespace SabreTools.Serialization.Wrappers
#region NES 1.0
- ///
- /// Indicates if the board has bus conflicts
- ///
+ ///
/// Defined only for NES 1.0
public bool HasBusConflicts
{
@@ -159,19 +157,13 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null || Header is not Header1 header1)
return false;
-#if NET20 || NET35
- return (header1.Flag10 & Flag10.BoardHasBusConflicts) != 0;
-#else
- return header1.Flag10.HasFlag(Flag10.BoardHasBusConflicts);
-#endif
+ return header1.HasBusConflicts;
}
}
- ///
- /// Indicates if PRG RAM at $6000-$7FFF is present
- ///
+ ///
/// Defined only for NES 1.0
- public bool HasPRGRAM
+ public bool PRGRAMPresent
{
get
{
@@ -179,11 +171,35 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null || Header is not Header1 header1)
return false;
-#if NET20 || NET35
- return (header1.Flag10 & Flag10.PRGRAMNotPresent) == 0;
-#else
- return !header1.Flag10.HasFlag(Flag10.PRGRAMNotPresent);
-#endif
+ return header1.PRGRAMPresent;
+ }
+ }
+
+ ///
+ /// Defined only for NES 1.0
+ public TVSystem TVSystem
+ {
+ get
+ {
+ // Missing or invalid header
+ if (Header is null || Header is not Header1 header1)
+ return TVSystem.NTSC;
+
+ return header1.TVSystem;
+ }
+ }
+
+ ///
+ /// Defined only for NES 1.0
+ public TVSystemExtended TVSystemExtended
+ {
+ get
+ {
+ // Missing or invalid header
+ if (Header is null || Header is not Header1 header1)
+ return TVSystemExtended.NTSC;
+
+ return header1.TVSystemExtended;
}
}