Split flag 6

This commit is contained in:
Matt Nadareski
2026-03-06 14:59:19 -05:00
parent ff67caee25
commit 756d5fe03c
6 changed files with 372 additions and 427 deletions

View File

@@ -137,6 +137,19 @@ namespace SabreTools.Data.Extensions
};
}
/// <summary>
/// Convert a <see cref="NametableArrangement"/> value to string
/// </summary>
public static string FromNametableArrangement(this NametableArrangement type)
{
return type switch
{
NametableArrangement.Vertical => "Vertical",
NametableArrangement.Horizontal => "Horizontal",
_ => $"Unknown {(byte)type}",
};
}
/// <summary>
/// Convert a <see cref="VsHardwareType"/> value to string
/// </summary>

View File

@@ -2,70 +2,6 @@ using System;
namespace SabreTools.Data.Models.NES
{
/// <summary>
/// Mapper, mirroring, battery, trainer
/// </summary>
/// <remarks>Bits 4-7 are the lower nybble of mapper number</remarks>
[Flags]
public enum Flag6 : byte
{
#region Bit 0
/// <summary>
/// Vertical arrangement ("horizontal mirrored") or mapper-controlled
/// </summary>
/// <remarks>CIRAM A10 = PPU A11</remarks>
NametableArrangementVertical = 0b0000,
/// <summary>
/// Horizontal arrangement ("vertically mirrored")
/// </summary>
/// <remarks>CIRAM A10 = PPU A10</remarks>
NametableArrangementHorizontal = 0b0001,
#endregion
#region Bit 1
/// <summary>
/// Cartridge contains battery-backed PRG RAM ($6000-7FFF)
/// or other persistent memory not present
/// </summary>
BatteryBackedPRGRAMNotPresent = 0b0000,
/// <summary>
/// Cartridge contains battery-backed PRG RAM ($6000-7FFF)
/// or other persistent memory present
/// </summary>
BatteryBackedPRGRAMPresent = 0b0010,
#endregion
#region Bit 2
/// <summary>
/// 512-byte trainer at $7000-$71FF
/// </summary>
TrainerNotPresent = 0b0000,
/// <summary>
/// 512-byte trainer at $7000-$71FF
/// </summary>
/// <remarks>Stored before PRG data</remarks>
TrainerPresent = 0b0100,
#endregion
#region Bit 3
/// <summary>
/// Alternative nametable layout
/// </summary>
AlternativeNametableLayout = 0b1000,
#endregion
}
/// <summary>
/// Mapper, VS/Playchoice, NES 2.0
/// </summary>
@@ -107,15 +43,6 @@ namespace SabreTools.Data.Models.NES
#endregion
}
/// <summary>
/// TV system (rarely used extension)
/// </summary>
public enum TVSystem : byte
{
NTSC = 0x00,
PAL = 0x01,
}
/// <summary>
/// TV system, PRG-RAM presence (unofficial, rarely used extension)
/// </summary>
@@ -160,6 +87,33 @@ namespace SabreTools.Data.Models.NES
#endregion
}
/// <summary>
/// Console Type
/// </summary>
/// <remarks>Actually only 2 bits (bits 0-1 of flag 7)</remarks>
public enum ConsoleType : byte
{
/// <summary>
/// Nintendo Entertainment System/Family Computer
/// </summary>
StandardSystem = 0x00,
/// <summary>
/// VS Unisystem
/// </summary>
VSUnisystem = 0x01,
/// <summary>
/// PlayChoice-10 (8 KB of Hint Screen data stored after CHR data)
/// </summary>
PlayChoice10 = 0x02,
/// <summary>
/// Extended Console Type
/// </summary>
ExtendedConsoleType = 0x03,
}
/// <summary>
/// CPU/PPU Timing
/// </summary>
@@ -186,221 +140,6 @@ namespace SabreTools.Data.Models.NES
UA6538 = 0x03,
}
/// <summary>
/// Vs. System Type
/// </summary>
/// <remarks>Actually only 4 bits</remarks>
public enum VsSystemType : byte
{
/// <summary>
/// Any RP2C03/RC2C03 variant
/// </summary>
AnyRP2C03RC2C03Variant = 0x00,
/// <summary>
/// Reserved
/// </summary>
Reserved1 = 0x01,
/// <summary>
/// RP2C04-0001
/// </summary>
RP2C040001 = 0x02,
/// <summary>
/// RP2C04-0002
/// </summary>
RP2C040002 = 0x03,
/// <summary>
/// RP2C04-0003
/// </summary>
RP2C040003 = 0x04,
/// <summary>
/// RP2C04-0004
/// </summary>
RP2C040004 = 0x05,
/// <summary>
/// Reserved
/// </summary>
Reserved6 = 0x06,
/// <summary>
/// Reserved
/// </summary>
Reserved7 = 0x07,
/// <summary>
/// RC2C05-01 (signature unknown)
/// </summary>
RC2C0501 = 0x08,
/// <summary>
/// RC2C05-02 ($2002 AND $3F =$3D)
/// </summary>
RC2C0502 = 0x09,
/// <summary>
/// RC2C05-03 ($2002 AND $1F =$1C)
/// </summary>
RC2C0503 = 0x0A,
/// <summary>
/// RC2C05-04 ($2002 AND $1F =$1B)
/// </summary>
RC2C0504 = 0x0B,
/// <summary>
/// Reserved
/// </summary>
ReservedC = 0x0C,
/// <summary>
/// Reserved
/// </summary>
ReservedD = 0x0D,
/// <summary>
/// Reserved
/// </summary>
ReservedE = 0x0E,
/// <summary>
/// Reserved
/// </summary>
ReservedF = 0x0F,
}
/// <summary>
/// Vs. Hardware Type
/// </summary>
/// <remarks>Actually only 4 bits</remarks>
public enum VsHardwareType : byte
{
/// <summary>
/// Vs. Unisystem (normal)
/// </summary>
VsUnisystem = 0x00,
/// <summary>
/// Vs. Unisystem (RBI Baseball protection)
/// </summary>
VsUnisystemRBIBaseballProtection = 0x01,
/// <summary>
/// Vs. Unisystem (TKO Boxing protection)
/// </summary>
VsUnisystemTKOBoxingProtection = 0x02,
/// <summary>
/// Vs. Unisystem (Super Xevious protection)
/// </summary>
VsUnisystemSuperXeviousProtection = 0x03,
/// <summary>
/// Vs. Unisystem (Vs. Ice Climber Japan protection)
/// </summary>
VsUnisystemVsIceClimberJapanProtection = 0x04,
/// <summary>
/// Vs. Dual System (normal)
/// </summary>
VsDualSystem = 0x05,
/// <summary>
/// Vs. Dual System (Raid on Bungeling Bay protection)
/// </summary>
VsDualSystemRaidOnBungelingBayProtection = 0x06,
}
/// <summary>
/// Extended Console Type
/// </summary>
public enum ExtendedConsoleType : byte
{
/// <summary>
/// Regular NES/Famicom/Dendy
/// </summary>
RegularSystem = 0x00,
/// <summary>
/// Nintendo Vs. System
/// </summary>
NintendoVsSystem = 0x01,
/// <summary>
/// Playchoice 10
/// </summary>
Playchoice10 = 0x02,
/// <summary>
/// Regular Famiclone, but with CPU that supports Decimal Mode
/// </summary>
RegularFamicloneDecimalMode = 0x03,
/// <summary>
/// Regular NES/Famicom with EPSM module or plug-through cartridge
/// </summary>
RegularNESWithEPSM = 0x04,
/// <summary>
/// V.R. Technology VT01 with red/cyan STN palette
/// </summary>
VRTechnologyVT01 = 0x05,
/// <summary>
/// V.R. Technology VT02
/// </summary>
VRTechnologyVT02 = 0x06,
/// <summary>
/// V.R. Technology VT03
/// </summary>
VRTechnologyVT03 = 0x07,
/// <summary>
/// V.R. Technology VT09
/// </summary>
VRTechnologyVT09 = 0x08,
/// <summary>
/// V.R. Technology VT32
/// </summary>
VRTechnologyVT32 = 0x09,
/// <summary>
/// V.R. Technology VT369
/// </summary>
VRTechnologyVT369 = 0x0A,
/// <summary>
/// UMC UM6578
/// </summary>
UMCUM6578 = 0x0B,
/// <summary>
/// Famicom Network System
/// </summary>
FamicomNetworkSystem = 0x0C,
/// <summary>
/// Reserved
/// </summary>
ReservedD = 0x0D,
/// <summary>
/// Reserved
/// </summary>
ReservedE = 0x0E,
/// <summary>
/// Reserved
/// </summary>
ReservedF = 0x0F,
}
/// <summary>
/// Default Expansion Device
/// </summary>
@@ -808,4 +547,257 @@ namespace SabreTools.Data.Models.NES
/// </summary>
SuborKeyboardPlusMegaBookMouse = 0x4F,
}
/// <summary>
/// Extended Console Type
/// </summary>
public enum ExtendedConsoleType : byte
{
/// <summary>
/// Regular NES/Famicom/Dendy
/// </summary>
RegularSystem = 0x00,
/// <summary>
/// Nintendo Vs. System
/// </summary>
NintendoVsSystem = 0x01,
/// <summary>
/// Playchoice 10
/// </summary>
Playchoice10 = 0x02,
/// <summary>
/// Regular Famiclone, but with CPU that supports Decimal Mode
/// </summary>
RegularFamicloneDecimalMode = 0x03,
/// <summary>
/// Regular NES/Famicom with EPSM module or plug-through cartridge
/// </summary>
RegularNESWithEPSM = 0x04,
/// <summary>
/// V.R. Technology VT01 with red/cyan STN palette
/// </summary>
VRTechnologyVT01 = 0x05,
/// <summary>
/// V.R. Technology VT02
/// </summary>
VRTechnologyVT02 = 0x06,
/// <summary>
/// V.R. Technology VT03
/// </summary>
VRTechnologyVT03 = 0x07,
/// <summary>
/// V.R. Technology VT09
/// </summary>
VRTechnologyVT09 = 0x08,
/// <summary>
/// V.R. Technology VT32
/// </summary>
VRTechnologyVT32 = 0x09,
/// <summary>
/// V.R. Technology VT369
/// </summary>
VRTechnologyVT369 = 0x0A,
/// <summary>
/// UMC UM6578
/// </summary>
UMCUM6578 = 0x0B,
/// <summary>
/// Famicom Network System
/// </summary>
FamicomNetworkSystem = 0x0C,
/// <summary>
/// Reserved
/// </summary>
ReservedD = 0x0D,
/// <summary>
/// Reserved
/// </summary>
ReservedE = 0x0E,
/// <summary>
/// Reserved
/// </summary>
ReservedF = 0x0F,
}
/// <summary>
/// Nametable arrangement
/// </summary>
/// <remarks>Actually only 1 bit (bit 0 of flag 6)</remarks>
public enum NametableArrangement : byte
{
/// <summary>
/// Vertical arrangement ("horizontal mirrored") or mapper-controlled
/// </summary>
/// <remarks>CIRAM A10 = PPU A11</remarks>
Vertical = 0x00,
/// <summary>
/// Horizontal arrangement ("vertically mirrored")
/// </summary>
/// <remarks>CIRAM A10 = PPU A10</remarks>
Horizontal = 0x01,
}
/// <summary>
/// PRG RAM ($6000-$7FFF)
/// </summary>
/// <remarks>Actually only 1 bit (bit 4 of flag 10)</remarks>
public enum PRGRAMPresent : byte
{
Present = 0x00,
NotPresent = 0x01,
}
/// <summary>
/// TV system (rarely used extension)
/// </summary>
public enum TVSystem : byte
{
NTSC = 0x00,
PAL = 0x01,
}
/// <summary>
/// Vs. Hardware Type
/// </summary>
/// <remarks>Actually only 4 bits</remarks>
public enum VsHardwareType : byte
{
/// <summary>
/// Vs. Unisystem (normal)
/// </summary>
VsUnisystem = 0x00,
/// <summary>
/// Vs. Unisystem (RBI Baseball protection)
/// </summary>
VsUnisystemRBIBaseballProtection = 0x01,
/// <summary>
/// Vs. Unisystem (TKO Boxing protection)
/// </summary>
VsUnisystemTKOBoxingProtection = 0x02,
/// <summary>
/// Vs. Unisystem (Super Xevious protection)
/// </summary>
VsUnisystemSuperXeviousProtection = 0x03,
/// <summary>
/// Vs. Unisystem (Vs. Ice Climber Japan protection)
/// </summary>
VsUnisystemVsIceClimberJapanProtection = 0x04,
/// <summary>
/// Vs. Dual System (normal)
/// </summary>
VsDualSystem = 0x05,
/// <summary>
/// Vs. Dual System (Raid on Bungeling Bay protection)
/// </summary>
VsDualSystemRaidOnBungelingBayProtection = 0x06,
}
/// <summary>
/// Vs. System Type
/// </summary>
/// <remarks>Actually only 4 bits</remarks>
public enum VsSystemType : byte
{
/// <summary>
/// Any RP2C03/RC2C03 variant
/// </summary>
AnyRP2C03RC2C03Variant = 0x00,
/// <summary>
/// Reserved
/// </summary>
Reserved1 = 0x01,
/// <summary>
/// RP2C04-0001
/// </summary>
RP2C040001 = 0x02,
/// <summary>
/// RP2C04-0002
/// </summary>
RP2C040002 = 0x03,
/// <summary>
/// RP2C04-0003
/// </summary>
RP2C040003 = 0x04,
/// <summary>
/// RP2C04-0004
/// </summary>
RP2C040004 = 0x05,
/// <summary>
/// Reserved
/// </summary>
Reserved6 = 0x06,
/// <summary>
/// Reserved
/// </summary>
Reserved7 = 0x07,
/// <summary>
/// RC2C05-01 (signature unknown)
/// </summary>
RC2C0501 = 0x08,
/// <summary>
/// RC2C05-02 ($2002 AND $3F =$3D)
/// </summary>
RC2C0502 = 0x09,
/// <summary>
/// RC2C05-03 ($2002 AND $1F =$1C)
/// </summary>
RC2C0503 = 0x0A,
/// <summary>
/// RC2C05-04 ($2002 AND $1F =$1B)
/// </summary>
RC2C0504 = 0x0B,
/// <summary>
/// Reserved
/// </summary>
ReservedC = 0x0C,
/// <summary>
/// Reserved
/// </summary>
ReservedD = 0x0D,
/// <summary>
/// Reserved
/// </summary>
ReservedE = 0x0E,
/// <summary>
/// Reserved
/// </summary>
ReservedF = 0x0F,
}
}

