diff --git a/SabreTools.Serialization/Extensions/NESCart.cs b/SabreTools.Serialization/Extensions/NESCart.cs
index 4fda5372..3be12544 100644
--- a/SabreTools.Serialization/Extensions/NESCart.cs
+++ b/SabreTools.Serialization/Extensions/NESCart.cs
@@ -4,6 +4,21 @@ namespace SabreTools.Data.Extensions
{
public static class NESCart
{
+ ///
+ /// Convert a value to string
+ ///
+ public static string FromConsoleType(this ConsoleType type)
+ {
+ return type switch
+ {
+ ConsoleType.StandardSystem => "Nintendo Entertainment System/Family Computer",
+ ConsoleType.VSUnisystem => "VS Unisystem",
+ ConsoleType.PlayChoice10 => "PlayChoice-10 (8 KB of Hint Screen data stored after CHR data)",
+ ConsoleType.ExtendedConsoleType => "Extended Console Type",
+ _ => $"Unknown {(byte)type}",
+ };
+ }
+
///
/// Convert a value to string
///
diff --git a/SabreTools.Serialization/Models/NES/Enums.cs b/SabreTools.Serialization/Models/NES/Enums.cs
index c1c7dc86..aa97467a 100644
--- a/SabreTools.Serialization/Models/NES/Enums.cs
+++ b/SabreTools.Serialization/Models/NES/Enums.cs
@@ -2,47 +2,6 @@ using System;
namespace SabreTools.Data.Models.NES
{
- ///
- /// Mapper, VS/Playchoice, NES 2.0
- ///
- /// Bits 4-7 are the upper nybble of mapper number
- [Flags]
- public enum Flag7 : byte
- {
- #region Bits 0-1
-
- ///
- /// Nintendo Entertainment System/Family Computer
- ///
- StandardSystem = 0b0000,
-
- ///
- /// VS Unisystem
- ///
- VSUnisystem = 0b0001,
-
- ///
- /// PlayChoice-10 (8 KB of Hint Screen data stored after CHR data)
- ///
- PlayChoice10 = 0b0010,
-
- ///
- /// Extended Console Type
- ///
- ExtendedConsoleType = 0b0011,
-
- #endregion
-
- #region Bits 2-3
-
- ///
- /// If equal to 2, flags 8-15 are in NES 2.0 format
- ///
- NES20 = 0b1000,
-
- #endregion
- }
-
///
/// TV system, PRG-RAM presence (unofficial, rarely used extension)
///
diff --git a/SabreTools.Serialization/Models/NES/Header.cs b/SabreTools.Serialization/Models/NES/Header.cs
index 41f7327c..36463fd5 100644
--- a/SabreTools.Serialization/Models/NES/Header.cs
+++ b/SabreTools.Serialization/Models/NES/Header.cs
@@ -23,45 +23,49 @@ namespace SabreTools.Data.Models.NES
/// Value 0 means the board uses CHR RAM
public byte CHRROMSize { get; set; }
- #region Flag 6
+ #region Byte 6
///
/// Nametable arrangement
///
- /// Flag 6, Bit 0
+ /// Byte 6, Bit 0
public NametableArrangement NametableArrangement { get; set; }
///
/// Cartridge contains battery-backed PRG RAM ($6000-7FFF)
/// or other persistent memory
///
- /// Flag 6, Bit 1
+ /// Byte 6, Bit 1
public bool BatteryBackedPRGRAM { get; set; }
///
/// 512-byte trainer at $7000-$71FF
///
- /// Flag 6, Bit 2
+ /// Byte 6, Bit 2
public bool TrainerPresent { get; set; }
///
/// Alternative nametable layout
///
- /// Flag 6, Bit 3
+ /// Byte 6, Bit 3
public bool AlternativeNametableLayout { get; set; }
///
/// Lower nibble of Mapper number
///
- /// Flag 6, Bits 4-7
+ /// Byte 6, Bits 4-7
public byte MapperLowerNibble { get; set; }
#endregion
+ #region Byte 7
+
///
- /// Mapper, VS/Playchoice, NES 2.0
+ /// Nametable arrangement
///
///
+ /// Byte 7, Bits 0-1
+ ///
/// The PlayChoice-10 bit is not part of the official specification,
/// and most emulators simply ignore the extra 8 KB of data. PlayChoice
/// games are designed to look good with the 2C03 RGB PPU, which handles
@@ -69,10 +73,26 @@ namespace SabreTools.Data.Models.NES
///
/// Vs. games have a coin slot and different palettes. The detection
/// of which palette a particular game uses is left unspecified.
+ ///
+ public ConsoleType ConsoleType { get; set; }
+
+ ///
+ /// Indicates NES 2.0 format
+ ///
+ ///
+ /// Byte 7, Bits 2-3 == 0x02
///
/// NES 2.0 is a more recent extension to the format that allows more
/// flexibility in ROM and RAM size, among other things.
///
- public Flag7 Flag7 { get; set; }
+ public bool NES20 { get; set; }
+
+ ///
+ /// Upper nibble of Mapper number
+ ///
+ /// Byte 7, Bits 4-7
+ public byte MapperUpperNibble { get; set; }
+
+ #endregion
}
}
diff --git a/SabreTools.Serialization/Readers/NESCart.cs b/SabreTools.Serialization/Readers/NESCart.cs
index 0edcf05e..4325857a 100644
--- a/SabreTools.Serialization/Readers/NESCart.cs
+++ b/SabreTools.Serialization/Readers/NESCart.cs
@@ -60,13 +60,7 @@ namespace SabreTools.Serialization.Readers
cart.CHRROMData = data.ReadBytes(chrRomSize);
// Read the PlayChoice INST-ROM and PROM data, if necessary
-#if NET20 || NET35
- if ((cart.Header.Flag7 & Flag7.PlayChoice10) != 0
- && (cart.Header.Flag7 & Flag7.VSUnisystem) == 0)
-#else
- if (cart.Header.Flag7.HasFlag(Flag7.PlayChoice10)
- && !cart.Header.Flag7.HasFlag(Flag7.VSUnisystem))
-#endif
+ if (cart.Header.ConsoleType == ConsoleType.PlayChoice10)
{
cart.PlayChoiceINSTROM = data.ReadBytes(8192);
cart.PlayChoicePROM = data.ReadBytes(32);
@@ -106,14 +100,13 @@ namespace SabreTools.Serialization.Readers
bool alternativeNametableLayout = ((flag6 >> 3) & 0x01) != 0;
byte mapperLowerNibble = (byte)(flag6 >> 4);
- Flag7 flag7 = (Flag7)data.ReadByteValue();
+ byte flag7 = data.ReadByteValue();
+ ConsoleType consoleType = (ConsoleType)(flag7 & 0x03);
+ bool nes20 = ((flag7 >> 2) & 0x02) == 0x02;
+ byte mapperUpperNibble = (byte)(flag7 >> 4);
// NES 2.0
-#if NET20 || NET35
- if ((flag7 & Flag7.NES20) != 0)
-#else
- if (flag7.HasFlag(Flag7.NES20))
-#endif
+ if (nes20)
{
var obj = new Header2();
@@ -128,7 +121,11 @@ namespace SabreTools.Serialization.Readers
obj.AlternativeNametableLayout = alternativeNametableLayout;
obj.MapperLowerNibble = mapperLowerNibble;
- obj.Flag7 = flag7;
+ // Flag 7
+ obj.ConsoleType = consoleType;
+ obj.NES20 = nes20;
+ obj.MapperUpperNibble = mapperUpperNibble;
+
obj.MapperMSBSubmapper = data.ReadByteValue();
obj.PRGCHRMSB = data.ReadByteValue();
obj.PRGRAMEEPROMSize = data.ReadByteValue();
@@ -157,7 +154,11 @@ namespace SabreTools.Serialization.Readers
obj.AlternativeNametableLayout = alternativeNametableLayout;
obj.MapperLowerNibble = mapperLowerNibble;
- obj.Flag7 = flag7;
+ // Flag 7
+ obj.ConsoleType = consoleType;
+ obj.NES20 = nes20;
+ obj.MapperUpperNibble = mapperUpperNibble;
+
obj.PRGRAMSize = data.ReadByteValue();
obj.TVSystem = (TVSystem)data.ReadByteValue();
obj.Flag10 = (Flag10)data.ReadByteValue();
diff --git a/SabreTools.Serialization/Wrappers/NESCart.Printing.cs b/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
index 9f428df7..d3418cc0 100644
--- a/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
+++ b/SabreTools.Serialization/Wrappers/NESCart.Printing.cs
@@ -74,40 +74,15 @@ namespace SabreTools.Serialization.Wrappers
builder.AppendLine(" Flag 7:");
// Bits 0-1
-#if NET20 || NET35
- if ((header.Flag7 & Flag7.ExtendedConsoleType) != 0)
-#else
- if (header.Flag7.HasFlag(Flag7.ExtendedConsoleType))
-#endif
- builder.AppendLine(" System Type: Extended Console Type");
-#if NET20 || NET35
- else if ((header.Flag7 & Flag7.PlayChoice10) != 0)
-#else
- else if (header.Flag7.HasFlag(Flag7.PlayChoice10))
-#endif
- builder.AppendLine(" System Type: PlayChoice-10");
-#if NET20 || NET35
- else if ((header.Flag7 & Flag7.VSUnisystem) != 0)
-#else
- else if (header.Flag7.HasFlag(Flag7.VSUnisystem))
-#endif
- builder.AppendLine(" System Type: Vs. Unisystem");
- else
- builder.AppendLine(" System Type: Nintendo Entertainment System/Family Computer");
+ string consoleType = header.ConsoleType.FromConsoleType();
+ builder.AppendLine(consoleType, " System Type");
// Bits 2-3
-#if NET20 || NET35
- if ((header.Flag7 & Flag7.NES20) != 0)
-#else
- if (header.Flag7.HasFlag(Flag7.NES20))
-#endif
- builder.AppendLine(" NES 2.0: True");
- else
- builder.AppendLine(" NES 2.0: False");
+ builder.AppendLine(header.NES20, " NES 2.0");
#endregion
- byte mapperNumber = (byte)((((byte)header.Flag7 >> 4) << 4) | header.MapperLowerNibble);
+ byte mapperNumber = (byte)((header.MapperUpperNibble << 4) | header.MapperLowerNibble);
builder.AppendLine(mapperNumber, " Mapper number");
if (header is Header1 header1)
@@ -175,7 +150,7 @@ namespace SabreTools.Serialization.Wrappers
// Byte 8
byte mapperMsb = (byte)(header2.MapperMSBSubmapper & 0x0F);
ushort extendedMapperNumber = (ushort)((mapperMsb << 8)
- | (byte)((((byte)header.Flag7 >> 4) << 4)
+ | (byte)((header.MapperUpperNibble << 4)
| header.MapperLowerNibble));
byte submapperNumber = (byte)(header2.MapperMSBSubmapper >> 4);
@@ -221,21 +196,13 @@ namespace SabreTools.Serialization.Wrappers
builder.AppendLine(cpuTiming, " CPU timing");
// Byte 13
-#if NET20 || NET35
- if ((header.Flag7 & Flag7.ExtendedConsoleType) != 0)
-#else
- if (header.Flag7.HasFlag(Flag7.ExtendedConsoleType))
-#endif
+ if (header.ConsoleType == ConsoleType.ExtendedConsoleType)
{
ExtendedConsoleType extendedConsoleType = (ExtendedConsoleType)(header2.ExtendedSystemType & 0x0F);
string extendedConsoleTypeString = extendedConsoleType.FromExtendedConsoleType();
builder.AppendLine(extendedConsoleTypeString, " Extended console type");
}
-#if NET20 || NET35
- else if ((header.Flag7 & Flag7.VSUnisystem) != 0)
-#else
- else if (header.Flag7.HasFlag(Flag7.VSUnisystem))
-#endif
+ else if (header.ConsoleType == ConsoleType.VSUnisystem)
{
VsSystemType vsSystemType = (VsSystemType)(header2.ExtendedSystemType & 0x0F);
string vsSystemTypeString = vsSystemType.FromVsSystemType();
diff --git a/SabreTools.Serialization/Wrappers/NESCart.cs b/SabreTools.Serialization/Wrappers/NESCart.cs
index d9660af2..f52e1164 100644
--- a/SabreTools.Serialization/Wrappers/NESCart.cs
+++ b/SabreTools.Serialization/Wrappers/NESCart.cs
@@ -48,107 +48,8 @@ namespace SabreTools.Serialization.Wrappers
}
}
- ///
- /// Indicates if the game is meant for an extended console type
- ///
- /// Possibly only valid for NES 2.0
- public bool IsExtendedConsole
- {
- get
- {
- // Missing header
- if (Header is null)
- return false;
-
-#if NET20 || NET35
- return (Header.Flag7 & Flag7.ExtendedConsoleType) != 0;
-#else
- return Header.Flag7.HasFlag(Flag7.ExtendedConsoleType);
-#endif
- }
- }
-
- ///
- /// Indicates if the cart is using an NES 2.0 header
- ///
- public bool IsNES20
- {
- get
- {
- // Missing header
- if (Header is null)
- return false;
-
-#if NET20 || NET35
- return (Header.Flag7 & Flag7.NES20) != 0;
-#else
- return Header.Flag7.HasFlag(Flag7.NES20);
-#endif
- }
- }
-
- ///
- /// Indicates if the game is meant for PlayChoice-10
- ///
- public bool IsPlayChoice10
- {
- get
- {
- // Missing header
- if (Header is null)
- return false;
-
-#if NET20 || NET35
- return (Header.Flag7 & Flag7.PlayChoice10) != 0
- && (Header.Flag7 & Flag7.VSUnisystem) == 0;
-#else
- return Header.Flag7.HasFlag(Flag7.PlayChoice10)
- && !Header.Flag7.HasFlag(Flag7.VSUnisystem);
-#endif
- }
- }
-
- ///
- /// Indicates if the game is meant for a standard console
- ///
- public bool IsStandardConsole
- {
- get
- {
- // Missing header
- if (Header is null)
- return false;
-
-#if NET20 || NET35
- return (Header.Flag7 & Flag7.PlayChoice10) == 0
- && (Header.Flag7 & Flag7.VSUnisystem) == 0;
-#else
- return !Header.Flag7.HasFlag(Flag7.PlayChoice10)
- && !Header.Flag7.HasFlag(Flag7.VSUnisystem);
-#endif
- }
- }
-
- ///
- /// Indicates if the game is meant for Vs. Unisystem
- ///
- public bool IsVsUnisystem
- {
- get
- {
- // Missing header
- if (Header is null)
- return false;
-
-#if NET20 || NET35
- return (Header.Flag7 & Flag7.PlayChoice10) == 0
- && (Header.Flag7 & Flag7.VSUnisystem) != 0;
-#else
- return !Header.Flag7.HasFlag(Flag7.PlayChoice10)
- && Header.Flag7.HasFlag(Flag7.VSUnisystem);
-#endif
- }
- }
+ ///
+ public ConsoleType ConsoleType => Header?.ConsoleType ?? ConsoleType.StandardSystem;
///
/// Mapper number
@@ -162,7 +63,7 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null)
return 0;
- int mapperNumber = (((byte)Header.Flag7 >> 4) << 4) | Header.MapperLowerNibble;
+ int mapperNumber = (Header.MapperUpperNibble << 4) | Header.MapperLowerNibble;
if (Header is Header2 header2)
mapperNumber = ((header2.MapperMSBSubmapper & 0x0F) << 8) | mapperNumber;
@@ -174,6 +75,9 @@ namespace SabreTools.Serialization.Wrappers
public NametableArrangement NametableArrangement
=> Header?.NametableArrangement ?? NametableArrangement.Vertical;
+ ///
+ public bool NES20 => Header?.NES20 ?? false;
+
///
/// PRG-RAM size in bytes
///
@@ -366,15 +270,11 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null || Header is not Header2 header2)
return ExtendedConsoleType.RegularSystem;
-#if NET20 || NET35
- if ((Header.Flag7 & Flag7.ExtendedConsoleType) != 0)
-#else
- if (Header.Flag7.HasFlag(Flag7.ExtendedConsoleType))
-#endif
- return (ExtendedConsoleType)(header2.ExtendedSystemType & 0x0F);
+ // Invalid console type
+ if (ConsoleType != ConsoleType.ExtendedConsoleType)
+ return ExtendedConsoleType.RegularSystem;
- // If flag is unset
- return ExtendedConsoleType.RegularSystem;
+ return (ExtendedConsoleType)(header2.ExtendedSystemType & 0x0F);
}
}
@@ -440,15 +340,11 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null || Header is not Header2 header2)
return VsHardwareType.VsUnisystem;
-#if NET20 || NET35
- else if ((Header.Flag7 & Flag7.VSUnisystem) != 0)
-#else
- else if (Header.Flag7.HasFlag(Flag7.VSUnisystem))
-#endif
- return (VsHardwareType)(header2.ExtendedSystemType >> 4);
+ // Invalid console type
+ if (ConsoleType != ConsoleType.VSUnisystem)
+ return VsHardwareType.VsUnisystem;
- // If flag is unset
- return VsHardwareType.VsUnisystem;
+ return (VsHardwareType)(header2.ExtendedSystemType >> 4);
}
}
@@ -465,15 +361,11 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null || Header is not Header2 header2)
return VsSystemType.AnyRP2C03RC2C03Variant;
-#if NET20 || NET35
- else if ((Header.Flag7 & Flag7.VSUnisystem) != 0)
-#else
- else if (Header.Flag7.HasFlag(Flag7.VSUnisystem))
-#endif
- return (VsSystemType)(header2.ExtendedSystemType & 0x0F);
+ // Invalid console type
+ if (ConsoleType != ConsoleType.VSUnisystem)
+ return VsSystemType.AnyRP2C03RC2C03Variant;
- // If flag is unset
- return VsSystemType.AnyRP2C03RC2C03Variant;
+ return (VsSystemType)(header2.ExtendedSystemType & 0x0F);
}
}