diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCCartridgeType.cs b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCCartridgeType.cs
new file mode 100644
index 00000000..48998f9b
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCCartridgeType.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
+{
+ ///
+ /// Indicates the hardware in the cartridge. Emulators use this byte to decide which hardware to emulate. A real SNES ignores this byte and uses the real hardware in the real cartridge.
+ ///
+ ///
+ public class SMCCartridgeType
+ {
+ private string mvarTitle = String.Empty;
+ ///
+ /// The title of the cartridge type.
+ ///
+ public string Title { get { return mvarTitle; } set { mvarTitle = value; } }
+
+ private byte mvarValue = 0;
+ ///
+ /// The single-byte code that represents this cartridge type in the Nintendo SNES game console.
+ ///
+ public byte Value { get { return mvarValue; } set { mvarValue = value; } }
+
+
+ ///
+ /// Gets the with the given licensee code if valid.
+ ///
+ /// The licensee code to search on.
+ /// If the licensee code is known, returns an instance of the associated . Otherwise, returns null.
+ public static SMCCartridgeType FromCode(byte value)
+ {
+ Type t = typeof(SMCCartridgeTypes);
+
+ MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.Static;
+ PropertyInfo[] properties = t.GetProperties();
+ for (int i = 0; i < properties.Length; i++)
+ {
+ PropertyInfo propertyInfo = properties[i];
+ if (propertyInfo.PropertyType == typeof(SMCCartridgeType))
+ {
+ MethodInfo getMethod = propertyInfo.GetGetMethod();
+ if (getMethod != null && (getMethod.Attributes & methodAttributes) == methodAttributes)
+ {
+ object[] index = null;
+ SMCCartridgeType val = (SMCCartridgeType)propertyInfo.GetValue(null, index);
+
+ if (val.Value == value) return val;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Creates a new instance of with the given title and value.
+ ///
+ ///
+ ///
+ public SMCCartridgeType(string title, byte value)
+ {
+ mvarTitle = title;
+ mvarValue = value;
+ }
+
+ ///
+ /// Translates this into a human-readable string, including the
+ /// title of the cartridge type and the internal identifier.
+ ///
+ /// A human-readable string representing this .
+ public override string ToString()
+ {
+ return mvarTitle + " (0x" + mvarValue.ToString("X").PadLeft(2, '0') + ")";
+ }
+ }
+ public sealed class SMCCartridgeTypes
+ {
+ private static SMCCartridgeType mvarROMOnly = new SMCCartridgeType("ROM-only", 0x00);
+ ///
+ /// The cartridge contains only ROM.
+ ///
+ public static SMCCartridgeType ROMOnly { get { return mvarROMOnly; } }
+
+ private static SMCCartridgeType mvarROMAndRAM = new SMCCartridgeType("ROM and RAM, no battery", 0x01);
+ ///
+ /// The cartridge contains ROM and RAM but no battery.
+ ///
+ public static SMCCartridgeType ROMAndRAM { get { return mvarROMAndRAM; } }
+
+ private static SMCCartridgeType mvarROMAndRAMWithBattery = new SMCCartridgeType("ROM and save-RAM, with battery", 0x02);
+ ///
+ /// The cartridge contains ROM and save-RAM (with a battery).
+ ///
+ public static SMCCartridgeType ROMAndRAMWithBattery { get { return mvarROMAndRAMWithBattery; } }
+
+ private static SMCCartridgeType mvarSuperFXNoBattery0x13 = new SMCCartridgeType("SuperFX, no battery", 0x13);
+ ///
+ /// SuperFX, no battery (0x13)
+ ///
+ public static SMCCartridgeType SuperFXNoBattery0x13 { get { return mvarSuperFXNoBattery0x13; } }
+
+ private static SMCCartridgeType mvarSuperFXNoBattery0x14 = new SMCCartridgeType("SuperFX, no battery", 0x14);
+ ///
+ /// SuperFX, no battery (0x14)
+ ///
+ public static SMCCartridgeType SuperFXNoBattery0x14 { get { return mvarSuperFXNoBattery0x14; } }
+
+ private static SMCCartridgeType mvarSuperFXWithBattery0x15 = new SMCCartridgeType("SuperFX, with battery", 0x15);
+ ///
+ /// SuperFX, with battery (0x15)
+ ///
+ public static SMCCartridgeType SuperFXWithBattery0x15 { get { return mvarSuperFXWithBattery0x15; } }
+
+ private static SMCCartridgeType mvarSuperFXWithBattery0x1A = new SMCCartridgeType("SuperFX, with battery", 0x1A);
+ ///
+ /// SuperFX, with battery (0x1A)
+ ///
+ public static SMCCartridgeType SuperFXWithBattery0x1A { get { return mvarSuperFXWithBattery0x1A; } }
+
+ private static SMCCartridgeType mvarSA10x34 = new SMCCartridgeType("SA-1", 0x34);
+ ///
+ /// SuperFX, with battery (0x15)
+ ///
+ public static SMCCartridgeType SA10x34 { get { return mvarSA10x34; } }
+
+ private static SMCCartridgeType mvarSA10x35 = new SMCCartridgeType("SA-1", 0x35);
+ ///
+ /// SuperFX, with battery (0x1A)
+ ///
+ public static SMCCartridgeType SA10x35 { get { return mvarSA10x35; } }
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCDataFormat.cs
index e2727b76..7556a898 100644
--- a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCDataFormat.cs
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCDataFormat.cs
@@ -21,6 +21,42 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
_dfr = base.MakeReferenceInternal();
_dfr.Capabilities.Add(typeof(ExecutableObjectModel), DataFormatCapabilities.All);
+ _dfr.ExportOptions.Add(new CustomOptionText("GameName", "Game &name:", String.Empty, 21));
+ _dfr.ExportOptions.Add(new CustomOptionChoice("CartridgeType", "Cartridge &type:", true, new CustomOptionFieldChoice[]
+ {
+ new CustomOptionFieldChoice(SMCCartridgeTypes.ROMOnly, true),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.ROMAndRAM),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.ROMAndRAMWithBattery),
+
+ // Values greater than $02 indicate special add-on hardware in the cartridge. The caveat is that emulators like
+ // Snes9x may ignore these values unless the add-on (at $ffd6) is compatible with the ROM layout (at $ffd5).
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SuperFXNoBattery0x13, true),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SuperFXNoBattery0x14),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SuperFXWithBattery0x15),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SuperFXWithBattery0x1A),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SA10x34),
+ new CustomOptionFieldChoice(SMCCartridgeTypes.SA10x35)
+ }));
+
+ CustomOptionFieldChoice[] _smcMemorySizes = new CustomOptionFieldChoice[]
+ {
+ new CustomOptionFieldChoice(SMCMemorySizes.K2),
+ new CustomOptionFieldChoice(SMCMemorySizes.K4),
+ new CustomOptionFieldChoice(SMCMemorySizes.K8),
+ new CustomOptionFieldChoice(SMCMemorySizes.K16),
+ new CustomOptionFieldChoice(SMCMemorySizes.K32),
+ new CustomOptionFieldChoice(SMCMemorySizes.K64),
+ new CustomOptionFieldChoice(SMCMemorySizes.K128),
+ new CustomOptionFieldChoice(SMCMemorySizes.K256, true),
+ new CustomOptionFieldChoice(SMCMemorySizes.K512),
+ new CustomOptionFieldChoice(SMCMemorySizes.M1),
+ new CustomOptionFieldChoice(SMCMemorySizes.M2),
+ new CustomOptionFieldChoice(SMCMemorySizes.M4),
+ };
+
+ _dfr.ExportOptions.Add(new CustomOptionChoice("ROMSize", "RO&M size:", true, _smcMemorySizes));
+ _dfr.ExportOptions.Add(new CustomOptionChoice("RAMSize", "R&AM size:", true, _smcMemorySizes));
+
_dfr.ExportOptions.Add(new CustomOptionChoice("Region", "&Region:", false, new CustomOptionFieldChoice[]
{
new CustomOptionFieldChoice(SMCRegions.Japan),
@@ -224,6 +260,7 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
new CustomOptionFieldChoice(SMCLicensees.Psygnosis),
new CustomOptionFieldChoice(SMCLicensees.Davidson),
}));
+ _dfr.ExportOptions.Add(new CustomOptionNumber("VersionNumber", "&Version number:", 0, Byte.MinValue, Byte.MaxValue));
_dfr.Sources.Add("http://romhack.wikia.com/wiki/SNES_ROM_layout");
_dfr.Sources.Add("http://romhack.wikia.com/wiki/SNES_header");
@@ -235,6 +272,33 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
private SMCExtendedHeader mvarExtendedHeader = new SMCExtendedHeader();
public SMCExtendedHeader ExtendedHeader { get { return mvarExtendedHeader; } }
+ private string mvarGameName = String.Empty;
+ ///
+ /// Name of the ROM, typically in ASCII, using spaces to pad the name to 21 bytes.
+ ///
+ public string GameName { get { return mvarGameName; } set { mvarGameName = value; } }
+
+ private SMCLayout mvarROMLayout = SMCLayout.LoROM;
+ public SMCLayout ROMLayout { get { return mvarROMLayout; } set { mvarROMLayout = value; } }
+
+ private SMCCartridgeType mvarCartridgeType = SMCCartridgeTypes.ROMOnly;
+ ///
+ /// indicates the hardware in the cartridge. Emulators use this byte to decide which hardware to emulate. A real SNES ignores this byte and uses the real hardware in the real cartridge.
+ ///
+ public SMCCartridgeType CartridgeType { get { return mvarCartridgeType; } set { mvarCartridgeType = value; } }
+
+ private SMCMemorySize mvarROMSize = SMCMemorySizes.K256;
+ ///
+ /// Indicates the amount of ROM in the cartridge.
+ ///
+ public SMCMemorySize ROMSize { get { return mvarROMSize; } set { mvarROMSize = value; } }
+
+ private SMCMemorySize mvarRAMSize = SMCMemorySizes.K256;
+ ///
+ /// Indicates the amount of RAM in the cartridge (excluding the RAM in the SNES system).
+ ///
+ public SMCMemorySize RAMSize { get { return mvarRAMSize; } set { mvarRAMSize = value; } }
+
private SMCRegion mvarRegion = SMCRegions.Japan;
///
/// The region in which the game is licensed.
@@ -247,6 +311,13 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
///
public SMCLicensee Licensee { get { return mvarLicensee; } set { mvarLicensee = value; } }
+ private byte mvarVersionNumber = 0;
+ ///
+ /// Typically contains 0x00. Most ROM hackers never touch this byte, so multiple versions of a ROM
+ /// hack may share the same value of this byte. A few ROM hackers actually set this byte.
+ ///
+ public byte VersionNumber { get { return mvarVersionNumber; } set { mvarVersionNumber = value; } }
+
///
/// Loads game data into the specified .
///
@@ -257,74 +328,82 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
if (exe == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
-
- mvarExtendedHeader.Enabled = (base.Accessor.Length % 1024 == 512);
- if (mvarExtendedHeader.Enabled)
+ #region Extended Header
{
- #region 00-02 The size of the ROM dump, in units of 8 kilobytes, as a little-endian integer.
+ mvarExtendedHeader.Enabled = (base.Accessor.Length % 1024 == 512);
+ if (mvarExtendedHeader.Enabled)
{
- mvarExtendedHeader.FileSize = reader.ReadInt16();
- mvarExtendedHeader.FileSize *= 8000;
- }
- #endregion
- #region 02-03 Flags
- byte flags = reader.ReadByte();
- mvarExtendedHeader.SplitFile = ((flags & 0x40) == 0x40);
- mvarExtendedHeader.HiRomEnabled = ((flags & 0x30) == 0x30);
+ #region 00-02 The size of the ROM dump, in units of 8 kilobytes, as a little-endian integer.
+ {
+ mvarExtendedHeader.FileSize = reader.ReadInt16();
+ mvarExtendedHeader.FileSize *= 8000;
+ }
+ #endregion
+ #region 02-03 Flags
+ SMCExtendedHeaderFlags flags = (SMCExtendedHeaderFlags)reader.ReadByte();
+ mvarExtendedHeader.SplitFile = ((flags & SMCExtendedHeaderFlags.SplitFile) == SMCExtendedHeaderFlags.SplitFile);
+ mvarExtendedHeader.HiRomEnabled = ((flags & SMCExtendedHeaderFlags.HiRomEnabled) == SMCExtendedHeaderFlags.HiRomEnabled);
- if ((flags & 0x04) == 0x04)
- {
- mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAM8K;
- }
- else if ((flags & 0x08) == 0x08)
- {
- mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAM2K;
- }
- else if ((flags & 0x0C) == 0x0C)
- {
- mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAMNone;
- }
+ if ((flags & SMCExtendedHeaderFlags.SaveRam8K) == SMCExtendedHeaderFlags.SaveRam8K)
+ {
+ mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAM8K;
+ }
+ else if ((flags & SMCExtendedHeaderFlags.SaveRam2K) == SMCExtendedHeaderFlags.SaveRam2K)
+ {
+ mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAM2K;
+ }
+ else if ((flags & SMCExtendedHeaderFlags.SaveRamNone) == SMCExtendedHeaderFlags.SaveRamNone)
+ {
+ mvarExtendedHeader.SaveRAMSize = SMCSaveRAMSize.SaveRAMNone;
+ }
- if ((flags & 0x80) == 0x80)
- {
- mvarExtendedHeader.ResetVectorOverride = 0x8000;
- }
- #endregion
- #region 03-04 HiRom/LoRom (Pro Fighter specific)
- byte hiRomLoRom = reader.ReadByte();
- if ((flags & 0x30) != 0x30)
- {
- // only set HiRom/LoRom from this field if not set in a flag
- mvarExtendedHeader.HiRomEnabled = ((hiRomLoRom & 0x80) == 0x80);
- }
- #endregion
- #region 04-06 DSP-1 settings (Pro Fighter specific)
- mvarExtendedHeader.DSP1Settings = reader.ReadInt16();
- #endregion
- #region 06-08 Unknown
- ushort unknown1 = reader.ReadUInt16();
- #endregion
- #region 08-16 SUPERUFO
- string creator = reader.ReadFixedLengthString(8); // SUPERUFO
- mvarExtendedHeader.Creator = creator;
- #endregion
- #region 16-24 Extra data
- byte[] extradata = reader.ReadBytes(8);
- #endregion
+ if ((flags & SMCExtendedHeaderFlags.ResetVectorAddressOverride) == SMCExtendedHeaderFlags.ResetVectorAddressOverride)
+ {
+ mvarExtendedHeader.ResetVectorOverride = 0x8000;
+ }
+ #endregion
+ #region 03-04 HiRom/LoRom (Pro Fighter specific)
+ byte hiRomLoRom = reader.ReadByte();
+ if ((flags & SMCExtendedHeaderFlags.HiRomEnabled) != SMCExtendedHeaderFlags.HiRomEnabled)
+ {
+ // only set HiRom/LoRom from this field if not set in a flag
+ mvarExtendedHeader.HiRomEnabled = ((hiRomLoRom & 0x80) == 0x80);
+ }
+ if (mvarExtendedHeader.HiRomEnabled)
+ {
+ mvarROMLayout = SMCLayout.HiROM;
+ }
+ #endregion
+ #region 04-06 DSP-1 settings (Pro Fighter specific)
+ mvarExtendedHeader.DSP1Settings = reader.ReadInt16();
+ #endregion
+ #region 06-08 Unknown
+ ushort unknown1 = reader.ReadUInt16();
+ #endregion
+ #region 08-16 SUPERUFO
+ string creator = reader.ReadFixedLengthString(8); // SUPERUFO
+ mvarExtendedHeader.Creator = creator;
+ #endregion
+ #region 16-24 Extra data
+ byte[] extradata = reader.ReadBytes(8);
+ #endregion
- if (mvarExtendedHeader.HiRomEnabled)
- {
- base.Accessor.Seek(0x101c0, SeekOrigin.Begin);
- }
- else
- {
- base.Accessor.Seek(0x81c0, SeekOrigin.Begin);
+ if (mvarExtendedHeader.HiRomEnabled)
+ {
+ base.Accessor.Seek(0x101c0, SeekOrigin.Begin);
+ }
+ else
+ {
+ base.Accessor.Seek(0x81c0, SeekOrigin.Begin);
+ }
}
}
+ #endregion
#region SNES header
- string gamename = reader.ReadFixedLengthString(21).Trim();
+ mvarGameName = reader.ReadFixedLengthString(21).Trim();
+
byte romLayout = reader.ReadByte();
if (romLayout == 0x20)
{
@@ -335,8 +414,13 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
// HiROM
}
byte cartridgeType = reader.ReadByte();
+ mvarCartridgeType = SMCCartridgeType.FromCode(cartridgeType);
+
byte romsize = reader.ReadByte();
+ mvarROMSize = SMCMemorySize.FromCode(romsize);
+
byte ramsize = reader.ReadByte();
+ mvarRAMSize = SMCMemorySize.FromCode(ramsize);
// Country code, which selects the video in the emulator. Values $00, $01, $0d use NTSC.
// Values in range $02..$0c use PAL. Other values are invalid.
@@ -353,7 +437,7 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
}
- byte versionNumber = reader.ReadByte();
+ mvarVersionNumber = reader.ReadByte();
ushort checksumComplement = reader.ReadUInt16();
ushort checksum = reader.ReadUInt16();
@@ -390,7 +474,77 @@ namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
ExecutableObjectModel exe = (objectModel as ExecutableObjectModel);
if (exe == null) throw new ObjectModelNotSupportedException();
- throw new NotImplementedException();
+ Writer writer = base.Accessor.Writer;
+
+ #region SNES header
+ writer.WriteFixedLengthString(mvarGameName, 21, ' ');
+
+ switch (mvarROMLayout)
+ {
+ case SMCLayout.LoROM:
+ {
+ writer.WriteByte(0x20);
+ break;
+ }
+ case SMCLayout.HiROM:
+ {
+ writer.WriteByte(0x21);
+ break;
+ }
+ }
+
+ writer.WriteByte((byte)(mvarCartridgeType != null ? mvarCartridgeType.Value : 0));
+ writer.WriteByte((byte)(mvarROMSize != null ? mvarROMSize.Value : 0));
+ writer.WriteByte((byte)(mvarRAMSize != null ? mvarRAMSize.Value : 0));
+ writer.WriteByte((byte)(mvarRegion != null ? mvarRegion.Value : 0));
+ writer.WriteByte((byte)(mvarLicensee != null ? mvarLicensee.Value : 0));
+
+ if (mvarLicensee != null && mvarLicensee.Value == 0x33)
+ {
+
+ }
+
+ writer.WriteByte(mvarVersionNumber);
+
+ ushort checksumComplement = 0;
+ ushort checksum = 0;
+ writer.WriteUInt16(checksumComplement);
+ writer.WriteUInt16(checksum);
+
+ int unknown2 = 0;
+ writer.WriteInt32(unknown2);
+
+ short nativeInterruptVectorCOP = 0;
+ short nativeInterruptVectorBRK = 0;
+ short nativeInterruptVectorABORT = 0;
+ short nativeInterruptVectorNMI = 0; // vertical blank
+ short nativeInterruptVectorUnused = 0;
+ short nativeInterruptVectorIRQ = 0;
+
+ writer.WriteInt16(nativeInterruptVectorCOP);
+ writer.WriteInt16(nativeInterruptVectorBRK);
+ writer.WriteInt16(nativeInterruptVectorABORT);
+ writer.WriteInt16(nativeInterruptVectorNMI);
+ writer.WriteInt16(nativeInterruptVectorUnused);
+ writer.WriteInt16(nativeInterruptVectorIRQ);
+
+ int unknown3 = 0;
+ writer.WriteInt32(unknown3);
+
+ short emulationInterruptVectorCOP = 0;
+ short emulationInterruptVectorUnused = 0;
+ short emulationInterruptVectorABORT = 0;
+ short emulationInterruptVectorNMI = 0; // vertical blank
+ short emulationInterruptVectorRESET = 0;
+ short emulationInterruptVectorIRQorBRK = 0;
+
+ writer.WriteInt16(emulationInterruptVectorCOP);
+ writer.WriteInt16(emulationInterruptVectorUnused);
+ writer.WriteInt16(emulationInterruptVectorABORT);
+ writer.WriteInt16(emulationInterruptVectorNMI);
+ writer.WriteInt16(emulationInterruptVectorRESET);
+ writer.WriteInt16(emulationInterruptVectorIRQorBRK);
+ #endregion
}
}
}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCExtendedHeaderFlags.cs b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCExtendedHeaderFlags.cs
new file mode 100644
index 00000000..f44d0c3c
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCExtendedHeaderFlags.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
+{
+ public enum SMCExtendedHeaderFlags : byte
+ {
+ ///
+ /// Save-RAM size is 32 kilobytes.
+ ///
+ SaveRam32K = 0x00,
+ ///
+ /// Save-RAM size is 8 kilobytes.
+ ///
+ SaveRam8K = 0x04,
+ ///
+ /// Save-RAM size is 2 kilobytes.
+ ///
+ SaveRam2K = 0x08,
+ ///
+ /// Save-RAM size is 0 kilobytes.
+ ///
+ SaveRamNone = 0x0C,
+ ///
+ /// Use HiROM.
+ ///
+ HiRomEnabled = 0x30,
+ ///
+ /// This is a split file but not the last image.
+ ///
+ SplitFile = 0x40,
+ ///
+ /// Jump to $8000 instead of the address in the reset vector.
+ ///
+ ResetVectorAddressOverride = 0x80
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCLayout.cs b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCLayout.cs
new file mode 100644
index 00000000..ab48fc0c
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCLayout.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
+{
+ public enum SMCLayout
+ {
+ LoROM = 0x20,
+ HiROM = 0x21
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCMemorySize.cs b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCMemorySize.cs
new file mode 100644
index 00000000..8382a1f1
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/DataFormats/Executable/Nintendo/SNES/SMCMemorySize.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace UniversalEditor.DataFormats.Executable.Nintendo.SNES
+{
+ ///
+ /// A company that has licensed the use of the Nintendo SNES game console for development.
+ ///
+ ///
+ public class SMCMemorySize
+ {
+ private string mvarTitle = String.Empty;
+ ///
+ /// The title of the memory size.
+ ///
+ public string Title { get { return mvarTitle; } set { mvarTitle = value; } }
+
+ private byte mvarValue = 0;
+ ///
+ /// The single-byte code that represents this memory size in the Nintendo SNES game console.
+ ///
+ public byte Value { get { return mvarValue; } set { mvarValue = value; } }
+
+ ///
+ /// Gets the with the given value if valid.
+ ///
+ /// The memory size code to search on.
+ /// If the code is known, returns an instance of the associated . Otherwise, returns null.
+ public static SMCMemorySize FromCode(byte value)
+ {
+ Type t = typeof(SMCMemorySizes);
+
+ MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.Static;
+ PropertyInfo[] properties = t.GetProperties();
+ for (int i = 0; i < properties.Length; i++)
+ {
+ PropertyInfo propertyInfo = properties[i];
+ if (propertyInfo.PropertyType == typeof(SMCMemorySize))
+ {
+ MethodInfo getMethod = propertyInfo.GetGetMethod();
+ if (getMethod != null && (getMethod.Attributes & methodAttributes) == methodAttributes)
+ {
+ object[] index = null;
+ SMCMemorySize val = (SMCMemorySize)propertyInfo.GetValue(null, index);
+
+ if (val.Value == value) return val;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Creates a new instance of with the given title and value.
+ ///
+ ///
+ ///
+ public SMCMemorySize(string title, byte value)
+ {
+ mvarTitle = title;
+ mvarValue = value;
+ }
+
+ ///
+ /// Translates this into a human-readable string, including the
+ /// title of the region and the country code.
+ ///
+ /// A human-readable string representing this .
+ public override string ToString()
+ {
+ return mvarTitle + " (0x" + mvarValue.ToString("X").PadLeft(2, '0') + ")";
+ }
+ }
+ ///
+ /// Licensees that have been defined by the SNES SMC data format. This class cannot be inherited.
+ ///
+ public sealed class SMCMemorySizes
+ {
+ private static SMCMemorySize mvarNone = new SMCMemorySize("(none)", 0x00);
+ ///
+ /// Gets the representing no memory.
+ ///
+ public static SMCMemorySize None { get { return mvarNone; } }
+
+ private static SMCMemorySize mvarK2 = new SMCMemorySize("2 KB (2048 bytes)", 0x01);
+ ///
+ /// Gets the representing 2KB (2048 bytes) worth of memory. This is the amount of RAM used in "Super Mario World".
+ ///
+ public static SMCMemorySize K2 { get { return mvarK2; } }
+
+ private static SMCMemorySize mvarK4 = new SMCMemorySize("4 KB (4096 bytes)", 0x02);
+ ///
+ /// Gets the representing 4KB (4096 bytes) worth of memory.
+ ///
+ public static SMCMemorySize K4 { get { return mvarK4; } }
+
+ private static SMCMemorySize mvarK8 = new SMCMemorySize("8 KB (8192 bytes)", 0x03);
+ ///
+ /// Gets the representing 8KB (8192 bytes) worth of memory.
+ ///
+ public static SMCMemorySize K8 { get { return mvarK8; } }
+
+ private static SMCMemorySize mvarK16 = new SMCMemorySize("16 KB (16 384 bytes)", 0x04);
+ ///
+ /// Gets the representing 16KB (16 384 bytes) worth of memory.
+ ///
+ public static SMCMemorySize K16 { get { return mvarK16; } }
+
+ private static SMCMemorySize mvarK32 = new SMCMemorySize("32 KB (32 768 bytes)", 0x05);
+ ///
+ /// Gets the representing 32KB (32 768 bytes) worth of memory. This is the amount of RAM used in "Mario Paint".
+ ///
+ public static SMCMemorySize K32 { get { return mvarK32; } }
+
+ private static SMCMemorySize mvarK64 = new SMCMemorySize("64 KB (65 536 bytes)", 0x06);
+ ///
+ /// Gets the representing 64KB (65 536 bytes) worth of memory.
+ ///
+ public static SMCMemorySize K64 { get { return mvarK64; } }
+
+ private static SMCMemorySize mvarK128 = new SMCMemorySize("128 KB (131 072 bytes)", 0x07);
+ ///
+ /// Gets the representing 128KB (131 072 bytes) worth of memory. This is the amount of RAM used in "Dezaemon - Kaite Tsukutte Asoberu".
+ ///
+ public static SMCMemorySize K128 { get { return mvarK128; } }
+
+ private static SMCMemorySize mvarK256 = new SMCMemorySize("256 KB (262 144 bytes)", 0x08);
+ ///
+ /// Gets the representing 256KB (262 144 bytes) worth of memory. This is the minimum amount of ROM.
+ ///
+ public static SMCMemorySize K256 { get { return mvarK256; } }
+
+ private static SMCMemorySize mvarK512 = new SMCMemorySize("512 KB (524 288 bytes)", 0x09);
+ ///
+ /// Gets the representing 512KB (524 288 bytes) worth of memory.
+ ///
+ public static SMCMemorySize K512 { get { return mvarK512; } }
+
+ private static SMCMemorySize mvarM1 = new SMCMemorySize("1 MB (1 048 576 bytes)", 0x0A);
+ ///
+ /// Gets the representing 1MB (1 048 576 bytes) worth of memory.
+ ///
+ public static SMCMemorySize M1 { get { return mvarM1; } }
+
+ private static SMCMemorySize mvarM2 = new SMCMemorySize("2 MB (2 097 152 bytes)", 0x0B);
+ ///
+ /// Gets the representing 2MB (2 097 152 bytes) worth of memory.
+ ///
+ public static SMCMemorySize M2 { get { return mvarM2; } }
+
+ private static SMCMemorySize mvarM4 = new SMCMemorySize("4 MB (4 194 304 bytes)", 0x0C);
+ ///
+ /// Gets the representing 4MB (4 194 304 bytes) worth of memory.
+ ///
+ public static SMCMemorySize M4 { get { return mvarM4; } }
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/UniversalEditor.Plugins.Nintendo.csproj b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/UniversalEditor.Plugins.Nintendo.csproj
index 65f2ceee..a1545d13 100644
--- a/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/UniversalEditor.Plugins.Nintendo.csproj
+++ b/CSharp/Plugins/UniversalEditor.Plugins.Nintendo/UniversalEditor.Plugins.Nintendo.csproj
@@ -37,8 +37,12 @@
+
+
+
+