From d108a815d71c17ec5bac6e646f54225dd47eec61 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 6 Mar 2026 13:39:47 -0500 Subject: [PATCH] Finish NES cart extension properties --- SabreTools.Serialization/Wrappers/NESCart.cs | 305 +++++++++++++------ 1 file changed, 213 insertions(+), 92 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/NESCart.cs b/SabreTools.Serialization/Wrappers/NESCart.cs index b7286cec..47ef4d2b 100644 --- a/SabreTools.Serialization/Wrappers/NESCart.cs +++ b/SabreTools.Serialization/Wrappers/NESCart.cs @@ -3,7 +3,6 @@ using SabreTools.Data.Models.NES; namespace SabreTools.Serialization.Wrappers { - // TODO: Add extension properties for more 1.0 and 2.0 header pieces public partial class NESCart : WrapperBase { #region Descriptive Properties @@ -15,47 +14,18 @@ namespace SabreTools.Serialization.Wrappers #region Extension Properties + #region Common + /// public Header? Header => Model.Header; /// public byte[] CHRROMData => Model.CHRROMData; - /// - /// CHR-NVRAM size in bytes - /// - public int CHRNVRAMSize - { - get - { - // Missing or invalid header - if (Header is null || Header is not Header2 header2) - return 0; - - byte shift = (byte)(header2.CHRRAMSize >> 4); - return shift > 0 ? 64 << shift : 0; - } - } - - /// - /// CHR-RAM size in bytes - /// - public int CHRRAMSize - { - get - { - // Missing or invalid header - if (Header is null || Header is not Header2 header2) - return 0; - - byte shift = (byte)(header2.CHRRAMSize & 0x0F); - return shift > 0 ? 64 << shift : 0; - } - } - /// /// CHR-ROM size in bytes /// + /// Extended by NES 2.0 public int CHRROMSize { get @@ -72,30 +42,6 @@ namespace SabreTools.Serialization.Wrappers } } - /// - /// Extended console type - /// - /// Only valid if is set - public ExtendedConsoleType ExtendedConsoleType - { - get - { - // Missing or invalid header - 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); - - // If flag is unset - return ExtendedConsoleType.RegularSystem; - } - } - /// /// Indicates if an alternative nametable layout is in use /// @@ -156,6 +102,7 @@ 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 @@ -257,6 +204,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Mapper number /// + /// Extended by NES 2.0 public int MapperNumber { get @@ -273,22 +221,6 @@ namespace SabreTools.Serialization.Wrappers } } - /// - /// PRG-NVRAM/EEPROM size in bytes - /// - public int PRGRAMEEPROMSize - { - get - { - // Missing or invalid header - if (Header is null || Header is not Header2 header2) - return 0; - - byte shift = (byte)(header2.PRGRAMEEPROMSize >> 4); - return shift > 0 ? 64 << shift : 0; - } - } - /// /// PRG-RAM size in bytes /// @@ -296,18 +228,30 @@ namespace SabreTools.Serialization.Wrappers { get { - // Missing or invalid header - if (Header is null || Header is not Header2 header2) + // Missing header + if (Header is null) return 0; - byte shift = (byte)(header2.PRGRAMEEPROMSize & 0x0F); - return shift > 0 ? 64 << shift : 0; + if (Header is Header1 header1) + { + return header1.PRGRAMSize > 0 ? header1.PRGRAMSize * 8192 : 8192; + } + else if (Header is Header2 header2) + { + byte shift = (byte)(header2.PRGRAMEEPROMSize & 0x0F); + return shift > 0 ? 64 << shift : 0; + } + else + { + return 0; + } } } /// /// PRG-ROM size in bytes /// + /// Extended by NES 2.0 public int PRGROMSize { get @@ -333,21 +277,6 @@ namespace SabreTools.Serialization.Wrappers /// public byte[] PlayChoicePROM => Model.PlayChoicePROM; - /// - /// Submapper number - /// - public int SubmapperNumber - { - get - { - // Missing or invalid header - if (Header is null || Header is not Header2 header2) - return 0; - - return header2.MapperMSBSubmapper >> 4; - } - } - /// public byte[] Title => Model.Title; @@ -392,9 +321,198 @@ namespace SabreTools.Serialization.Wrappers } } + #endregion + + #region NES 1.0 + + /// + /// Indicates if the board has bus conflicts + /// + /// Defined only for NES 1.0 + public bool HasBusConflicts + { + get + { + // Missing or invalid header + 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 + } + } + + /// + /// Indicates if PRG RAM at $6000-$7FFF is present + /// + /// Defined only for NES 1.0 + public bool HasPRGRAM + { + get + { + // Missing or invalid header + 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 + } + } + + #endregion + + #region NES 2.0 + + /// + /// CHR-NVRAM size in bytes + /// + /// Defined only for NES 2.0 + public int CHRNVRAMSize + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return 0; + + byte shift = (byte)(header2.CHRRAMSize >> 4); + return shift > 0 ? 64 << shift : 0; + } + } + + /// + /// CHR-RAM size in bytes + /// + /// Defined only for NES 2.0 + public int CHRRAMSize + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return 0; + + byte shift = (byte)(header2.CHRRAMSize & 0x0F); + return shift > 0 ? 64 << shift : 0; + } + } + + /// + /// CPU/PPU Timing + /// + /// Defined only for NES 2.0 + public CPUPPUTiming CPUPPUTiming + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return CPUPPUTiming.RP2C02; + + return header2.CPUPPUTiming; + } + } + + /// + /// Default expansion device + /// + /// Defined only for NES 2.0 + public DefaultExpansionDevice DefaultExpansionDevice + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return DefaultExpansionDevice.Unspecified; + + return header2.DefaultExpansionDevice; + } + } + + /// + /// Extended console type + /// + /// Defined only for NES 2.0 + /// Only valid if is set + public ExtendedConsoleType ExtendedConsoleType + { + get + { + // Missing or invalid header + 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); + + // If flag is unset + return ExtendedConsoleType.RegularSystem; + } + } + + /// + /// Number of miscellaneous ROMs present + /// + /// Defined only for NES 2.0 + public int MiscellaneousROMs + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return 0; + + return header2.MiscellaneousROMs; + } + } + + /// + /// PRG-NVRAM/EEPROM size in bytes + /// + /// Defined only for NES 2.0 + public int PRGRAMEEPROMSize + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return 0; + + byte shift = (byte)(header2.PRGRAMEEPROMSize >> 4); + return shift > 0 ? 64 << shift : 0; + } + } + + /// + /// Submapper number + /// + /// Defined only for NES 2.0 + public int SubmapperNumber + { + get + { + // Missing or invalid header + if (Header is null || Header is not Header2 header2) + return 0; + + return header2.MapperMSBSubmapper >> 4; + } + } + /// /// Vs. Hardware Type /// + /// Defined only for NES 2.0 /// Only valid if is set public VsHardwareType VsHardwareType { @@ -419,6 +537,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Vs. System Type /// + /// Defined only for NES 2.0 /// Only valid if is set public VsSystemType VsSystemType { @@ -442,6 +561,8 @@ namespace SabreTools.Serialization.Wrappers #endregion + #endregion + #region Constructors ///