View File

@@ -23,10 +23,40 @@ namespace SabreTools.Data.Models.NES
/// <remarks>Value 0 means the board uses CHR RAM</remarks>
public byte CHRROMSize { get; set; }
#region Flag 6
/// <summary>
/// Mapper, mirroring, battery, trainer
/// Nametable arrangement
/// </summary>
public Flag6 Flag6 { get; set; }
/// <remarks>Flag 6, Bit 0</remarks>
public NametableArrangement NametableArrangement { get; set; }
/// <summary>
/// Cartridge contains battery-backed PRG RAM ($6000-7FFF)
/// or other persistent memory
/// </summary>
/// <remarks>Flag 6, Bit 1</remarks>
public bool BatteryBackedPRGRAM { get; set; }
/// <summary>
/// 512-byte trainer at $7000-$71FF
/// </summary>
/// <remarks>Flag 6, Bit 2</remarks>
public bool TrainerPresent { get; set; }
/// <summary>
/// Alternative nametable layout
/// </summary>
/// <remarks>Flag 6, Bit 3</remarks>
public bool AlternativeNametableLayout { get; set; }
/// <summary>
/// Lower nibble of Mapper number
/// </summary>
/// <remarks>Flag 6, Bits 4-7</remarks>
public byte MapperLowerNibble { get; set; }
#endregion
/// <summary>
/// Mapper, VS/Playchoice, NES 2.0

