Split flag 10

This commit is contained in:
Matt Nadareski
2026-03-06 15:36:02 -05:00
parent 5e758d4b38
commit 93a6926b43
6 changed files with 160 additions and 115 deletions

View File

@@ -165,6 +165,34 @@ namespace SabreTools.Data.Extensions
};
}
/// <summary>
/// Convert a <see cref="TVSystem"/> value to string
/// </summary>
public static string FromTVSystem(this TVSystem system)
{
return system switch
{
TVSystem.NTSC => "NTSC",
TVSystem.PAL => "PAL",
_ => $"Unknown {(byte)system}",
};
}
/// <summary>
/// Convert a <see cref="TVSystemExtended"/> value to string
/// </summary>
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}",
};
}
/// <summary>
/// Convert a <see cref="VsHardwareType"/> value to string
/// </summary>

View File

@@ -1,51 +1,5 @@
using System;
namespace SabreTools.Data.Models.NES
{
/// <summary>
/// TV system, PRG-RAM presence (unofficial, rarely used extension)
/// </summary>
[Flags]
public enum Flag10 : byte
{
#region Bits 0-1
NTSC = 0b000000,
DualCompatible1 = 0b000001,
PAL = 0b000010,
DualCompatible2 = 0b000011,
#endregion
#region Bit 4
/// <summary>
/// PRG RAM ($6000-$7FFF) present
/// </summary>
PRGRAMPresent = 0b000000,
/// <summary>
/// PRG RAM ($6000-$7FFF) not present
/// </summary>
PRGRAMNotPresent = 0b010000,
#endregion
#region Bit 5
/// <summary>
/// Board has no bus conflicts
/// </summary>
BoardHasNoBusConflicts = 0b000000,
/// <summary>
/// Board has bus conflicts
/// </summary>
BoardHasBusConflicts = 0b100000,
#endregion
}
/// <summary>
/// Console Type
/// </summary>
@@ -625,12 +579,25 @@ namespace SabreTools.Data.Models.NES
/// <summary>
/// TV system (rarely used extension)
/// </summary>
/// <remarks>Byte 9</remarks>
public enum TVSystem : byte
{
NTSC = 0x00,
PAL = 0x01,
}
/// <summary>
/// TV system with extended values
/// </summary>
/// <remarks>Actually only 2 bits (bits 0-1 of flag 10)</remarks>
public enum TVSystemExtended : byte
{
NTSC = 0x00,
DualCompatible1 = 0x01,
PAL = 0x02,
DualCompatible3 = 0x03,
}
/// <summary>
/// Vs. Hardware Type
/// </summary>

View File

@@ -36,14 +36,64 @@ namespace SabreTools.Data.Models.NES
/// </remarks>
public TVSystem TVSystem { get; set; }
#region Byte 10
/// <summary>
/// TV system, PRG-RAM presence (unofficial, rarely used extension)
/// TV system with extended values
/// </summary>
/// <remarks>
/// Byte 10, Bits 0-1
///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
/// </remarks>
public Flag10 Flag10 { get; set; }
public TVSystemExtended TVSystemExtended { get; set; }
/// <summary>
/// Unknown reserved bits
/// </summary>
/// <remarks>
/// Byte 10, Bits 2-3
///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
/// </remarks>
public byte ReservedBits23 { get; set; }
/// <summary>
/// PRG RAM ($6000-$7FFF) present
/// </summary>
/// <remarks>
/// Byte 10, Bit 4
///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
/// </remarks>
public bool PRGRAMPresent { get; set; }
/// <summary>
/// Board has bus conflicts
/// </summary>
/// <remarks>
/// Byte 10, Bit 5
///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
/// </remarks>
public bool HasBusConflicts { get; set; }
/// <summary>
/// Unknown reserved bits
/// </summary>
/// <remarks>
/// Byte 10, Bits 6-7
///
/// This byte is not part of the official specification, and relatively
/// few emulators honor it.
/// </remarks>
public byte ReservedBits67 { get; set; }
#endregion
/// <summary>
/// Unused padding to align to 16 bytes

View File

@@ -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;

View File

@@ -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

View File

@@ -147,9 +147,7 @@ namespace SabreTools.Serialization.Wrappers
#region NES 1.0
/// <summary>
/// Indicates if the board has bus conflicts
/// </summary>
/// <inheritdoc cref="Header1.HasBusConflicts"/>
/// <remarks>Defined only for NES 1.0</remarks>
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;
}
}
/// <summary>
/// Indicates if PRG RAM at $6000-$7FFF is present
/// </summary>
/// <inheritdoc cref="Header1.PRGRAMPresent"/>
/// <remarks>Defined only for NES 1.0</remarks>
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;
}
}
/// <inheritdoc cref="Header1.TVSystem"/>
/// <remarks>Defined only for NES 1.0</remarks>
public TVSystem TVSystem
{
get
{
// Missing or invalid header
if (Header is null || Header is not Header1 header1)
return TVSystem.NTSC;
return header1.TVSystem;
}
}
/// <inheritdoc cref="Header1.TVSystemExtended"/>
/// <remarks>Defined only for NES 1.0</remarks>
public TVSystemExtended TVSystemExtended
{
get
{
// Missing or invalid header
if (Header is null || Header is not Header1 header1)
return TVSystemExtended.NTSC;
return header1.TVSystemExtended;
}
}