View File

@@ -35,11 +35,7 @@ namespace SabreTools.Serialization.Readers
#endregion
// Read the trainer data, if necessary
#if NET20 || NET35
if ((cart.Header.Flag6 & Flag6.TrainerPresent) != 0)
#else
if (cart.Header.Flag6.HasFlag(Flag6.TrainerPresent))
#endif
if (cart.Header.TrainerPresent)
cart.Trainer = data.ReadBytes(512);
// Derive the PRG-ROM and CHR-ROM data sizes
@@ -102,7 +98,14 @@ namespace SabreTools.Serialization.Readers
byte prgRomSize = data.ReadByteValue();
byte chrRomSize = data.ReadByteValue();
Flag6 flag6 = (Flag6)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);
Flag7 flag7 = (Flag7)data.ReadByteValue();
// NES 2.0
@@ -117,7 +120,14 @@ namespace SabreTools.Serialization.Readers
obj.IdentificationString = identificationString;
obj.PRGROMSize = prgRomSize;
obj.CHRROMSize = chrRomSize;
obj.Flag6 = flag6;
// Flag 6
obj.NametableArrangement = nametableArrangement;
obj.BatteryBackedPRGRAM = batteryBackedPrgRam;
obj.TrainerPresent = trainerPresent;
obj.AlternativeNametableLayout = alternativeNametableLayout;
obj.MapperLowerNibble = mapperLowerNibble;
obj.Flag7 = flag7;
obj.MapperMSBSubmapper = data.ReadByteValue();
obj.PRGCHRMSB = data.ReadByteValue();
@@ -139,7 +149,14 @@ namespace SabreTools.Serialization.Readers
obj.IdentificationString = identificationString;
obj.PRGROMSize = prgRomSize;
obj.CHRROMSize = chrRomSize;
obj.Flag6 = flag6;
// Flag 6
obj.NametableArrangement = nametableArrangement;
obj.BatteryBackedPRGRAM = batteryBackedPrgRam;
obj.TrainerPresent = trainerPresent;
obj.AlternativeNametableLayout = alternativeNametableLayout;
obj.MapperLowerNibble = mapperLowerNibble;
obj.Flag7 = flag7;
obj.PRGRAMSize = data.ReadByteValue();
obj.TVSystem = (TVSystem)data.ReadByteValue();

View File

@@ -53,44 +53,19 @@ namespace SabreTools.Serialization.Wrappers
builder.AppendLine(" Flag 6:");
// Bit 0
#if NET20 || NET35
if ((header.Flag6 & Flag6.NametableArrangementHorizontal) != 0)
#else
if (header.Flag6.HasFlag(Flag6.NametableArrangementHorizontal))
#endif
builder.AppendLine(" Nametable Arrangement: Horizontal");
else
builder.AppendLine(" Nametable Arrangement: Vertical");
string nametableArrangement = header.NametableArrangement.FromNametableArrangement();
builder.AppendLine(nametableArrangement, " Nametable Arrangement");
// Bit 1
#if NET20 || NET35
if ((header.Flag6 & Flag6.BatteryBackedPRGRAMPresent) != 0)
#else
if (header.Flag6.HasFlag(Flag6.BatteryBackedPRGRAMPresent))
#endif
builder.AppendLine(" Battery-Backed PRG RAM: Present");
else
builder.AppendLine(" Battery-Backed PRG RAM: Not present");
string batteryBackedPrgRam = header.BatteryBackedPRGRAM ? "Present" : "Not present";
builder.AppendLine(batteryBackedPrgRam, " Battery-Backed PRG RAM");
// Bit 2
#if NET20 || NET35
if ((header.Flag6 & Flag6.TrainerPresent) != 0)
#else
if (header.Flag6.HasFlag(Flag6.TrainerPresent))
#endif
builder.AppendLine(" Trainer: Present");
else
builder.AppendLine(" Trainer: Not present");
string trainerPresent = header.TrainerPresent ? "Present" : "Not present";
builder.AppendLine(trainerPresent, " Trainer");
// Bit 3
#if NET20 || NET35
if ((header.Flag6 & Flag6.AlternativeNametableLayout) != 0)
#else
if (header.Flag6.HasFlag(Flag6.AlternativeNametableLayout))
#endif
builder.AppendLine(" Alternative Nametable Layout: True");
else
builder.AppendLine(" Alternative Nametable Layout: False");
builder.AppendLine(header.AlternativeNametableLayout, " Alternative Nametable Layout");
#endregion
@@ -132,7 +107,7 @@ namespace SabreTools.Serialization.Wrappers
#endregion
byte mapperNumber = (byte)((((byte)header.Flag7 >> 4) << 4) | (byte)((byte)header.Flag6 >> 4));
byte mapperNumber = (byte)((((byte)header.Flag7 >> 4) << 4) | header.MapperLowerNibble);
builder.AppendLine(mapperNumber, " Mapper number");
if (header is Header1 header1)
@@ -201,7 +176,7 @@ namespace SabreTools.Serialization.Wrappers
byte mapperMsb = (byte)(header2.MapperMSBSubmapper & 0x0F);
ushort extendedMapperNumber = (ushort)((mapperMsb << 8)
| (byte)((((byte)header.Flag7 >> 4) << 4)
| (byte)((byte)header.Flag6 >> 4)));
| header.MapperLowerNibble));
byte submapperNumber = (byte)(header2.MapperMSBSubmapper >> 4);
builder.AppendLine(mapperMsb, " Mapper MSB");

View File

@@ -19,6 +19,12 @@ namespace SabreTools.Serialization.Wrappers
/// <inheritdoc cref="Cart.Header"/>
public Header? Header => Model.Header;
/// <inheritdoc cref="Header.AlternativeNametableLayout"/>
public bool AlternativeNametableLayout => Header?.AlternativeNametableLayout ?? false;
/// <inheritdoc cref="Header.BatteryBackedPRGRAM"/>
public bool BatteryBackedPRGRAM => Header?.BatteryBackedPRGRAM ?? false;
/// <inheritdoc cref="Cart.CHRROMData"/>
public byte[] CHRROMData => Model.CHRROMData;
@@ -42,63 +48,6 @@ namespace SabreTools.Serialization.Wrappers
}
}
/// <summary>
/// Indicates if an alternative nametable layout is in use
/// </summary>
public bool HasAlternativeNametableLayout
{
get
{
// Missing header
if (Header is null)
return false;
#if NET20 || NET35
return (Header.Flag6 & Flag6.AlternativeNametableLayout) != 0;
#else
return Header.Flag6.HasFlag(Flag6.AlternativeNametableLayout);
#endif
}
}
/// <summary>
/// Indicates if battery-backed PRG RAM is present
/// </summary>
public bool HasBatteryBackedPRGRAM
{
get
{
// Missing header
if (Header is null)
return false;
#if NET20 || NET35
return (Header.Flag6 & Flag6.BatteryBackedPRGRAMPresent) != 0;
#else
return Header.Flag6.HasFlag(Flag6.BatteryBackedPRGRAMPresent);
#endif
}
}
/// <summary>
/// Indicates if trainer data is present
/// </summary>
public bool HasTrainer
{
get
{
// Missing header
if (Header is null)
return false;
#if NET20 || NET35
return (Header.Flag6 & Flag6.TrainerPresent) != 0;
#else
return Header.Flag6.HasFlag(Flag6.TrainerPresent);
#endif
}
}
/// <summary>
/// Indicates if the game is meant for an extended console type
/// </summary>
@@ -213,7 +162,7 @@ namespace SabreTools.Serialization.Wrappers
if (Header is null)
return 0;
int mapperNumber = (((byte)Header.Flag7 >> 4) << 4) | ((byte)Header.Flag6 >> 4);
int mapperNumber = (((byte)Header.Flag7 >> 4) << 4) | Header.MapperLowerNibble;
if (Header is Header2 header2)
mapperNumber = ((header2.MapperMSBSubmapper & 0x0F) << 8) | mapperNumber;
@@ -221,6 +170,10 @@ namespace SabreTools.Serialization.Wrappers
}
}
/// <inheritdoc cref="Header.NametableArrangement"/>
public NametableArrangement NametableArrangement
=> Header?.NametableArrangement ?? NametableArrangement.Vertical;
/// <summary>
/// PRG-RAM size in bytes
/// </summary>
@@ -283,43 +236,8 @@ namespace SabreTools.Serialization.Wrappers
/// <inheritdoc cref="Cart.Trainer"/>
public byte[] Trainer => Model.Trainer;
/// <summary>
/// Indicates if horizontal nametable arrangement is in use
/// </summary>
public bool UsesHorizontalNametableArrangement
{
get
{
// Missing header
if (Header is null)
return false;
#if NET20 || NET35
return (Header.Flag6 & Flag6.NametableArrangementHorizontal) != 0;
#else
return Header.Flag6.HasFlag(Flag6.NametableArrangementHorizontal);
#endif
}
}
/// <summary>
/// Indicates if vertical nametable arrangement is in use
/// </summary>
public bool UsesVerticalNametableArrangement
{
get
{
// Missing header
if (Header is null)
return false;
#if NET20 || NET35
return (Header.Flag6 & Flag6.NametableArrangementHorizontal) == 0;
#else
return !Header.Flag6.HasFlag(Flag6.NametableArrangementHorizontal);
#endif
}
}
/// <inheritdoc cref="Header.TrainerPresent"/>
public bool TrainerPresent => Header?.TrainerPresent ?? false;
#endregion