diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Bandai.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Bandai.cs
new file mode 100644
index 00000000..b1419f62
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Bandai.cs
@@ -0,0 +1,141 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal abstract class Bandai : Board
+    {
+    	private bool irq_enable;
+
+    	private int irq_counter;
+
+    	private Eprom eprom;
+
+    	internal override void Initialize(IRom rom)
+    	{
+    		base.Initialize(rom);
+    		if (base.BoardType.ToLower().Contains("24c01"))
+    		{
+    			eprom = new Eprom(128);
+    		}
+    		else
+    		{
+    			eprom = new Eprom((base.MapperNumber == 16) ? 256 : 128);
+    		}
+    	}
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		irq_enable = false;
+    		irq_counter = 0;
+    		eprom.HardReset();
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		WritePRG(ref address, ref data);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF)
+    		{
+    		case 0:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 1:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 2:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 3:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 4:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 5:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 6:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 7:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 8:
+    			Switch16KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 9:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 10:
+    			irq_enable = (data & 1) == 1;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 11:
+    			irq_counter = (irq_counter & 0xFF00) | data;
+    			break;
+    		case 12:
+    			irq_counter = (irq_counter & 0xFF) | (data << 8);
+    			break;
+    		case 13:
+    			eprom.Write(address, data);
+    			break;
+    		}
+    	}
+
+    	internal override void ReadSRM(ref ushort address, out byte value)
+    	{
+    		value = eprom.Read(address);
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_enable)
+    		{
+    			irq_counter--;
+    			if (irq_counter == 0)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    			if (irq_counter < 0)
+    			{
+    				irq_counter = 65535;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_counter);
+    		eprom.SaveState(stream);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_enable = stream.ReadBoolean();
+    		irq_counter = stream.ReadInt32();
+    		eprom.LoadState(stream);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BankInfo.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BankInfo.cs
new file mode 100644
index 00000000..6aaab59a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BankInfo.cs
@@ -0,0 +1,27 @@
+namespace MyNes.Core
+{
+    internal struct BankInfo
+    {
+    	public bool IsRAM;
+
+    	public bool Enabled;
+
+    	public bool Writable;
+
+    	public bool IsBattery;
+
+    	public string ID;
+
+    	public byte[] DATA;
+
+    	public BankInfo(string ID, bool IsRAM, bool Writable, bool Enabled, bool IsBattery, byte[] DATA)
+    	{
+    		this.ID = ID;
+    		this.IsRAM = IsRAM;
+    		this.Writable = Writable;
+    		this.Enabled = Enabled;
+    		this.DATA = DATA;
+    		this.IsBattery = IsBattery;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BankInfoSorter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BankInfoSorter.cs
new file mode 100644
index 00000000..19ad97fb
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BankInfoSorter.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace MyNes.Core
+{
+    internal class BankInfoSorter : IComparer<BankInfo>
+    {
+    	public int Compare(BankInfo x, BankInfo y)
+    	{
+    		int result = 0;
+    		int result2 = 0;
+    		int.TryParse(x.ID, out result);
+    		int.TryParse(y.ID, out result2);
+    		return result2 - result;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BlankJoypad.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BlankJoypad.cs
new file mode 100644
index 00000000..6dd61be4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BlankJoypad.cs
@@ -0,0 +1,9 @@
+namespace MyNes.Core
+{
+    internal class BlankJoypad : IJoypadConnecter
+    {
+    	public override void Update()
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BlankShortuctsHandler.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BlankShortuctsHandler.cs
new file mode 100644
index 00000000..ca02201a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BlankShortuctsHandler.cs
@@ -0,0 +1,9 @@
+namespace MyNes.Core
+{
+    internal class BlankShortuctsHandler : IShortcutsHandler
+    {
+    	public void Update()
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Board.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Board.cs
new file mode 100644
index 00000000..acb93742
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Board.cs
@@ -0,0 +1,1117 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal abstract class Board
+    {
+    	protected byte[][] PRG_RAM;
+
+    	protected bool[] PRG_RAM_ENABLED;
+
+    	protected bool[] PRG_RAM_WRITABLE;
+
+    	protected bool[] PRG_RAM_BATTERY;
+
+    	protected byte[][] PRG_ROM;
+
+    	protected int PRG_RAM_08KB_DEFAULT_BLK_Count;
+
+    	internal int PRG_ROM_04KB_Count;
+
+    	protected int PRG_ROM_08KB_Count;
+
+    	protected int PRG_ROM_16KB_Count;
+
+    	protected int PRG_ROM_32KB_Count;
+
+    	protected int PRG_ROM_04KB_Mask;
+
+    	protected int PRG_ROM_08KB_Mask;
+
+    	protected int PRG_ROM_16KB_Mask;
+
+    	protected int PRG_ROM_32KB_Mask;
+
+    	internal int PRG_RAM_04KB_Count;
+
+    	protected int PRG_RAM_08KB_Count;
+
+    	protected int PRG_RAM_16KB_Count;
+
+    	protected int PRG_RAM_32KB_Count;
+
+    	protected int PRG_RAM_04KB_Mask;
+
+    	protected int PRG_RAM_08KB_Mask;
+
+    	protected int PRG_RAM_16KB_Mask;
+
+    	protected int PRG_RAM_32KB_Mask;
+
+    	protected bool[] PRG_AREA_BLK_RAM;
+
+    	protected int[] PRG_AREA_BLK_INDEX;
+
+    	protected int PRG_TMP_INDX;
+
+    	protected int PRG_TMP_AREA;
+
+    	protected byte[][] CHR_RAM;
+
+    	protected bool[] CHR_RAM_ENABLED;
+
+    	protected bool[] CHR_RAM_WRITABLE;
+
+    	protected bool[] CHR_RAM_BATTERY;
+
+    	protected byte[][] CHR_ROM;
+
+    	protected bool[] CHR_AREA_BLK_RAM;
+
+    	protected int[] CHR_AREA_BLK_INDEX;
+
+    	protected int CHR_TMP_INDX;
+
+    	protected int CHR_TMP_AREA;
+
+    	protected int CHR_ROM_01KB_DEFAULT_BLK_Count;
+
+    	internal int CHR_ROM_01KB_Count;
+
+    	protected int CHR_ROM_02KB_Count;
+
+    	protected int CHR_ROM_04KB_Count;
+
+    	protected int CHR_ROM_08KB_Count;
+
+    	internal int CHR_ROM_01KB_Mask;
+
+    	protected int CHR_ROM_02KB_Mask;
+
+    	protected int CHR_ROM_04KB_Mask;
+
+    	protected int CHR_ROM_08KB_Mask;
+
+    	internal int CHR_RAM_01KB_Count;
+
+    	protected int CHR_RAM_02KB_Count;
+
+    	protected int CHR_RAM_04KB_Count;
+
+    	protected int CHR_RAM_08KB_Count;
+
+    	internal int CHR_RAM_01KB_Mask;
+
+    	protected int CHR_RAM_02KB_Mask;
+
+    	protected int CHR_RAM_04KB_Mask;
+
+    	protected int CHR_RAM_08KB_Mask;
+
+    	protected byte[][] NMT_RAM;
+
+    	internal int[] NMT_AREA_BLK_INDEX;
+
+    	protected int NMT_TMP_INDX;
+
+    	protected int NMT_TMP_AREA;
+
+    	internal Mirroring NMT_DEFAULT_MIRROR;
+
+    	internal string SHA1 = "";
+
+    	internal string CRC = "";
+
+    	internal bool IsGameFoundOnDB;
+
+    	internal NesCartDatabaseGameInfo GameInfo;
+
+    	internal NesCartDatabaseCartridgeInfo GameCartInfo;
+
+    	internal bool SRAMSaveRequired;
+
+    	protected bool enabled_ppuA12ToggleTimer;
+
+    	protected bool ppuA12TogglesOnRaisingEdge;
+
+    	protected int old_vram_address;
+
+    	protected int new_vram_address;
+
+    	protected int ppu_cycles_timer;
+
+    	internal bool enable_external_sound;
+
+    	internal bool IsGameGenieActive;
+
+    	internal GameGenieCode[] GameGenieCodes;
+
+    	internal string BoardType { get; private set; }
+
+    	internal string BoardPCB { get; private set; }
+
+    	internal List<string> Chips { get; private set; }
+
+    	internal string Name { get; set; }
+
+    	internal int MapperNumber { get; set; }
+
+    	internal bool HasIssues { get; set; }
+
+    	internal virtual string Issues { get; set; }
+
+    	public Board()
+    	{
+    		MapperNumber = -1;
+    		PRG_RAM_08KB_DEFAULT_BLK_Count = 1;
+    		CHR_ROM_01KB_DEFAULT_BLK_Count = 8;
+    		LoadAttrs();
+    	}
+
+    	internal virtual void Initialize(IRom rom)
+    	{
+    		SHA1 = rom.SHA1;
+    		SRAMSaveRequired = false;
+    		IsGameGenieActive = false;
+    		BoardType = "N/A";
+    		BoardPCB = "N/A";
+    		Chips = new List<string>();
+    		if (NesCartDatabase.Ready)
+    		{
+    			Tracer.WriteLine("Looking for rom in the database ..");
+    			GameInfo = NesCartDatabase.Find(SHA1, out IsGameFoundOnDB);
+    			if (GameInfo.Cartridges != null)
+    			{
+    				foreach (NesCartDatabaseCartridgeInfo cartridge in GameInfo.Cartridges)
+    				{
+    					if (cartridge.SHA1.ToLower() == SHA1.ToLower())
+    					{
+    						GameCartInfo = cartridge;
+    						break;
+    					}
+    				}
+    			}
+    			if (IsGameFoundOnDB)
+    			{
+    				Tracer.WriteInformation("Game found in Database !!");
+    				Tracer.WriteLine("> Game name: " + GameInfo.Game_Name);
+    				Tracer.WriteLine("> Game alt name: " + GameInfo.Game_AltName);
+    				BoardType = GameCartInfo.Board_Type;
+    				Tracer.WriteLine("> Board Type: " + BoardType);
+    				BoardPCB = GameCartInfo.Board_Pcb;
+    				Tracer.WriteLine("> Board Pcb: " + BoardPCB);
+    				if (GameCartInfo.chip_type != null)
+    				{
+    					for (int i = 0; i < GameCartInfo.chip_type.Count; i++)
+    					{
+    						Console.WriteLine($"> CHIP {(i + 1).ToString()}: {GameCartInfo.chip_type[i]}");
+    						Chips.Add(GameCartInfo.chip_type[i]);
+    					}
+    				}
+    			}
+    			else
+    			{
+    				Tracer.WriteWarning("Game is not found in database .");
+    			}
+    		}
+    		Tracer.WriteLine("Initializing the board (Mapper # " + MapperNumber + ") ....");
+    		Tracer.WriteLine("Loading PRG ROM ...");
+    		PRG_AREA_BLK_RAM = new bool[16];
+    		PRG_AREA_BLK_INDEX = new int[16];
+    		PRG_ROM = new byte[0][];
+    		int num = 0;
+    		for (int j = 0; j < rom.PRG.Length; j += 4096)
+    		{
+    			Array.Resize(ref PRG_ROM, PRG_ROM.GetLength(0) + 1);
+    			PRG_ROM[num] = new byte[4096];
+    			for (int k = 0; k < 4096; k++)
+    			{
+    				PRG_ROM[num][k] = rom.PRG[j + k];
+    			}
+    			num++;
+    		}
+    		PRG_ROM_04KB_Count = PRG_ROM.GetLength(0);
+    		PRG_ROM_04KB_Mask = PRG_ROM_04KB_Count - 1;
+    		PRG_ROM_08KB_Count = PRG_ROM_04KB_Count / 2;
+    		PRG_ROM_08KB_Mask = PRG_ROM_08KB_Count - 1;
+    		PRG_ROM_16KB_Count = PRG_ROM_04KB_Count / 4;
+    		PRG_ROM_16KB_Mask = PRG_ROM_16KB_Count - 1;
+    		PRG_ROM_32KB_Count = PRG_ROM_04KB_Count / 8;
+    		PRG_ROM_32KB_Mask = PRG_ROM_32KB_Count - 1;
+    		Tracer.WriteLine("PRG ROM loaded successfully.");
+    		Tracer.WriteLine("PRG ROM Size = " + PRG_ROM_04KB_Count * 4 + "KB");
+    		Tracer.WriteLine("Loading PRG RAM ...");
+    		SRAMBankInfo[] pRGRAM8KCountFromDB = GetPRGRAM8KCountFromDB();
+    		PRG_RAM = new byte[0][];
+    		PRG_RAM_BATTERY = new bool[0];
+    		PRG_RAM_ENABLED = new bool[0];
+    		PRG_RAM_WRITABLE = new bool[0];
+    		SRAMBankInfo[] array = pRGRAM8KCountFromDB;
+    		for (int l = 0; l < array.Length; l++)
+    		{
+    			SRAMBankInfo sRAMBankInfo = array[l];
+    			if (sRAMBankInfo.BATTERY)
+    			{
+    				SRAMSaveRequired = true;
+    			}
+    			int result = 0;
+    			int.TryParse(sRAMBankInfo.SIZE.Replace("k", ""), out result);
+    			if (result > 0)
+    			{
+    				int num2 = result / 2;
+    				for (int m = 0; m < num2; m++)
+    				{
+    					Array.Resize(ref PRG_RAM_BATTERY, PRG_RAM_BATTERY.Length + 1);
+    					Array.Resize(ref PRG_RAM_ENABLED, PRG_RAM_ENABLED.Length + 1);
+    					Array.Resize(ref PRG_RAM_WRITABLE, PRG_RAM_WRITABLE.Length + 1);
+    					Array.Resize(ref PRG_RAM, PRG_RAM.GetLength(0) + 1);
+    					PRG_RAM[PRG_RAM.GetLength(0) - 1] = new byte[4096];
+    					PRG_RAM_BATTERY[PRG_RAM_BATTERY.Length - 1] = sRAMBankInfo.BATTERY;
+    					PRG_RAM_ENABLED[PRG_RAM_ENABLED.Length - 1] = true;
+    					PRG_RAM_WRITABLE[PRG_RAM_WRITABLE.Length - 1] = true;
+    				}
+    			}
+    		}
+    		PRG_RAM_04KB_Count = PRG_RAM.GetLength(0);
+    		PRG_RAM_04KB_Mask = PRG_RAM_04KB_Count - 1;
+    		PRG_RAM_08KB_Count = PRG_RAM_04KB_Count / 2;
+    		PRG_RAM_08KB_Mask = PRG_RAM_08KB_Count - 1;
+    		PRG_RAM_16KB_Count = PRG_RAM_04KB_Count / 4;
+    		PRG_RAM_16KB_Mask = PRG_RAM_16KB_Count - 1;
+    		PRG_RAM_32KB_Count = PRG_RAM_04KB_Count / 8;
+    		PRG_RAM_32KB_Mask = PRG_RAM_32KB_Count - 1;
+    		Tracer.WriteLine("PRG RAM loaded successfully.");
+    		Tracer.WriteLine("PRG RAM Size = " + PRG_RAM_04KB_Count * 4 + "KB");
+    		if (rom.HasTrainer)
+    		{
+    			rom.Trainer.CopyTo(PRG_RAM[3], 0);
+    		}
+    		Tracer.WriteLine("Loading CHR ROM ...");
+    		CHR_ROM = new byte[0][];
+    		CHR_AREA_BLK_RAM = new bool[8];
+    		CHR_AREA_BLK_INDEX = new int[8];
+    		num = 0;
+    		for (int n = 0; n < rom.CHR.Length; n += 1024)
+    		{
+    			Array.Resize(ref CHR_ROM, CHR_ROM.GetLength(0) + 1);
+    			CHR_ROM[num] = new byte[1024];
+    			for (int num3 = 0; num3 < 1024; num3++)
+    			{
+    				CHR_ROM[num][num3] = rom.CHR[n + num3];
+    			}
+    			num++;
+    		}
+    		CHR_ROM_01KB_Count = CHR_ROM.GetLength(0);
+    		CHR_ROM_01KB_Mask = CHR_ROM_01KB_Count - 1;
+    		CHR_ROM_02KB_Count = CHR_ROM_01KB_Count / 2;
+    		CHR_ROM_02KB_Mask = CHR_ROM_02KB_Count - 1;
+    		CHR_ROM_04KB_Count = CHR_ROM_01KB_Count / 4;
+    		CHR_ROM_04KB_Mask = CHR_ROM_04KB_Count - 1;
+    		CHR_ROM_08KB_Count = CHR_ROM_01KB_Count / 8;
+    		CHR_ROM_08KB_Mask = CHR_ROM_08KB_Count - 1;
+    		Tracer.WriteLine("CHR ROM loaded successfully.");
+    		Tracer.WriteLine("CHR ROM Size = " + CHR_ROM_01KB_Count + "KB");
+    		Tracer.WriteLine("Loading CHR RAM ...");
+    		int cHRRAM1KCountFromDB = GetCHRRAM1KCountFromDB();
+    		CHR_RAM = new byte[0][];
+    		CHR_RAM_BATTERY = new bool[cHRRAM1KCountFromDB];
+    		CHR_RAM_ENABLED = new bool[cHRRAM1KCountFromDB];
+    		CHR_RAM_WRITABLE = new bool[cHRRAM1KCountFromDB];
+    		for (int num4 = 0; num4 < cHRRAM1KCountFromDB; num4++)
+    		{
+    			Array.Resize(ref CHR_RAM, CHR_RAM.GetLength(0) + 1);
+    			CHR_RAM[num4] = new byte[1024];
+    			CHR_RAM_BATTERY[num4] = false;
+    			CHR_RAM_ENABLED[num4] = true;
+    			CHR_RAM_WRITABLE[num4] = true;
+    		}
+    		CHR_RAM_01KB_Count = CHR_RAM.GetLength(0);
+    		CHR_RAM_01KB_Mask = CHR_RAM_01KB_Count - 1;
+    		CHR_RAM_02KB_Count = CHR_RAM_01KB_Count / 2;
+    		CHR_RAM_02KB_Mask = CHR_RAM_02KB_Count - 1;
+    		CHR_RAM_04KB_Count = CHR_RAM_01KB_Count / 4;
+    		CHR_RAM_04KB_Mask = CHR_RAM_04KB_Count - 1;
+    		CHR_RAM_08KB_Count = CHR_RAM_01KB_Count / 8;
+    		CHR_RAM_08KB_Mask = CHR_RAM_08KB_Count - 1;
+    		Tracer.WriteLine("CHR RAM loaded successfully.");
+    		Tracer.WriteLine("CHR RAM Size = " + CHR_RAM_01KB_Count + "KB");
+    		Tracer.WriteLine("Loading Nametables ...");
+    		NMT_AREA_BLK_INDEX = new int[4];
+    		NMT_RAM = new byte[0][];
+    		for (int num5 = 0; num5 < 4; num5++)
+    		{
+    			Array.Resize(ref NMT_RAM, NMT_RAM.GetLength(0) + 1);
+    			NMT_RAM[num5] = new byte[1024];
+    		}
+    		NMT_DEFAULT_MIRROR = rom.Mirroring;
+    		Tracer.WriteLine("Mirroring set to " + NMT_DEFAULT_MIRROR);
+    		Tracer.WriteLine("Board (Mapper # " + MapperNumber + ") initialized successfully.");
+    	}
+
+    	internal virtual void HardReset()
+    	{
+    		Tracer.WriteLine("Hard reset board (Mapper # " + MapperNumber + ") ....");
+    		Tracer.WriteLine("Switching 16KB PRG RAM at 0x4000 - 0x7000");
+    		Toggle16KPRG_RAM(ram: true, PRGArea.Area4000);
+    		Switch16KPRG(0, PRGArea.Area4000);
+    		Tracer.WriteLine("Switching 32KB PRG ROM at 0x8000 - 0xF000");
+    		Toggle32KPRG_RAM(ram: false, PRGArea.Area8000);
+    		Switch32KPRG(0, PRGArea.Area8000);
+    		Tracer.WriteLine("Switching 8KB CHR " + ((CHR_ROM_01KB_Count == 0) ? "RAM" : "ROM") + " at 0x0000 - 0x1000");
+    		Toggle08KCHR_RAM(CHR_ROM_01KB_Count == 0);
+    		Switch08KCHR(0);
+    		Tracer.WriteLine("Switching to mirroring: " + NMT_DEFAULT_MIRROR);
+    		Switch01KNMTFromMirroring(NMT_DEFAULT_MIRROR);
+    		Tracer.WriteLine("Hard reset board (Mapper # " + MapperNumber + ") is done successfully.");
+    	}
+
+    	internal virtual void SoftReset()
+    	{
+    	}
+
+    	protected virtual void LoadAttrs()
+    	{
+    		enable_external_sound = false;
+    		Attribute[] customAttributes = Attribute.GetCustomAttributes(GetType());
+    		foreach (Attribute attribute in customAttributes)
+    		{
+    			if (attribute.GetType() == typeof(BoardInfoAttribute))
+    			{
+    				BoardInfoAttribute boardInfoAttribute = (BoardInfoAttribute)attribute;
+    				Name = boardInfoAttribute.Name;
+    				MapperNumber = boardInfoAttribute.Mapper;
+    				PRG_RAM_08KB_DEFAULT_BLK_Count = boardInfoAttribute.DefaultPRG_RAM_8KB_BanksCount;
+    				CHR_ROM_01KB_DEFAULT_BLK_Count = boardInfoAttribute.DefaultCHR_RAM_1KB_BanksCount;
+    				enabled_ppuA12ToggleTimer = boardInfoAttribute.Enabled_ppuA12ToggleTimer;
+    				ppuA12TogglesOnRaisingEdge = boardInfoAttribute.PPUA12TogglesOnRaisingEdge;
+    			}
+    			else if (attribute.GetType() == typeof(WithExternalSoundAttribute))
+    			{
+    				enable_external_sound = true;
+    			}
+    			else if (attribute.GetType() == typeof(HassIssuesAttribute))
+    			{
+    				HasIssues = true;
+    			}
+    		}
+    	}
+
+    	protected SRAMBankInfo[] GetPRGRAM8KCountFromDB()
+    	{
+    		Tracer.WriteLine("Retrieving PRG RAM information from database ....");
+    		List<SRAMBankInfo> list = new List<SRAMBankInfo>();
+    		if (IsGameFoundOnDB)
+    		{
+    			if (GameCartInfo.WRAMBanks.Count > 0)
+    			{
+    				foreach (SRAMBankInfo wRAMBank in GameCartInfo.WRAMBanks)
+    				{
+    					list.Add(wRAMBank);
+    				}
+    			}
+    			else
+    			{
+    				Tracer.WriteLine("This game has no PRG RAM !");
+    				Tracer.WriteWarning("> Adding 8K x " + PRG_RAM_08KB_DEFAULT_BLK_Count + " PRG RAM BANKS to avoid exceptions.");
+    				SRAMBankInfo item = new SRAMBankInfo(0, PRG_RAM_08KB_DEFAULT_BLK_Count * 8 + "k", BATTERY: true);
+    				list.Add(item);
+    			}
+    		}
+    		else
+    		{
+    			Tracer.WriteWarning("Could't find this game in database .... Adding 8K x " + PRG_RAM_08KB_DEFAULT_BLK_Count + " PRG RAM BANKS to avoid exceptions.");
+    			SRAMBankInfo item2 = new SRAMBankInfo(0, PRG_RAM_08KB_DEFAULT_BLK_Count * 8 + "k", BATTERY: true);
+    			list.Add(item2);
+    		}
+    		return list.ToArray();
+    	}
+
+    	protected int GetCHRRAM1KCountFromDB()
+    	{
+    		int num = 0;
+    		Tracer.WriteLine("Retrieving CHR RAM information from database ....");
+    		if (IsGameFoundOnDB)
+    		{
+    			bool flag = false;
+    			if (GameCartInfo.VRAM_sizes != null)
+    			{
+    				Tracer.WriteLine("Using database to initialize CHR RAM .....");
+    				foreach (string vRAM_size in GameCartInfo.VRAM_sizes)
+    				{
+    					int result = 0;
+    					if (int.TryParse(vRAM_size.Replace("k", ""), out result))
+    					{
+    						Tracer.WriteLine(">CHR RAM CHIP SIZE " + vRAM_size + " KB added");
+    						num += result;
+    						if (num > 0)
+    						{
+    							flag = true;
+    						}
+    					}
+    				}
+    			}
+    			if (!flag)
+    			{
+    				Tracer.WriteLine("Game not found in database to initialize CHR RAM; CHR RAM size set to " + CHR_ROM_01KB_DEFAULT_BLK_Count + " KB");
+    				num = CHR_ROM_01KB_DEFAULT_BLK_Count;
+    			}
+    		}
+    		else
+    		{
+    			Tracer.WriteWarning("Game not found in database to initialize CHR RAM; CHR RAM size set to " + CHR_ROM_01KB_DEFAULT_BLK_Count + " KB");
+    			num = CHR_ROM_01KB_DEFAULT_BLK_Count;
+    		}
+    		return num;
+    	}
+
+    	internal virtual void WriteEX(ref ushort addr, ref byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
+    			{
+    				PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
+    			}
+    		}
+    	}
+
+    	internal virtual void WriteSRM(ref ushort addr, ref byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
+    			{
+    				PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
+    			}
+    		}
+    	}
+
+    	internal virtual void WritePRG(ref ushort addr, ref byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX] && PRG_RAM_WRITABLE[PRG_TMP_INDX])
+    			{
+    				PRG_RAM[PRG_TMP_INDX][addr & 0xFFF] = val;
+    			}
+    		}
+    	}
+
+    	internal virtual void ReadEX(ref ushort addr, out byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX])
+    			{
+    				val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
+    			}
+    			else
+    			{
+    				val = 0;
+    			}
+    		}
+    		else
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
+    			val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
+    		}
+    	}
+
+    	internal virtual void ReadSRM(ref ushort addr, out byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX])
+    			{
+    				val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
+    			}
+    			else
+    			{
+    				val = 0;
+    			}
+    		}
+    		else
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
+    			val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
+    		}
+    	}
+
+    	internal virtual void ReadPRG(ref ushort addr, out byte val)
+    	{
+    		PRG_TMP_AREA = (addr >> 12) & 0xF;
+    		if (PRG_AREA_BLK_RAM[PRG_TMP_AREA])
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_RAM_04KB_Mask;
+    			if (PRG_RAM_ENABLED[PRG_TMP_INDX])
+    			{
+    				val = PRG_RAM[PRG_TMP_INDX][addr & 0xFFF];
+    			}
+    			else
+    			{
+    				val = 0;
+    			}
+    		}
+    		else
+    		{
+    			PRG_TMP_INDX = PRG_AREA_BLK_INDEX[PRG_TMP_AREA] & PRG_ROM_04KB_Mask;
+    			val = PRG_ROM[PRG_TMP_INDX][addr & 0xFFF];
+    		}
+    		if (!IsGameGenieActive)
+    		{
+    			return;
+    		}
+    		GameGenieCode[] gameGenieCodes = GameGenieCodes;
+    		for (int i = 0; i < gameGenieCodes.Length; i++)
+    		{
+    			GameGenieCode gameGenieCode = gameGenieCodes[i];
+    			if (!gameGenieCode.Enabled || gameGenieCode.Address != addr)
+    			{
+    				continue;
+    			}
+    			if (gameGenieCode.IsCompare)
+    			{
+    				if (gameGenieCode.Compare == val)
+    				{
+    					val = gameGenieCode.Value;
+    				}
+    			}
+    			else
+    			{
+    				val = gameGenieCode.Value;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal virtual void WriteCHR(ref ushort addr, ref byte val)
+    	{
+    		CHR_TMP_AREA = (addr >> 10) & 7;
+    		if (CHR_AREA_BLK_RAM[CHR_TMP_AREA])
+    		{
+    			CHR_TMP_INDX = CHR_AREA_BLK_INDEX[CHR_TMP_AREA] & CHR_RAM_01KB_Mask;
+    			if (CHR_RAM_ENABLED[CHR_TMP_INDX] && CHR_RAM_WRITABLE[CHR_TMP_INDX])
+    			{
+    				CHR_RAM[CHR_TMP_INDX][addr & 0x3FF] = val;
+    			}
+    		}
+    	}
+
+    	internal virtual void ReadCHR(ref ushort addr, out byte val)
+    	{
+    		CHR_TMP_AREA = (addr >> 10) & 7;
+    		CHR_TMP_INDX = CHR_AREA_BLK_INDEX[CHR_TMP_AREA];
+    		if (CHR_AREA_BLK_RAM[CHR_TMP_AREA])
+    		{
+    			CHR_TMP_INDX &= CHR_RAM_01KB_Mask;
+    			if (CHR_RAM_ENABLED[CHR_TMP_INDX])
+    			{
+    				val = CHR_RAM[CHR_TMP_INDX][addr & 0x3FF];
+    			}
+    			else
+    			{
+    				val = 0;
+    			}
+    		}
+    		else
+    		{
+    			CHR_TMP_INDX &= CHR_ROM_01KB_Mask;
+    			val = CHR_ROM[CHR_TMP_INDX][addr & 0x3FF];
+    		}
+    	}
+
+    	internal virtual void WriteNMT(ref ushort addr, ref byte val)
+    	{
+    		NMT_TMP_AREA = (addr >> 10) & 3;
+    		NMT_TMP_INDX = NMT_AREA_BLK_INDEX[NMT_TMP_AREA];
+    		NMT_RAM[NMT_TMP_INDX][addr & 0x3FF] = val;
+    	}
+
+    	internal virtual void ReadNMT(ref ushort addr, out byte val)
+    	{
+    		NMT_TMP_AREA = (addr >> 10) & 3;
+    		NMT_TMP_INDX = NMT_AREA_BLK_INDEX[NMT_TMP_AREA];
+    		val = NMT_RAM[NMT_TMP_INDX][addr & 0x3FF];
+    	}
+
+    	protected void Switch04KPRG(int index, PRGArea area)
+    	{
+    		PRG_AREA_BLK_INDEX[(uint)area] = index;
+    	}
+
+    	protected void Switch08KPRG(int index, PRGArea area)
+    	{
+    		index *= 2;
+    		PRG_AREA_BLK_INDEX[(uint)area] = index;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
+    	}
+
+    	protected void Switch16KPRG(int index, PRGArea area)
+    	{
+    		index *= 4;
+    		PRG_AREA_BLK_INDEX[(uint)area] = index;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
+    	}
+
+    	protected void Switch32KPRG(int index, PRGArea area)
+    	{
+    		index *= 8;
+    		PRG_AREA_BLK_INDEX[(uint)area] = index;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 4)] = index + 4;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 5)] = index + 5;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 6)] = index + 6;
+    		PRG_AREA_BLK_INDEX[(uint)(area + 7)] = index + 7;
+    	}
+
+    	protected void Toggle04KPRG_RAM(bool ram, PRGArea area)
+    	{
+    		PRG_AREA_BLK_RAM[(uint)area] = ram;
+    	}
+
+    	protected void Toggle08KPRG_RAM(bool ram, PRGArea area)
+    	{
+    		PRG_AREA_BLK_RAM[(uint)area] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
+    	}
+
+    	protected void Toggle16KPRG_RAM(bool ram, PRGArea area)
+    	{
+    		PRG_AREA_BLK_RAM[(uint)area] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 2)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 3)] = ram;
+    	}
+
+    	protected void Toggle32KPRG_RAM(bool ram, PRGArea area)
+    	{
+    		PRG_AREA_BLK_RAM[(uint)area] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 1)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 2)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 3)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 4)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 5)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 6)] = ram;
+    		PRG_AREA_BLK_RAM[(uint)(area + 7)] = ram;
+    	}
+
+    	protected void TogglePRGRAMEnable(bool enable)
+    	{
+    		for (int i = 0; i < PRG_RAM_ENABLED.Length; i++)
+    		{
+    			PRG_RAM_ENABLED[i] = enable;
+    		}
+    	}
+
+    	protected void TogglePRGRAMWritableEnable(bool enable)
+    	{
+    		for (int i = 0; i < PRG_RAM_WRITABLE.Length; i++)
+    		{
+    			PRG_RAM_WRITABLE[i] = enable;
+    		}
+    	}
+
+    	protected void Toggle04KPRG_RAM_Enabled(bool enable, int index)
+    	{
+    		PRG_RAM_ENABLED[index] = enable;
+    	}
+
+    	protected void Toggle04KPRG_RAM_Writable(bool enable, int index)
+    	{
+    		PRG_RAM_WRITABLE[index] = enable;
+    	}
+
+    	protected void Toggle04KPRG_RAM_Battery(bool enable, int index)
+    	{
+    		PRG_RAM_BATTERY[index] = enable;
+    	}
+
+    	protected void Switch01KCHR(int index, CHRArea area)
+    	{
+    		CHR_AREA_BLK_INDEX[(uint)area] = index;
+    	}
+
+    	protected void Switch02KCHR(int index, CHRArea area)
+    	{
+    		index *= 2;
+    		CHR_AREA_BLK_INDEX[(uint)area] = index;
+    		CHR_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
+    	}
+
+    	protected void Switch04KCHR(int index, CHRArea area)
+    	{
+    		index *= 4;
+    		CHR_AREA_BLK_INDEX[(uint)area] = index;
+    		CHR_AREA_BLK_INDEX[(uint)(area + 1)] = index + 1;
+    		CHR_AREA_BLK_INDEX[(uint)(area + 2)] = index + 2;
+    		CHR_AREA_BLK_INDEX[(uint)(area + 3)] = index + 3;
+    	}
+
+    	protected void Switch08KCHR(int index)
+    	{
+    		index *= 8;
+    		CHR_AREA_BLK_INDEX[0] = index;
+    		CHR_AREA_BLK_INDEX[1] = index + 1;
+    		CHR_AREA_BLK_INDEX[2] = index + 2;
+    		CHR_AREA_BLK_INDEX[3] = index + 3;
+    		CHR_AREA_BLK_INDEX[4] = index + 4;
+    		CHR_AREA_BLK_INDEX[5] = index + 5;
+    		CHR_AREA_BLK_INDEX[6] = index + 6;
+    		CHR_AREA_BLK_INDEX[7] = index + 7;
+    	}
+
+    	protected void Toggle01KCHR_RAM(bool ram, CHRArea area)
+    	{
+    		CHR_AREA_BLK_RAM[(uint)area] = ram;
+    	}
+
+    	protected void Toggle02KCHR_RAM(bool ram, CHRArea area)
+    	{
+    		CHR_AREA_BLK_RAM[(uint)area] = ram;
+    		CHR_AREA_BLK_RAM[(uint)(area + 1)] = ram;
+    	}
+
+    	protected void Toggle04KCHR_RAM(bool ram, CHRArea area)
+    	{
+    		CHR_AREA_BLK_RAM[(uint)area] = ram;
+    		CHR_AREA_BLK_RAM[(uint)(area + 1)] = ram;
+    		CHR_AREA_BLK_RAM[(uint)(area + 2)] = ram;
+    		CHR_AREA_BLK_RAM[(uint)(area + 3)] = ram;
+    	}
+
+    	protected void Toggle08KCHR_RAM(bool ram)
+    	{
+    		CHR_AREA_BLK_RAM[0] = ram;
+    		CHR_AREA_BLK_RAM[1] = ram;
+    		CHR_AREA_BLK_RAM[2] = ram;
+    		CHR_AREA_BLK_RAM[3] = ram;
+    		CHR_AREA_BLK_RAM[4] = ram;
+    		CHR_AREA_BLK_RAM[5] = ram;
+    		CHR_AREA_BLK_RAM[6] = ram;
+    		CHR_AREA_BLK_RAM[7] = ram;
+    	}
+
+    	protected void Toggle01KCHR_RAM_Enabled(bool enable, int index)
+    	{
+    		CHR_RAM_ENABLED[index] = enable;
+    	}
+
+    	protected void Toggle01KCHR_RAM_Writable(bool enable, int index)
+    	{
+    		CHR_RAM_WRITABLE[index] = enable;
+    	}
+
+    	protected void ToggleCHRRAMWritableEnable(bool enable)
+    	{
+    		for (int i = 0; i < CHR_RAM_WRITABLE.Length; i++)
+    		{
+    			CHR_RAM_WRITABLE[i] = enable;
+    		}
+    	}
+
+    	protected void Toggle01KCHR_RAM_Battery(bool enable, int index)
+    	{
+    		CHR_RAM_BATTERY[index] = enable;
+    	}
+
+    	protected void Switch01KNMT(int index, byte area)
+    	{
+    		NMT_AREA_BLK_INDEX[area] = index;
+    	}
+
+    	protected void Switch01KNMT(byte mirroring)
+    	{
+    		NMT_AREA_BLK_INDEX[0] = mirroring & 3;
+    		NMT_AREA_BLK_INDEX[1] = (mirroring >> 2) & 3;
+    		NMT_AREA_BLK_INDEX[2] = (mirroring >> 4) & 3;
+    		NMT_AREA_BLK_INDEX[3] = (mirroring >> 6) & 3;
+    	}
+
+    	protected void Switch01KNMTFromMirroring(Mirroring mirroring)
+    	{
+    		NMT_AREA_BLK_INDEX[0] = (int)(mirroring & (Mirroring)3);
+    		NMT_AREA_BLK_INDEX[1] = ((int)mirroring >> 2) & 3;
+    		NMT_AREA_BLK_INDEX[2] = ((int)mirroring >> 4) & 3;
+    		NMT_AREA_BLK_INDEX[3] = ((int)mirroring >> 6) & 3;
+    	}
+
+    	internal virtual void OnPPUAddressUpdate(ref ushort address)
+    	{
+    		if (!enabled_ppuA12ToggleTimer)
+    		{
+    			return;
+    		}
+    		old_vram_address = new_vram_address;
+    		new_vram_address = address & 0x1000;
+    		if (ppuA12TogglesOnRaisingEdge)
+    		{
+    			if (old_vram_address < new_vram_address)
+    			{
+    				if (ppu_cycles_timer > 8)
+    				{
+    					OnPPUA12RaisingEdge();
+    				}
+    				ppu_cycles_timer = 0;
+    			}
+    		}
+    		else if (old_vram_address > new_vram_address)
+    		{
+    			if (ppu_cycles_timer > 8)
+    			{
+    				OnPPUA12RaisingEdge();
+    			}
+    			ppu_cycles_timer = 0;
+    		}
+    	}
+
+    	internal virtual void OnCPUClock()
+    	{
+    	}
+
+    	internal virtual void OnPPUClock()
+    	{
+    		if (enabled_ppuA12ToggleTimer)
+    		{
+    			ppu_cycles_timer++;
+    		}
+    	}
+
+    	internal virtual void OnPPUA12RaisingEdge()
+    	{
+    	}
+
+    	internal virtual void OnPPUScanlineTick()
+    	{
+    	}
+
+    	internal virtual void OnAPUClockDuration()
+    	{
+    	}
+
+    	internal virtual void OnAPUClockEnvelope()
+    	{
+    	}
+
+    	internal virtual void OnAPUClockSingle()
+    	{
+    	}
+
+    	internal virtual void OnAPUClock()
+    	{
+    	}
+
+    	internal virtual double APUGetSample()
+    	{
+    		return 0.0;
+    	}
+
+    	internal virtual void APUApplyChannelsSettings()
+    	{
+    	}
+
+    	internal void SetupGameGenie(bool IsGameGenieActive, GameGenieCode[] GameGenieCodes)
+    	{
+    		this.IsGameGenieActive = IsGameGenieActive;
+    		this.GameGenieCodes = GameGenieCodes;
+    	}
+
+    	internal virtual void WriteStateData(ref BinaryWriter bin)
+    	{
+    		for (int i = 0; i < PRG_RAM.Length; i++)
+    		{
+    			bin.Write(PRG_RAM[i]);
+    		}
+    		for (int j = 0; j < PRG_RAM_ENABLED.Length; j++)
+    		{
+    			bin.Write(PRG_RAM_ENABLED[j]);
+    		}
+    		for (int k = 0; k < PRG_RAM_WRITABLE.Length; k++)
+    		{
+    			bin.Write(PRG_RAM_WRITABLE[k]);
+    		}
+    		for (int l = 0; l < PRG_RAM_BATTERY.Length; l++)
+    		{
+    			bin.Write(PRG_RAM_BATTERY[l]);
+    		}
+    		for (int m = 0; m < PRG_AREA_BLK_RAM.Length; m++)
+    		{
+    			bin.Write(PRG_AREA_BLK_RAM[m]);
+    		}
+    		for (int n = 0; n < PRG_AREA_BLK_INDEX.Length; n++)
+    		{
+    			bin.Write(PRG_AREA_BLK_INDEX[n]);
+    		}
+    		bin.Write(PRG_TMP_INDX);
+    		bin.Write(PRG_TMP_AREA);
+    		for (int num = 0; num < CHR_RAM.Length; num++)
+    		{
+    			bin.Write(CHR_RAM[num]);
+    		}
+    		for (int num2 = 0; num2 < CHR_RAM_ENABLED.Length; num2++)
+    		{
+    			bin.Write(CHR_RAM_ENABLED[num2]);
+    		}
+    		for (int num3 = 0; num3 < CHR_RAM_WRITABLE.Length; num3++)
+    		{
+    			bin.Write(CHR_RAM_WRITABLE[num3]);
+    		}
+    		for (int num4 = 0; num4 < CHR_RAM_BATTERY.Length; num4++)
+    		{
+    			bin.Write(CHR_RAM_BATTERY[num4]);
+    		}
+    		for (int num5 = 0; num5 < CHR_AREA_BLK_RAM.Length; num5++)
+    		{
+    			bin.Write(CHR_AREA_BLK_RAM[num5]);
+    		}
+    		for (int num6 = 0; num6 < CHR_AREA_BLK_INDEX.Length; num6++)
+    		{
+    			bin.Write(CHR_AREA_BLK_INDEX[num6]);
+    		}
+    		bin.Write(CHR_TMP_INDX);
+    		bin.Write(CHR_TMP_AREA);
+    		for (int num7 = 0; num7 < NMT_RAM.Length; num7++)
+    		{
+    			bin.Write(NMT_RAM[num7]);
+    		}
+    		for (int num8 = 0; num8 < NMT_AREA_BLK_INDEX.Length; num8++)
+    		{
+    			bin.Write(NMT_AREA_BLK_INDEX[num8]);
+    		}
+    		bin.Write(NMT_TMP_INDX);
+    		bin.Write(NMT_TMP_AREA);
+    	}
+
+    	internal virtual void ReadStateData(ref BinaryReader bin)
+    	{
+    		for (int i = 0; i < PRG_RAM.Length; i++)
+    		{
+    			bin.Read(PRG_RAM[i], 0, PRG_RAM[i].Length);
+    		}
+    		for (int j = 0; j < PRG_RAM_ENABLED.Length; j++)
+    		{
+    			PRG_RAM_ENABLED[j] = bin.ReadBoolean();
+    		}
+    		for (int k = 0; k < PRG_RAM_WRITABLE.Length; k++)
+    		{
+    			PRG_RAM_WRITABLE[k] = bin.ReadBoolean();
+    		}
+    		for (int l = 0; l < PRG_RAM_BATTERY.Length; l++)
+    		{
+    			PRG_RAM_BATTERY[l] = bin.ReadBoolean();
+    		}
+    		for (int m = 0; m < PRG_AREA_BLK_RAM.Length; m++)
+    		{
+    			PRG_AREA_BLK_RAM[m] = bin.ReadBoolean();
+    		}
+    		for (int n = 0; n < PRG_AREA_BLK_INDEX.Length; n++)
+    		{
+    			PRG_AREA_BLK_INDEX[n] = bin.ReadInt32();
+    		}
+    		PRG_TMP_INDX = bin.ReadInt32();
+    		PRG_TMP_AREA = bin.ReadInt32();
+    		for (int num = 0; num < CHR_RAM.Length; num++)
+    		{
+    			bin.Read(CHR_RAM[num], 0, CHR_RAM[num].Length);
+    		}
+    		for (int num2 = 0; num2 < CHR_RAM_ENABLED.Length; num2++)
+    		{
+    			CHR_RAM_ENABLED[num2] = bin.ReadBoolean();
+    		}
+    		for (int num3 = 0; num3 < CHR_RAM_WRITABLE.Length; num3++)
+    		{
+    			CHR_RAM_WRITABLE[num3] = bin.ReadBoolean();
+    		}
+    		for (int num4 = 0; num4 < CHR_RAM_BATTERY.Length; num4++)
+    		{
+    			CHR_RAM_BATTERY[num4] = bin.ReadBoolean();
+    		}
+    		for (int num5 = 0; num5 < CHR_AREA_BLK_RAM.Length; num5++)
+    		{
+    			CHR_AREA_BLK_RAM[num5] = bin.ReadBoolean();
+    		}
+    		for (int num6 = 0; num6 < CHR_AREA_BLK_INDEX.Length; num6++)
+    		{
+    			CHR_AREA_BLK_INDEX[num6] = bin.ReadInt32();
+    		}
+    		CHR_TMP_INDX = bin.ReadInt32();
+    		CHR_TMP_AREA = bin.ReadInt32();
+    		for (int num7 = 0; num7 < NMT_RAM.Length; num7++)
+    		{
+    			bin.Read(NMT_RAM[num7], 0, NMT_RAM[num7].Length);
+    		}
+    		for (int num8 = 0; num8 < NMT_AREA_BLK_INDEX.Length; num8++)
+    		{
+    			NMT_AREA_BLK_INDEX[num8] = bin.ReadInt32();
+    		}
+    		NMT_TMP_INDX = bin.ReadInt32();
+    		NMT_TMP_AREA = bin.ReadInt32();
+    	}
+
+    	internal void SaveSRAM(Stream stream)
+    	{
+    		for (int i = 0; i < PRG_RAM_04KB_Count; i++)
+    		{
+    			if (PRG_RAM_BATTERY[i])
+    			{
+    				stream.Write(PRG_RAM[i], 0, 4096);
+    			}
+    		}
+    	}
+
+    	internal byte[] GetSRAMBuffer()
+    	{
+    		List<byte> list = new List<byte>();
+    		for (int i = 0; i < PRG_RAM_04KB_Count; i++)
+    		{
+    			if (PRG_RAM_BATTERY[i])
+    			{
+    				list.AddRange(PRG_RAM[i]);
+    			}
+    		}
+    		return list.ToArray();
+    	}
+
+    	internal void LoadSRAM(Stream stream)
+    	{
+    		for (int i = 0; i < PRG_RAM_04KB_Count; i++)
+    		{
+    			if (PRG_RAM_BATTERY[i])
+    			{
+    				stream.Read(PRG_RAM[i], 0, 4096);
+    			}
+    		}
+    	}
+
+    	internal void LoadSRAM(byte[] buffer)
+    	{
+    		int num = 0;
+    		for (int i = 0; i < PRG_RAM_04KB_Count; i++)
+    		{
+    			if (PRG_RAM_BATTERY[i])
+    			{
+    				for (int j = 0; j < 4096; j++)
+    				{
+    					PRG_RAM[i][j] = buffer[j + num];
+    				}
+    				num += 4096;
+    			}
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoAttribute.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoAttribute.cs
new file mode 100644
index 00000000..ae76a0fd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoAttribute.cs
@@ -0,0 +1,57 @@
+using System;
+
+namespace MyNes.Core
+{
+    internal class BoardInfoAttribute : Attribute
+    {
+    	public string Name { get; private set; }
+
+    	public int Mapper { get; private set; }
+
+    	public int DefaultPRG_RAM_8KB_BanksCount { get; private set; }
+
+    	public int DefaultCHR_RAM_1KB_BanksCount { get; private set; }
+
+    	public bool Enabled_ppuA12ToggleTimer { get; private set; }
+
+    	public bool PPUA12TogglesOnRaisingEdge { get; private set; }
+
+    	public BoardInfoAttribute(string boardName, int inesMapperNumber)
+    	{
+    		Name = boardName;
+    		Mapper = inesMapperNumber;
+    		DefaultPRG_RAM_8KB_BanksCount = 1;
+    		DefaultCHR_RAM_1KB_BanksCount = 8;
+    		Enabled_ppuA12ToggleTimer = (PPUA12TogglesOnRaisingEdge = false);
+    	}
+
+    	public BoardInfoAttribute(string boardName, int inesMapperNumber, int defaultPRG_RAM_8KB_BanksCount, int defaultCHR_RAM_1KB_BanksCount)
+    	{
+    		Name = boardName;
+    		Mapper = inesMapperNumber;
+    		DefaultPRG_RAM_8KB_BanksCount = defaultPRG_RAM_8KB_BanksCount;
+    		DefaultCHR_RAM_1KB_BanksCount = defaultCHR_RAM_1KB_BanksCount;
+    		Enabled_ppuA12ToggleTimer = (PPUA12TogglesOnRaisingEdge = false);
+    	}
+
+    	public BoardInfoAttribute(string boardName, int inesMapperNumber, bool Enabled_ppuA12ToggleTimer, bool PPUA12TogglesOnRaisingEdge)
+    	{
+    		Name = boardName;
+    		Mapper = inesMapperNumber;
+    		DefaultPRG_RAM_8KB_BanksCount = 1;
+    		DefaultCHR_RAM_1KB_BanksCount = 8;
+    		this.Enabled_ppuA12ToggleTimer = Enabled_ppuA12ToggleTimer;
+    		this.PPUA12TogglesOnRaisingEdge = PPUA12TogglesOnRaisingEdge;
+    	}
+
+    	public BoardInfoAttribute(string boardName, int inesMapperNumber, int defaultPRG_RAM_8KB_BanksCount, int defaultCHR_RAM_1KB_BanksCount, bool Enabled_ppuA12ToggleTimer, bool PPUA12TogglesOnRaisingEdge)
+    	{
+    		Name = boardName;
+    		Mapper = inesMapperNumber;
+    		DefaultPRG_RAM_8KB_BanksCount = defaultPRG_RAM_8KB_BanksCount;
+    		DefaultCHR_RAM_1KB_BanksCount = defaultCHR_RAM_1KB_BanksCount;
+    		this.Enabled_ppuA12ToggleTimer = Enabled_ppuA12ToggleTimer;
+    		this.PPUA12TogglesOnRaisingEdge = PPUA12TogglesOnRaisingEdge;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoObject.cs b/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoObject.cs
new file mode 100644
index 00000000..77bbc670
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/BoardInfoObject.cs
@@ -0,0 +1,15 @@
+namespace MyNes.Core
+{
+    public class BoardInfoObject
+    {
+    	public string Name { get; internal set; }
+
+    	public int MapperNumber { get; internal set; }
+
+    	public bool IsSupported { get; internal set; }
+
+    	public string Issues { get; internal set; }
+
+    	public bool HasIssues { get; internal set; }
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/CHRArea.cs b/OtherCore/MyNes.Standard2/MyNes.Core/CHRArea.cs
new file mode 100644
index 00000000..c314e1b6
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/CHRArea.cs
@@ -0,0 +1,14 @@
+namespace MyNes.Core
+{
+    internal enum CHRArea : byte
+    {
+    	Area0000,
+    	Area0400,
+    	Area0800,
+    	Area0C00,
+    	Area1000,
+    	Area1400,
+    	Area1800,
+    	Area1C00
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Adler32.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Adler32.cs
new file mode 100644
index 00000000..2830aba8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Adler32.cs
@@ -0,0 +1,72 @@
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class Adler32
+    {
+    	private const int BASE = 65521;
+
+    	private const int NMAX = 5552;
+
+    	internal long adler32(long adler, byte[] buf, int index, int len)
+    	{
+    		if (buf == null)
+    		{
+    			return 1L;
+    		}
+    		long num = adler & 0xFFFF;
+    		long num2 = (adler >> 16) & 0xFFFF;
+    		while (len > 0)
+    		{
+    			int num3 = ((len < 5552) ? len : 5552);
+    			len -= num3;
+    			while (num3 >= 16)
+    			{
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num += buf[index++] & 0xFF;
+    				num2 += num;
+    				num3 -= 16;
+    			}
+    			if (num3 != 0)
+    			{
+    				do
+    				{
+    					num += buf[index++] & 0xFF;
+    					num2 += num;
+    				}
+    				while (--num3 != 0);
+    			}
+    			num %= 65521;
+    			num2 %= 65521;
+    		}
+    		return (num2 << 16) | num;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Deflate.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Deflate.cs
new file mode 100644
index 00000000..04b24d8e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Deflate.cs
@@ -0,0 +1,1412 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public sealed class Deflate
+    {
+    	internal class Config
+    	{
+    		internal int good_length;
+
+    		internal int max_lazy;
+
+    		internal int nice_length;
+
+    		internal int max_chain;
+
+    		internal int func;
+
+    		internal Config(int good_length, int max_lazy, int nice_length, int max_chain, int func)
+    		{
+    			this.good_length = good_length;
+    			this.max_lazy = max_lazy;
+    			this.nice_length = nice_length;
+    			this.max_chain = max_chain;
+    			this.func = func;
+    		}
+    	}
+
+    	private const int MAX_MEM_LEVEL = 9;
+
+    	private const int Z_DEFAULT_COMPRESSION = -1;
+
+    	private const int MAX_WBITS = 15;
+
+    	private const int DEF_MEM_LEVEL = 8;
+
+    	private const int STORED = 0;
+
+    	private const int FAST = 1;
+
+    	private const int SLOW = 2;
+
+    	private static Config[] config_table;
+
+    	private static readonly string[] z_errmsg;
+
+    	private const int NeedMore = 0;
+
+    	private const int BlockDone = 1;
+
+    	private const int FinishStarted = 2;
+
+    	private const int FinishDone = 3;
+
+    	private const int PRESET_DICT = 32;
+
+    	private const int Z_FILTERED = 1;
+
+    	private const int Z_HUFFMAN_ONLY = 2;
+
+    	private const int Z_DEFAULT_STRATEGY = 0;
+
+    	private const int Z_NO_FLUSH = 0;
+
+    	private const int Z_PARTIAL_FLUSH = 1;
+
+    	private const int Z_SYNC_FLUSH = 2;
+
+    	private const int Z_FULL_FLUSH = 3;
+
+    	private const int Z_FINISH = 4;
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	private const int INIT_STATE = 42;
+
+    	private const int BUSY_STATE = 113;
+
+    	private const int FINISH_STATE = 666;
+
+    	private const int Z_DEFLATED = 8;
+
+    	private const int STORED_BLOCK = 0;
+
+    	private const int STATIC_TREES = 1;
+
+    	private const int DYN_TREES = 2;
+
+    	private const int Z_BINARY = 0;
+
+    	private const int Z_ASCII = 1;
+
+    	private const int Z_UNKNOWN = 2;
+
+    	private const int Buf_size = 16;
+
+    	private const int REP_3_6 = 16;
+
+    	private const int REPZ_3_10 = 17;
+
+    	private const int REPZ_11_138 = 18;
+
+    	private const int MIN_MATCH = 3;
+
+    	private const int MAX_MATCH = 258;
+
+    	private static readonly int MIN_LOOKAHEAD;
+
+    	private const int MAX_BITS = 15;
+
+    	private const int D_CODES = 30;
+
+    	private const int BL_CODES = 19;
+
+    	private const int LENGTH_CODES = 29;
+
+    	private const int LITERALS = 256;
+
+    	private static readonly int L_CODES;
+
+    	private static readonly int HEAP_SIZE;
+
+    	private const int END_BLOCK = 256;
+
+    	internal ZStream strm;
+
+    	internal int status;
+
+    	internal byte[] pending_buf;
+
+    	internal int pending_buf_size;
+
+    	internal int pending_out;
+
+    	internal int pending;
+
+    	internal int noheader;
+
+    	internal byte data_type;
+
+    	internal byte method;
+
+    	internal int last_flush;
+
+    	internal int w_size;
+
+    	internal int w_bits;
+
+    	internal int w_mask;
+
+    	internal byte[] window;
+
+    	internal int window_size;
+
+    	internal short[] prev;
+
+    	internal short[] head;
+
+    	internal int ins_h;
+
+    	internal int hash_size;
+
+    	internal int hash_bits;
+
+    	internal int hash_mask;
+
+    	internal int hash_shift;
+
+    	internal int block_start;
+
+    	internal int match_length;
+
+    	internal int prev_match;
+
+    	internal int match_available;
+
+    	internal int strstart;
+
+    	internal int match_start;
+
+    	internal int lookahead;
+
+    	internal int prev_length;
+
+    	internal int max_chain_length;
+
+    	internal int max_lazy_match;
+
+    	internal int level;
+
+    	internal int strategy;
+
+    	internal int good_match;
+
+    	internal int nice_match;
+
+    	internal short[] dyn_ltree;
+
+    	internal short[] dyn_dtree;
+
+    	internal short[] bl_tree;
+
+    	internal Tree l_desc = new Tree();
+
+    	internal Tree d_desc = new Tree();
+
+    	internal Tree bl_desc = new Tree();
+
+    	internal short[] bl_count = new short[16];
+
+    	internal int[] heap = new int[2 * L_CODES + 1];
+
+    	internal int heap_len;
+
+    	internal int heap_max;
+
+    	internal byte[] depth = new byte[2 * L_CODES + 1];
+
+    	internal int l_buf;
+
+    	internal int lit_bufsize;
+
+    	internal int last_lit;
+
+    	internal int d_buf;
+
+    	internal int opt_len;
+
+    	internal int static_len;
+
+    	internal int matches;
+
+    	internal int last_eob_len;
+
+    	internal short bi_buf;
+
+    	internal int bi_valid;
+
+    	internal Deflate()
+    	{
+    		dyn_ltree = new short[HEAP_SIZE * 2];
+    		dyn_dtree = new short[122];
+    		bl_tree = new short[78];
+    	}
+
+    	internal void lm_init()
+    	{
+    		window_size = 2 * w_size;
+    		head[hash_size - 1] = 0;
+    		for (int i = 0; i < hash_size - 1; i++)
+    		{
+    			head[i] = 0;
+    		}
+    		max_lazy_match = config_table[level].max_lazy;
+    		good_match = config_table[level].good_length;
+    		nice_match = config_table[level].nice_length;
+    		max_chain_length = config_table[level].max_chain;
+    		strstart = 0;
+    		block_start = 0;
+    		lookahead = 0;
+    		match_length = (prev_length = 2);
+    		match_available = 0;
+    		ins_h = 0;
+    	}
+
+    	internal void tr_init()
+    	{
+    		l_desc.dyn_tree = dyn_ltree;
+    		l_desc.stat_desc = StaticTree.static_l_desc;
+    		d_desc.dyn_tree = dyn_dtree;
+    		d_desc.stat_desc = StaticTree.static_d_desc;
+    		bl_desc.dyn_tree = bl_tree;
+    		bl_desc.stat_desc = StaticTree.static_bl_desc;
+    		bi_buf = 0;
+    		bi_valid = 0;
+    		last_eob_len = 8;
+    		init_block();
+    	}
+
+    	internal void init_block()
+    	{
+    		for (int i = 0; i < L_CODES; i++)
+    		{
+    			dyn_ltree[i * 2] = 0;
+    		}
+    		for (int j = 0; j < 30; j++)
+    		{
+    			dyn_dtree[j * 2] = 0;
+    		}
+    		for (int k = 0; k < 19; k++)
+    		{
+    			bl_tree[k * 2] = 0;
+    		}
+    		dyn_ltree[512] = 1;
+    		opt_len = (static_len = 0);
+    		last_lit = (matches = 0);
+    	}
+
+    	internal void pqdownheap(short[] tree, int k)
+    	{
+    		int num = heap[k];
+    		for (int num2 = k << 1; num2 <= heap_len; num2 <<= 1)
+    		{
+    			if (num2 < heap_len && smaller(tree, heap[num2 + 1], heap[num2], depth))
+    			{
+    				num2++;
+    			}
+    			if (smaller(tree, num, heap[num2], depth))
+    			{
+    				break;
+    			}
+    			heap[k] = heap[num2];
+    			k = num2;
+    		}
+    		heap[k] = num;
+    	}
+
+    	internal static bool smaller(short[] tree, int n, int m, byte[] depth)
+    	{
+    		if (tree[n * 2] >= tree[m * 2])
+    		{
+    			if (tree[n * 2] == tree[m * 2])
+    			{
+    				return depth[n] <= depth[m];
+    			}
+    			return false;
+    		}
+    		return true;
+    	}
+
+    	internal void scan_tree(short[] tree, int max_code)
+    	{
+    		int num = -1;
+    		int num2 = tree[1];
+    		int num3 = 0;
+    		int num4 = 7;
+    		int num5 = 4;
+    		if (num2 == 0)
+    		{
+    			num4 = 138;
+    			num5 = 3;
+    		}
+    		tree[(max_code + 1) * 2 + 1] = (short)SupportClass.Identity(65535L);
+    		for (int i = 0; i <= max_code; i++)
+    		{
+    			int num6 = num2;
+    			num2 = tree[(i + 1) * 2 + 1];
+    			if (++num3 < num4 && num6 == num2)
+    			{
+    				continue;
+    			}
+    			if (num3 < num5)
+    			{
+    				bl_tree[num6 * 2] = (short)(bl_tree[num6 * 2] + num3);
+    			}
+    			else if (num6 != 0)
+    			{
+    				if (num6 != num)
+    				{
+    					bl_tree[num6 * 2]++;
+    				}
+    				bl_tree[32]++;
+    			}
+    			else if (num3 <= 10)
+    			{
+    				bl_tree[34]++;
+    			}
+    			else
+    			{
+    				bl_tree[36]++;
+    			}
+    			num3 = 0;
+    			num = num6;
+    			if (num2 == 0)
+    			{
+    				num4 = 138;
+    				num5 = 3;
+    			}
+    			else if (num6 == num2)
+    			{
+    				num4 = 6;
+    				num5 = 3;
+    			}
+    			else
+    			{
+    				num4 = 7;
+    				num5 = 4;
+    			}
+    		}
+    	}
+
+    	internal int build_bl_tree()
+    	{
+    		scan_tree(dyn_ltree, l_desc.max_code);
+    		scan_tree(dyn_dtree, d_desc.max_code);
+    		bl_desc.build_tree(this);
+    		int num = 18;
+    		while (num >= 3 && bl_tree[Tree.bl_order[num] * 2 + 1] == 0)
+    		{
+    			num--;
+    		}
+    		opt_len += 3 * (num + 1) + 5 + 5 + 4;
+    		return num;
+    	}
+
+    	internal void send_all_trees(int lcodes, int dcodes, int blcodes)
+    	{
+    		send_bits(lcodes - 257, 5);
+    		send_bits(dcodes - 1, 5);
+    		send_bits(blcodes - 4, 4);
+    		for (int i = 0; i < blcodes; i++)
+    		{
+    			send_bits(bl_tree[Tree.bl_order[i] * 2 + 1], 3);
+    		}
+    		send_tree(dyn_ltree, lcodes - 1);
+    		send_tree(dyn_dtree, dcodes - 1);
+    	}
+
+    	internal void send_tree(short[] tree, int max_code)
+    	{
+    		int num = -1;
+    		int num2 = tree[1];
+    		int num3 = 0;
+    		int num4 = 7;
+    		int num5 = 4;
+    		if (num2 == 0)
+    		{
+    			num4 = 138;
+    			num5 = 3;
+    		}
+    		for (int i = 0; i <= max_code; i++)
+    		{
+    			int num6 = num2;
+    			num2 = tree[(i + 1) * 2 + 1];
+    			if (++num3 < num4 && num6 == num2)
+    			{
+    				continue;
+    			}
+    			if (num3 < num5)
+    			{
+    				do
+    				{
+    					send_code(num6, bl_tree);
+    				}
+    				while (--num3 != 0);
+    			}
+    			else if (num6 != 0)
+    			{
+    				if (num6 != num)
+    				{
+    					send_code(num6, bl_tree);
+    					num3--;
+    				}
+    				send_code(16, bl_tree);
+    				send_bits(num3 - 3, 2);
+    			}
+    			else if (num3 <= 10)
+    			{
+    				send_code(17, bl_tree);
+    				send_bits(num3 - 3, 3);
+    			}
+    			else
+    			{
+    				send_code(18, bl_tree);
+    				send_bits(num3 - 11, 7);
+    			}
+    			num3 = 0;
+    			num = num6;
+    			if (num2 == 0)
+    			{
+    				num4 = 138;
+    				num5 = 3;
+    			}
+    			else if (num6 == num2)
+    			{
+    				num4 = 6;
+    				num5 = 3;
+    			}
+    			else
+    			{
+    				num4 = 7;
+    				num5 = 4;
+    			}
+    		}
+    	}
+
+    	internal void put_byte(byte[] p, int start, int len)
+    	{
+    		Array.Copy(p, start, pending_buf, pending, len);
+    		pending += len;
+    	}
+
+    	internal void put_byte(byte c)
+    	{
+    		pending_buf[pending++] = c;
+    	}
+
+    	internal void put_short(int w)
+    	{
+    		put_byte((byte)w);
+    		put_byte((byte)SupportClass.URShift(w, 8));
+    	}
+
+    	internal void putShortMSB(int b)
+    	{
+    		put_byte((byte)(b >> 8));
+    		put_byte((byte)b);
+    	}
+
+    	internal void send_code(int c, short[] tree)
+    	{
+    		send_bits(tree[c * 2] & 0xFFFF, tree[c * 2 + 1] & 0xFFFF);
+    	}
+
+    	internal void send_bits(int value_Renamed, int length)
+    	{
+    		if (bi_valid > 16 - length)
+    		{
+    			bi_buf = (short)((ushort)bi_buf | (ushort)((value_Renamed << bi_valid) & 0xFFFF));
+    			put_short(bi_buf);
+    			bi_buf = (short)SupportClass.URShift(value_Renamed, 16 - bi_valid);
+    			bi_valid += length - 16;
+    		}
+    		else
+    		{
+    			bi_buf = (short)((ushort)bi_buf | (ushort)((value_Renamed << bi_valid) & 0xFFFF));
+    			bi_valid += length;
+    		}
+    	}
+
+    	internal void _tr_align()
+    	{
+    		send_bits(2, 3);
+    		send_code(256, StaticTree.static_ltree);
+    		bi_flush();
+    		if (1 + last_eob_len + 10 - bi_valid < 9)
+    		{
+    			send_bits(2, 3);
+    			send_code(256, StaticTree.static_ltree);
+    			bi_flush();
+    		}
+    		last_eob_len = 7;
+    	}
+
+    	internal bool _tr_tally(int dist, int lc)
+    	{
+    		pending_buf[d_buf + last_lit * 2] = (byte)SupportClass.URShift(dist, 8);
+    		pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+    		pending_buf[l_buf + last_lit] = (byte)lc;
+    		last_lit++;
+    		if (dist == 0)
+    		{
+    			dyn_ltree[lc * 2]++;
+    		}
+    		else
+    		{
+    			matches++;
+    			dist--;
+    			dyn_ltree[(Tree._length_code[lc] + 256 + 1) * 2]++;
+    			dyn_dtree[Tree.d_code(dist) * 2]++;
+    		}
+    		if ((last_lit & 0x1FFF) == 0 && level > 2)
+    		{
+    			int num = last_lit * 8;
+    			int num2 = strstart - block_start;
+    			for (int i = 0; i < 30; i++)
+    			{
+    				num = (int)(num + dyn_dtree[i * 2] * (5L + (long)Tree.extra_dbits[i]));
+    			}
+    			num = SupportClass.URShift(num, 3);
+    			if (matches < last_lit / 2 && num < num2 / 2)
+    			{
+    				return true;
+    			}
+    		}
+    		return last_lit == lit_bufsize - 1;
+    	}
+
+    	internal void compress_block(short[] ltree, short[] dtree)
+    	{
+    		int num = 0;
+    		if (last_lit != 0)
+    		{
+    			do
+    			{
+    				int num2 = ((pending_buf[d_buf + num * 2] << 8) & 0xFF00) | (pending_buf[d_buf + num * 2 + 1] & 0xFF);
+    				int num3 = pending_buf[l_buf + num] & 0xFF;
+    				num++;
+    				if (num2 == 0)
+    				{
+    					send_code(num3, ltree);
+    					continue;
+    				}
+    				int num4 = Tree._length_code[num3];
+    				send_code(num4 + 256 + 1, ltree);
+    				int num5 = Tree.extra_lbits[num4];
+    				if (num5 != 0)
+    				{
+    					num3 -= Tree.base_length[num4];
+    					send_bits(num3, num5);
+    				}
+    				num2--;
+    				num4 = Tree.d_code(num2);
+    				send_code(num4, dtree);
+    				num5 = Tree.extra_dbits[num4];
+    				if (num5 != 0)
+    				{
+    					num2 -= Tree.base_dist[num4];
+    					send_bits(num2, num5);
+    				}
+    			}
+    			while (num < last_lit);
+    		}
+    		send_code(256, ltree);
+    		last_eob_len = ltree[513];
+    	}
+
+    	internal void set_data_type()
+    	{
+    		int i = 0;
+    		int num = 0;
+    		int num2 = 0;
+    		for (; i < 7; i++)
+    		{
+    			num2 += dyn_ltree[i * 2];
+    		}
+    		for (; i < 128; i++)
+    		{
+    			num += dyn_ltree[i * 2];
+    		}
+    		for (; i < 256; i++)
+    		{
+    			num2 += dyn_ltree[i * 2];
+    		}
+    		data_type = (byte)((num2 <= SupportClass.URShift(num, 2)) ? 1u : 0u);
+    	}
+
+    	internal void bi_flush()
+    	{
+    		if (bi_valid == 16)
+    		{
+    			put_short(bi_buf);
+    			bi_buf = 0;
+    			bi_valid = 0;
+    		}
+    		else if (bi_valid >= 8)
+    		{
+    			put_byte((byte)bi_buf);
+    			bi_buf = (short)SupportClass.URShift(bi_buf, 8);
+    			bi_valid -= 8;
+    		}
+    	}
+
+    	internal void bi_windup()
+    	{
+    		if (bi_valid > 8)
+    		{
+    			put_short(bi_buf);
+    		}
+    		else if (bi_valid > 0)
+    		{
+    			put_byte((byte)bi_buf);
+    		}
+    		bi_buf = 0;
+    		bi_valid = 0;
+    	}
+
+    	internal void copy_block(int buf, int len, bool header)
+    	{
+    		bi_windup();
+    		last_eob_len = 8;
+    		if (header)
+    		{
+    			put_short((short)len);
+    			put_short((short)(~len));
+    		}
+    		put_byte(window, buf, len);
+    	}
+
+    	internal void flush_block_only(bool eof)
+    	{
+    		_tr_flush_block((block_start >= 0) ? block_start : (-1), strstart - block_start, eof);
+    		block_start = strstart;
+    		strm.flush_pending();
+    	}
+
+    	internal int deflate_stored(int flush)
+    	{
+    		int num = 65535;
+    		if (num > pending_buf_size - 5)
+    		{
+    			num = pending_buf_size - 5;
+    		}
+    		while (true)
+    		{
+    			if (lookahead <= 1)
+    			{
+    				fill_window();
+    				if (lookahead == 0 && flush == 0)
+    				{
+    					return 0;
+    				}
+    				if (lookahead == 0)
+    				{
+    					break;
+    				}
+    			}
+    			strstart += lookahead;
+    			lookahead = 0;
+    			int num2 = block_start + num;
+    			if (strstart == 0 || strstart >= num2)
+    			{
+    				lookahead = strstart - num2;
+    				strstart = num2;
+    				flush_block_only(eof: false);
+    				if (strm.avail_out == 0)
+    				{
+    					return 0;
+    				}
+    			}
+    			if (strstart - block_start >= w_size - MIN_LOOKAHEAD)
+    			{
+    				flush_block_only(eof: false);
+    				if (strm.avail_out == 0)
+    				{
+    					return 0;
+    				}
+    			}
+    		}
+    		flush_block_only(flush == 4);
+    		if (strm.avail_out == 0)
+    		{
+    			if (flush != 4)
+    			{
+    				return 0;
+    			}
+    			return 2;
+    		}
+    		if (flush != 4)
+    		{
+    			return 1;
+    		}
+    		return 3;
+    	}
+
+    	internal void _tr_stored_block(int buf, int stored_len, bool eof)
+    	{
+    		send_bits(eof ? 1 : 0, 3);
+    		copy_block(buf, stored_len, header: true);
+    	}
+
+    	internal void _tr_flush_block(int buf, int stored_len, bool eof)
+    	{
+    		int num = 0;
+    		int num2;
+    		int num3;
+    		if (level > 0)
+    		{
+    			if (data_type == 2)
+    			{
+    				set_data_type();
+    			}
+    			l_desc.build_tree(this);
+    			d_desc.build_tree(this);
+    			num = build_bl_tree();
+    			num2 = SupportClass.URShift(opt_len + 3 + 7, 3);
+    			num3 = SupportClass.URShift(static_len + 3 + 7, 3);
+    			if (num3 <= num2)
+    			{
+    				num2 = num3;
+    			}
+    		}
+    		else
+    		{
+    			num2 = (num3 = stored_len + 5);
+    		}
+    		if (stored_len + 4 <= num2 && buf != -1)
+    		{
+    			_tr_stored_block(buf, stored_len, eof);
+    		}
+    		else if (num3 == num2)
+    		{
+    			send_bits(2 + (eof ? 1 : 0), 3);
+    			compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
+    		}
+    		else
+    		{
+    			send_bits(4 + (eof ? 1 : 0), 3);
+    			send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, num + 1);
+    			compress_block(dyn_ltree, dyn_dtree);
+    		}
+    		init_block();
+    		if (eof)
+    		{
+    			bi_windup();
+    		}
+    	}
+
+    	internal void fill_window()
+    	{
+    		do
+    		{
+    			int num = window_size - lookahead - strstart;
+    			int num2;
+    			if (num == 0 && strstart == 0 && lookahead == 0)
+    			{
+    				num = w_size;
+    			}
+    			else if (num == -1)
+    			{
+    				num--;
+    			}
+    			else if (strstart >= w_size + w_size - MIN_LOOKAHEAD)
+    			{
+    				Array.Copy(window, w_size, window, 0, w_size);
+    				match_start -= w_size;
+    				strstart -= w_size;
+    				block_start -= w_size;
+    				num2 = hash_size;
+    				int num3 = num2;
+    				do
+    				{
+    					int num4 = head[--num3] & 0xFFFF;
+    					head[num3] = (short)((num4 >= w_size) ? (num4 - w_size) : 0);
+    				}
+    				while (--num2 != 0);
+    				num2 = w_size;
+    				num3 = num2;
+    				do
+    				{
+    					int num4 = prev[--num3] & 0xFFFF;
+    					prev[num3] = (short)((num4 >= w_size) ? (num4 - w_size) : 0);
+    				}
+    				while (--num2 != 0);
+    				num += w_size;
+    			}
+    			if (strm.avail_in == 0)
+    			{
+    				break;
+    			}
+    			num2 = strm.read_buf(window, strstart + lookahead, num);
+    			lookahead += num2;
+    			if (lookahead >= 3)
+    			{
+    				ins_h = window[strstart] & 0xFF;
+    				ins_h = ((ins_h << hash_shift) ^ (window[strstart + 1] & 0xFF)) & hash_mask;
+    			}
+    		}
+    		while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0);
+    	}
+
+    	internal int deflate_fast(int flush)
+    	{
+    		int num = 0;
+    		while (true)
+    		{
+    			if (lookahead < MIN_LOOKAHEAD)
+    			{
+    				fill_window();
+    				if (lookahead < MIN_LOOKAHEAD && flush == 0)
+    				{
+    					return 0;
+    				}
+    				if (lookahead == 0)
+    				{
+    					break;
+    				}
+    			}
+    			if (lookahead >= 3)
+    			{
+    				ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask;
+    				num = head[ins_h] & 0xFFFF;
+    				prev[strstart & w_mask] = head[ins_h];
+    				head[ins_h] = (short)strstart;
+    			}
+    			if (num != 0L && ((strstart - num) & 0xFFFF) <= w_size - MIN_LOOKAHEAD && strategy != 2)
+    			{
+    				match_length = longest_match(num);
+    			}
+    			bool flag;
+    			if (match_length >= 3)
+    			{
+    				flag = _tr_tally(strstart - match_start, match_length - 3);
+    				lookahead -= match_length;
+    				if (match_length <= max_lazy_match && lookahead >= 3)
+    				{
+    					match_length--;
+    					do
+    					{
+    						strstart++;
+    						ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask;
+    						num = head[ins_h] & 0xFFFF;
+    						prev[strstart & w_mask] = head[ins_h];
+    						head[ins_h] = (short)strstart;
+    					}
+    					while (--match_length != 0);
+    					strstart++;
+    				}
+    				else
+    				{
+    					strstart += match_length;
+    					match_length = 0;
+    					ins_h = window[strstart] & 0xFF;
+    					ins_h = ((ins_h << hash_shift) ^ (window[strstart + 1] & 0xFF)) & hash_mask;
+    				}
+    			}
+    			else
+    			{
+    				flag = _tr_tally(0, window[strstart] & 0xFF);
+    				lookahead--;
+    				strstart++;
+    			}
+    			if (flag)
+    			{
+    				flush_block_only(eof: false);
+    				if (strm.avail_out == 0)
+    				{
+    					return 0;
+    				}
+    			}
+    		}
+    		flush_block_only(flush == 4);
+    		if (strm.avail_out == 0)
+    		{
+    			if (flush == 4)
+    			{
+    				return 2;
+    			}
+    			return 0;
+    		}
+    		if (flush != 4)
+    		{
+    			return 1;
+    		}
+    		return 3;
+    	}
+
+    	internal int deflate_slow(int flush)
+    	{
+    		int num = 0;
+    		while (true)
+    		{
+    			if (lookahead < MIN_LOOKAHEAD)
+    			{
+    				fill_window();
+    				if (lookahead < MIN_LOOKAHEAD && flush == 0)
+    				{
+    					return 0;
+    				}
+    				if (lookahead == 0)
+    				{
+    					break;
+    				}
+    			}
+    			if (lookahead >= 3)
+    			{
+    				ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask;
+    				num = head[ins_h] & 0xFFFF;
+    				prev[strstart & w_mask] = head[ins_h];
+    				head[ins_h] = (short)strstart;
+    			}
+    			prev_length = match_length;
+    			prev_match = match_start;
+    			match_length = 2;
+    			if (num != 0 && prev_length < max_lazy_match && ((strstart - num) & 0xFFFF) <= w_size - MIN_LOOKAHEAD)
+    			{
+    				if (strategy != 2)
+    				{
+    					match_length = longest_match(num);
+    				}
+    				if (match_length <= 5 && (strategy == 1 || (match_length == 3 && strstart - match_start > 4096)))
+    				{
+    					match_length = 2;
+    				}
+    			}
+    			if (prev_length >= 3 && match_length <= prev_length)
+    			{
+    				int num2 = strstart + lookahead - 3;
+    				bool flag = _tr_tally(strstart - 1 - prev_match, prev_length - 3);
+    				lookahead -= prev_length - 1;
+    				prev_length -= 2;
+    				do
+    				{
+    					if (++strstart <= num2)
+    					{
+    						ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask;
+    						num = head[ins_h] & 0xFFFF;
+    						prev[strstart & w_mask] = head[ins_h];
+    						head[ins_h] = (short)strstart;
+    					}
+    				}
+    				while (--prev_length != 0);
+    				match_available = 0;
+    				match_length = 2;
+    				strstart++;
+    				if (flag)
+    				{
+    					flush_block_only(eof: false);
+    					if (strm.avail_out == 0)
+    					{
+    						return 0;
+    					}
+    				}
+    			}
+    			else if (match_available != 0)
+    			{
+    				if (_tr_tally(0, window[strstart - 1] & 0xFF))
+    				{
+    					flush_block_only(eof: false);
+    				}
+    				strstart++;
+    				lookahead--;
+    				if (strm.avail_out == 0)
+    				{
+    					return 0;
+    				}
+    			}
+    			else
+    			{
+    				match_available = 1;
+    				strstart++;
+    				lookahead--;
+    			}
+    		}
+    		if (match_available != 0)
+    		{
+    			bool flag = _tr_tally(0, window[strstart - 1] & 0xFF);
+    			match_available = 0;
+    		}
+    		flush_block_only(flush == 4);
+    		if (strm.avail_out == 0)
+    		{
+    			if (flush == 4)
+    			{
+    				return 2;
+    			}
+    			return 0;
+    		}
+    		if (flush != 4)
+    		{
+    			return 1;
+    		}
+    		return 3;
+    	}
+
+    	internal int longest_match(int cur_match)
+    	{
+    		int num = max_chain_length;
+    		int num2 = strstart;
+    		int num3 = prev_length;
+    		int num4 = ((strstart > w_size - MIN_LOOKAHEAD) ? (strstart - (w_size - MIN_LOOKAHEAD)) : 0);
+    		int num5 = nice_match;
+    		int num6 = w_mask;
+    		int num7 = strstart + 258;
+    		byte b = window[num2 + num3 - 1];
+    		byte b2 = window[num2 + num3];
+    		if (prev_length >= good_match)
+    		{
+    			num >>= 2;
+    		}
+    		if (num5 > lookahead)
+    		{
+    			num5 = lookahead;
+    		}
+    		do
+    		{
+    			int num8 = cur_match;
+    			if (window[num8 + num3] != b2 || window[num8 + num3 - 1] != b || window[num8] != window[num2] || window[++num8] != window[num2 + 1])
+    			{
+    				continue;
+    			}
+    			num2 += 2;
+    			num8++;
+    			while (window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && num2 < num7)
+    			{
+    			}
+    			int num9 = 258 - (num7 - num2);
+    			num2 = num7 - 258;
+    			if (num9 > num3)
+    			{
+    				match_start = cur_match;
+    				num3 = num9;
+    				if (num9 >= num5)
+    				{
+    					break;
+    				}
+    				b = window[num2 + num3 - 1];
+    				b2 = window[num2 + num3];
+    			}
+    		}
+    		while ((cur_match = prev[cur_match & num6] & 0xFFFF) > num4 && --num != 0);
+    		if (num3 <= lookahead)
+    		{
+    			return num3;
+    		}
+    		return lookahead;
+    	}
+
+    	internal int deflateInit(ZStream strm, int level, int bits)
+    	{
+    		return deflateInit2(strm, level, 8, bits, 8, 0);
+    	}
+
+    	internal int deflateInit(ZStream strm, int level)
+    	{
+    		return deflateInit(strm, level, 15);
+    	}
+
+    	internal int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy)
+    	{
+    		int num = 0;
+    		strm.msg = null;
+    		if (level == -1)
+    		{
+    			level = 6;
+    		}
+    		if (windowBits < 0)
+    		{
+    			num = 1;
+    			windowBits = -windowBits;
+    		}
+    		if (memLevel < 1 || memLevel > 9 || method != 8 || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > 2)
+    		{
+    			return -2;
+    		}
+    		strm.dstate = this;
+    		noheader = num;
+    		w_bits = windowBits;
+    		w_size = 1 << w_bits;
+    		w_mask = w_size - 1;
+    		hash_bits = memLevel + 7;
+    		hash_size = 1 << hash_bits;
+    		hash_mask = hash_size - 1;
+    		hash_shift = (hash_bits + 3 - 1) / 3;
+    		window = new byte[w_size * 2];
+    		prev = new short[w_size];
+    		head = new short[hash_size];
+    		lit_bufsize = 1 << memLevel + 6;
+    		pending_buf = new byte[lit_bufsize * 4];
+    		pending_buf_size = lit_bufsize * 4;
+    		d_buf = lit_bufsize;
+    		l_buf = 3 * lit_bufsize;
+    		this.level = level;
+    		this.strategy = strategy;
+    		this.method = (byte)method;
+    		return deflateReset(strm);
+    	}
+
+    	internal int deflateReset(ZStream strm)
+    	{
+    		strm.total_in = (strm.total_out = 0L);
+    		strm.msg = null;
+    		strm.data_type = 2;
+    		pending = 0;
+    		pending_out = 0;
+    		if (noheader < 0)
+    		{
+    			noheader = 0;
+    		}
+    		status = ((noheader != 0) ? 113 : 42);
+    		strm.adler = strm._adler.adler32(0L, null, 0, 0);
+    		last_flush = 0;
+    		tr_init();
+    		lm_init();
+    		return 0;
+    	}
+
+    	internal int deflateEnd()
+    	{
+    		if (status != 42 && status != 113 && status != 666)
+    		{
+    			return -2;
+    		}
+    		pending_buf = null;
+    		head = null;
+    		prev = null;
+    		window = null;
+    		if (status != 113)
+    		{
+    			return 0;
+    		}
+    		return -3;
+    	}
+
+    	internal int deflateParams(ZStream strm, int _level, int _strategy)
+    	{
+    		int result = 0;
+    		if (_level == -1)
+    		{
+    			_level = 6;
+    		}
+    		if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > 2)
+    		{
+    			return -2;
+    		}
+    		if (config_table[level].func != config_table[_level].func && strm.total_in != 0L)
+    		{
+    			result = strm.deflate(1);
+    		}
+    		if (level != _level)
+    		{
+    			level = _level;
+    			max_lazy_match = config_table[level].max_lazy;
+    			good_match = config_table[level].good_length;
+    			nice_match = config_table[level].nice_length;
+    			max_chain_length = config_table[level].max_chain;
+    		}
+    		strategy = _strategy;
+    		return result;
+    	}
+
+    	internal int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength)
+    	{
+    		int num = dictLength;
+    		int sourceIndex = 0;
+    		if (dictionary == null || status != 42)
+    		{
+    			return -2;
+    		}
+    		strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength);
+    		if (num < 3)
+    		{
+    			return 0;
+    		}
+    		if (num > w_size - MIN_LOOKAHEAD)
+    		{
+    			num = w_size - MIN_LOOKAHEAD;
+    			sourceIndex = dictLength - num;
+    		}
+    		Array.Copy(dictionary, sourceIndex, window, 0, num);
+    		strstart = num;
+    		block_start = num;
+    		ins_h = window[0] & 0xFF;
+    		ins_h = ((ins_h << hash_shift) ^ (window[1] & 0xFF)) & hash_mask;
+    		for (int i = 0; i <= num - 3; i++)
+    		{
+    			ins_h = ((ins_h << hash_shift) ^ (window[i + 2] & 0xFF)) & hash_mask;
+    			prev[i & w_mask] = head[ins_h];
+    			head[ins_h] = (short)i;
+    		}
+    		return 0;
+    	}
+
+    	internal int deflate(ZStream strm, int flush)
+    	{
+    		if (flush > 4 || flush < 0)
+    		{
+    			return -2;
+    		}
+    		if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == 666 && flush != 4))
+    		{
+    			strm.msg = z_errmsg[4];
+    			return -2;
+    		}
+    		if (strm.avail_out == 0)
+    		{
+    			strm.msg = z_errmsg[7];
+    			return -5;
+    		}
+    		this.strm = strm;
+    		int num = last_flush;
+    		last_flush = flush;
+    		if (status == 42)
+    		{
+    			int num2 = 8 + (w_bits - 8 << 4) << 8;
+    			int num3 = ((level - 1) & 0xFF) >> 1;
+    			if (num3 > 3)
+    			{
+    				num3 = 3;
+    			}
+    			num2 |= num3 << 6;
+    			if (strstart != 0)
+    			{
+    				num2 |= 0x20;
+    			}
+    			num2 += 31 - num2 % 31;
+    			status = 113;
+    			putShortMSB(num2);
+    			if (strstart != 0)
+    			{
+    				putShortMSB((int)SupportClass.URShift(strm.adler, 16));
+    				putShortMSB((int)(strm.adler & 0xFFFF));
+    			}
+    			strm.adler = strm._adler.adler32(0L, null, 0, 0);
+    		}
+    		if (pending != 0)
+    		{
+    			strm.flush_pending();
+    			if (strm.avail_out == 0)
+    			{
+    				last_flush = -1;
+    				return 0;
+    			}
+    		}
+    		else if (strm.avail_in == 0 && flush <= num && flush != 4)
+    		{
+    			strm.msg = z_errmsg[7];
+    			return -5;
+    		}
+    		if (status == 666 && strm.avail_in != 0)
+    		{
+    			strm.msg = z_errmsg[7];
+    			return -5;
+    		}
+    		if (strm.avail_in != 0 || lookahead != 0 || (flush != 0 && status != 666))
+    		{
+    			int num4 = -1;
+    			switch (config_table[level].func)
+    			{
+    			case 0:
+    				num4 = deflate_stored(flush);
+    				break;
+    			case 1:
+    				num4 = deflate_fast(flush);
+    				break;
+    			case 2:
+    				num4 = deflate_slow(flush);
+    				break;
+    			}
+    			if (num4 == 2 || num4 == 3)
+    			{
+    				status = 666;
+    			}
+    			switch (num4)
+    			{
+    			case 0:
+    			case 2:
+    				if (strm.avail_out == 0)
+    				{
+    					last_flush = -1;
+    				}
+    				return 0;
+    			case 1:
+    				if (flush == 1)
+    				{
+    					_tr_align();
+    				}
+    				else
+    				{
+    					_tr_stored_block(0, 0, eof: false);
+    					if (flush == 3)
+    					{
+    						for (int i = 0; i < hash_size; i++)
+    						{
+    							head[i] = 0;
+    						}
+    					}
+    				}
+    				strm.flush_pending();
+    				if (strm.avail_out == 0)
+    				{
+    					last_flush = -1;
+    					return 0;
+    				}
+    				break;
+    			}
+    		}
+    		if (flush != 4)
+    		{
+    			return 0;
+    		}
+    		if (noheader != 0)
+    		{
+    			return 1;
+    		}
+    		putShortMSB((int)SupportClass.URShift(strm.adler, 16));
+    		putShortMSB((int)(strm.adler & 0xFFFF));
+    		strm.flush_pending();
+    		noheader = -1;
+    		if (pending == 0)
+    		{
+    			return 1;
+    		}
+    		return 0;
+    	}
+
+    	static Deflate()
+    	{
+    		z_errmsg = new string[10] { "need dictionary", "stream end", "", "file error", "stream error", "data error", "insufficient memory", "buffer error", "incompatible version", "" };
+    		MIN_LOOKAHEAD = 262;
+    		L_CODES = 286;
+    		HEAP_SIZE = 2 * L_CODES + 1;
+    		config_table = new Config[10];
+    		config_table[0] = new Config(0, 0, 0, 0, 0);
+    		config_table[1] = new Config(4, 4, 8, 4, 1);
+    		config_table[2] = new Config(4, 5, 16, 8, 1);
+    		config_table[3] = new Config(4, 6, 32, 32, 1);
+    		config_table[4] = new Config(4, 4, 16, 16, 2);
+    		config_table[5] = new Config(8, 16, 32, 32, 2);
+    		config_table[6] = new Config(8, 16, 128, 128, 2);
+    		config_table[7] = new Config(8, 32, 128, 256, 2);
+    		config_table[8] = new Config(32, 128, 258, 1024, 2);
+    		config_table[9] = new Config(32, 258, 258, 4096, 2);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfBlocks.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfBlocks.cs
new file mode 100644
index 00000000..0a1e57ba
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfBlocks.cs
@@ -0,0 +1,661 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class InfBlocks
+    {
+    	private const int MANY = 1440;
+
+    	private static readonly int[] inflate_mask = new int[17]
+    	{
+    		0, 1, 3, 7, 15, 31, 63, 127, 255, 511,
+    		1023, 2047, 4095, 8191, 16383, 32767, 65535
+    	};
+
+    	internal static readonly int[] border = new int[19]
+    	{
+    		16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
+    		11, 4, 12, 3, 13, 2, 14, 1, 15
+    	};
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	private const int TYPE = 0;
+
+    	private const int LENS = 1;
+
+    	private const int STORED = 2;
+
+    	private const int TABLE = 3;
+
+    	private const int BTREE = 4;
+
+    	private const int DTREE = 5;
+
+    	private const int CODES = 6;
+
+    	private const int DRY = 7;
+
+    	private const int DONE = 8;
+
+    	private const int BAD = 9;
+
+    	internal int mode;
+
+    	internal int left;
+
+    	internal int table;
+
+    	internal int index;
+
+    	internal int[] blens;
+
+    	internal int[] bb = new int[1];
+
+    	internal int[] tb = new int[1];
+
+    	internal InfCodes codes;
+
+    	internal int last;
+
+    	internal int bitk;
+
+    	internal int bitb;
+
+    	internal int[] hufts;
+
+    	internal byte[] window;
+
+    	internal int end;
+
+    	internal int read;
+
+    	internal int write;
+
+    	internal object checkfn;
+
+    	internal long check;
+
+    	internal InfBlocks(ZStream z, object checkfn, int w)
+    	{
+    		hufts = new int[4320];
+    		window = new byte[w];
+    		end = w;
+    		this.checkfn = checkfn;
+    		mode = 0;
+    		reset(z, null);
+    	}
+
+    	internal void reset(ZStream z, long[] c)
+    	{
+    		if (c != null)
+    		{
+    			c[0] = check;
+    		}
+    		if (mode == 4 || mode == 5)
+    		{
+    			blens = null;
+    		}
+    		if (mode == 6)
+    		{
+    			codes.free(z);
+    		}
+    		mode = 0;
+    		bitk = 0;
+    		bitb = 0;
+    		read = (write = 0);
+    		if (checkfn != null)
+    		{
+    			z.adler = (check = z._adler.adler32(0L, null, 0, 0));
+    		}
+    	}
+
+    	internal int proc(ZStream z, int r)
+    	{
+    		int num = z.next_in_index;
+    		int num2 = z.avail_in;
+    		int num3 = bitb;
+    		int i = bitk;
+    		int num4 = write;
+    		int num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    		while (true)
+    		{
+    			switch (mode)
+    			{
+    			case 0:
+    			{
+    				for (; i < 3; i += 8)
+    				{
+    					if (num2 != 0)
+    					{
+    						r = 0;
+    						num2--;
+    						num3 |= (z.next_in[num++] & 0xFF) << i;
+    						continue;
+    					}
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				int num6 = num3 & 7;
+    				last = num6 & 1;
+    				switch (SupportClass.URShift(num6, 1))
+    				{
+    				case 0:
+    					num3 = SupportClass.URShift(num3, 3);
+    					i -= 3;
+    					num6 = i & 7;
+    					num3 = SupportClass.URShift(num3, num6);
+    					i -= num6;
+    					mode = 1;
+    					break;
+    				case 1:
+    				{
+    					int[] array5 = new int[1];
+    					int[] array6 = new int[1];
+    					int[][] array7 = new int[1][];
+    					int[][] array8 = new int[1][];
+    					InfTree.inflate_trees_fixed(array5, array6, array7, array8, z);
+    					codes = new InfCodes(array5[0], array6[0], array7[0], array8[0], z);
+    					num3 = SupportClass.URShift(num3, 3);
+    					i -= 3;
+    					mode = 6;
+    					break;
+    				}
+    				case 2:
+    					num3 = SupportClass.URShift(num3, 3);
+    					i -= 3;
+    					mode = 3;
+    					break;
+    				case 3:
+    					num3 = SupportClass.URShift(num3, 3);
+    					i -= 3;
+    					mode = 9;
+    					z.msg = "invalid block type";
+    					r = -3;
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				break;
+    			}
+    			case 1:
+    				for (; i < 32; i += 8)
+    				{
+    					if (num2 != 0)
+    					{
+    						r = 0;
+    						num2--;
+    						num3 |= (z.next_in[num++] & 0xFF) << i;
+    						continue;
+    					}
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				if ((SupportClass.URShift(~num3, 16) & 0xFFFF) != (num3 & 0xFFFF))
+    				{
+    					mode = 9;
+    					z.msg = "invalid stored block lengths";
+    					r = -3;
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				left = num3 & 0xFFFF;
+    				num3 = (i = 0);
+    				mode = ((left != 0) ? 2 : ((last != 0) ? 7 : 0));
+    				break;
+    			case 2:
+    			{
+    				if (num2 == 0)
+    				{
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				if (num5 == 0)
+    				{
+    					if (num4 == end && read != 0)
+    					{
+    						num4 = 0;
+    						num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    					}
+    					if (num5 == 0)
+    					{
+    						write = num4;
+    						r = inflate_flush(z, r);
+    						num4 = write;
+    						num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    						if (num4 == end && read != 0)
+    						{
+    							num4 = 0;
+    							num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    						}
+    						if (num5 == 0)
+    						{
+    							bitb = num3;
+    							bitk = i;
+    							z.avail_in = num2;
+    							z.total_in += num - z.next_in_index;
+    							z.next_in_index = num;
+    							write = num4;
+    							return inflate_flush(z, r);
+    						}
+    					}
+    				}
+    				r = 0;
+    				int num6 = left;
+    				if (num6 > num2)
+    				{
+    					num6 = num2;
+    				}
+    				if (num6 > num5)
+    				{
+    					num6 = num5;
+    				}
+    				Array.Copy(z.next_in, num, window, num4, num6);
+    				num += num6;
+    				num2 -= num6;
+    				num4 += num6;
+    				num5 -= num6;
+    				if ((left -= num6) == 0)
+    				{
+    					mode = ((last != 0) ? 7 : 0);
+    				}
+    				break;
+    			}
+    			case 3:
+    			{
+    				for (; i < 14; i += 8)
+    				{
+    					if (num2 != 0)
+    					{
+    						r = 0;
+    						num2--;
+    						num3 |= (z.next_in[num++] & 0xFF) << i;
+    						continue;
+    					}
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				int num6 = (table = num3 & 0x3FFF);
+    				if ((num6 & 0x1F) > 29 || ((num6 >> 5) & 0x1F) > 29)
+    				{
+    					mode = 9;
+    					z.msg = "too many length or distance symbols";
+    					r = -3;
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				num6 = 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F);
+    				blens = new int[num6];
+    				num3 = SupportClass.URShift(num3, 14);
+    				i -= 14;
+    				index = 0;
+    				mode = 4;
+    				goto case 4;
+    			}
+    			case 4:
+    			{
+    				while (index < 4 + SupportClass.URShift(table, 10))
+    				{
+    					for (; i < 3; i += 8)
+    					{
+    						if (num2 != 0)
+    						{
+    							r = 0;
+    							num2--;
+    							num3 |= (z.next_in[num++] & 0xFF) << i;
+    							continue;
+    						}
+    						bitb = num3;
+    						bitk = i;
+    						z.avail_in = num2;
+    						z.total_in += num - z.next_in_index;
+    						z.next_in_index = num;
+    						write = num4;
+    						return inflate_flush(z, r);
+    					}
+    					blens[border[index++]] = num3 & 7;
+    					num3 = SupportClass.URShift(num3, 3);
+    					i -= 3;
+    				}
+    				while (index < 19)
+    				{
+    					blens[border[index++]] = 0;
+    				}
+    				bb[0] = 7;
+    				int num6 = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z);
+    				if (num6 != 0)
+    				{
+    					r = num6;
+    					if (r == -3)
+    					{
+    						blens = null;
+    						mode = 9;
+    					}
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				index = 0;
+    				mode = 5;
+    				goto case 5;
+    			}
+    			case 5:
+    			{
+    				int num6;
+    				while (true)
+    				{
+    					num6 = table;
+    					if (index >= 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F))
+    					{
+    						break;
+    					}
+    					for (num6 = bb[0]; i < num6; i += 8)
+    					{
+    						if (num2 != 0)
+    						{
+    							r = 0;
+    							num2--;
+    							num3 |= (z.next_in[num++] & 0xFF) << i;
+    							continue;
+    						}
+    						bitb = num3;
+    						bitk = i;
+    						z.avail_in = num2;
+    						z.total_in += num - z.next_in_index;
+    						z.next_in_index = num;
+    						write = num4;
+    						return inflate_flush(z, r);
+    					}
+    					_ = tb[0];
+    					_ = -1;
+    					num6 = hufts[(tb[0] + (num3 & inflate_mask[num6])) * 3 + 1];
+    					int num7 = hufts[(tb[0] + (num3 & inflate_mask[num6])) * 3 + 2];
+    					if (num7 < 16)
+    					{
+    						num3 = SupportClass.URShift(num3, num6);
+    						i -= num6;
+    						blens[index++] = num7;
+    						continue;
+    					}
+    					int num8 = ((num7 == 18) ? 7 : (num7 - 14));
+    					int num9 = ((num7 == 18) ? 11 : 3);
+    					for (; i < num6 + num8; i += 8)
+    					{
+    						if (num2 != 0)
+    						{
+    							r = 0;
+    							num2--;
+    							num3 |= (z.next_in[num++] & 0xFF) << i;
+    							continue;
+    						}
+    						bitb = num3;
+    						bitk = i;
+    						z.avail_in = num2;
+    						z.total_in += num - z.next_in_index;
+    						z.next_in_index = num;
+    						write = num4;
+    						return inflate_flush(z, r);
+    					}
+    					num3 = SupportClass.URShift(num3, num6);
+    					i -= num6;
+    					num9 += num3 & inflate_mask[num8];
+    					num3 = SupportClass.URShift(num3, num8);
+    					i -= num8;
+    					num8 = index;
+    					num6 = table;
+    					if (num8 + num9 > 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F) || (num7 == 16 && num8 < 1))
+    					{
+    						blens = null;
+    						mode = 9;
+    						z.msg = "invalid bit length repeat";
+    						r = -3;
+    						bitb = num3;
+    						bitk = i;
+    						z.avail_in = num2;
+    						z.total_in += num - z.next_in_index;
+    						z.next_in_index = num;
+    						write = num4;
+    						return inflate_flush(z, r);
+    					}
+    					num7 = ((num7 == 16) ? blens[num8 - 1] : 0);
+    					do
+    					{
+    						blens[num8++] = num7;
+    					}
+    					while (--num9 != 0);
+    					index = num8;
+    				}
+    				tb[0] = -1;
+    				int[] array = new int[1];
+    				int[] array2 = new int[1];
+    				int[] array3 = new int[1];
+    				int[] array4 = new int[1];
+    				array[0] = 9;
+    				array2[0] = 6;
+    				num6 = table;
+    				num6 = InfTree.inflate_trees_dynamic(257 + (num6 & 0x1F), 1 + ((num6 >> 5) & 0x1F), blens, array, array2, array3, array4, hufts, z);
+    				if (num6 != 0)
+    				{
+    					if (num6 == -3)
+    					{
+    						blens = null;
+    						mode = 9;
+    					}
+    					r = num6;
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				codes = new InfCodes(array[0], array2[0], hufts, array3[0], hufts, array4[0], z);
+    				blens = null;
+    				mode = 6;
+    				goto case 6;
+    			}
+    			case 6:
+    				bitb = num3;
+    				bitk = i;
+    				z.avail_in = num2;
+    				z.total_in += num - z.next_in_index;
+    				z.next_in_index = num;
+    				write = num4;
+    				if ((r = codes.proc(this, z, r)) != 1)
+    				{
+    					return inflate_flush(z, r);
+    				}
+    				r = 0;
+    				codes.free(z);
+    				num = z.next_in_index;
+    				num2 = z.avail_in;
+    				num3 = bitb;
+    				i = bitk;
+    				num4 = write;
+    				num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    				if (last == 0)
+    				{
+    					mode = 0;
+    					break;
+    				}
+    				mode = 7;
+    				goto case 7;
+    			case 7:
+    				write = num4;
+    				r = inflate_flush(z, r);
+    				num4 = write;
+    				num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4));
+    				if (read != write)
+    				{
+    					bitb = num3;
+    					bitk = i;
+    					z.avail_in = num2;
+    					z.total_in += num - z.next_in_index;
+    					z.next_in_index = num;
+    					write = num4;
+    					return inflate_flush(z, r);
+    				}
+    				mode = 8;
+    				goto case 8;
+    			case 8:
+    				r = 1;
+    				bitb = num3;
+    				bitk = i;
+    				z.avail_in = num2;
+    				z.total_in += num - z.next_in_index;
+    				z.next_in_index = num;
+    				write = num4;
+    				return inflate_flush(z, r);
+    			case 9:
+    				r = -3;
+    				bitb = num3;
+    				bitk = i;
+    				z.avail_in = num2;
+    				z.total_in += num - z.next_in_index;
+    				z.next_in_index = num;
+    				write = num4;
+    				return inflate_flush(z, r);
+    			default:
+    				r = -2;
+    				bitb = num3;
+    				bitk = i;
+    				z.avail_in = num2;
+    				z.total_in += num - z.next_in_index;
+    				z.next_in_index = num;
+    				write = num4;
+    				return inflate_flush(z, r);
+    			}
+    		}
+    	}
+
+    	internal void free(ZStream z)
+    	{
+    		reset(z, null);
+    		window = null;
+    		hufts = null;
+    	}
+
+    	internal void set_dictionary(byte[] d, int start, int n)
+    	{
+    		Array.Copy(d, start, window, 0, n);
+    		read = (write = n);
+    	}
+
+    	internal int sync_point()
+    	{
+    		if (mode != 1)
+    		{
+    			return 0;
+    		}
+    		return 1;
+    	}
+
+    	internal int inflate_flush(ZStream z, int r)
+    	{
+    		int next_out_index = z.next_out_index;
+    		int num = read;
+    		int num2 = ((num <= write) ? write : end) - num;
+    		if (num2 > z.avail_out)
+    		{
+    			num2 = z.avail_out;
+    		}
+    		if (num2 != 0 && r == -5)
+    		{
+    			r = 0;
+    		}
+    		z.avail_out -= num2;
+    		z.total_out += num2;
+    		if (checkfn != null)
+    		{
+    			z.adler = (check = z._adler.adler32(check, window, num, num2));
+    		}
+    		Array.Copy(window, num, z.next_out, next_out_index, num2);
+    		next_out_index += num2;
+    		num += num2;
+    		if (num == end)
+    		{
+    			num = 0;
+    			if (write == end)
+    			{
+    				write = 0;
+    			}
+    			num2 = write - num;
+    			if (num2 > z.avail_out)
+    			{
+    				num2 = z.avail_out;
+    			}
+    			if (num2 != 0 && r == -5)
+    			{
+    				r = 0;
+    			}
+    			z.avail_out -= num2;
+    			z.total_out += num2;
+    			if (checkfn != null)
+    			{
+    				z.adler = (check = z._adler.adler32(check, window, num, num2));
+    			}
+    			Array.Copy(window, num, z.next_out, next_out_index, num2);
+    			next_out_index += num2;
+    			num += num2;
+    		}
+    		z.next_out_index = next_out_index;
+    		read = num;
+    		return r;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfCodes.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfCodes.cs
new file mode 100644
index 00000000..cee63ce1
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfCodes.cs
@@ -0,0 +1,664 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class InfCodes
+    {
+    	private static readonly int[] inflate_mask = new int[17]
+    	{
+    		0, 1, 3, 7, 15, 31, 63, 127, 255, 511,
+    		1023, 2047, 4095, 8191, 16383, 32767, 65535
+    	};
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	private const int START = 0;
+
+    	private const int LEN = 1;
+
+    	private const int LENEXT = 2;
+
+    	private const int DIST = 3;
+
+    	private const int DISTEXT = 4;
+
+    	private const int COPY = 5;
+
+    	private const int LIT = 6;
+
+    	private const int WASH = 7;
+
+    	private const int END = 8;
+
+    	private const int BADCODE = 9;
+
+    	internal int mode;
+
+    	internal int len;
+
+    	internal int[] tree;
+
+    	internal int tree_index;
+
+    	internal int need;
+
+    	internal int lit;
+
+    	internal int get_Renamed;
+
+    	internal int dist;
+
+    	internal byte lbits;
+
+    	internal byte dbits;
+
+    	internal int[] ltree;
+
+    	internal int ltree_index;
+
+    	internal int[] dtree;
+
+    	internal int dtree_index;
+
+    	internal InfCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z)
+    	{
+    		mode = 0;
+    		lbits = (byte)bl;
+    		dbits = (byte)bd;
+    		ltree = tl;
+    		ltree_index = tl_index;
+    		dtree = td;
+    		dtree_index = td_index;
+    	}
+
+    	internal InfCodes(int bl, int bd, int[] tl, int[] td, ZStream z)
+    	{
+    		mode = 0;
+    		lbits = (byte)bl;
+    		dbits = (byte)bd;
+    		ltree = tl;
+    		ltree_index = 0;
+    		dtree = td;
+    		dtree_index = 0;
+    	}
+
+    	internal int proc(InfBlocks s, ZStream z, int r)
+    	{
+    		int num = 0;
+    		int num2 = 0;
+    		int num3 = 0;
+    		num3 = z.next_in_index;
+    		int num4 = z.avail_in;
+    		num = s.bitb;
+    		num2 = s.bitk;
+    		int num5 = s.write;
+    		int num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    		while (true)
+    		{
+    			switch (mode)
+    			{
+    			case 0:
+    				if (num6 >= 258 && num4 >= 10)
+    				{
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);
+    					num3 = z.next_in_index;
+    					num4 = z.avail_in;
+    					num = s.bitb;
+    					num2 = s.bitk;
+    					num5 = s.write;
+    					num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    					if (r != 0)
+    					{
+    						mode = ((r == 1) ? 7 : 9);
+    						break;
+    					}
+    				}
+    				need = lbits;
+    				tree = ltree;
+    				tree_index = ltree_index;
+    				mode = 1;
+    				goto case 1;
+    			case 1:
+    			{
+    				int num7;
+    				for (num7 = need; num2 < num7; num2 += 8)
+    				{
+    					if (num4 != 0)
+    					{
+    						r = 0;
+    						num4--;
+    						num |= (z.next_in[num3++] & 0xFF) << num2;
+    						continue;
+    					}
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					return s.inflate_flush(z, r);
+    				}
+    				int num8 = (tree_index + (num & inflate_mask[num7])) * 3;
+    				num = SupportClass.URShift(num, tree[num8 + 1]);
+    				num2 -= tree[num8 + 1];
+    				int num9 = tree[num8];
+    				if (num9 == 0)
+    				{
+    					lit = tree[num8 + 2];
+    					mode = 6;
+    					break;
+    				}
+    				if (((uint)num9 & 0x10u) != 0)
+    				{
+    					get_Renamed = num9 & 0xF;
+    					len = tree[num8 + 2];
+    					mode = 2;
+    					break;
+    				}
+    				if ((num9 & 0x40) == 0)
+    				{
+    					need = num9;
+    					tree_index = num8 / 3 + tree[num8 + 2];
+    					break;
+    				}
+    				if (((uint)num9 & 0x20u) != 0)
+    				{
+    					mode = 7;
+    					break;
+    				}
+    				mode = 9;
+    				z.msg = "invalid literal/length code";
+    				r = -3;
+    				s.bitb = num;
+    				s.bitk = num2;
+    				z.avail_in = num4;
+    				z.total_in += num3 - z.next_in_index;
+    				z.next_in_index = num3;
+    				s.write = num5;
+    				return s.inflate_flush(z, r);
+    			}
+    			case 2:
+    			{
+    				int num7;
+    				for (num7 = get_Renamed; num2 < num7; num2 += 8)
+    				{
+    					if (num4 != 0)
+    					{
+    						r = 0;
+    						num4--;
+    						num |= (z.next_in[num3++] & 0xFF) << num2;
+    						continue;
+    					}
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					return s.inflate_flush(z, r);
+    				}
+    				len += num & inflate_mask[num7];
+    				num >>= num7;
+    				num2 -= num7;
+    				need = dbits;
+    				tree = dtree;
+    				tree_index = dtree_index;
+    				mode = 3;
+    				goto case 3;
+    			}
+    			case 3:
+    			{
+    				int num7;
+    				for (num7 = need; num2 < num7; num2 += 8)
+    				{
+    					if (num4 != 0)
+    					{
+    						r = 0;
+    						num4--;
+    						num |= (z.next_in[num3++] & 0xFF) << num2;
+    						continue;
+    					}
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					return s.inflate_flush(z, r);
+    				}
+    				int num8 = (tree_index + (num & inflate_mask[num7])) * 3;
+    				num >>= tree[num8 + 1];
+    				num2 -= tree[num8 + 1];
+    				int num9 = tree[num8];
+    				if (((uint)num9 & 0x10u) != 0)
+    				{
+    					get_Renamed = num9 & 0xF;
+    					dist = tree[num8 + 2];
+    					mode = 4;
+    					break;
+    				}
+    				if ((num9 & 0x40) == 0)
+    				{
+    					need = num9;
+    					tree_index = num8 / 3 + tree[num8 + 2];
+    					break;
+    				}
+    				mode = 9;
+    				z.msg = "invalid distance code";
+    				r = -3;
+    				s.bitb = num;
+    				s.bitk = num2;
+    				z.avail_in = num4;
+    				z.total_in += num3 - z.next_in_index;
+    				z.next_in_index = num3;
+    				s.write = num5;
+    				return s.inflate_flush(z, r);
+    			}
+    			case 4:
+    			{
+    				int num7;
+    				for (num7 = get_Renamed; num2 < num7; num2 += 8)
+    				{
+    					if (num4 != 0)
+    					{
+    						r = 0;
+    						num4--;
+    						num |= (z.next_in[num3++] & 0xFF) << num2;
+    						continue;
+    					}
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					return s.inflate_flush(z, r);
+    				}
+    				dist += num & inflate_mask[num7];
+    				num >>= num7;
+    				num2 -= num7;
+    				mode = 5;
+    				goto case 5;
+    			}
+    			case 5:
+    			{
+    				int i;
+    				for (i = num5 - dist; i < 0; i += s.end)
+    				{
+    				}
+    				while (len != 0)
+    				{
+    					if (num6 == 0)
+    					{
+    						if (num5 == s.end && s.read != 0)
+    						{
+    							num5 = 0;
+    							num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    						}
+    						if (num6 == 0)
+    						{
+    							s.write = num5;
+    							r = s.inflate_flush(z, r);
+    							num5 = s.write;
+    							num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    							if (num5 == s.end && s.read != 0)
+    							{
+    								num5 = 0;
+    								num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    							}
+    							if (num6 == 0)
+    							{
+    								s.bitb = num;
+    								s.bitk = num2;
+    								z.avail_in = num4;
+    								z.total_in += num3 - z.next_in_index;
+    								z.next_in_index = num3;
+    								s.write = num5;
+    								return s.inflate_flush(z, r);
+    							}
+    						}
+    					}
+    					s.window[num5++] = s.window[i++];
+    					num6--;
+    					if (i == s.end)
+    					{
+    						i = 0;
+    					}
+    					len--;
+    				}
+    				mode = 0;
+    				break;
+    			}
+    			case 6:
+    				if (num6 == 0)
+    				{
+    					if (num5 == s.end && s.read != 0)
+    					{
+    						num5 = 0;
+    						num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    					}
+    					if (num6 == 0)
+    					{
+    						s.write = num5;
+    						r = s.inflate_flush(z, r);
+    						num5 = s.write;
+    						num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    						if (num5 == s.end && s.read != 0)
+    						{
+    							num5 = 0;
+    							num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    						}
+    						if (num6 == 0)
+    						{
+    							s.bitb = num;
+    							s.bitk = num2;
+    							z.avail_in = num4;
+    							z.total_in += num3 - z.next_in_index;
+    							z.next_in_index = num3;
+    							s.write = num5;
+    							return s.inflate_flush(z, r);
+    						}
+    					}
+    				}
+    				r = 0;
+    				s.window[num5++] = (byte)lit;
+    				num6--;
+    				mode = 0;
+    				break;
+    			case 7:
+    				if (num2 > 7)
+    				{
+    					num2 -= 8;
+    					num4++;
+    					num3--;
+    				}
+    				s.write = num5;
+    				r = s.inflate_flush(z, r);
+    				num5 = s.write;
+    				num6 = ((num5 < s.read) ? (s.read - num5 - 1) : (s.end - num5));
+    				if (s.read != s.write)
+    				{
+    					s.bitb = num;
+    					s.bitk = num2;
+    					z.avail_in = num4;
+    					z.total_in += num3 - z.next_in_index;
+    					z.next_in_index = num3;
+    					s.write = num5;
+    					return s.inflate_flush(z, r);
+    				}
+    				mode = 8;
+    				goto case 8;
+    			case 8:
+    				r = 1;
+    				s.bitb = num;
+    				s.bitk = num2;
+    				z.avail_in = num4;
+    				z.total_in += num3 - z.next_in_index;
+    				z.next_in_index = num3;
+    				s.write = num5;
+    				return s.inflate_flush(z, r);
+    			case 9:
+    				r = -3;
+    				s.bitb = num;
+    				s.bitk = num2;
+    				z.avail_in = num4;
+    				z.total_in += num3 - z.next_in_index;
+    				z.next_in_index = num3;
+    				s.write = num5;
+    				return s.inflate_flush(z, r);
+    			default:
+    				r = -2;
+    				s.bitb = num;
+    				s.bitk = num2;
+    				z.avail_in = num4;
+    				z.total_in += num3 - z.next_in_index;
+    				z.next_in_index = num3;
+    				s.write = num5;
+    				return s.inflate_flush(z, r);
+    			}
+    		}
+    	}
+
+    	internal void free(ZStream z)
+    	{
+    	}
+
+    	internal int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream z)
+    	{
+    		int next_in_index = z.next_in_index;
+    		int num = z.avail_in;
+    		int num2 = s.bitb;
+    		int num3 = s.bitk;
+    		int num4 = s.write;
+    		int num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4));
+    		int num6 = inflate_mask[bl];
+    		int num7 = inflate_mask[bd];
+    		int num11;
+    		while (true)
+    		{
+    			if (num3 < 20)
+    			{
+    				num--;
+    				num2 |= (z.next_in[next_in_index++] & 0xFF) << num3;
+    				num3 += 8;
+    				continue;
+    			}
+    			int num8 = num2 & num6;
+    			int[] array = tl;
+    			int num9 = tl_index;
+    			int num10;
+    			if ((num10 = array[(num9 + num8) * 3]) == 0)
+    			{
+    				num2 >>= array[(num9 + num8) * 3 + 1];
+    				num3 -= array[(num9 + num8) * 3 + 1];
+    				s.window[num4++] = (byte)array[(num9 + num8) * 3 + 2];
+    				num5--;
+    			}
+    			else
+    			{
+    				while (true)
+    				{
+    					num2 >>= array[(num9 + num8) * 3 + 1];
+    					num3 -= array[(num9 + num8) * 3 + 1];
+    					if (((uint)num10 & 0x10u) != 0)
+    					{
+    						num10 &= 0xF;
+    						num11 = array[(num9 + num8) * 3 + 2] + (num2 & inflate_mask[num10]);
+    						num2 >>= num10;
+    						for (num3 -= num10; num3 < 15; num3 += 8)
+    						{
+    							num--;
+    							num2 |= (z.next_in[next_in_index++] & 0xFF) << num3;
+    						}
+    						num8 = num2 & num7;
+    						array = td;
+    						num9 = td_index;
+    						num10 = array[(num9 + num8) * 3];
+    						while (true)
+    						{
+    							num2 >>= array[(num9 + num8) * 3 + 1];
+    							num3 -= array[(num9 + num8) * 3 + 1];
+    							if (((uint)num10 & 0x10u) != 0)
+    							{
+    								break;
+    							}
+    							if ((num10 & 0x40) == 0)
+    							{
+    								num8 += array[(num9 + num8) * 3 + 2];
+    								num8 += num2 & inflate_mask[num10];
+    								num10 = array[(num9 + num8) * 3];
+    								continue;
+    							}
+    							z.msg = "invalid distance code";
+    							num11 = z.avail_in - num;
+    							num11 = ((num3 >> 3 < num11) ? (num3 >> 3) : num11);
+    							num += num11;
+    							next_in_index -= num11;
+    							num3 -= num11 << 3;
+    							s.bitb = num2;
+    							s.bitk = num3;
+    							z.avail_in = num;
+    							z.total_in += next_in_index - z.next_in_index;
+    							z.next_in_index = next_in_index;
+    							s.write = num4;
+    							return -3;
+    						}
+    						for (num10 &= 0xF; num3 < num10; num3 += 8)
+    						{
+    							num--;
+    							num2 |= (z.next_in[next_in_index++] & 0xFF) << num3;
+    						}
+    						int num12 = array[(num9 + num8) * 3 + 2] + (num2 & inflate_mask[num10]);
+    						num2 >>= num10;
+    						num3 -= num10;
+    						num5 -= num11;
+    						int num13;
+    						if (num4 >= num12)
+    						{
+    							num13 = num4 - num12;
+    							if (num4 - num13 > 0 && 2 > num4 - num13)
+    							{
+    								s.window[num4++] = s.window[num13++];
+    								num11--;
+    								s.window[num4++] = s.window[num13++];
+    								num11--;
+    							}
+    							else
+    							{
+    								Array.Copy(s.window, num13, s.window, num4, 2);
+    								num4 += 2;
+    								num13 += 2;
+    								num11 -= 2;
+    							}
+    						}
+    						else
+    						{
+    							num13 = num4 - num12;
+    							do
+    							{
+    								num13 += s.end;
+    							}
+    							while (num13 < 0);
+    							num10 = s.end - num13;
+    							if (num11 > num10)
+    							{
+    								num11 -= num10;
+    								if (num4 - num13 > 0 && num10 > num4 - num13)
+    								{
+    									do
+    									{
+    										s.window[num4++] = s.window[num13++];
+    									}
+    									while (--num10 != 0);
+    								}
+    								else
+    								{
+    									Array.Copy(s.window, num13, s.window, num4, num10);
+    									num4 += num10;
+    									num13 += num10;
+    									num10 = 0;
+    								}
+    								num13 = 0;
+    							}
+    						}
+    						if (num4 - num13 > 0 && num11 > num4 - num13)
+    						{
+    							do
+    							{
+    								s.window[num4++] = s.window[num13++];
+    							}
+    							while (--num11 != 0);
+    							break;
+    						}
+    						Array.Copy(s.window, num13, s.window, num4, num11);
+    						num4 += num11;
+    						num13 += num11;
+    						num11 = 0;
+    						break;
+    					}
+    					if ((num10 & 0x40) == 0)
+    					{
+    						num8 += array[(num9 + num8) * 3 + 2];
+    						num8 += num2 & inflate_mask[num10];
+    						if ((num10 = array[(num9 + num8) * 3]) == 0)
+    						{
+    							num2 >>= array[(num9 + num8) * 3 + 1];
+    							num3 -= array[(num9 + num8) * 3 + 1];
+    							s.window[num4++] = (byte)array[(num9 + num8) * 3 + 2];
+    							num5--;
+    							break;
+    						}
+    						continue;
+    					}
+    					if (((uint)num10 & 0x20u) != 0)
+    					{
+    						num11 = z.avail_in - num;
+    						num11 = ((num3 >> 3 < num11) ? (num3 >> 3) : num11);
+    						num += num11;
+    						next_in_index -= num11;
+    						num3 -= num11 << 3;
+    						s.bitb = num2;
+    						s.bitk = num3;
+    						z.avail_in = num;
+    						z.total_in += next_in_index - z.next_in_index;
+    						z.next_in_index = next_in_index;
+    						s.write = num4;
+    						return 1;
+    					}
+    					z.msg = "invalid literal/length code";
+    					num11 = z.avail_in - num;
+    					num11 = ((num3 >> 3 < num11) ? (num3 >> 3) : num11);
+    					num += num11;
+    					next_in_index -= num11;
+    					num3 -= num11 << 3;
+    					s.bitb = num2;
+    					s.bitk = num3;
+    					z.avail_in = num;
+    					z.total_in += next_in_index - z.next_in_index;
+    					z.next_in_index = next_in_index;
+    					s.write = num4;
+    					return -3;
+    				}
+    			}
+    			if (num5 < 258 || num < 10)
+    			{
+    				break;
+    			}
+    		}
+    		num11 = z.avail_in - num;
+    		num11 = ((num3 >> 3 < num11) ? (num3 >> 3) : num11);
+    		num += num11;
+    		next_in_index -= num11;
+    		num3 -= num11 << 3;
+    		s.bitb = num2;
+    		s.bitk = num3;
+    		z.avail_in = num;
+    		z.total_in += next_in_index - z.next_in_index;
+    		z.next_in_index = next_in_index;
+    		s.write = num4;
+    		return 0;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfTree.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfTree.cs
new file mode 100644
index 00000000..3d05472c
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/InfTree.cs
@@ -0,0 +1,479 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class InfTree
+    {
+    	private const int MANY = 1440;
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	internal const int fixed_bl = 9;
+
+    	internal const int fixed_bd = 5;
+
+    	internal static readonly int[] fixed_tl = new int[1536]
+    	{
+    		96, 7, 256, 0, 8, 80, 0, 8, 16, 84,
+    		8, 115, 82, 7, 31, 0, 8, 112, 0, 8,
+    		48, 0, 9, 192, 80, 7, 10, 0, 8, 96,
+    		0, 8, 32, 0, 9, 160, 0, 8, 0, 0,
+    		8, 128, 0, 8, 64, 0, 9, 224, 80, 7,
+    		6, 0, 8, 88, 0, 8, 24, 0, 9, 144,
+    		83, 7, 59, 0, 8, 120, 0, 8, 56, 0,
+    		9, 208, 81, 7, 17, 0, 8, 104, 0, 8,
+    		40, 0, 9, 176, 0, 8, 8, 0, 8, 136,
+    		0, 8, 72, 0, 9, 240, 80, 7, 4, 0,
+    		8, 84, 0, 8, 20, 85, 8, 227, 83, 7,
+    		43, 0, 8, 116, 0, 8, 52, 0, 9, 200,
+    		81, 7, 13, 0, 8, 100, 0, 8, 36, 0,
+    		9, 168, 0, 8, 4, 0, 8, 132, 0, 8,
+    		68, 0, 9, 232, 80, 7, 8, 0, 8, 92,
+    		0, 8, 28, 0, 9, 152, 84, 7, 83, 0,
+    		8, 124, 0, 8, 60, 0, 9, 216, 82, 7,
+    		23, 0, 8, 108, 0, 8, 44, 0, 9, 184,
+    		0, 8, 12, 0, 8, 140, 0, 8, 76, 0,
+    		9, 248, 80, 7, 3, 0, 8, 82, 0, 8,
+    		18, 85, 8, 163, 83, 7, 35, 0, 8, 114,
+    		0, 8, 50, 0, 9, 196, 81, 7, 11, 0,
+    		8, 98, 0, 8, 34, 0, 9, 164, 0, 8,
+    		2, 0, 8, 130, 0, 8, 66, 0, 9, 228,
+    		80, 7, 7, 0, 8, 90, 0, 8, 26, 0,
+    		9, 148, 84, 7, 67, 0, 8, 122, 0, 8,
+    		58, 0, 9, 212, 82, 7, 19, 0, 8, 106,
+    		0, 8, 42, 0, 9, 180, 0, 8, 10, 0,
+    		8, 138, 0, 8, 74, 0, 9, 244, 80, 7,
+    		5, 0, 8, 86, 0, 8, 22, 192, 8, 0,
+    		83, 7, 51, 0, 8, 118, 0, 8, 54, 0,
+    		9, 204, 81, 7, 15, 0, 8, 102, 0, 8,
+    		38, 0, 9, 172, 0, 8, 6, 0, 8, 134,
+    		0, 8, 70, 0, 9, 236, 80, 7, 9, 0,
+    		8, 94, 0, 8, 30, 0, 9, 156, 84, 7,
+    		99, 0, 8, 126, 0, 8, 62, 0, 9, 220,
+    		82, 7, 27, 0, 8, 110, 0, 8, 46, 0,
+    		9, 188, 0, 8, 14, 0, 8, 142, 0, 8,
+    		78, 0, 9, 252, 96, 7, 256, 0, 8, 81,
+    		0, 8, 17, 85, 8, 131, 82, 7, 31, 0,
+    		8, 113, 0, 8, 49, 0, 9, 194, 80, 7,
+    		10, 0, 8, 97, 0, 8, 33, 0, 9, 162,
+    		0, 8, 1, 0, 8, 129, 0, 8, 65, 0,
+    		9, 226, 80, 7, 6, 0, 8, 89, 0, 8,
+    		25, 0, 9, 146, 83, 7, 59, 0, 8, 121,
+    		0, 8, 57, 0, 9, 210, 81, 7, 17, 0,
+    		8, 105, 0, 8, 41, 0, 9, 178, 0, 8,
+    		9, 0, 8, 137, 0, 8, 73, 0, 9, 242,
+    		80, 7, 4, 0, 8, 85, 0, 8, 21, 80,
+    		8, 258, 83, 7, 43, 0, 8, 117, 0, 8,
+    		53, 0, 9, 202, 81, 7, 13, 0, 8, 101,
+    		0, 8, 37, 0, 9, 170, 0, 8, 5, 0,
+    		8, 133, 0, 8, 69, 0, 9, 234, 80, 7,
+    		8, 0, 8, 93, 0, 8, 29, 0, 9, 154,
+    		84, 7, 83, 0, 8, 125, 0, 8, 61, 0,
+    		9, 218, 82, 7, 23, 0, 8, 109, 0, 8,
+    		45, 0, 9, 186, 0, 8, 13, 0, 8, 141,
+    		0, 8, 77, 0, 9, 250, 80, 7, 3, 0,
+    		8, 83, 0, 8, 19, 85, 8, 195, 83, 7,
+    		35, 0, 8, 115, 0, 8, 51, 0, 9, 198,
+    		81, 7, 11, 0, 8, 99, 0, 8, 35, 0,
+    		9, 166, 0, 8, 3, 0, 8, 131, 0, 8,
+    		67, 0, 9, 230, 80, 7, 7, 0, 8, 91,
+    		0, 8, 27, 0, 9, 150, 84, 7, 67, 0,
+    		8, 123, 0, 8, 59, 0, 9, 214, 82, 7,
+    		19, 0, 8, 107, 0, 8, 43, 0, 9, 182,
+    		0, 8, 11, 0, 8, 139, 0, 8, 75, 0,
+    		9, 246, 80, 7, 5, 0, 8, 87, 0, 8,
+    		23, 192, 8, 0, 83, 7, 51, 0, 8, 119,
+    		0, 8, 55, 0, 9, 206, 81, 7, 15, 0,
+    		8, 103, 0, 8, 39, 0, 9, 174, 0, 8,
+    		7, 0, 8, 135, 0, 8, 71, 0, 9, 238,
+    		80, 7, 9, 0, 8, 95, 0, 8, 31, 0,
+    		9, 158, 84, 7, 99, 0, 8, 127, 0, 8,
+    		63, 0, 9, 222, 82, 7, 27, 0, 8, 111,
+    		0, 8, 47, 0, 9, 190, 0, 8, 15, 0,
+    		8, 143, 0, 8, 79, 0, 9, 254, 96, 7,
+    		256, 0, 8, 80, 0, 8, 16, 84, 8, 115,
+    		82, 7, 31, 0, 8, 112, 0, 8, 48, 0,
+    		9, 193, 80, 7, 10, 0, 8, 96, 0, 8,
+    		32, 0, 9, 161, 0, 8, 0, 0, 8, 128,
+    		0, 8, 64, 0, 9, 225, 80, 7, 6, 0,
+    		8, 88, 0, 8, 24, 0, 9, 145, 83, 7,
+    		59, 0, 8, 120, 0, 8, 56, 0, 9, 209,
+    		81, 7, 17, 0, 8, 104, 0, 8, 40, 0,
+    		9, 177, 0, 8, 8, 0, 8, 136, 0, 8,
+    		72, 0, 9, 241, 80, 7, 4, 0, 8, 84,
+    		0, 8, 20, 85, 8, 227, 83, 7, 43, 0,
+    		8, 116, 0, 8, 52, 0, 9, 201, 81, 7,
+    		13, 0, 8, 100, 0, 8, 36, 0, 9, 169,
+    		0, 8, 4, 0, 8, 132, 0, 8, 68, 0,
+    		9, 233, 80, 7, 8, 0, 8, 92, 0, 8,
+    		28, 0, 9, 153, 84, 7, 83, 0, 8, 124,
+    		0, 8, 60, 0, 9, 217, 82, 7, 23, 0,
+    		8, 108, 0, 8, 44, 0, 9, 185, 0, 8,
+    		12, 0, 8, 140, 0, 8, 76, 0, 9, 249,
+    		80, 7, 3, 0, 8, 82, 0, 8, 18, 85,
+    		8, 163, 83, 7, 35, 0, 8, 114, 0, 8,
+    		50, 0, 9, 197, 81, 7, 11, 0, 8, 98,
+    		0, 8, 34, 0, 9, 165, 0, 8, 2, 0,
+    		8, 130, 0, 8, 66, 0, 9, 229, 80, 7,
+    		7, 0, 8, 90, 0, 8, 26, 0, 9, 149,
+    		84, 7, 67, 0, 8, 122, 0, 8, 58, 0,
+    		9, 213, 82, 7, 19, 0, 8, 106, 0, 8,
+    		42, 0, 9, 181, 0, 8, 10, 0, 8, 138,
+    		0, 8, 74, 0, 9, 245, 80, 7, 5, 0,
+    		8, 86, 0, 8, 22, 192, 8, 0, 83, 7,
+    		51, 0, 8, 118, 0, 8, 54, 0, 9, 205,
+    		81, 7, 15, 0, 8, 102, 0, 8, 38, 0,
+    		9, 173, 0, 8, 6, 0, 8, 134, 0, 8,
+    		70, 0, 9, 237, 80, 7, 9, 0, 8, 94,
+    		0, 8, 30, 0, 9, 157, 84, 7, 99, 0,
+    		8, 126, 0, 8, 62, 0, 9, 221, 82, 7,
+    		27, 0, 8, 110, 0, 8, 46, 0, 9, 189,
+    		0, 8, 14, 0, 8, 142, 0, 8, 78, 0,
+    		9, 253, 96, 7, 256, 0, 8, 81, 0, 8,
+    		17, 85, 8, 131, 82, 7, 31, 0, 8, 113,
+    		0, 8, 49, 0, 9, 195, 80, 7, 10, 0,
+    		8, 97, 0, 8, 33, 0, 9, 163, 0, 8,
+    		1, 0, 8, 129, 0, 8, 65, 0, 9, 227,
+    		80, 7, 6, 0, 8, 89, 0, 8, 25, 0,
+    		9, 147, 83, 7, 59, 0, 8, 121, 0, 8,
+    		57, 0, 9, 211, 81, 7, 17, 0, 8, 105,
+    		0, 8, 41, 0, 9, 179, 0, 8, 9, 0,
+    		8, 137, 0, 8, 73, 0, 9, 243, 80, 7,
+    		4, 0, 8, 85, 0, 8, 21, 80, 8, 258,
+    		83, 7, 43, 0, 8, 117, 0, 8, 53, 0,
+    		9, 203, 81, 7, 13, 0, 8, 101, 0, 8,
+    		37, 0, 9, 171, 0, 8, 5, 0, 8, 133,
+    		0, 8, 69, 0, 9, 235, 80, 7, 8, 0,
+    		8, 93, 0, 8, 29, 0, 9, 155, 84, 7,
+    		83, 0, 8, 125, 0, 8, 61, 0, 9, 219,
+    		82, 7, 23, 0, 8, 109, 0, 8, 45, 0,
+    		9, 187, 0, 8, 13, 0, 8, 141, 0, 8,
+    		77, 0, 9, 251, 80, 7, 3, 0, 8, 83,
+    		0, 8, 19, 85, 8, 195, 83, 7, 35, 0,
+    		8, 115, 0, 8, 51, 0, 9, 199, 81, 7,
+    		11, 0, 8, 99, 0, 8, 35, 0, 9, 167,
+    		0, 8, 3, 0, 8, 131, 0, 8, 67, 0,
+    		9, 231, 80, 7, 7, 0, 8, 91, 0, 8,
+    		27, 0, 9, 151, 84, 7, 67, 0, 8, 123,
+    		0, 8, 59, 0, 9, 215, 82, 7, 19, 0,
+    		8, 107, 0, 8, 43, 0, 9, 183, 0, 8,
+    		11, 0, 8, 139, 0, 8, 75, 0, 9, 247,
+    		80, 7, 5, 0, 8, 87, 0, 8, 23, 192,
+    		8, 0, 83, 7, 51, 0, 8, 119, 0, 8,
+    		55, 0, 9, 207, 81, 7, 15, 0, 8, 103,
+    		0, 8, 39, 0, 9, 175, 0, 8, 7, 0,
+    		8, 135, 0, 8, 71, 0, 9, 239, 80, 7,
+    		9, 0, 8, 95, 0, 8, 31, 0, 9, 159,
+    		84, 7, 99, 0, 8, 127, 0, 8, 63, 0,
+    		9, 223, 82, 7, 27, 0, 8, 111, 0, 8,
+    		47, 0, 9, 191, 0, 8, 15, 0, 8, 143,
+    		0, 8, 79, 0, 9, 255
+    	};
+
+    	internal static readonly int[] fixed_td = new int[96]
+    	{
+    		80, 5, 1, 87, 5, 257, 83, 5, 17, 91,
+    		5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5,
+    		65, 93, 5, 16385, 80, 5, 3, 88, 5, 513,
+    		84, 5, 33, 92, 5, 8193, 82, 5, 9, 90,
+    		5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5,
+    		2, 87, 5, 385, 83, 5, 25, 91, 5, 6145,
+    		81, 5, 7, 89, 5, 1537, 85, 5, 97, 93,
+    		5, 24577, 80, 5, 4, 88, 5, 769, 84, 5,
+    		49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073,
+    		86, 5, 193, 192, 5, 24577
+    	};
+
+    	internal static readonly int[] cplens = new int[31]
+    	{
+    		3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
+    		15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
+    		67, 83, 99, 115, 131, 163, 195, 227, 258, 0,
+    		0
+    	};
+
+    	internal static readonly int[] cplext = new int[31]
+    	{
+    		0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+    		1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+    		4, 4, 4, 4, 5, 5, 5, 5, 0, 112,
+    		112
+    	};
+
+    	internal static readonly int[] cpdist = new int[30]
+    	{
+    		1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
+    		33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
+    		1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
+    	};
+
+    	internal static readonly int[] cpdext = new int[30]
+    	{
+    		0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+    		4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+    		9, 9, 10, 10, 11, 11, 12, 12, 13, 13
+    	};
+
+    	internal const int BMAX = 15;
+
+    	internal static int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v)
+    	{
+    		int[] array = new int[16];
+    		int[] array2 = new int[3];
+    		int[] array3 = new int[15];
+    		int[] array4 = new int[16];
+    		int num = 0;
+    		int num2 = n;
+    		do
+    		{
+    			array[b[bindex + num]]++;
+    			num++;
+    			num2--;
+    		}
+    		while (num2 != 0);
+    		if (array[0] == n)
+    		{
+    			t[0] = -1;
+    			m[0] = 0;
+    			return 0;
+    		}
+    		int num3 = m[0];
+    		int i;
+    		for (i = 1; i <= 15 && array[i] == 0; i++)
+    		{
+    		}
+    		int j = i;
+    		if (num3 < i)
+    		{
+    			num3 = i;
+    		}
+    		num2 = 15;
+    		while (num2 != 0 && array[num2] == 0)
+    		{
+    			num2--;
+    		}
+    		int num4 = num2;
+    		if (num3 > num2)
+    		{
+    			num3 = num2;
+    		}
+    		m[0] = num3;
+    		int num5 = 1 << i;
+    		while (i < num2)
+    		{
+    			if ((num5 -= array[i]) < 0)
+    			{
+    				return -3;
+    			}
+    			i++;
+    			num5 <<= 1;
+    		}
+    		if ((num5 -= array[num2]) < 0)
+    		{
+    			return -3;
+    		}
+    		array[num2] += num5;
+    		i = (array4[1] = 0);
+    		num = 1;
+    		int num6 = 2;
+    		while (--num2 != 0)
+    		{
+    			i = (array4[num6] = i + array[num]);
+    			num6++;
+    			num++;
+    		}
+    		num2 = 0;
+    		num = 0;
+    		do
+    		{
+    			if ((i = b[bindex + num]) != 0)
+    			{
+    				v[array4[i]++] = num2;
+    			}
+    			num++;
+    		}
+    		while (++num2 < n);
+    		n = array4[num4];
+    		num2 = (array4[0] = 0);
+    		num = 0;
+    		int num7 = -1;
+    		int num8 = -num3;
+    		array3[0] = 0;
+    		int num9 = 0;
+    		int num10 = 0;
+    		for (; j <= num4; j++)
+    		{
+    			int num11 = array[j];
+    			while (num11-- != 0)
+    			{
+    				int num12;
+    				while (j > num8 + num3)
+    				{
+    					num7++;
+    					num8 += num3;
+    					num10 = num4 - num8;
+    					num10 = ((num10 > num3) ? num3 : num10);
+    					if ((num12 = 1 << (i = j - num8)) > num11 + 1)
+    					{
+    						num12 -= num11 + 1;
+    						num6 = j;
+    						if (i < num10)
+    						{
+    							while (++i < num10 && (num12 <<= 1) > array[++num6])
+    							{
+    								num12 -= array[num6];
+    							}
+    						}
+    					}
+    					num10 = 1 << i;
+    					if (hn[0] + num10 > 1440)
+    					{
+    						return -3;
+    					}
+    					num9 = (array3[num7] = hn[0]);
+    					hn[0] += num10;
+    					if (num7 != 0)
+    					{
+    						array4[num7] = num2;
+    						array2[0] = (byte)i;
+    						array2[1] = (byte)num3;
+    						i = SupportClass.URShift(num2, num8 - num3);
+    						array2[2] = num9 - array3[num7 - 1] - i;
+    						Array.Copy(array2, 0, hp, (array3[num7 - 1] + i) * 3, 3);
+    					}
+    					else
+    					{
+    						t[0] = num9;
+    					}
+    				}
+    				array2[1] = (byte)(j - num8);
+    				if (num >= n)
+    				{
+    					array2[0] = 192;
+    				}
+    				else if (v[num] < s)
+    				{
+    					array2[0] = (byte)((v[num] >= 256) ? 96 : 0);
+    					array2[2] = v[num++];
+    				}
+    				else
+    				{
+    					array2[0] = (byte)(e[v[num] - s] + 16 + 64);
+    					array2[2] = d[v[num++] - s];
+    				}
+    				num12 = 1 << j - num8;
+    				for (i = SupportClass.URShift(num2, num8); i < num10; i += num12)
+    				{
+    					Array.Copy(array2, 0, hp, (num9 + i) * 3, 3);
+    				}
+    				i = 1 << j - 1;
+    				while ((num2 & i) != 0)
+    				{
+    					num2 ^= i;
+    					i = SupportClass.URShift(i, 1);
+    				}
+    				num2 ^= i;
+    				int num13 = (1 << num8) - 1;
+    				while ((num2 & num13) != array4[num7])
+    				{
+    					num7--;
+    					num8 -= num3;
+    					num13 = (1 << num8) - 1;
+    				}
+    			}
+    		}
+    		if (num5 == 0 || num4 == 1)
+    		{
+    			return 0;
+    		}
+    		return -5;
+    	}
+
+    	internal static int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z)
+    	{
+    		int[] hn = new int[1];
+    		int[] v = new int[19];
+    		int num = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+    		if (num == -3)
+    		{
+    			z.msg = "oversubscribed dynamic bit lengths tree";
+    		}
+    		else if (num == -5 || bb[0] == 0)
+    		{
+    			z.msg = "incomplete dynamic bit lengths tree";
+    			num = -3;
+    		}
+    		return num;
+    	}
+
+    	internal static int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z)
+    	{
+    		int[] hn = new int[1];
+    		int[] v = new int[288];
+    		int num = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+    		if (num != 0 || bl[0] == 0)
+    		{
+    			switch (num)
+    			{
+    			case -3:
+    				z.msg = "oversubscribed literal/length tree";
+    				break;
+    			default:
+    				z.msg = "incomplete literal/length tree";
+    				num = -3;
+    				break;
+    			case -4:
+    				break;
+    			}
+    			return num;
+    		}
+    		num = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+    		if (num != 0 || (bd[0] == 0 && nl > 257))
+    		{
+    			switch (num)
+    			{
+    			case -3:
+    				z.msg = "oversubscribed distance tree";
+    				break;
+    			case -5:
+    				z.msg = "incomplete distance tree";
+    				num = -3;
+    				break;
+    			default:
+    				z.msg = "empty distance tree with lengths";
+    				num = -3;
+    				break;
+    			case -4:
+    				break;
+    			}
+    			return num;
+    		}
+    		return 0;
+    	}
+
+    	internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z)
+    	{
+    		bl[0] = 9;
+    		bd[0] = 5;
+    		tl[0] = fixed_tl;
+    		td[0] = fixed_td;
+    		return 0;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Inflate.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Inflate.cs
new file mode 100644
index 00000000..5aea0eb3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Inflate.cs
@@ -0,0 +1,409 @@
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class Inflate
+    {
+    	private const int MAX_WBITS = 15;
+
+    	private const int PRESET_DICT = 32;
+
+    	internal const int Z_NO_FLUSH = 0;
+
+    	internal const int Z_PARTIAL_FLUSH = 1;
+
+    	internal const int Z_SYNC_FLUSH = 2;
+
+    	internal const int Z_FULL_FLUSH = 3;
+
+    	internal const int Z_FINISH = 4;
+
+    	private const int Z_DEFLATED = 8;
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	private const int METHOD = 0;
+
+    	private const int FLAG = 1;
+
+    	private const int DICT4 = 2;
+
+    	private const int DICT3 = 3;
+
+    	private const int DICT2 = 4;
+
+    	private const int DICT1 = 5;
+
+    	private const int DICT0 = 6;
+
+    	private const int BLOCKS = 7;
+
+    	private const int CHECK4 = 8;
+
+    	private const int CHECK3 = 9;
+
+    	private const int CHECK2 = 10;
+
+    	private const int CHECK1 = 11;
+
+    	private const int DONE = 12;
+
+    	private const int BAD = 13;
+
+    	internal int mode;
+
+    	internal int method;
+
+    	internal long[] was = new long[1];
+
+    	internal long need;
+
+    	internal int marker;
+
+    	internal int nowrap;
+
+    	internal int wbits;
+
+    	internal InfBlocks blocks;
+
+    	private static byte[] mark = new byte[4]
+    	{
+    		0,
+    		0,
+    		(byte)SupportClass.Identity(255L),
+    		(byte)SupportClass.Identity(255L)
+    	};
+
+    	internal int inflateReset(ZStream z)
+    	{
+    		if (z == null || z.istate == null)
+    		{
+    			return -2;
+    		}
+    		z.total_in = (z.total_out = 0L);
+    		z.msg = null;
+    		z.istate.mode = ((z.istate.nowrap != 0) ? 7 : 0);
+    		z.istate.blocks.reset(z, null);
+    		return 0;
+    	}
+
+    	internal int inflateEnd(ZStream z)
+    	{
+    		if (blocks != null)
+    		{
+    			blocks.free(z);
+    		}
+    		blocks = null;
+    		return 0;
+    	}
+
+    	internal int inflateInit(ZStream z, int w)
+    	{
+    		z.msg = null;
+    		blocks = null;
+    		nowrap = 0;
+    		if (w < 0)
+    		{
+    			w = -w;
+    			nowrap = 1;
+    		}
+    		if (w < 8 || w > 15)
+    		{
+    			inflateEnd(z);
+    			return -2;
+    		}
+    		wbits = w;
+    		z.istate.blocks = new InfBlocks(z, (z.istate.nowrap != 0) ? null : this, 1 << w);
+    		inflateReset(z);
+    		return 0;
+    	}
+
+    	internal int inflate(ZStream z, int f)
+    	{
+    		if (z == null || z.istate == null || z.next_in == null)
+    		{
+    			return -2;
+    		}
+    		f = ((f == 4) ? (-5) : 0);
+    		int num = -5;
+    		while (true)
+    		{
+    			switch (z.istate.mode)
+    			{
+    			case 0:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xF) != 8)
+    				{
+    					z.istate.mode = 13;
+    					z.msg = "unknown compression method";
+    					z.istate.marker = 5;
+    					break;
+    				}
+    				if ((z.istate.method >> 4) + 8 > z.istate.wbits)
+    				{
+    					z.istate.mode = 13;
+    					z.msg = "invalid window size";
+    					z.istate.marker = 5;
+    					break;
+    				}
+    				z.istate.mode = 1;
+    				goto case 1;
+    			case 1:
+    			{
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				int num2 = z.next_in[z.next_in_index++] & 0xFF;
+    				if (((z.istate.method << 8) + num2) % 31 != 0)
+    				{
+    					z.istate.mode = 13;
+    					z.msg = "incorrect header check";
+    					z.istate.marker = 5;
+    					break;
+    				}
+    				if ((num2 & 0x20) == 0)
+    				{
+    					z.istate.mode = 7;
+    					break;
+    				}
+    				z.istate.mode = 2;
+    				goto case 2;
+    			}
+    			case 2:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need = ((z.next_in[z.next_in_index++] & 0xFF) << 24) & -16777216;
+    				z.istate.mode = 3;
+    				goto case 3;
+    			case 3:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 16) & 0xFF0000uL);
+    				z.istate.mode = 4;
+    				goto case 4;
+    			case 4:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 8) & 0xFF00uL);
+    				z.istate.mode = 5;
+    				goto case 5;
+    			case 5:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 0xFFuL);
+    				z.adler = z.istate.need;
+    				z.istate.mode = 6;
+    				return 2;
+    			case 6:
+    				z.istate.mode = 13;
+    				z.msg = "need dictionary";
+    				z.istate.marker = 0;
+    				return -2;
+    			case 7:
+    				num = z.istate.blocks.proc(z, num);
+    				switch (num)
+    				{
+    				case -3:
+    					z.istate.mode = 13;
+    					z.istate.marker = 0;
+    					goto end_IL_0031;
+    				case 0:
+    					num = f;
+    					break;
+    				}
+    				if (num != 1)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.istate.blocks.reset(z, z.istate.was);
+    				if (z.istate.nowrap != 0)
+    				{
+    					z.istate.mode = 12;
+    					break;
+    				}
+    				z.istate.mode = 8;
+    				goto case 8;
+    			case 8:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need = ((z.next_in[z.next_in_index++] & 0xFF) << 24) & -16777216;
+    				z.istate.mode = 9;
+    				goto case 9;
+    			case 9:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 16) & 0xFF0000uL);
+    				z.istate.mode = 10;
+    				goto case 10;
+    			case 10:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)((z.next_in[z.next_in_index++] & 0xFF) << 8) & 0xFF00uL);
+    				z.istate.mode = 11;
+    				goto case 11;
+    			case 11:
+    				if (z.avail_in == 0)
+    				{
+    					return num;
+    				}
+    				num = f;
+    				z.avail_in--;
+    				z.total_in++;
+    				z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 0xFFuL);
+    				if ((int)z.istate.was[0] != (int)z.istate.need)
+    				{
+    					z.istate.mode = 13;
+    					z.msg = "incorrect data check";
+    					z.istate.marker = 5;
+    					break;
+    				}
+    				z.istate.mode = 12;
+    				goto case 12;
+    			case 12:
+    				return 1;
+    			case 13:
+    				return -3;
+    			default:
+    				{
+    					return -2;
+    				}
+    				end_IL_0031:
+    				break;
+    			}
+    		}
+    	}
+
+    	internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength)
+    	{
+    		int start = 0;
+    		int num = dictLength;
+    		if (z == null || z.istate == null || z.istate.mode != 6)
+    		{
+    			return -2;
+    		}
+    		if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler)
+    		{
+    			return -3;
+    		}
+    		z.adler = z._adler.adler32(0L, null, 0, 0);
+    		if (num >= 1 << z.istate.wbits)
+    		{
+    			num = (1 << z.istate.wbits) - 1;
+    			start = dictLength - num;
+    		}
+    		z.istate.blocks.set_dictionary(dictionary, start, num);
+    		z.istate.mode = 7;
+    		return 0;
+    	}
+
+    	internal int inflateSync(ZStream z)
+    	{
+    		if (z == null || z.istate == null)
+    		{
+    			return -2;
+    		}
+    		if (z.istate.mode != 13)
+    		{
+    			z.istate.mode = 13;
+    			z.istate.marker = 0;
+    		}
+    		int num;
+    		if ((num = z.avail_in) == 0)
+    		{
+    			return -5;
+    		}
+    		int num2 = z.next_in_index;
+    		int num3 = z.istate.marker;
+    		while (num != 0 && num3 < 4)
+    		{
+    			num3 = ((z.next_in[num2] != mark[num3]) ? ((z.next_in[num2] == 0) ? (4 - num3) : 0) : (num3 + 1));
+    			num2++;
+    			num--;
+    		}
+    		z.total_in += num2 - z.next_in_index;
+    		z.next_in_index = num2;
+    		z.avail_in = num;
+    		z.istate.marker = num3;
+    		if (num3 != 4)
+    		{
+    			return -3;
+    		}
+    		long total_in = z.total_in;
+    		long total_out = z.total_out;
+    		inflateReset(z);
+    		z.total_in = total_in;
+    		z.total_out = total_out;
+    		z.istate.mode = 7;
+    		return 0;
+    	}
+
+    	internal int inflateSyncPoint(ZStream z)
+    	{
+    		if (z == null || z.istate == null || z.istate.blocks == null)
+    		{
+    			return -2;
+    		}
+    		return z.istate.blocks.sync_point();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/StaticTree.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/StaticTree.cs
new file mode 100644
index 00000000..eba1f819
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/StaticTree.cs
@@ -0,0 +1,126 @@
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class StaticTree
+    {
+    	private const int MAX_BITS = 15;
+
+    	private const int BL_CODES = 19;
+
+    	private const int D_CODES = 30;
+
+    	private const int LITERALS = 256;
+
+    	private const int LENGTH_CODES = 29;
+
+    	private static readonly int L_CODES;
+
+    	internal const int MAX_BL_BITS = 7;
+
+    	internal static readonly short[] static_ltree;
+
+    	internal static readonly short[] static_dtree;
+
+    	internal static StaticTree static_l_desc;
+
+    	internal static StaticTree static_d_desc;
+
+    	internal static StaticTree static_bl_desc;
+
+    	internal short[] static_tree;
+
+    	internal int[] extra_bits;
+
+    	internal int extra_base;
+
+    	internal int elems;
+
+    	internal int max_length;
+
+    	internal StaticTree(short[] static_tree, int[] extra_bits, int extra_base, int elems, int max_length)
+    	{
+    		this.static_tree = static_tree;
+    		this.extra_bits = extra_bits;
+    		this.extra_base = extra_base;
+    		this.elems = elems;
+    		this.max_length = max_length;
+    	}
+
+    	static StaticTree()
+    	{
+    		L_CODES = 286;
+    		static_ltree = new short[576]
+    		{
+    			12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+    			172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+    			92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+    			252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+    			34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+    			146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+    			114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+    			202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+    			26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+    			186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+    			70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+    			230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+    			54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+    			142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+    			110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+    			222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+    			1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+    			161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+    			81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+    			241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+    			41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+    			153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+    			121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+    			197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+    			21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+    			181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+    			77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+    			237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+    			61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+    			275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+    			211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+    			435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+    			11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+    			331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+    			171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+    			491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+    			91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+    			315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+    			251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+    			391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+    			39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+    			359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+    			151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+    			471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+    			119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+    			271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+    			207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+    			431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+    			31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+    			351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+    			191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+    			511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+    			16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+    			72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+    			56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+    			100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+    			3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+    			163, 8, 99, 8, 227, 8
+    		};
+    		static_dtree = new short[60]
+    		{
+    			0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+    			20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+    			10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+    			30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+    			5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+    			19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+    		};
+    		static_l_desc = new StaticTree(static_ltree, Tree.extra_lbits, 257, L_CODES, 15);
+    		static_d_desc = new StaticTree(static_dtree, Tree.extra_dbits, 0, 30, 15);
+    		static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, 19, 7);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/SupportClass.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/SupportClass.cs
new file mode 100644
index 00000000..509d185d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/SupportClass.cs
@@ -0,0 +1,104 @@
+using System.IO;
+using System.Text;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public class SupportClass
+    {
+    	public static long Identity(long literal)
+    	{
+    		return literal;
+    	}
+
+    	public static ulong Identity(ulong literal)
+    	{
+    		return literal;
+    	}
+
+    	public static float Identity(float literal)
+    	{
+    		return literal;
+    	}
+
+    	public static double Identity(double literal)
+    	{
+    		return literal;
+    	}
+
+    	public static int URShift(int number, int bits)
+    	{
+    		if (number >= 0)
+    		{
+    			return number >> bits;
+    		}
+    		return (number >> bits) + (2 << ~bits);
+    	}
+
+    	public static int URShift(int number, long bits)
+    	{
+    		return URShift(number, (int)bits);
+    	}
+
+    	public static long URShift(long number, int bits)
+    	{
+    		if (number >= 0)
+    		{
+    			return number >> bits;
+    		}
+    		return (number >> bits) + (2L << ~bits);
+    	}
+
+    	public static long URShift(long number, long bits)
+    	{
+    		return URShift(number, (int)bits);
+    	}
+
+    	public static int ReadInput(Stream sourceStream, byte[] target, int start, int count)
+    	{
+    		if (target.Length == 0)
+    		{
+    			return 0;
+    		}
+    		byte[] array = new byte[target.Length];
+    		int num = sourceStream.Read(array, start, count);
+    		if (num == 0)
+    		{
+    			return -1;
+    		}
+    		for (int i = start; i < start + num; i++)
+    		{
+    			target[i] = array[i];
+    		}
+    		return num;
+    	}
+
+    	public static int ReadInput(TextReader sourceTextReader, byte[] target, int start, int count)
+    	{
+    		if (target.Length == 0)
+    		{
+    			return 0;
+    		}
+    		char[] array = new char[target.Length];
+    		int num = sourceTextReader.Read(array, start, count);
+    		if (num == 0)
+    		{
+    			return -1;
+    		}
+    		for (int i = start; i < start + num; i++)
+    		{
+    			target[i] = (byte)array[i];
+    		}
+    		return num;
+    	}
+
+    	public static byte[] ToByteArray(string sourceString)
+    	{
+    		return Encoding.UTF8.GetBytes(sourceString);
+    	}
+
+    	public static char[] ToCharArray(byte[] byteArray)
+    	{
+    		return Encoding.UTF8.GetChars(byteArray);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Tree.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Tree.cs
new file mode 100644
index 00000000..4f5cb73a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Tree.cs
@@ -0,0 +1,341 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    internal sealed class Tree
+    {
+    	private const int MAX_BITS = 15;
+
+    	private const int BL_CODES = 19;
+
+    	private const int D_CODES = 30;
+
+    	private const int LITERALS = 256;
+
+    	private const int LENGTH_CODES = 29;
+
+    	private static readonly int L_CODES = 286;
+
+    	private static readonly int HEAP_SIZE = 2 * L_CODES + 1;
+
+    	internal const int MAX_BL_BITS = 7;
+
+    	internal const int END_BLOCK = 256;
+
+    	internal const int REP_3_6 = 16;
+
+    	internal const int REPZ_3_10 = 17;
+
+    	internal const int REPZ_11_138 = 18;
+
+    	internal static readonly int[] extra_lbits = new int[29]
+    	{
+    		0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+    		1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+    		4, 4, 4, 4, 5, 5, 5, 5, 0
+    	};
+
+    	internal static readonly int[] extra_dbits = new int[30]
+    	{
+    		0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
+    		4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
+    		9, 9, 10, 10, 11, 11, 12, 12, 13, 13
+    	};
+
+    	internal static readonly int[] extra_blbits = new int[19]
+    	{
+    		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    		0, 0, 0, 0, 0, 0, 2, 3, 7
+    	};
+
+    	internal static readonly byte[] bl_order = new byte[19]
+    	{
+    		16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
+    		11, 4, 12, 3, 13, 2, 14, 1, 15
+    	};
+
+    	internal const int Buf_size = 16;
+
+    	internal const int DIST_CODE_LEN = 512;
+
+    	internal static readonly byte[] _dist_code = new byte[512]
+    	{
+    		0, 1, 2, 3, 4, 4, 5, 5, 6, 6,
+    		6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+    		8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
+    		9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+    		10, 10, 10, 10, 10, 10, 10, 10, 11, 11,
+    		11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    		11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+    		12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    		12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    		12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+    		13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    		13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    		13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    		14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    		15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+    		18, 18, 19, 19, 20, 20, 20, 20, 21, 21,
+    		21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+    		23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
+    		24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    		24, 24, 24, 24, 25, 25, 25, 25, 25, 25,
+    		25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+    		26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+    		28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+    		29, 29
+    	};
+
+    	internal static readonly byte[] _length_code = new byte[256]
+    	{
+    		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
+    		9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+    		13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
+    		15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+    		17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
+    		18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+    		19, 19, 19, 19, 20, 20, 20, 20, 20, 20,
+    		20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+    		21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+    		21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+    		22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+    		22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+    		23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
+    		24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    		24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    		24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+    		25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+    		25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+    		25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+    		25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+    		26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+    		27, 27, 27, 27, 27, 28
+    	};
+
+    	internal static readonly int[] base_length = new int[29]
+    	{
+    		0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
+    		12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+    		64, 80, 96, 112, 128, 160, 192, 224, 0
+    	};
+
+    	internal static readonly int[] base_dist = new int[30]
+    	{
+    		0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+    		32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+    		1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+    	};
+
+    	internal short[] dyn_tree;
+
+    	internal int max_code;
+
+    	internal StaticTree stat_desc;
+
+    	internal static int d_code(int dist)
+    	{
+    		if (dist >= 256)
+    		{
+    			return _dist_code[256 + SupportClass.URShift(dist, 7)];
+    		}
+    		return _dist_code[dist];
+    	}
+
+    	internal void gen_bitlen(Deflate s)
+    	{
+    		short[] array = dyn_tree;
+    		short[] static_tree = stat_desc.static_tree;
+    		int[] extra_bits = stat_desc.extra_bits;
+    		int extra_base = stat_desc.extra_base;
+    		int max_length = stat_desc.max_length;
+    		int num = 0;
+    		for (int i = 0; i <= 15; i++)
+    		{
+    			s.bl_count[i] = 0;
+    		}
+    		array[s.heap[s.heap_max] * 2 + 1] = 0;
+    		int j;
+    		for (j = s.heap_max + 1; j < HEAP_SIZE; j++)
+    		{
+    			int num2 = s.heap[j];
+    			int i = array[array[num2 * 2 + 1] * 2 + 1] + 1;
+    			if (i > max_length)
+    			{
+    				i = max_length;
+    				num++;
+    			}
+    			array[num2 * 2 + 1] = (short)i;
+    			if (num2 <= max_code)
+    			{
+    				s.bl_count[i]++;
+    				int num3 = 0;
+    				if (num2 >= extra_base)
+    				{
+    					num3 = extra_bits[num2 - extra_base];
+    				}
+    				short num4 = array[num2 * 2];
+    				s.opt_len += num4 * (i + num3);
+    				if (static_tree != null)
+    				{
+    					s.static_len += num4 * (static_tree[num2 * 2 + 1] + num3);
+    				}
+    			}
+    		}
+    		if (num == 0)
+    		{
+    			return;
+    		}
+    		do
+    		{
+    			int i = max_length - 1;
+    			while (s.bl_count[i] == 0)
+    			{
+    				i--;
+    			}
+    			s.bl_count[i]--;
+    			s.bl_count[i + 1] = (short)(s.bl_count[i + 1] + 2);
+    			s.bl_count[max_length]--;
+    			num -= 2;
+    		}
+    		while (num > 0);
+    		for (int i = max_length; i != 0; i--)
+    		{
+    			int num2 = s.bl_count[i];
+    			while (num2 != 0)
+    			{
+    				int num5 = s.heap[--j];
+    				if (num5 <= max_code)
+    				{
+    					if (array[num5 * 2 + 1] != i)
+    					{
+    						s.opt_len = (int)(s.opt_len + ((long)i - (long)array[num5 * 2 + 1]) * array[num5 * 2]);
+    						array[num5 * 2 + 1] = (short)i;
+    					}
+    					num2--;
+    				}
+    			}
+    		}
+    	}
+
+    	internal void build_tree(Deflate s)
+    	{
+    		short[] array = dyn_tree;
+    		short[] static_tree = stat_desc.static_tree;
+    		int elems = stat_desc.elems;
+    		int num = -1;
+    		s.heap_len = 0;
+    		s.heap_max = HEAP_SIZE;
+    		for (int i = 0; i < elems; i++)
+    		{
+    			if (array[i * 2] != 0)
+    			{
+    				num = (s.heap[++s.heap_len] = i);
+    				s.depth[i] = 0;
+    			}
+    			else
+    			{
+    				array[i * 2 + 1] = 0;
+    			}
+    		}
+    		int num2;
+    		while (s.heap_len < 2)
+    		{
+    			num2 = (s.heap[++s.heap_len] = ((num < 2) ? (++num) : 0));
+    			array[num2 * 2] = 1;
+    			s.depth[num2] = 0;
+    			s.opt_len--;
+    			if (static_tree != null)
+    			{
+    				s.static_len -= static_tree[num2 * 2 + 1];
+    			}
+    		}
+    		max_code = num;
+    		for (int i = s.heap_len / 2; i >= 1; i--)
+    		{
+    			s.pqdownheap(array, i);
+    		}
+    		num2 = elems;
+    		do
+    		{
+    			int i = s.heap[1];
+    			s.heap[1] = s.heap[s.heap_len--];
+    			s.pqdownheap(array, 1);
+    			int num3 = s.heap[1];
+    			s.heap[--s.heap_max] = i;
+    			s.heap[--s.heap_max] = num3;
+    			array[num2 * 2] = (short)(array[i * 2] + array[num3 * 2]);
+    			s.depth[num2] = (byte)(Math.Max(s.depth[i], s.depth[num3]) + 1);
+    			array[i * 2 + 1] = (array[num3 * 2 + 1] = (short)num2);
+    			s.heap[1] = num2++;
+    			s.pqdownheap(array, 1);
+    		}
+    		while (s.heap_len >= 2);
+    		s.heap[--s.heap_max] = s.heap[1];
+    		gen_bitlen(s);
+    		gen_codes(array, num, s.bl_count);
+    	}
+
+    	internal static void gen_codes(short[] tree, int max_code, short[] bl_count)
+    	{
+    		short[] array = new short[16];
+    		short num = 0;
+    		for (int i = 1; i <= 15; i++)
+    		{
+    			num = (array[i] = (short)(num + bl_count[i - 1] << 1));
+    		}
+    		for (int j = 0; j <= max_code; j++)
+    		{
+    			int num2 = tree[j * 2 + 1];
+    			if (num2 != 0)
+    			{
+    				tree[j * 2] = (short)bi_reverse(array[num2]++, num2);
+    			}
+    		}
+    	}
+
+    	internal static int bi_reverse(int code, int len)
+    	{
+    		int num = 0;
+    		do
+    		{
+    			num |= code & 1;
+    			code = SupportClass.URShift(code, 1);
+    			num <<= 1;
+    		}
+    		while (--len > 0);
+    		return SupportClass.URShift(num, 1);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZInputStream.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZInputStream.cs
new file mode 100644
index 00000000..5a9effcf
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZInputStream.cs
@@ -0,0 +1,134 @@
+using System.IO;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public class ZInputStream : BinaryReader
+    {
+    	protected ZStream z = new ZStream();
+
+    	protected int bufsize = 512;
+
+    	protected int flush;
+
+    	protected byte[] buf;
+
+    	protected byte[] buf1 = new byte[1];
+
+    	protected bool compress;
+
+    	internal Stream in_Renamed;
+
+    	internal bool nomoreinput;
+
+    	public virtual int FlushMode
+    	{
+    		get
+    		{
+    			return flush;
+    		}
+    		set
+    		{
+    			flush = value;
+    		}
+    	}
+
+    	public virtual long TotalIn => z.total_in;
+
+    	public virtual long TotalOut => z.total_out;
+
+    	internal void InitBlock()
+    	{
+    		flush = 0;
+    		buf = new byte[bufsize];
+    	}
+
+    	public ZInputStream(Stream in_Renamed)
+    		: base(in_Renamed)
+    	{
+    		InitBlock();
+    		this.in_Renamed = in_Renamed;
+    		z.inflateInit();
+    		compress = false;
+    		z.next_in = buf;
+    		z.next_in_index = 0;
+    		z.avail_in = 0;
+    	}
+
+    	public ZInputStream(Stream in_Renamed, int level)
+    		: base(in_Renamed)
+    	{
+    		InitBlock();
+    		this.in_Renamed = in_Renamed;
+    		z.deflateInit(level);
+    		compress = true;
+    		z.next_in = buf;
+    		z.next_in_index = 0;
+    		z.avail_in = 0;
+    	}
+
+    	public override int Read()
+    	{
+    		if (read(buf1, 0, 1) == -1)
+    		{
+    			return -1;
+    		}
+    		return buf1[0] & 0xFF;
+    	}
+
+    	public int read(byte[] b, int off, int len)
+    	{
+    		if (len == 0)
+    		{
+    			return 0;
+    		}
+    		z.next_out = b;
+    		z.next_out_index = off;
+    		z.avail_out = len;
+    		int num;
+    		do
+    		{
+    			if (z.avail_in == 0 && !nomoreinput)
+    			{
+    				z.next_in_index = 0;
+    				z.avail_in = SupportClass.ReadInput(in_Renamed, buf, 0, bufsize);
+    				if (z.avail_in == -1)
+    				{
+    					z.avail_in = 0;
+    					nomoreinput = true;
+    				}
+    			}
+    			num = ((!compress) ? z.inflate(flush) : z.deflate(flush));
+    			if (nomoreinput && num == -5)
+    			{
+    				return -1;
+    			}
+    			if (num != 0 && num != 1)
+    			{
+    				throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+    			}
+    			if (nomoreinput && z.avail_out == len)
+    			{
+    				return -1;
+    			}
+    		}
+    		while (z.avail_out == len && num == 0);
+    		return len - z.avail_out;
+    	}
+
+    	public long skip(long n)
+    	{
+    		int num = 512;
+    		if (n < num)
+    		{
+    			num = (int)n;
+    		}
+    		byte[] array = new byte[num];
+    		return SupportClass.ReadInput(BaseStream, array, 0, array.Length);
+    	}
+
+    	public override void Close()
+    	{
+    		in_Renamed.Close();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZOutputStream.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZOutputStream.cs
new file mode 100644
index 00000000..84492772
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZOutputStream.cs
@@ -0,0 +1,193 @@
+using System;
+using System.IO;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public class ZOutputStream : Stream
+    {
+    	protected internal ZStream z = new ZStream();
+
+    	protected internal int bufsize = 4096;
+
+    	protected internal int flush_Renamed_Field;
+
+    	protected internal byte[] buf;
+
+    	protected internal byte[] buf1 = new byte[1];
+
+    	protected internal bool compress;
+
+    	private Stream out_Renamed;
+
+    	public virtual int FlushMode
+    	{
+    		get
+    		{
+    			return flush_Renamed_Field;
+    		}
+    		set
+    		{
+    			flush_Renamed_Field = value;
+    		}
+    	}
+
+    	public virtual long TotalIn => z.total_in;
+
+    	public virtual long TotalOut => z.total_out;
+
+    	public override bool CanRead => false;
+
+    	public override bool CanSeek => false;
+
+    	public override bool CanWrite => false;
+
+    	public override long Length => 0L;
+
+    	public override long Position
+    	{
+    		get
+    		{
+    			return 0L;
+    		}
+    		set
+    		{
+    		}
+    	}
+
+    	private void InitBlock()
+    	{
+    		flush_Renamed_Field = 0;
+    		buf = new byte[bufsize];
+    	}
+
+    	public ZOutputStream(Stream out_Renamed)
+    	{
+    		InitBlock();
+    		this.out_Renamed = out_Renamed;
+    		z.inflateInit();
+    		compress = false;
+    	}
+
+    	public ZOutputStream(Stream out_Renamed, int level)
+    	{
+    		InitBlock();
+    		this.out_Renamed = out_Renamed;
+    		z.deflateInit(level);
+    		compress = true;
+    	}
+
+    	public void WriteByte(int b)
+    	{
+    		buf1[0] = (byte)b;
+    		Write(buf1, 0, 1);
+    	}
+
+    	public override void WriteByte(byte b)
+    	{
+    		WriteByte(b);
+    	}
+
+    	public override void Write(byte[] b1, int off, int len)
+    	{
+    		if (len == 0)
+    		{
+    			return;
+    		}
+    		byte[] array = new byte[b1.Length];
+    		Array.Copy(b1, 0, array, 0, b1.Length);
+    		z.next_in = array;
+    		z.next_in_index = off;
+    		z.avail_in = len;
+    		do
+    		{
+    			z.next_out = buf;
+    			z.next_out_index = 0;
+    			z.avail_out = bufsize;
+    			int num = ((!compress) ? z.inflate(flush_Renamed_Field) : z.deflate(flush_Renamed_Field));
+    			if (num != 0 && num != 1)
+    			{
+    				throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+    			}
+    			out_Renamed.Write(buf, 0, bufsize - z.avail_out);
+    		}
+    		while (z.avail_in > 0 || z.avail_out == 0);
+    	}
+
+    	public virtual void finish()
+    	{
+    		do
+    		{
+    			z.next_out = buf;
+    			z.next_out_index = 0;
+    			z.avail_out = bufsize;
+    			int num = ((!compress) ? z.inflate(4) : z.deflate(4));
+    			if (num != 1 && num != 0)
+    			{
+    				throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+    			}
+    			if (bufsize - z.avail_out > 0)
+    			{
+    				out_Renamed.Write(buf, 0, bufsize - z.avail_out);
+    			}
+    		}
+    		while (z.avail_in > 0 || z.avail_out == 0);
+    		try
+    		{
+    			Flush();
+    		}
+    		catch
+    		{
+    		}
+    	}
+
+    	public virtual void end()
+    	{
+    		if (compress)
+    		{
+    			z.deflateEnd();
+    		}
+    		else
+    		{
+    			z.inflateEnd();
+    		}
+    		z.free();
+    		z = null;
+    	}
+
+    	public override void Close()
+    	{
+    		try
+    		{
+    			finish();
+    		}
+    		catch
+    		{
+    		}
+    		finally
+    		{
+    			end();
+    			out_Renamed.Close();
+    			out_Renamed = null;
+    		}
+    	}
+
+    	public override void Flush()
+    	{
+    		out_Renamed.Flush();
+    	}
+
+    	public override int Read(byte[] buffer, int offset, int count)
+    	{
+    		return 0;
+    	}
+
+    	public override void SetLength(long value)
+    	{
+    	}
+
+    	public override long Seek(long offset, SeekOrigin origin)
+    	{
+    		return 0L;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStream.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStream.cs
new file mode 100644
index 00000000..6a4d0f77
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStream.cs
@@ -0,0 +1,224 @@
+using System;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public sealed class ZStream
+    {
+    	private const int MAX_WBITS = 15;
+
+    	private static readonly int DEF_WBITS = 15;
+
+    	private const int Z_NO_FLUSH = 0;
+
+    	private const int Z_PARTIAL_FLUSH = 1;
+
+    	private const int Z_SYNC_FLUSH = 2;
+
+    	private const int Z_FULL_FLUSH = 3;
+
+    	private const int Z_FINISH = 4;
+
+    	private const int MAX_MEM_LEVEL = 9;
+
+    	private const int Z_OK = 0;
+
+    	private const int Z_STREAM_END = 1;
+
+    	private const int Z_NEED_DICT = 2;
+
+    	private const int Z_ERRNO = -1;
+
+    	private const int Z_STREAM_ERROR = -2;
+
+    	private const int Z_DATA_ERROR = -3;
+
+    	private const int Z_MEM_ERROR = -4;
+
+    	private const int Z_BUF_ERROR = -5;
+
+    	private const int Z_VERSION_ERROR = -6;
+
+    	public byte[] next_in;
+
+    	public int next_in_index;
+
+    	public int avail_in;
+
+    	public long total_in;
+
+    	public byte[] next_out;
+
+    	public int next_out_index;
+
+    	public int avail_out;
+
+    	public long total_out;
+
+    	public string msg;
+
+    	internal Deflate dstate;
+
+    	internal Inflate istate;
+
+    	internal int data_type;
+
+    	public long adler;
+
+    	internal Adler32 _adler = new Adler32();
+
+    	public int inflateInit()
+    	{
+    		return inflateInit(DEF_WBITS);
+    	}
+
+    	public int inflateInit(int w)
+    	{
+    		istate = new Inflate();
+    		return istate.inflateInit(this, w);
+    	}
+
+    	public int inflate(int f)
+    	{
+    		if (istate == null)
+    		{
+    			return -2;
+    		}
+    		return istate.inflate(this, f);
+    	}
+
+    	public int inflateEnd()
+    	{
+    		if (istate == null)
+    		{
+    			return -2;
+    		}
+    		int result = istate.inflateEnd(this);
+    		istate = null;
+    		return result;
+    	}
+
+    	public int inflateSync()
+    	{
+    		if (istate == null)
+    		{
+    			return -2;
+    		}
+    		return istate.inflateSync(this);
+    	}
+
+    	public int inflateSetDictionary(byte[] dictionary, int dictLength)
+    	{
+    		if (istate == null)
+    		{
+    			return -2;
+    		}
+    		return istate.inflateSetDictionary(this, dictionary, dictLength);
+    	}
+
+    	public int deflateInit(int level)
+    	{
+    		return deflateInit(level, 15);
+    	}
+
+    	public int deflateInit(int level, int bits)
+    	{
+    		dstate = new Deflate();
+    		return dstate.deflateInit(this, level, bits);
+    	}
+
+    	public int deflate(int flush)
+    	{
+    		if (dstate == null)
+    		{
+    			return -2;
+    		}
+    		return dstate.deflate(this, flush);
+    	}
+
+    	public int deflateEnd()
+    	{
+    		if (dstate == null)
+    		{
+    			return -2;
+    		}
+    		int result = dstate.deflateEnd();
+    		dstate = null;
+    		return result;
+    	}
+
+    	public int deflateParams(int level, int strategy)
+    	{
+    		if (dstate == null)
+    		{
+    			return -2;
+    		}
+    		return dstate.deflateParams(this, level, strategy);
+    	}
+
+    	public int deflateSetDictionary(byte[] dictionary, int dictLength)
+    	{
+    		if (dstate == null)
+    		{
+    			return -2;
+    		}
+    		return dstate.deflateSetDictionary(this, dictionary, dictLength);
+    	}
+
+    	internal void flush_pending()
+    	{
+    		int pending = dstate.pending;
+    		if (pending > avail_out)
+    		{
+    			pending = avail_out;
+    		}
+    		if (pending != 0)
+    		{
+    			if (dstate.pending_buf.Length > dstate.pending_out && next_out.Length > next_out_index && dstate.pending_buf.Length >= dstate.pending_out + pending)
+    			{
+    				_ = next_out.Length;
+    				_ = next_out_index + pending;
+    			}
+    			Array.Copy(dstate.pending_buf, dstate.pending_out, next_out, next_out_index, pending);
+    			next_out_index += pending;
+    			dstate.pending_out += pending;
+    			total_out += pending;
+    			avail_out -= pending;
+    			dstate.pending -= pending;
+    			if (dstate.pending == 0)
+    			{
+    				dstate.pending_out = 0;
+    			}
+    		}
+    	}
+
+    	internal int read_buf(byte[] buf, int start, int size)
+    	{
+    		int num = avail_in;
+    		if (num > size)
+    		{
+    			num = size;
+    		}
+    		if (num == 0)
+    		{
+    			return 0;
+    		}
+    		avail_in -= num;
+    		if (dstate.noheader == 0)
+    		{
+    			adler = _adler.adler32(adler, next_in, next_in_index, num);
+    		}
+    		Array.Copy(next_in, next_in_index, buf, start, num);
+    		next_in_index += num;
+    		total_in += num;
+    		return num;
+    	}
+
+    	public void free()
+    	{
+    		next_in = null;
+    		next_out = null;
+    		msg = null;
+    		_adler = null;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStreamException.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStreamException.cs
new file mode 100644
index 00000000..c993062d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/ZStreamException.cs
@@ -0,0 +1,16 @@
+using System.IO;
+
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public class ZStreamException : IOException
+    {
+    	public ZStreamException()
+    	{
+    	}
+
+    	public ZStreamException(string s)
+    		: base(s)
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/zlibConst.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/zlibConst.cs
new file mode 100644
index 00000000..5544d125
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/zlibConst.cs
@@ -0,0 +1,54 @@
+namespace ComponentAce.Compression.Libs.zlib
+{
+    public sealed class zlibConst
+    {
+    	private const string version_Renamed_Field = "1.0.2";
+
+    	public const int Z_NO_COMPRESSION = 0;
+
+    	public const int Z_BEST_SPEED = 1;
+
+    	public const int Z_BEST_COMPRESSION = 9;
+
+    	public const int Z_DEFAULT_COMPRESSION = -1;
+
+    	public const int Z_FILTERED = 1;
+
+    	public const int Z_HUFFMAN_ONLY = 2;
+
+    	public const int Z_DEFAULT_STRATEGY = 0;
+
+    	public const int Z_NO_FLUSH = 0;
+
+    	public const int Z_PARTIAL_FLUSH = 1;
+
+    	public const int Z_SYNC_FLUSH = 2;
+
+    	public const int Z_FULL_FLUSH = 3;
+
+    	public const int Z_FINISH = 4;
+
+    	public const int Z_OK = 0;
+
+    	public const int Z_STREAM_END = 1;
+
+    	public const int Z_NEED_DICT = 2;
+
+    	public const int Z_ERRNO = -1;
+
+    	public const int Z_STREAM_ERROR = -2;
+
+    	public const int Z_DATA_ERROR = -3;
+
+    	public const int Z_MEM_ERROR = -4;
+
+    	public const int Z_BUF_ERROR = -5;
+
+    	public const int Z_VERSION_ERROR = -6;
+
+    	public static string version()
+    	{
+    		return "1.0.2";
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Crc32.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Crc32.cs
new file mode 100644
index 00000000..58cc40b2
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Crc32.cs
@@ -0,0 +1,109 @@
+using System.Security.Cryptography;
+
+namespace MyNes.Core
+{
+    public class Crc32 : HashAlgorithm
+    {
+    	public const uint DefaultPolynomial = 3988292384u;
+
+    	public const uint DefaultSeed = uint.MaxValue;
+
+    	private uint hash;
+
+    	private uint seed;
+
+    	private uint[] table;
+
+    	private static uint[] defaultTable;
+
+    	public override int HashSize => 32;
+
+    	public Crc32()
+    	{
+    		table = InitializeTable(3988292384u);
+    		seed = uint.MaxValue;
+    		Initialize();
+    	}
+
+    	public Crc32(uint polynomial, uint seed)
+    	{
+    		table = InitializeTable(polynomial);
+    		this.seed = seed;
+    		Initialize();
+    	}
+
+    	public override void Initialize()
+    	{
+    		hash = seed;
+    	}
+
+    	protected override void HashCore(byte[] buffer, int start, int length)
+    	{
+    		hash = CalculateHash(table, hash, buffer, start, length);
+    	}
+
+    	protected override byte[] HashFinal()
+    	{
+    		return HashValue = UInt32ToBigEndianBytes(~hash);
+    	}
+
+    	public static uint Compute(byte[] buffer)
+    	{
+    		return ~CalculateHash(InitializeTable(3988292384u), uint.MaxValue, buffer, 0, buffer.Length);
+    	}
+
+    	public static uint Compute(uint seed, byte[] buffer)
+    	{
+    		return ~CalculateHash(InitializeTable(3988292384u), seed, buffer, 0, buffer.Length);
+    	}
+
+    	public static uint Compute(uint polynomial, uint seed, byte[] buffer)
+    	{
+    		return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
+    	}
+
+    	private static uint[] InitializeTable(uint polynomial)
+    	{
+    		if (polynomial == 3988292384u && defaultTable != null)
+    		{
+    			return defaultTable;
+    		}
+    		uint[] array = new uint[256];
+    		for (int i = 0; i < 256; i++)
+    		{
+    			uint num = (uint)i;
+    			for (int j = 0; j < 8; j++)
+    			{
+    				num = (((num & 1) != 1) ? (num >> 1) : ((num >> 1) ^ polynomial));
+    			}
+    			array[i] = num;
+    		}
+    		if (polynomial == 3988292384u)
+    		{
+    			defaultTable = array;
+    		}
+    		return array;
+    	}
+
+    	private static uint CalculateHash(uint[] table, uint seed, byte[] buffer, int start, int size)
+    	{
+    		uint num = seed;
+    		for (int i = start; i < size; i++)
+    		{
+    			num = (num >> 8) ^ table[buffer[i] ^ (num & 0xFF)];
+    		}
+    		return num;
+    	}
+
+    	private byte[] UInt32ToBigEndianBytes(uint x)
+    	{
+    		return new byte[4]
+    		{
+    			(byte)((x >> 24) & 0xFFu),
+    			(byte)((x >> 16) & 0xFFu),
+    			(byte)((x >> 8) & 0xFFu),
+    			(byte)(x & 0xFFu)
+    		};
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/EmuRegion.cs b/OtherCore/MyNes.Standard2/MyNes.Core/EmuRegion.cs
new file mode 100644
index 00000000..1d75bb23
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/EmuRegion.cs
@@ -0,0 +1,9 @@
+namespace MyNes.Core
+{
+    public enum EmuRegion
+    {
+    	NTSC,
+    	PALB,
+    	DENDY
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/EmuSettings.cs b/OtherCore/MyNes.Standard2/MyNes.Core/EmuSettings.cs
new file mode 100644
index 00000000..c11a6347
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/EmuSettings.cs
@@ -0,0 +1,100 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    public class EmuSettings : ISettings
+    {
+    	public string SnapsFolder = "Snaps";
+
+    	public string WavesFolder = "SoundRecords";
+
+    	public string SnapsFormat = ".png";
+
+    	public bool SnapsReplace;
+
+    	public int RegionSetting;
+
+    	public string StateFolder = "States";
+
+    	public string GameGenieFolder = "GMCodes";
+
+    	public string SRAMFolder = "Srams";
+
+    	public bool SaveSRAMAtEmuShutdown = true;
+
+    	public EmuSettings(string path)
+    		: base(path)
+    	{
+    	}
+
+    	public override void LoadSettings()
+    	{
+    		base.LoadSettings();
+    		if (MyNesMain.WorkingFolder == null)
+    		{
+    			MyNesMain.MakeWorkingFolder();
+    		}
+    		if (SnapsFolder == "Snaps")
+    		{
+    			SnapsFolder = Path.Combine(MyNesMain.WorkingFolder, "Snaps");
+    		}
+    		if (StateFolder == "States")
+    		{
+    			StateFolder = Path.Combine(MyNesMain.WorkingFolder, "States");
+    		}
+    		if (GameGenieFolder == "GMCodes")
+    		{
+    			GameGenieFolder = Path.Combine(MyNesMain.WorkingFolder, "GMCodes");
+    		}
+    		if (SRAMFolder == "Srams")
+    		{
+    			SRAMFolder = Path.Combine(MyNesMain.WorkingFolder, "Srams");
+    		}
+    		if (WavesFolder == "SoundRecords")
+    		{
+    			WavesFolder = Path.Combine(MyNesMain.WorkingFolder, "SoundRecords");
+    		}
+    		try
+    		{
+    			Directory.CreateDirectory(WavesFolder);
+    		}
+    		catch
+    		{
+    			Tracer.WriteError("Cannot create sound records folder !!");
+    		}
+    		try
+    		{
+    			Directory.CreateDirectory(SnapsFolder);
+    		}
+    		catch
+    		{
+    			Tracer.WriteError("Cannot create snaps folder !!");
+    		}
+    		try
+    		{
+    			Directory.CreateDirectory(StateFolder);
+    		}
+    		catch
+    		{
+    			Tracer.WriteError("Cannot create states folder !!");
+    		}
+    		try
+    		{
+    			Directory.CreateDirectory(SRAMFolder);
+    		}
+    		catch
+    		{
+    			Tracer.WriteError("Cannot create srams folder !!");
+    		}
+    		try
+    		{
+    			Directory.CreateDirectory(GameGenieFolder);
+    		}
+    		catch
+    		{
+    			Tracer.WriteError("Cannot create game genie codes folder !!");
+    		}
+    		StateHandler.StateFolder = StateFolder;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Eprom.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Eprom.cs
new file mode 100644
index 00000000..b4833bda
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Eprom.cs
@@ -0,0 +1,383 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class Eprom
+    {
+    	private enum EpromDevice
+    	{
+    		X24C01,
+    		X24C02
+    	}
+
+    	private enum EpromMode
+    	{
+    		Data,
+    		Addressing,
+    		Idle,
+    		Read,
+    		Write,
+    		Ack,
+    		NotAck,
+    		AckWait
+    	}
+
+    	private byte[] data;
+
+    	private EpromMode mode;
+
+    	private EpromMode nextmode;
+
+    	private EpromDevice device;
+
+    	private bool psda;
+
+    	private bool pscl;
+
+    	private int output;
+
+    	private int cbit;
+
+    	private int caddress;
+
+    	private int cdata;
+
+    	private bool isRead;
+
+    	private bool cSCL;
+
+    	private bool cSDA;
+
+    	public Eprom(int memorySize)
+    	{
+    		Console.WriteLine("Initializing Eprom ...");
+    		data = new byte[memorySize];
+    		device = ((memorySize == 256) ? EpromDevice.X24C02 : EpromDevice.X24C01);
+    		Console.WriteLine("Eprom memory size = " + memorySize);
+    		Console.WriteLine("Eprom device = " + device);
+    	}
+
+    	public void HardReset()
+    	{
+    		pscl = false;
+    		psda = false;
+    		mode = EpromMode.Idle;
+    		nextmode = EpromMode.Idle;
+    		cbit = 0;
+    		caddress = 0;
+    		cdata = 0;
+    		isRead = false;
+    		output = 16;
+    	}
+
+    	public void Write(int address, byte data)
+    	{
+    		cSCL = (data & 0x20) == 32;
+    		cSDA = (data & 0x40) == 64;
+    		if (pscl && (!cSDA & psda))
+    		{
+    			Start();
+    		}
+    		else if (pscl && (cSDA & !psda))
+    		{
+    			Stop();
+    		}
+    		else if (cSCL & !pscl)
+    		{
+    			switch (device)
+    			{
+    			case EpromDevice.X24C01:
+    				RiseX24C01((data >> 6) & 1);
+    				break;
+    			case EpromDevice.X24C02:
+    				RiseX24C02((data >> 6) & 1);
+    				break;
+    			}
+    		}
+    		else if (!cSCL & pscl)
+    		{
+    			switch (device)
+    			{
+    			case EpromDevice.X24C01:
+    				FallX24C01();
+    				break;
+    			case EpromDevice.X24C02:
+    				FallX24C02();
+    				break;
+    			}
+    		}
+    		pscl = cSCL;
+    		psda = cSDA;
+    	}
+
+    	public byte Read(int address)
+    	{
+    		return (byte)output;
+    	}
+
+    	private void Start()
+    	{
+    		switch (device)
+    		{
+    		case EpromDevice.X24C01:
+    			mode = EpromMode.Addressing;
+    			cbit = 0;
+    			caddress = 0;
+    			output = 16;
+    			break;
+    		case EpromDevice.X24C02:
+    			mode = EpromMode.Data;
+    			cbit = 0;
+    			output = 16;
+    			break;
+    		}
+    	}
+
+    	private void Stop()
+    	{
+    		mode = EpromMode.Idle;
+    		output = 16;
+    	}
+
+    	private void RiseX24C01(int bit)
+    	{
+    		switch (mode)
+    		{
+    		case EpromMode.Addressing:
+    			if (cbit < 7)
+    			{
+    				caddress &= ~(1 << cbit);
+    				caddress |= bit << cbit++;
+    			}
+    			else if (cbit < 8)
+    			{
+    				cbit = 8;
+    				if (bit != 0)
+    				{
+    					nextmode = EpromMode.Read;
+    					cdata = data[caddress];
+    				}
+    				else
+    				{
+    					nextmode = EpromMode.Write;
+    				}
+    			}
+    			break;
+    		case EpromMode.Ack:
+    			output = 0;
+    			break;
+    		case EpromMode.Read:
+    			if (cbit < 8)
+    			{
+    				output = (((cdata & (1 << cbit++)) != 0) ? 16 : 0);
+    			}
+    			break;
+    		case EpromMode.Write:
+    			if (cbit < 8)
+    			{
+    				cdata &= ~(1 << cbit);
+    				cdata |= bit << cbit++;
+    			}
+    			break;
+    		case EpromMode.AckWait:
+    			if (bit == 0)
+    			{
+    				nextmode = EpromMode.Idle;
+    			}
+    			break;
+    		case EpromMode.Idle:
+    		case EpromMode.NotAck:
+    			break;
+    		}
+    	}
+
+    	private void RiseX24C02(int bit)
+    	{
+    		switch (mode)
+    		{
+    		case EpromMode.Data:
+    			if (cbit < 8)
+    			{
+    				cdata &= ~(1 << 7 - cbit);
+    				cdata |= bit << 7 - cbit++;
+    			}
+    			break;
+    		case EpromMode.Addressing:
+    			if (cbit < 8)
+    			{
+    				caddress &= ~(1 << 7 - cbit);
+    				caddress |= bit << 7 - cbit++;
+    			}
+    			break;
+    		case EpromMode.Read:
+    			if (cbit < 8)
+    			{
+    				output = (((cdata & (1 << 7 - cbit++)) != 0) ? 16 : 0);
+    			}
+    			break;
+    		case EpromMode.Write:
+    			if (cbit < 8)
+    			{
+    				cdata &= ~(1 << 7 - cbit);
+    				cdata |= bit << 7 - cbit++;
+    			}
+    			break;
+    		case EpromMode.NotAck:
+    			output = 16;
+    			break;
+    		case EpromMode.Ack:
+    			output = 0;
+    			break;
+    		case EpromMode.AckWait:
+    			if (bit == 0)
+    			{
+    				nextmode = EpromMode.Read;
+    				cdata = data[caddress];
+    			}
+    			break;
+    		case EpromMode.Idle:
+    			break;
+    		}
+    	}
+
+    	private void FallX24C01()
+    	{
+    		switch (mode)
+    		{
+    		case EpromMode.Addressing:
+    			if (cbit == 8)
+    			{
+    				mode = EpromMode.Ack;
+    				output = 16;
+    			}
+    			break;
+    		case EpromMode.Ack:
+    			mode = nextmode;
+    			cbit = 0;
+    			output = 16;
+    			break;
+    		case EpromMode.Read:
+    			if (cbit == 8)
+    			{
+    				mode = EpromMode.AckWait;
+    				caddress = (caddress + 1) & 0x7F;
+    			}
+    			break;
+    		case EpromMode.Write:
+    			if (cbit == 8)
+    			{
+    				mode = EpromMode.Ack;
+    				nextmode = EpromMode.Idle;
+    				data[caddress] = (byte)cdata;
+    				caddress = (caddress + 1) & 0x7F;
+    			}
+    			break;
+    		case EpromMode.Idle:
+    			break;
+    		}
+    	}
+
+    	private void FallX24C02()
+    	{
+    		switch (mode)
+    		{
+    		case EpromMode.Data:
+    			if (cbit != 8)
+    			{
+    				break;
+    			}
+    			if ((cdata & 0xA0) == 160)
+    			{
+    				cbit = 0;
+    				mode = EpromMode.Ack;
+    				isRead = (cdata & 1) == 1;
+    				output = 16;
+    				if (isRead)
+    				{
+    					nextmode = EpromMode.Read;
+    					cdata = data[caddress];
+    				}
+    				else
+    				{
+    					nextmode = EpromMode.Addressing;
+    				}
+    			}
+    			else
+    			{
+    				mode = EpromMode.NotAck;
+    				nextmode = EpromMode.Idle;
+    				output = 16;
+    			}
+    			break;
+    		case EpromMode.Addressing:
+    			if (cbit == 8)
+    			{
+    				cbit = 0;
+    				mode = EpromMode.Ack;
+    				nextmode = (isRead ? EpromMode.Idle : EpromMode.Write);
+    				output = 16;
+    			}
+    			break;
+    		case EpromMode.Read:
+    			if (cbit == 8)
+    			{
+    				mode = EpromMode.AckWait;
+    				caddress = (caddress + 1) & 0xFF;
+    			}
+    			break;
+    		case EpromMode.Write:
+    			if (cbit == 8)
+    			{
+    				cbit = 0;
+    				mode = EpromMode.Ack;
+    				nextmode = EpromMode.Write;
+    				data[caddress] = (byte)cdata;
+    				caddress = (caddress + 1) & 0xFF;
+    			}
+    			break;
+    		case EpromMode.NotAck:
+    			mode = EpromMode.Idle;
+    			cbit = 0;
+    			output = 16;
+    			break;
+    		case EpromMode.Ack:
+    		case EpromMode.AckWait:
+    			mode = nextmode;
+    			cbit = 0;
+    			output = 16;
+    			break;
+    		case EpromMode.Idle:
+    			break;
+    		}
+    	}
+
+    	public void SaveState(BinaryWriter stream)
+    	{
+    		stream.Write(data);
+    		stream.Write((int)mode);
+    		stream.Write((int)nextmode);
+    		stream.Write(psda);
+    		stream.Write(pscl);
+    		stream.Write(output);
+    		stream.Write(cbit);
+    		stream.Write(caddress);
+    		stream.Write(cdata);
+    		stream.Write(isRead);
+    	}
+
+    	public void LoadState(BinaryReader stream)
+    	{
+    		stream.Read(data, 0, data.Length);
+    		mode = (EpromMode)stream.ReadInt32();
+    		nextmode = (EpromMode)stream.ReadInt32();
+    		psda = stream.ReadBoolean();
+    		pscl = stream.ReadBoolean();
+    		output = stream.ReadInt32();
+    		cbit = stream.ReadInt32();
+    		caddress = stream.ReadInt32();
+    		cdata = stream.ReadInt32();
+    		isRead = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/FFE.cs b/OtherCore/MyNes.Standard2/MyNes.Core/FFE.cs
new file mode 100644
index 00000000..8bf30ca3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/FFE.cs
@@ -0,0 +1,56 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal abstract class FFE : Board
+    {
+    	protected bool irqEnable;
+
+    	protected int irqCounter;
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 17665:
+    			irqEnable = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 17666:
+    			irqCounter = (irqCounter & 0xFF00) | data;
+    			break;
+    		case 17667:
+    			irqEnable = true;
+    			irqCounter = (irqCounter & 0xFF) | (data << 8);
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irqEnable)
+    		{
+    			irqCounter++;
+    			if (irqCounter >= 65535)
+    			{
+    				irqCounter = 0;
+    				NesEmu.IRQFlags |= 8;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter bin)
+    	{
+    		base.WriteStateData(ref bin);
+    		bin.Write(irqEnable);
+    		bin.Write(irqCounter);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader bin)
+    	{
+    		base.ReadStateData(ref bin);
+    		irqEnable = bin.ReadBoolean();
+    		irqCounter = bin.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/GameGenie.cs b/OtherCore/MyNes.Standard2/MyNes.Core/GameGenie.cs
new file mode 100644
index 00000000..7c6d969f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/GameGenie.cs
@@ -0,0 +1,152 @@
+using System.Collections.Generic;
+
+namespace MyNes.Core
+{
+    public class GameGenie
+    {
+    	public string[] LettersTable = new string[16]
+    	{
+    		"A", "P", "Z", "L", "G", "I", "T", "Y", "E", "O",
+    		"X", "U", "K", "S", "V", "N"
+    	};
+
+    	public byte[] HEXTable = new byte[16]
+    	{
+    		0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+    		10, 11, 12, 13, 14, 15
+    	};
+
+    	private List<string> lettersTable = new List<string>();
+
+    	public GameGenie()
+    	{
+    		lettersTable = new List<string>(LettersTable);
+    	}
+
+    	public int GetCodeAsHEX(string code)
+    	{
+    		int num = 0;
+    		int num2 = code.ToCharArray().Length - 1;
+    		char[] array = code.ToCharArray();
+    		foreach (char c in array)
+    		{
+    			num |= HEXTable[lettersTable.IndexOf(c.ToString())] << num2 * 4;
+    			num2--;
+    		}
+    		return num;
+    	}
+
+    	public byte GetGGValue(int code, int length)
+    	{
+    		int num = 0;
+    		int num2 = 0;
+    		int num3 = 0;
+    		int num4 = 0;
+    		int num5 = 0;
+    		int num6 = 0;
+    		int num7 = 0;
+    		int num8 = 0;
+    		switch (length)
+    		{
+    		case 6:
+    			num8 = (code & 0x800000) >> 23;
+    			num7 = (code & 0x40000) >> 18;
+    			num6 = (code & 0x20000) >> 17;
+    			num5 = (code & 0x10000) >> 16;
+    			num4 = (code & 8) >> 3;
+    			num3 = (code & 0x400000) >> 22;
+    			num2 = (code & 0x200000) >> 21;
+    			num = (code & 0x100000) >> 20;
+    			break;
+    		case 8:
+    			num8 = (code >> 31) & 1;
+    			num7 = (code >> 27) & 1;
+    			num6 = (code >> 26) & 1;
+    			num5 = (code >> 25) & 1;
+    			num4 = (code >> 3) & 1;
+    			num3 = (code >> 30) & 1;
+    			num2 = (code >> 29) & 1;
+    			num = (code >> 28) & 1;
+    			break;
+    		}
+    		return (byte)((num8 << 7) | (num7 << 6) | (num6 << 5) | (num5 << 4) | (num4 << 3) | (num3 << 2) | (num2 << 1) | num);
+    	}
+
+    	public int GetGGAddress(int code, int length)
+    	{
+    		int num = 0;
+    		int num2 = 0;
+    		int num3 = 0;
+    		int num4 = 0;
+    		int num5 = 0;
+    		int num6 = 0;
+    		int num7 = 0;
+    		int num8 = 0;
+    		int num9 = 0;
+    		int num10 = 0;
+    		int num11 = 0;
+    		int num12 = 0;
+    		int num13 = 0;
+    		int num14 = 0;
+    		int num15 = 0;
+    		switch (length)
+    		{
+    		case 6:
+    			num15 = (code >> 10) & 1;
+    			num14 = (code >> 9) & 1;
+    			num13 = (code >> 8) & 1;
+    			num12 = (code >> 7) & 1;
+    			num11 = (code >> 2) & 1;
+    			num10 = (code >> 1) & 1;
+    			num9 = code & 1;
+    			num8 = (code >> 19) & 1;
+    			num7 = (code >> 14) & 1;
+    			num6 = (code >> 13) & 1;
+    			num5 = (code >> 12) & 1;
+    			num4 = (code >> 11) & 1;
+    			num3 = (code >> 6) & 1;
+    			num2 = (code >> 5) & 1;
+    			num = (code >> 4) & 1;
+    			break;
+    		case 8:
+    			num15 = (code >> 18) & 1;
+    			num14 = (code >> 17) & 1;
+    			num13 = (code >> 16) & 1;
+    			num12 = (code >> 15) & 1;
+    			num11 = (code >> 10) & 1;
+    			num10 = (code >> 9) & 1;
+    			num9 = (code >> 8) & 1;
+    			num8 = (code >> 25) & 1;
+    			num7 = (code >> 22) & 1;
+    			num6 = (code >> 21) & 1;
+    			num5 = (code >> 20) & 1;
+    			num4 = (code >> 19) & 1;
+    			num3 = (code >> 14) & 1;
+    			num2 = (code >> 13) & 1;
+    			num = (code >> 12) & 1;
+    			break;
+    		}
+    		return (num15 << 14) | (num14 << 13) | (num13 << 12) | (num12 << 11) | (num11 << 10) | (num10 << 9) | (num9 << 8) | (num8 << 7) | (num7 << 6) | (num6 << 5) | (num5 << 4) | (num4 << 3) | (num3 << 2) | (num2 << 1) | num;
+    	}
+
+    	public byte GetGGCompareValue(int code)
+    	{
+    		int num = 0;
+    		int num2 = 0;
+    		int num3 = 0;
+    		int num4 = 0;
+    		int num5 = 0;
+    		int num6 = 0;
+    		int num7 = 0;
+    		int num8 = (code >> 7) & 1;
+    		num7 = (code >> 2) & 1;
+    		num6 = (code >> 1) & 1;
+    		num5 = code & 1;
+    		num4 = (code >> 11) & 1;
+    		num3 = (code >> 6) & 1;
+    		num2 = (code >> 5) & 1;
+    		num = (code >> 4) & 1;
+    		return (byte)((num8 << 7) | (num7 << 6) | (num6 << 5) | (num5 << 4) | (num4 << 3) | (num3 << 2) | (num2 << 1) | num);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/GameGenieCode.cs b/OtherCore/MyNes.Standard2/MyNes.Core/GameGenieCode.cs
new file mode 100644
index 00000000..fb22f4dc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/GameGenieCode.cs
@@ -0,0 +1,19 @@
+namespace MyNes.Core
+{
+    public struct GameGenieCode
+    {
+    	public string Name;
+
+    	public string Descreption;
+
+    	public int Address;
+
+    	public byte Compare;
+
+    	public byte Value;
+
+    	public bool IsCompare;
+
+    	public bool Enabled;
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/GetIsPlaying.cs b/OtherCore/MyNes.Standard2/MyNes.Core/GetIsPlaying.cs
new file mode 100644
index 00000000..b0a51f6b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/GetIsPlaying.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void GetIsPlaying(out bool playing);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/HassIssuesAttribute.cs b/OtherCore/MyNes.Standard2/MyNes.Core/HassIssuesAttribute.cs
new file mode 100644
index 00000000..fd2ae220
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/HassIssuesAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace MyNes.Core
+{
+    internal class HassIssuesAttribute : Attribute
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/HelperTools.cs b/OtherCore/MyNes.Standard2/MyNes.Core/HelperTools.cs
new file mode 100644
index 00000000..f396a669
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/HelperTools.cs
@@ -0,0 +1,174 @@
+using System.IO;
+using System.Security.Cryptography;
+
+namespace MyNes.Core
+{
+    public class HelperTools
+    {
+    	public static string GetFileSize(string FilePath)
+    	{
+    		if (File.Exists(Path.GetFullPath(FilePath)))
+    		{
+    			FileInfo fileInfo = new FileInfo(FilePath);
+    			string text = " Byte";
+    			double num = fileInfo.Length;
+    			if (fileInfo.Length >= 1024)
+    			{
+    				num = (double)fileInfo.Length / 1024.0;
+    				text = " KB";
+    			}
+    			if (num >= 1024.0)
+    			{
+    				num /= 1024.0;
+    				text = " MB";
+    			}
+    			if (num >= 1024.0)
+    			{
+    				num /= 1024.0;
+    				text = " GB";
+    			}
+    			return num.ToString("F2") + text;
+    		}
+    		return "";
+    	}
+
+    	public static string GetSize(long size)
+    	{
+    		string text = " Byte";
+    		double num = size;
+    		if (size >= 1024)
+    		{
+    			num = (double)size / 1024.0;
+    			text = " KB";
+    		}
+    		if (num >= 1024.0)
+    		{
+    			num /= 1024.0;
+    			text = " MB";
+    		}
+    		if (num >= 1024.0)
+    		{
+    			num /= 1024.0;
+    			text = " GB";
+    		}
+    		if (num < 0.0)
+    		{
+    			return "???";
+    		}
+    		return num.ToString("F2") + text;
+    	}
+
+    	public static string GetSize(ulong size)
+    	{
+    		string text = " Byte";
+    		double num = size;
+    		if (size >= 1024)
+    		{
+    			num = (double)size / 1024.0;
+    			text = " KB";
+    		}
+    		if (num >= 1024.0)
+    		{
+    			num /= 1024.0;
+    			text = " MB";
+    		}
+    		if (num >= 1024.0)
+    		{
+    			num /= 1024.0;
+    			text = " GB";
+    		}
+    		if (num < 0.0)
+    		{
+    			return "???";
+    		}
+    		return num.ToString("F2") + text;
+    	}
+
+    	public static long GetSizeAsBytes(string FilePath)
+    	{
+    		if (File.Exists(FilePath))
+    		{
+    			return new FileInfo(FilePath).Length;
+    		}
+    		return 0L;
+    	}
+
+    	public static bool IsStringContainsNumbers(string text)
+    	{
+    		char[] array = text.ToCharArray();
+    		foreach (char c in array)
+    		{
+    			int result = 0;
+    			if (int.TryParse(c.ToString(), out result))
+    			{
+    				return true;
+    			}
+    		}
+    		return false;
+    	}
+
+    	public static string CalculateCRC(string filePath)
+    	{
+    		if (File.Exists(filePath))
+    		{
+    			Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
+    			byte[] buffer = new byte[stream.Length];
+    			stream.Read(buffer, 0, (int)stream.Length);
+    			stream.Close();
+    			string text = "";
+    			byte[] array = new Crc32().ComputeHash(buffer);
+    			foreach (byte b in array)
+    			{
+    				text += b.ToString("x2").ToLower();
+    			}
+    			return text;
+    		}
+    		return "";
+    	}
+
+    	public static string CalculateCRC(string filePath, int bytesToSkip)
+    	{
+    		if (File.Exists(filePath))
+    		{
+    			Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
+    			stream.Read(new byte[bytesToSkip], 0, bytesToSkip);
+    			byte[] buffer = new byte[stream.Length - bytesToSkip];
+    			stream.Read(buffer, 0, (int)(stream.Length - bytesToSkip));
+    			stream.Close();
+    			string text = "";
+    			byte[] array = new Crc32().ComputeHash(buffer);
+    			foreach (byte b in array)
+    			{
+    				text += b.ToString("x2").ToLower();
+    			}
+    			return text;
+    		}
+    		return "";
+    	}
+
+    	public static string CalculateSHA1(string filePath)
+    	{
+    		if (File.Exists(filePath))
+    		{
+    			byte[] buffer = GetBuffer(filePath);
+    			string text = "";
+    			byte[] array = new SHA1Managed().ComputeHash(buffer);
+    			foreach (byte b in array)
+    			{
+    				text += b.ToString("x2").ToLower();
+    			}
+    			return text;
+    		}
+    		return "";
+    	}
+
+    	public static byte[] GetBuffer(string filePath)
+    	{
+    		Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
+    		byte[] array = new byte[stream.Length];
+    		stream.Read(array, 0, (int)stream.Length);
+    		stream.Close();
+    		return array;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IAudioProvider.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IAudioProvider.cs
new file mode 100644
index 00000000..247b0963
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IAudioProvider.cs
@@ -0,0 +1,29 @@
+namespace MyNes.Core
+{
+    public interface IAudioProvider
+    {
+    	string Name { get; }
+
+    	string ID { get; }
+
+    	bool AllowBufferChange { get; }
+
+    	bool AllowFrequencyChange { get; }
+
+    	void SubmitSamples(ref short[] buffer, ref int samples_added);
+
+    	void TogglePause(bool paused);
+
+    	void GetIsPlaying(out bool playing);
+
+    	void Initialize();
+
+    	void ShutDown();
+
+    	void Reset();
+
+    	void SignalToggle(bool started);
+
+    	void SetVolume(int Vol);
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IJoypadConnecter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IJoypadConnecter.cs
new file mode 100644
index 00000000..85fed6c3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IJoypadConnecter.cs
@@ -0,0 +1,18 @@
+namespace MyNes.Core
+{
+    public abstract class IJoypadConnecter
+    {
+    	protected byte DATA;
+
+    	public abstract void Update();
+
+    	public virtual void Destroy()
+    	{
+    	}
+
+    	public virtual byte GetData()
+    	{
+    		return DATA;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/INes.cs b/OtherCore/MyNes.Standard2/MyNes.Core/INes.cs
new file mode 100644
index 00000000..18726a3b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/INes.cs
@@ -0,0 +1,95 @@
+using System.IO;
+using System.Security.Cryptography;
+
+namespace MyNes.Core
+{
+    public class INes : IRom
+    {
+        public bool HasBattery { get; private set; }
+
+        public bool IsPlaychoice10 { get; private set; }
+
+        public bool IsVSUnisystem { get; private set; }
+
+        public override void Load(string fileName, bool loadDumps)
+        {
+            var fileStream = MyNesMain.Supporter.OpenRomFile(fileName);
+            if (fileStream.Length < 16)
+            {
+                fileStream.Close();
+                base.IsValid = false;
+                return;
+            }
+            byte[] array = new byte[16];
+            fileStream.Read(array, 0, 16);
+            byte[] buffer = new byte[fileStream.Length - 16];
+            fileStream.Read(buffer, 0, (int)(fileStream.Length - 16));
+            base.SHA1 = "";
+            byte[] array2 = new SHA1Managed().ComputeHash(buffer);
+            foreach (byte b in array2)
+            {
+                base.SHA1 += b.ToString("x2").ToLower();
+            }
+            if (array[0] != 78 || array[1] != 69 || array[2] != 83 || array[3] != 26)
+            {
+                fileStream.Close();
+                base.IsValid = false;
+                return;
+            }
+            base.PRGCount = array[4];
+            base.CHRCount = array[5];
+            switch (array[6] & 9)
+            {
+                case 0:
+                    base.Mirroring = Mirroring.Horz;
+                    break;
+                case 1:
+                    base.Mirroring = Mirroring.Vert;
+                    break;
+                case 8:
+                case 9:
+                    base.Mirroring = Mirroring.Full;
+                    break;
+            }
+            HasBattery = (array[6] & 2) != 0;
+            base.HasTrainer = (array[6] & 4) != 0;
+            if ((array[7] & 0xF) == 0)
+            {
+                base.MapperNumber = (byte)((array[7] & 0xF0) | (array[6] >> 4));
+            }
+            else
+            {
+                base.MapperNumber = (byte)(array[6] >> 4);
+            }
+            IsVSUnisystem = (array[7] & 1) != 0;
+            IsPlaychoice10 = (array[7] & 2) != 0;
+            if (loadDumps)
+            {
+                fileStream.Seek(16L, SeekOrigin.Begin);
+                if (base.HasTrainer)
+                {
+                    base.Trainer = new byte[512];
+                    fileStream.Read(base.Trainer, 0, 512);
+                }
+                else
+                {
+                    base.Trainer = new byte[0];
+                }
+                base.PRG = new byte[base.PRGCount * 16384];
+                fileStream.Read(base.PRG, 0, base.PRGCount * 16384);
+                if (base.CHRCount > 0)
+                {
+                    base.CHR = new byte[base.CHRCount * 8192];
+                    fileStream.Read(base.CHR, 0, base.CHRCount * 8192);
+                }
+                else
+                {
+                    base.CHR = new byte[0];
+                }
+            }
+            base.IsValid = true;
+            fileStream.Dispose();
+            fileStream.Close();
+        }
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IRom.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IRom.cs
new file mode 100644
index 00000000..a39891c8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IRom.cs
@@ -0,0 +1,29 @@
+namespace MyNes.Core
+{
+    public abstract class IRom
+    {
+    	public bool IsValid { get; set; }
+
+    	public int PRGCount { get; set; }
+
+    	public int CHRCount { get; set; }
+
+    	public int MapperNumber { get; set; }
+
+    	public Mirroring Mirroring { get; set; }
+
+    	public bool HasTrainer { get; set; }
+
+    	public byte[] PRG { get; set; }
+
+    	public byte[] CHR { get; set; }
+
+    	public byte[] Trainer { get; set; }
+
+    	public string SHA1 { get; set; }
+
+    	public virtual void Load(string fileName, bool loadDumps)
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ISettings.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ISettings.cs
new file mode 100644
index 00000000..d32c0bd5
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ISettings.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+
+namespace MyNes.Core
+{
+    public abstract class ISettings
+    {
+    	protected string filePath;
+
+    	protected FieldInfo[] Fields;
+
+    	public ISettings(string filePath)
+    	{
+    		this.filePath = filePath;
+    	}
+
+    	public virtual void LoadSettings()
+    	{
+    		Fields = GetType().GetFields();
+    		if (!File.Exists(filePath))
+    		{
+    			return;
+    		}
+    		string[] array = File.ReadAllLines(filePath);
+    		for (int i = 0; i < array.Length; i++)
+    		{
+    			string[] array2 = array[i].Split('=');
+    			if (array2 != null && array2.Length == 2)
+    			{
+    				SetField(array2[0], array2[1]);
+    			}
+    		}
+    	}
+
+    	public virtual void SaveSettings()
+    	{
+    		Fields = GetType().GetFields();
+    		List<string> list = new List<string>();
+    		FieldInfo[] fields = Fields;
+    		foreach (FieldInfo fieldInfo in fields)
+    		{
+    			if (fieldInfo.IsPublic)
+    			{
+    				list.Add(fieldInfo.Name + "=" + GetFieldValue(fieldInfo));
+    			}
+    		}
+    		File.WriteAllLines(filePath, list.ToArray());
+    	}
+
+    	protected virtual void SetField(string fieldName, string val)
+    	{
+    		for (int i = 0; i < Fields.Length; i++)
+    		{
+    			if (!(Fields[i].Name == fieldName))
+    			{
+    				continue;
+    			}
+    			if (Fields[i].FieldType == typeof(string))
+    			{
+    				Fields[i].SetValue(this, val);
+    			}
+    			else if (Fields[i].FieldType == typeof(bool))
+    			{
+    				Fields[i].SetValue(this, val == "1");
+    			}
+    			else if (Fields[i].FieldType == typeof(int))
+    			{
+    				int result = 0;
+    				if (int.TryParse(val, out result))
+    				{
+    					Fields[i].SetValue(this, result);
+    				}
+    			}
+    			else if (Fields[i].FieldType == typeof(float))
+    			{
+    				float result2 = 0f;
+    				if (float.TryParse(val, out result2))
+    				{
+    					Fields[i].SetValue(this, result2);
+    				}
+    			}
+    			else if (Fields[i].FieldType == typeof(string[]))
+    			{
+    				string[] value = val.Split(new string[1] { "*" }, StringSplitOptions.RemoveEmptyEntries);
+    				Fields[i].SetValue(this, value);
+    			}
+    			else
+    			{
+    				Tracer.WriteLine("Unknown setting type = " + Fields[i].FieldType);
+    			}
+    			break;
+    		}
+    	}
+
+    	protected virtual string GetFieldValue(string fieldName)
+    	{
+    		for (int i = 0; i < Fields.Length; i++)
+    		{
+    			if (Fields[i].Name == fieldName)
+    			{
+    				return GetFieldValue(Fields[i]);
+    			}
+    		}
+    		return "";
+    	}
+
+    	protected virtual string GetFieldValue(FieldInfo field)
+    	{
+    		object value = field.GetValue(this);
+    		if (field.FieldType == typeof(string))
+    		{
+    			return value.ToString();
+    		}
+    		if (field.FieldType == typeof(bool))
+    		{
+    			if (!(bool)value)
+    			{
+    				return "0";
+    			}
+    			return "1";
+    		}
+    		if (field.FieldType == typeof(int))
+    		{
+    			return value.ToString();
+    		}
+    		if (field.FieldType == typeof(float))
+    		{
+    			return value.ToString();
+    		}
+    		if (field.FieldType == typeof(string[]))
+    		{
+    			string text = "";
+    			string[] array = (string[])value;
+    			if (array != null)
+    			{
+    				string[] array2 = array;
+    				foreach (string text2 in array2)
+    				{
+    					text = text + text2 + "*";
+    				}
+    			}
+    			if (text.Length > 0)
+    			{
+    				return text.Substring(0, text.Length - 1);
+    			}
+    			return "";
+    		}
+    		return "";
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IShortcutsHandler.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IShortcutsHandler.cs
new file mode 100644
index 00000000..709bee99
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IShortcutsHandler.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    public interface IShortcutsHandler
+    {
+    	void Update();
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IVSUnisystemDIPConnecter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IVSUnisystemDIPConnecter.cs
new file mode 100644
index 00000000..9ad3ec6f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IVSUnisystemDIPConnecter.cs
@@ -0,0 +1,25 @@
+namespace MyNes.Core
+{
+    public abstract class IVSUnisystemDIPConnecter
+    {
+    	public abstract void Update();
+
+    	public virtual void OnEmuShutdown()
+    	{
+    	}
+
+    	public virtual byte GetData4016()
+    	{
+    		return 0;
+    	}
+
+    	public virtual byte GetData4017()
+    	{
+    		return 0;
+    	}
+
+    	public virtual void Write4020(ref byte data)
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IVideoProvider.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IVideoProvider.cs
new file mode 100644
index 00000000..0eca4cdd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IVideoProvider.cs
@@ -0,0 +1,41 @@
+namespace MyNes.Core
+{
+    public interface IVideoProvider
+    {
+    	string Name { get; }
+
+    	string ID { get; }
+
+    	void WriteErrorNotification(string message, bool instant);
+
+    	void WriteInfoNotification(string message, bool instant);
+
+    	void WriteWarningNotification(string message, bool instant);
+
+    	void TakeSnapshotAs(string path, string format);
+
+    	void TakeSnapshot();
+
+    	void Initialize();
+
+    	void ShutDown();
+
+    	void SignalToggle(bool started);
+
+    	void SubmitFrame(ref int[] buffer);
+
+    	void ResizeBegin();
+
+    	void ResizeEnd();
+
+    	void ApplyRegionChanges();
+
+    	void Resume();
+
+    	void ToggleAspectRatio(bool keep_aspect);
+
+    	void ToggleFPS(bool show_fps);
+
+    	void ApplyFilter();
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/IZapperConnecter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/IZapperConnecter.cs
new file mode 100644
index 00000000..72242bdf
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/IZapperConnecter.cs
@@ -0,0 +1,16 @@
+namespace MyNes.Core
+{
+    public abstract class IZapperConnecter
+    {
+    	protected bool Trigger;
+
+    	protected bool State;
+
+    	public abstract void Update();
+
+    	public virtual byte GetData()
+    	{
+    		return (byte)((Trigger ? 16u : 0u) | (State ? 8u : 0u));
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MMC2.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MMC2.cs
new file mode 100644
index 00000000..743e7553
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MMC2.cs
@@ -0,0 +1,116 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal abstract class MMC2 : Board
+    {
+    	private byte chr_reg0A;
+
+    	private byte chr_reg0B;
+
+    	private byte chr_reg1A;
+
+    	private byte chr_reg1B;
+
+    	private byte latch_a = 254;
+
+    	private byte latch_b = 254;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask - 2, PRGArea.AreaA000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask - 1, PRGArea.AreaC000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		chr_reg0B = 4;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF000)
+    		{
+    		case 40960:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 45056:
+    			chr_reg0A = data;
+    			if (latch_a == 253)
+    			{
+    				Switch04KCHR(chr_reg0A, CHRArea.Area0000);
+    			}
+    			break;
+    		case 49152:
+    			chr_reg0B = data;
+    			if (latch_a == 254)
+    			{
+    				Switch04KCHR(chr_reg0B, CHRArea.Area0000);
+    			}
+    			break;
+    		case 53248:
+    			chr_reg1A = data;
+    			if (latch_b == 253)
+    			{
+    				Switch04KCHR(chr_reg1A, CHRArea.Area1000);
+    			}
+    			break;
+    		case 57344:
+    			chr_reg1B = data;
+    			if (latch_b == 254)
+    			{
+    				Switch04KCHR(chr_reg1B, CHRArea.Area1000);
+    			}
+    			break;
+    		case 61440:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		}
+    	}
+
+    	internal override void ReadCHR(ref ushort address, out byte data)
+    	{
+    		if ((address & 0x1FF0) == 4048 && latch_a != 253)
+    		{
+    			latch_a = 253;
+    			Switch04KCHR(chr_reg0A, CHRArea.Area0000);
+    		}
+    		else if ((address & 0x1FF0) == 4064 && latch_a != 254)
+    		{
+    			latch_a = 254;
+    			Switch04KCHR(chr_reg0B, CHRArea.Area0000);
+    		}
+    		else if ((address & 0x1FF0) == 8144 && latch_b != 253)
+    		{
+    			latch_b = 253;
+    			Switch04KCHR(chr_reg1A, CHRArea.Area1000);
+    		}
+    		else if ((address & 0x1FF0) == 8160 && latch_b != 254)
+    		{
+    			latch_b = 254;
+    			Switch04KCHR(chr_reg1B, CHRArea.Area1000);
+    		}
+    		base.ReadCHR(ref address, out data);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr_reg0A);
+    		stream.Write(chr_reg0B);
+    		stream.Write(chr_reg1A);
+    		stream.Write(chr_reg1B);
+    		stream.Write(latch_a);
+    		stream.Write(latch_b);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr_reg0A = stream.ReadByte();
+    		chr_reg0B = stream.ReadByte();
+    		chr_reg1A = stream.ReadByte();
+    		chr_reg1B = stream.ReadByte();
+    		latch_a = stream.ReadByte();
+    		latch_b = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Pcm.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Pcm.cs
new file mode 100644
index 00000000..87d7266a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Pcm.cs
@@ -0,0 +1,86 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class MMC5Pcm
+    {
+    	internal byte output;
+
+    	internal bool Outputable;
+
+    	private bool readMode;
+
+    	private bool PCMIRQenable;
+
+    	private bool irqTrip;
+
+    	internal void HardReset()
+    	{
+    		output = 0;
+    		readMode = false;
+    		PCMIRQenable = false;
+    		irqTrip = false;
+    	}
+
+    	internal void SoftReset()
+    	{
+    		HardReset();
+    	}
+
+    	internal void Write5010(byte data)
+    	{
+    		readMode = (data & 1) == 1;
+    		PCMIRQenable = (data & 0x80) == 128;
+    		if (PCMIRQenable && irqTrip)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    	}
+
+    	internal byte Read5010()
+    	{
+    		byte result = (byte)((irqTrip & PCMIRQenable) ? 128 : 0);
+    		irqTrip = false;
+    		NesEmu.IRQFlags &= -9;
+    		return result;
+    	}
+
+    	internal void Write5011(byte data)
+    	{
+    		if (readMode)
+    		{
+    			return;
+    		}
+    		if (data == 0)
+    		{
+    			irqTrip = true;
+    		}
+    		else
+    		{
+    			irqTrip = false;
+    			if (Outputable)
+    			{
+    				output = data;
+    			}
+    		}
+    		if (PCMIRQenable && irqTrip)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    	}
+
+    	internal void SaveState(ref BinaryWriter stream)
+    	{
+    		stream.Write(readMode);
+    		stream.Write(PCMIRQenable);
+    		stream.Write(irqTrip);
+    	}
+
+    	internal void LoadState(ref BinaryReader stream)
+    	{
+    		readMode = stream.ReadBoolean();
+    		PCMIRQenable = stream.ReadBoolean();
+    		irqTrip = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Sqr.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Sqr.cs
new file mode 100644
index 00000000..3416a743
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MMC5Sqr.cs
@@ -0,0 +1,214 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class MMC5Sqr
+    {
+    	private byte[][] duty_cycle_sequences = new byte[4][]
+    	{
+    		new byte[8] { 0, 0, 0, 0, 0, 0, 0, 1 },
+    		new byte[8] { 0, 0, 0, 0, 0, 0, 1, 1 },
+    		new byte[8] { 0, 0, 0, 0, 1, 1, 1, 1 },
+    		new byte[8] { 1, 1, 1, 1, 1, 1, 0, 0 }
+    	};
+
+    	private byte[] duration_table = new byte[32]
+    	{
+    		10, 254, 20, 2, 40, 4, 80, 6, 160, 8,
+    		60, 10, 14, 12, 26, 14, 12, 16, 24, 18,
+    		48, 20, 96, 22, 192, 24, 72, 26, 16, 28,
+    		32, 30
+    	};
+
+    	private byte duty_cycle;
+
+    	private bool length_halt;
+
+    	private bool constant_volume_envelope;
+
+    	private byte volume_devider_period;
+
+    	private int timer;
+
+    	private int period_devider;
+
+    	private byte seqencer;
+
+    	private bool length_enabled;
+
+    	private int length_counter;
+
+    	private bool envelope_start_flag;
+
+    	private byte envelope_devider;
+
+    	private byte envelope_decay_level_counter;
+
+    	private byte envelope;
+
+    	internal int output;
+
+    	internal bool Outputable;
+
+    	internal void HardReset()
+    	{
+    		duty_cycle = 0;
+    		length_halt = false;
+    		constant_volume_envelope = false;
+    		volume_devider_period = 0;
+    		timer = 0;
+    		period_devider = 0;
+    		seqencer = 0;
+    		length_enabled = false;
+    		length_counter = 0;
+    		envelope_start_flag = false;
+    		envelope_devider = 0;
+    		envelope_decay_level_counter = 0;
+    		envelope = 0;
+    	}
+
+    	internal void SoftReset()
+    	{
+    		HardReset();
+    	}
+
+    	internal void Clock()
+    	{
+    		period_devider--;
+    		if (period_devider > 0)
+    		{
+    			return;
+    		}
+    		period_devider = timer + 1;
+    		if (length_counter > 0)
+    		{
+    			if (Outputable)
+    			{
+    				output = duty_cycle_sequences[duty_cycle][seqencer] * envelope;
+    			}
+    		}
+    		else
+    		{
+    			output = 0;
+    		}
+    		if (seqencer == 0)
+    		{
+    			seqencer = 7;
+    		}
+    		else
+    		{
+    			seqencer--;
+    		}
+    	}
+
+    	internal void ClockLength()
+    	{
+    		if (length_counter > 0 && !length_halt)
+    		{
+    			length_counter--;
+    		}
+    	}
+
+    	internal void ClockEnvelope()
+    	{
+    		if (envelope_start_flag)
+    		{
+    			envelope_start_flag = false;
+    			envelope_decay_level_counter = 15;
+    			envelope_devider = (byte)(volume_devider_period + 1);
+    		}
+    		else if (envelope_devider > 0)
+    		{
+    			envelope_devider--;
+    		}
+    		else
+    		{
+    			envelope_devider = (byte)(volume_devider_period + 1);
+    			if (envelope_decay_level_counter > 0)
+    			{
+    				envelope_decay_level_counter--;
+    			}
+    			else if (length_halt)
+    			{
+    				envelope_decay_level_counter = 15;
+    			}
+    		}
+    		envelope = (constant_volume_envelope ? volume_devider_period : envelope_decay_level_counter);
+    	}
+
+    	internal void Write0(ref byte value)
+    	{
+    		duty_cycle = (byte)((value & 0xC0) >> 6);
+    		volume_devider_period = (byte)(value & 0xFu);
+    		length_halt = (value & 0x20) != 0;
+    		constant_volume_envelope = (value & 0x10) != 0;
+    		envelope = (constant_volume_envelope ? volume_devider_period : envelope_decay_level_counter);
+    	}
+
+    	internal void Write2(ref byte value)
+    	{
+    		timer = (timer & 0xFF00) | value;
+    	}
+
+    	internal void Write3(ref byte value)
+    	{
+    		timer = (timer & 0xFF) | ((value & 7) << 8);
+    		if (length_enabled)
+    		{
+    			length_counter = duration_table[value >> 3];
+    		}
+    		seqencer = 0;
+    		envelope_start_flag = true;
+    	}
+
+    	internal void WriteEnabled(bool enabled)
+    	{
+    		length_enabled = enabled;
+    		if (!length_enabled)
+    		{
+    			length_counter = 0;
+    		}
+    	}
+
+    	internal bool ReadEnable()
+    	{
+    		return length_counter > 0;
+    	}
+
+    	internal void WriteStateData(ref BinaryWriter bin)
+    	{
+    		bin.Write(duty_cycle);
+    		bin.Write(length_halt);
+    		bin.Write(constant_volume_envelope);
+    		bin.Write(volume_devider_period);
+    		bin.Write(timer);
+    		bin.Write(period_devider);
+    		bin.Write(seqencer);
+    		bin.Write(length_enabled);
+    		bin.Write(length_counter);
+    		bin.Write(envelope_start_flag);
+    		bin.Write(envelope_devider);
+    		bin.Write(envelope_decay_level_counter);
+    		bin.Write(envelope);
+    		bin.Write(output);
+    	}
+
+    	internal void ReadStateData(ref BinaryReader bin)
+    	{
+    		duty_cycle = bin.ReadByte();
+    		length_halt = bin.ReadBoolean();
+    		constant_volume_envelope = bin.ReadBoolean();
+    		volume_devider_period = bin.ReadByte();
+    		timer = bin.ReadInt32();
+    		period_devider = bin.ReadInt32();
+    		seqencer = bin.ReadByte();
+    		length_enabled = bin.ReadBoolean();
+    		length_counter = bin.ReadInt32();
+    		envelope_start_flag = bin.ReadBoolean();
+    		envelope_devider = bin.ReadByte();
+    		envelope_decay_level_counter = bin.ReadByte();
+    		envelope = bin.ReadByte();
+    		output = bin.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MNInterfaceLanguage.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MNInterfaceLanguage.cs
new file mode 100644
index 00000000..42dcc727
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MNInterfaceLanguage.cs
@@ -0,0 +1,129 @@
+namespace MyNes.Core
+{
+    public class MNInterfaceLanguage
+    {
+    	public static string Message_RomInfoCanBeOnlyShown = "Rom info can be shown only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_StateSlotSetTo = "State slot set to";
+
+    	public static string Message_LoadStateCanBeUsedOnly = "Load state as can be used only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_SaveStateCanBeUseOnly = "Save state as can be used only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_HardResetCanBeUsedOnly = "Hard reset can be used only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_SoftResetCanBeUsedOnly = "Soft reset can be used only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_TurboCanBeToggledOnly = "Turbo can be toggled only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_GameGenieCanBeConfiguredOnly = "Game Genie can be enabled/configured only when emulation is on (i.e. game is loaded)";
+
+    	public static string Message_Error1 = "Can't save state, emu is off.";
+
+    	public static string Message_Error2 = "Can't save state, no rom file is loaded.";
+
+    	public static string Message_Error3 = "Can't save state while loading a state !";
+
+    	public static string Message_Error4 = "Already saving state !!";
+
+    	public static string Message_Error5 = "Can't load state, emu is off.";
+
+    	public static string Message_Error6 = "Can't load state, no rom file is loaded.";
+
+    	public static string Message_Error7 = "Can't load state while saving a state !";
+
+    	public static string Message_Error8 = "Already loading state !!";
+
+    	public static string Message_Error9 = "No state found in slot";
+
+    	public static string Message_Error10 = "Unable load state at slot";
+
+    	public static string Message_Error11 = "Not My Nes State File !";
+
+    	public static string Message_Error12 = "Not compatible state file version !";
+
+    	public static string Message_Error13 = "This state file is not for this game; not same SHA1 !";
+
+    	public static string Message_Error14 = "IS NOT LOCATED, mapper is not supported or unable to find it.";
+
+    	public static string Message_Error15 = "will be used instead, assigned successfully.";
+
+    	public static string Message_Error16 = "Game Genie code length cannot be more than 8 letters";
+
+    	public static string Message_Error17 = "has issues and may not function probably with this game.";
+
+    	public static string Message_Info1 = "State saved at slot";
+
+    	public static string Message_Info2 = "State loaded from slot";
+
+    	public static string Message_Info3 = "Snapshot saved";
+
+    	public static string Message_Info4 = "Interface language set to";
+
+    	public static string Message_PleaseRestartToApply = "Please restart My Nes to apply.";
+
+    	public static string Message_HardReset = "HARD RESET !";
+
+    	public static string Message_SoftReset = "SOFT RESET !";
+
+    	public static string Message_Paused = "PAUSED";
+
+    	public static string Mapper = "Mapper";
+
+    	public static string IssueMapper5 = "Split screen not implemented.\nUchuu Keibitai SDF game graphic corruption for unknown reason in the intro (not in the split screen).";
+
+    	public static string IssueMapper6 = "Mapper 6 is not tested, issues may occur";
+
+    	public static string IssueMapper8 = "Mapper 8 is not tested, issues may occur";
+
+    	public static string IssueMapper33 = "Mapper 33: Akira is not working for unknown reason.";
+
+    	public static string IssueMapper44 = "In game Super Big 7 - in - 1 : Double Dragon 3 game does not work.";
+
+    	public static string IssueMapper53 = "Mapper 53 does not work with the test roms i have, maybe something wrong with the implementation or the roms themselves";
+
+    	public static string IssueMapper56 = "Mapper 56 does not work with the test roms i have, maybe something wrong with the implementation or the roms themselves";
+
+    	public static string IssueMapper58 = "Study and Game 32-in-1 (Ch) [!].nes needs keyboard ?";
+
+    	public static string IssueMapper60 = "Mapper 60 does not work with the test roms i have, maybe something wrong with the implementation or the roms themselves";
+
+    	public static string IssueMapper85 = "VRC7 sound channels are not supported";
+
+    	public static string IssueMapper90 = "DipSwitch is not implemented, the irq modes 2-3 are not implemented yet.";
+
+    	public static string IssueMapper96 = "Mapper 96 does not function probably and needs special controller to be implemented.";
+
+    	public static string IssueMapper105 = "Game hangs on title screen !";
+
+    	public static string IssueMapper119 = "Mapper 119 does not function probably";
+
+    	public static string IssueMapper154 = "Game shows glitches with chr";
+
+    	public static string IssueMapper180 = "Crazy Climber needs special controller which not implemented yet.";
+
+    	public static string IssueMapper191 = "Mapper 191 is not tested, issues may occur";
+
+    	public static string IssueMapper193 = "Game show nothing but fighter sprite !";
+
+    	public static string IssueMapper202 = "150 in 1: some games not work well. Is it mapper or rom dump ?";
+
+    	public static string IssueMapper203 = "64-in-1: some games not work, maybe something wrong with the implementation or the rom itself";
+
+    	public static string IssueMapper207 = "Fudou Myouou Den is not assigned as mapper 207 while it should be !";
+
+    	public static string IssueMapper222 = "Mapper 222 is not tested, issues may occur";
+
+    	public static string IssueMapper228 = "Mapper 228 does not function probably";
+
+    	public static string IssueMapper229 = "Mapper 229 is not tested, issues may occur";
+
+    	public static string IssueMapper230 = "Only Contra works !?";
+
+    	public static string IssueMapper243 = "Shows glitches in some games.";
+
+    	public static string IssueMapper245 = "Graphic glitches, maybe chr switches.";
+
+    	public static string IssueMapper255 = "Mapper 255 is not tested, issues may occur";
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper000.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper000.cs
new file mode 100644
index 00000000..037d8f2e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper000.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    [BoardInfo("NROM", 0)]
+    internal class Mapper000 : Board
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper001.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper001.cs
new file mode 100644
index 00000000..9360686f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper001.cs
@@ -0,0 +1,245 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC1", 1, 4, 64)]
+    internal class Mapper001 : Board
+    {
+    	private int address_reg;
+
+    	private byte[] reg = new byte[4];
+
+    	private byte shift;
+
+    	private byte buffer;
+
+    	private bool flag_p;
+
+    	private bool flag_c;
+
+    	private bool flag_s;
+
+    	private bool enable_wram_enable;
+
+    	private int prg_hijackedbit;
+
+    	private bool use_hijacked;
+
+    	private bool use_sram_switch;
+
+    	private int sram_switch_mask;
+
+    	private int cpuCycles;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		cpuCycles = 0;
+    		address_reg = 0;
+    		reg = new byte[4];
+    		reg[0] = 12;
+    		flag_c = false;
+    		flag_s = (flag_p = true);
+    		prg_hijackedbit = 0;
+    		reg[1] = (reg[2] = (reg[3] = 0));
+    		buffer = 0;
+    		shift = 0;
+    		if (base.Chips.Contains("MMC1B") || base.Chips.Contains("MMC1B2"))
+    		{
+    			TogglePRGRAMEnable(enable: false);
+    			Console.WriteLine("MMC1: SRAM Disabled.");
+    		}
+    		enable_wram_enable = !base.Chips.Contains("MMC1A");
+    		Console.WriteLine("MMC1: enable_wram_enable = " + enable_wram_enable);
+    		use_hijacked = (PRG_ROM_16KB_Mask & 0x10) == 16;
+    		if (use_hijacked)
+    		{
+    			prg_hijackedbit = 16;
+    		}
+    		use_sram_switch = false;
+    		if (PRG_RAM_08KB_Count > 0)
+    		{
+    			use_sram_switch = true;
+    			sram_switch_mask = (use_hijacked ? 8 : 24);
+    			sram_switch_mask &= PRG_RAM_08KB_Mask << 3;
+    			if (sram_switch_mask == 0)
+    			{
+    				use_sram_switch = false;
+    			}
+    		}
+    		Switch16KPRG(0xF | prg_hijackedbit, PRGArea.AreaC000);
+    		Console.WriteLine("MMC1: use_hijacked = " + use_hijacked);
+    		Console.WriteLine("MMC1: use_sram_switch = " + use_sram_switch);
+    		Console.WriteLine("MMC1: sram_switch_mask = " + sram_switch_mask.ToString("X2"));
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte value)
+    	{
+    		if (cpuCycles > 0)
+    		{
+    			return;
+    		}
+    		cpuCycles = 3;
+    		if ((value & 0x80) == 128)
+    		{
+    			reg[0] |= 12;
+    			flag_s = (flag_p = true);
+    			shift = (buffer = 0);
+    			return;
+    		}
+    		if ((value & 1) == 1)
+    		{
+    			buffer |= (byte)(1 << (int)shift);
+    		}
+    		if (++shift < 5)
+    		{
+    			return;
+    		}
+    		address_reg = (address & 0x7FFF) >> 13;
+    		reg[address_reg] = buffer;
+    		shift = (buffer = 0);
+    		switch (address_reg)
+    		{
+    		case 0:
+    			flag_c = (reg[0] & 0x10) != 0;
+    			flag_p = (reg[0] & 8) != 0;
+    			flag_s = (reg[0] & 4) != 0;
+    			UpdatePRG();
+    			UpdateCHR();
+    			switch (reg[0] & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			}
+    			break;
+    		case 1:
+    			if (!flag_c)
+    			{
+    				Switch08KCHR(reg[1] >> 1);
+    			}
+    			else
+    			{
+    				Switch04KCHR(reg[1], CHRArea.Area0000);
+    			}
+    			if (use_sram_switch)
+    			{
+    				Switch08KPRG((reg[1] & sram_switch_mask) >> 3, PRGArea.Area6000);
+    			}
+    			if (use_hijacked)
+    			{
+    				prg_hijackedbit = reg[1] & 0x10;
+    				UpdatePRG();
+    			}
+    			break;
+    		case 2:
+    			if (flag_c)
+    			{
+    				Switch04KCHR(reg[2], CHRArea.Area1000);
+    			}
+    			if (use_sram_switch)
+    			{
+    				Switch08KPRG((reg[2] & sram_switch_mask) >> 3, PRGArea.Area6000);
+    			}
+    			if (use_hijacked)
+    			{
+    				prg_hijackedbit = reg[2] & 0x10;
+    				UpdatePRG();
+    			}
+    			break;
+    		case 3:
+    			if (enable_wram_enable)
+    			{
+    				TogglePRGRAMEnable((reg[3] & 0x10) == 0);
+    			}
+    			UpdatePRG();
+    			break;
+    		}
+    	}
+
+    	private void UpdateCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch08KCHR(reg[1] >> 1);
+    		}
+    		else
+    		{
+    			Switch04KCHR(reg[1], CHRArea.Area0000);
+    			Switch04KCHR(reg[2], CHRArea.Area1000);
+    		}
+    		if (use_sram_switch)
+    		{
+    			Switch08KPRG((reg[1] & sram_switch_mask) >> 3, PRGArea.Area6000);
+    		}
+    	}
+
+    	private void UpdatePRG()
+    	{
+    		if (!flag_p)
+    		{
+    			Switch32KPRG(((reg[3] & 0xF) | prg_hijackedbit) >> 1, PRGArea.Area8000);
+    		}
+    		else if (flag_s)
+    		{
+    			Switch16KPRG((reg[3] & 0xF) | prg_hijackedbit, PRGArea.Area8000);
+    			Switch16KPRG(0xF | prg_hijackedbit, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch16KPRG(prg_hijackedbit, PRGArea.Area8000);
+    			Switch16KPRG((reg[3] & 0xF) | prg_hijackedbit, PRGArea.AreaC000);
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (cpuCycles > 0)
+    		{
+    			cpuCycles--;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(reg);
+    		stream.Write(shift);
+    		stream.Write(buffer);
+    		stream.Write(flag_p);
+    		stream.Write(flag_c);
+    		stream.Write(flag_s);
+    		stream.Write(enable_wram_enable);
+    		stream.Write(prg_hijackedbit);
+    		stream.Write(use_hijacked);
+    		stream.Write(use_sram_switch);
+    		stream.Write(cpuCycles);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		stream.Read(reg, 0, reg.Length);
+    		shift = stream.ReadByte();
+    		buffer = stream.ReadByte();
+    		flag_p = stream.ReadBoolean();
+    		flag_c = stream.ReadBoolean();
+    		flag_s = stream.ReadBoolean();
+    		enable_wram_enable = stream.ReadBoolean();
+    		prg_hijackedbit = stream.ReadInt32();
+    		use_hijacked = stream.ReadBoolean();
+    		use_sram_switch = stream.ReadBoolean();
+    		cpuCycles = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper002.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper002.cs
new file mode 100644
index 00000000..738c11ab
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper002.cs
@@ -0,0 +1,17 @@
+namespace MyNes.Core
+{
+    [BoardInfo("UxROM", 2)]
+    internal class Mapper002 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort addr, ref byte val)
+    	{
+    		Switch16KPRG(val, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper003.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper003.cs
new file mode 100644
index 00000000..4dcedf5c
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper003.cs
@@ -0,0 +1,15 @@
+namespace MyNes.Core
+{
+    [BoardInfo("CNROM", 3)]
+    internal class Mapper003 : Board
+    {
+    	private byte data_temp;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		ReadPRG(ref address, out data_temp);
+    		data_temp &= data;
+    		Switch08KCHR(data_temp);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper004.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper004.cs
new file mode 100644
index 00000000..6187d55a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper004.cs
@@ -0,0 +1,224 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC3", 4, true, true)]
+    internal class Mapper004 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		mmc3_alt_behavior = false;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Tracer.WriteWarning("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Tracer.WriteWarning("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Tracer.WriteWarning("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort addr, ref byte val)
+    	{
+    		switch (addr & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = val & 7;
+    			flag_c = (val & 0x80) != 0;
+    			flag_p = (val & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = val;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = val & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((val & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((val & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((val & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = val;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter bin)
+    	{
+    		base.WriteStateData(ref bin);
+    		bin.Write(flag_c);
+    		bin.Write(flag_p);
+    		bin.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			bin.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			bin.Write(prg_reg[j]);
+    		}
+    		bin.Write(irq_enabled);
+    		bin.Write(irq_counter);
+    		bin.Write(old_irq_counter);
+    		bin.Write(irq_reload);
+    		bin.Write(irq_clear);
+    		bin.Write(mmc3_alt_behavior);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader bin)
+    	{
+    		base.ReadStateData(ref bin);
+    		flag_c = bin.ReadBoolean();
+    		flag_p = bin.ReadBoolean();
+    		address_8001 = bin.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = bin.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = bin.ReadInt32();
+    		}
+    		irq_enabled = bin.ReadBoolean();
+    		irq_counter = bin.ReadByte();
+    		old_irq_counter = bin.ReadInt32();
+    		irq_reload = bin.ReadByte();
+    		irq_clear = bin.ReadBoolean();
+    		mmc3_alt_behavior = bin.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper005.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper005.cs
new file mode 100644
index 00000000..a47e0014
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper005.cs
@@ -0,0 +1,870 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC5", 5, 8, 16)]
+    [WithExternalSound]
+    [HassIssues]
+    internal class Mapper005 : Board
+    {
+    	private int ram_protectA;
+
+    	private int ram_protectB;
+
+    	private int ExRAM_mode;
+
+    	private int[] CHROffset_spr;
+
+    	private int[] CHROffsetEX;
+
+    	private int[] CHROffsetSP;
+
+    	private int[] chrRegA;
+
+    	private int[] chrRegB;
+
+    	private int[] prgReg;
+
+    	private bool useSRAMmirroring;
+
+    	private int chr_high;
+
+    	private int chr_mode;
+
+    	private int prg_mode;
+
+    	private bool chr_setB_last;
+
+    	private byte temp_val;
+
+    	private byte temp_fill;
+
+    	private int lastAccessVRAM;
+
+    	private int paletteNo;
+
+    	private int shift;
+
+    	private int EXtilenumber;
+
+    	private byte multiplicand;
+
+    	private byte multiplier;
+
+    	private ushort product;
+
+    	private bool split_enable;
+
+    	private bool split_right;
+
+    	private int split_tile;
+
+    	private int split_yscroll;
+
+    	private bool split_doit;
+
+    	private int split_watch_tile;
+
+    	private byte irq_line;
+
+    	private byte irq_enable;
+
+    	private int irq_pending;
+
+    	private int irq_current_counter;
+
+    	private int irq_current_inframe;
+
+    	private MMC5Sqr snd_1;
+
+    	private MMC5Sqr snd_2;
+
+    	private MMC5Pcm snd_3;
+
+    	private double[] audio_pulse_table;
+
+    	private double[] audio_tnd_table;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper5;
+
+    	internal override void Initialize(IRom rom)
+    	{
+    		base.Initialize(rom);
+    		snd_1 = new MMC5Sqr();
+    		snd_2 = new MMC5Sqr();
+    		snd_3 = new MMC5Pcm();
+    		audio_pulse_table = new double[32];
+    		for (int i = 0; i < 32; i++)
+    		{
+    			audio_pulse_table[i] = 95.52 / (8128.0 / (double)i + 100.0);
+    		}
+    		audio_tnd_table = new double[204];
+    		for (int j = 0; j < 204; j++)
+    		{
+    			audio_tnd_table[j] = 163.67 / (24329.0 / (double)j + 100.0);
+    		}
+    	}
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		switch (SHA1.ToUpper())
+    		{
+    		case "37267833C984F176DB4B0BC9D45DABA0FFF45304":
+    			useSRAMmirroring = true;
+    			break;
+    		case "800AEFE756E85A0A78CCB4DAE68EBBA5DF24BF41":
+    			useSRAMmirroring = true;
+    			break;
+    		}
+    		Console.WriteLine("MMC5: using PRG RAM mirroring = " + useSRAMmirroring);
+    		CHROffset_spr = new int[8];
+    		CHROffsetEX = new int[8];
+    		CHROffsetSP = new int[8];
+    		chrRegA = new int[8];
+    		chrRegB = new int[4];
+    		prgReg = new int[4];
+    		prgReg[3] = PRG_ROM_08KB_Mask;
+    		prg_mode = 3;
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.Area8000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaA000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaC000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		Switch04kCHREX(0, 0);
+    		Switch04kCHRSP(0, 0);
+    		Switch08kCHR_spr(0);
+    		TogglePRGRAMWritableEnable(enable: true);
+    		TogglePRGRAMEnable(enable: true);
+    		APUApplyChannelsSettings();
+    		snd_1.HardReset();
+    		snd_2.HardReset();
+    		snd_3.HardReset();
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		base.SoftReset();
+    		snd_1.SoftReset();
+    		snd_2.SoftReset();
+    		snd_3.SoftReset();
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte value)
+    	{
+    		if (address >= 23552)
+    		{
+    			if (ExRAM_mode == 2)
+    			{
+    				NMT_RAM[2][address & 0x3FF] = value;
+    			}
+    			else if (ExRAM_mode < 2)
+    			{
+    				if (irq_current_inframe == 64)
+    				{
+    					NMT_RAM[2][address & 0x3FF] = value;
+    				}
+    				else
+    				{
+    					NMT_RAM[2][address & 0x3FF] = 0;
+    				}
+    			}
+    			return;
+    		}
+    		switch (address)
+    		{
+    		case 20480:
+    			snd_1.Write0(ref value);
+    			break;
+    		case 20482:
+    			snd_1.Write2(ref value);
+    			break;
+    		case 20483:
+    			snd_1.Write3(ref value);
+    			break;
+    		case 20484:
+    			snd_2.Write0(ref value);
+    			break;
+    		case 20486:
+    			snd_2.Write2(ref value);
+    			break;
+    		case 20487:
+    			snd_2.Write3(ref value);
+    			break;
+    		case 20496:
+    			snd_3.Write5010(value);
+    			break;
+    		case 20497:
+    			snd_3.Write5011(value);
+    			break;
+    		case 20501:
+    			snd_1.WriteEnabled((value & 1) != 0);
+    			snd_2.WriteEnabled((value & 2) != 0);
+    			break;
+    		case 20736:
+    			prg_mode = value & 3;
+    			break;
+    		case 20737:
+    			chr_mode = value & 3;
+    			break;
+    		case 20738:
+    			ram_protectA = value & 3;
+    			UpdateRamProtect();
+    			break;
+    		case 20739:
+    			ram_protectB = value & 3;
+    			UpdateRamProtect();
+    			break;
+    		case 20740:
+    			ExRAM_mode = value & 3;
+    			break;
+    		case 20741:
+    			Switch01KNMT(value);
+    			break;
+    		case 20755:
+    			if (!useSRAMmirroring)
+    			{
+    				Switch08KPRG(value & 7, PRGArea.Area6000);
+    			}
+    			else
+    			{
+    				Switch08KPRG((value >> 2) & 1, PRGArea.Area6000);
+    			}
+    			break;
+    		case 20756:
+    			if (prg_mode == 3)
+    			{
+    				Toggle08KPRG_RAM((value & 0x80) == 0, PRGArea.Area8000);
+    				Switch08KPRG(value & 0x7F, PRGArea.Area8000);
+    			}
+    			break;
+    		case 20757:
+    			switch (prg_mode)
+    			{
+    			case 1:
+    				Toggle16KPRG_RAM((value & 0x80) == 0, PRGArea.Area8000);
+    				Switch16KPRG((value & 0x7F) >> 1, PRGArea.Area8000);
+    				break;
+    			case 2:
+    				Toggle16KPRG_RAM((value & 0x80) == 0, PRGArea.Area8000);
+    				Switch16KPRG((value & 0x7F) >> 1, PRGArea.Area8000);
+    				break;
+    			case 3:
+    				Toggle08KPRG_RAM((value & 0x80) == 0, PRGArea.AreaA000);
+    				Switch08KPRG(value & 0x7F, PRGArea.AreaA000);
+    				break;
+    			}
+    			break;
+    		case 20758:
+    		{
+    			int num = prg_mode;
+    			if ((uint)(num - 2) <= 1u)
+    			{
+    				Toggle08KPRG_RAM((value & 0x80) == 0, PRGArea.AreaC000);
+    				Switch08KPRG(value & 0x7F, PRGArea.AreaC000);
+    			}
+    			break;
+    		}
+    		case 20759:
+    			switch (prg_mode)
+    			{
+    			case 0:
+    				Switch32KPRG((value & 0x7C) >> 2, PRGArea.Area8000);
+    				break;
+    			case 1:
+    				Switch16KPRG((value & 0x7F) >> 1, PRGArea.AreaC000);
+    				break;
+    			case 2:
+    				Switch08KPRG(value & 0x7F, PRGArea.AreaE000);
+    				break;
+    			case 3:
+    				Switch08KPRG(value & 0x7F, PRGArea.AreaE000);
+    				break;
+    			}
+    			break;
+    		case 20768:
+    			chr_setB_last = false;
+    			if (chr_mode == 3)
+    			{
+    				Switch01kCHR_spr(value | chr_high, 0);
+    			}
+    			break;
+    		case 20769:
+    			chr_setB_last = false;
+    			switch (chr_mode)
+    			{
+    			case 2:
+    				Switch02kCHR_spr(value | chr_high, 0);
+    				break;
+    			case 3:
+    				Switch01kCHR_spr(value | chr_high, 1024);
+    				break;
+    			}
+    			break;
+    		case 20770:
+    			chr_setB_last = false;
+    			if (chr_mode == 3)
+    			{
+    				Switch01kCHR_spr(value | chr_high, 2048);
+    			}
+    			break;
+    		case 20771:
+    			chr_setB_last = false;
+    			switch (chr_mode)
+    			{
+    			case 1:
+    				Switch04kCHR_spr(value | chr_high, 0);
+    				break;
+    			case 2:
+    				Switch02kCHR_spr(value | chr_high, 2048);
+    				break;
+    			case 3:
+    				Switch01kCHR_spr(value | chr_high, 3072);
+    				break;
+    			}
+    			break;
+    		case 20772:
+    			chr_setB_last = false;
+    			if (chr_mode == 3)
+    			{
+    				Switch01kCHR_spr(value | chr_high, 4096);
+    			}
+    			break;
+    		case 20773:
+    			chr_setB_last = false;
+    			switch (chr_mode)
+    			{
+    			case 2:
+    				Switch02kCHR_spr(value | chr_high, 4096);
+    				break;
+    			case 3:
+    				Switch01kCHR_spr(value | chr_high, 5120);
+    				break;
+    			}
+    			break;
+    		case 20774:
+    			chr_setB_last = false;
+    			if (chr_mode == 3)
+    			{
+    				Switch01kCHR_spr(value | chr_high, 6144);
+    			}
+    			break;
+    		case 20775:
+    			chr_setB_last = false;
+    			switch (chr_mode)
+    			{
+    			case 0:
+    				Switch08kCHR_spr(value | chr_high);
+    				break;
+    			case 1:
+    				Switch04kCHR_spr(value | chr_high, 4096);
+    				break;
+    			case 2:
+    				Switch02kCHR_spr(value | chr_high, 6144);
+    				break;
+    			case 3:
+    				Switch01kCHR_spr(value | chr_high, 7168);
+    				break;
+    			}
+    			break;
+    		case 20776:
+    			chr_setB_last = true;
+    			if (chr_mode == 3)
+    			{
+    				Switch01KCHR(value | chr_high, CHRArea.Area0000);
+    				Switch01KCHR(value | chr_high, CHRArea.Area1000);
+    			}
+    			break;
+    		case 20777:
+    			chr_setB_last = true;
+    			switch (chr_mode)
+    			{
+    			case 2:
+    				Switch02KCHR(value | chr_high, CHRArea.Area0000);
+    				Switch02KCHR(value | chr_high, CHRArea.Area1000);
+    				break;
+    			case 3:
+    				Switch01KCHR(value | chr_high, CHRArea.Area0400);
+    				Switch01KCHR(value | chr_high, CHRArea.Area1400);
+    				break;
+    			}
+    			break;
+    		case 20778:
+    			chr_setB_last = true;
+    			if (chr_mode == 3)
+    			{
+    				Switch01KCHR(value | chr_high, CHRArea.Area0800);
+    				Switch01KCHR(value | chr_high, CHRArea.Area1800);
+    			}
+    			break;
+    		case 20779:
+    			chr_setB_last = true;
+    			switch (chr_mode)
+    			{
+    			case 0:
+    				Switch04kCHR_bkg(value | chr_high, 0);
+    				Switch04kCHR_bkg(value | chr_high, 4096);
+    				break;
+    			case 1:
+    				Switch04KCHR(value | chr_high, CHRArea.Area0000);
+    				Switch04KCHR(value | chr_high, CHRArea.Area1000);
+    				break;
+    			case 2:
+    				Switch02KCHR(value | chr_high, CHRArea.Area0800);
+    				Switch02KCHR(value | chr_high, CHRArea.Area1800);
+    				break;
+    			case 3:
+    				Switch01KCHR(value | chr_high, CHRArea.Area0C00);
+    				Switch01KCHR(value | chr_high, CHRArea.Area1C00);
+    				break;
+    			}
+    			break;
+    		case 20784:
+    			chr_high = (value & 3) << 8;
+    			break;
+    		case 20742:
+    		{
+    			for (int j = 0; j < 960; j++)
+    			{
+    				NMT_RAM[3][j] = value;
+    			}
+    			break;
+    		}
+    		case 20743:
+    		{
+    			for (int i = 960; i < 1024; i++)
+    			{
+    				temp_fill = (byte)((uint)(2 << (value & 3)) | (value & 3u));
+    				temp_fill |= (byte)((temp_fill & 0xF) << 4);
+    				NMT_RAM[3][i] = temp_fill;
+    			}
+    			break;
+    		}
+    		case 20992:
+    			split_tile = value & 0x1F;
+    			split_enable = (value & 0x80) == 128;
+    			split_right = (value & 0x40) == 64;
+    			break;
+    		case 20993:
+    			split_yscroll = value;
+    			break;
+    		case 20994:
+    			Switch04kCHRSP(value, address & 0);
+    			Switch04kCHRSP(value, address & 0x1000);
+    			break;
+    		case 20995:
+    			irq_line = value;
+    			break;
+    		case 20996:
+    			irq_enable = value;
+    			break;
+    		case 20997:
+    			multiplicand = value;
+    			product = (ushort)(multiplicand * multiplier);
+    			break;
+    		case 20998:
+    			multiplier = value;
+    			product = (ushort)(multiplicand * multiplier);
+    			break;
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte data)
+    	{
+    		if (address >= 23552 && ExRAM_mode >= 2)
+    		{
+    			data = NMT_RAM[2][address & 0x3FF];
+    			return;
+    		}
+    		switch (address)
+    		{
+    		case 20496:
+    			data = snd_3.Read5010();
+    			break;
+    		case 20996:
+    			data = (byte)(irq_current_inframe | irq_pending);
+    			irq_pending = 0;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 20997:
+    			data = (byte)(product & 0xFFu);
+    			break;
+    		case 20998:
+    			data = (byte)((product & 0xFF00) >> 8);
+    			break;
+    		case 20501:
+    			data = (byte)((snd_1.ReadEnable() ? 1u : 0u) | (snd_2.ReadEnable() ? 2u : 0u));
+    			data = 0;
+    			break;
+    		default:
+    			data = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void ReadCHR(ref ushort address, out byte data)
+    	{
+    		if (!NesEmu.ppu_is_sprfetch && split_enable && ExRAM_mode < 2)
+    		{
+    			split_watch_tile = address & 0x3F;
+    			if (!split_right)
+    			{
+    				split_doit = split_watch_tile < split_tile;
+    			}
+    			else
+    			{
+    				split_doit = split_watch_tile >= split_tile;
+    			}
+    			_ = split_doit;
+    		}
+    		if (ExRAM_mode == 1)
+    		{
+    			if (!NesEmu.ppu_is_sprfetch)
+    			{
+    				EXtilenumber = NMT_RAM[2][lastAccessVRAM] & 0x3F;
+    				Switch04kCHREX(EXtilenumber | chr_high, address & 0x1000);
+    				data = CHR_ROM[CHROffsetEX[(address >> 10) & 7]][address & 0x3FF];
+    			}
+    			else
+    			{
+    				data = CHR_ROM[CHROffset_spr[(address >> 10) & 7]][address & 0x3FF];
+    			}
+    		}
+    		else if (NesEmu.ppu_reg_2000_Sprite_size == 16)
+    		{
+    			if (!NesEmu.ppu_is_sprfetch)
+    			{
+    				data = CHR_ROM[CHR_AREA_BLK_INDEX[(address >> 10) & 7]][address & 0x3FF];
+    			}
+    			else
+    			{
+    				data = CHR_ROM[CHROffset_spr[(address >> 10) & 7]][address & 0x3FF];
+    			}
+    		}
+    		else if (chr_setB_last)
+    		{
+    			data = CHR_ROM[CHR_AREA_BLK_INDEX[(address >> 10) & 7]][address & 0x3FF];
+    		}
+    		else
+    		{
+    			data = CHR_ROM[CHROffset_spr[(address >> 10) & 7]][address & 0x3FF];
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte data)
+    	{
+    		_ = split_doit;
+    		if (ExRAM_mode == 1)
+    		{
+    			if ((address & 0x3FF) <= 959)
+    			{
+    				lastAccessVRAM = address & 0x3FF;
+    			}
+    			else
+    			{
+    				paletteNo = NMT_RAM[2][lastAccessVRAM] & 0xC0;
+    				shift = ((lastAccessVRAM >> 4) & 4) | (lastAccessVRAM & 2);
+    				switch (shift)
+    				{
+    				case 0:
+    					data = (byte)(paletteNo >> 6);
+    					return;
+    				case 2:
+    					data = (byte)(paletteNo >> 4);
+    					return;
+    				case 4:
+    					data = (byte)(paletteNo >> 2);
+    					return;
+    				case 6:
+    					data = (byte)paletteNo;
+    					return;
+    				}
+    			}
+    		}
+    		data = NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF];
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte value)
+    	{
+    		if (ExRAM_mode == 1 && (address & 0x3FF) <= 959)
+    		{
+    			lastAccessVRAM = address & 0x3FF;
+    		}
+    		NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF] = value;
+    	}
+
+    	private void UpdateRamProtect()
+    	{
+    		TogglePRGRAMWritableEnable(ram_protectA == 2 && ram_protectB == 1);
+    	}
+
+    	private void Switch04kCHR_bkg(int index, int where)
+    	{
+    		int num = (where >> 10) & 7;
+    		index <<= 2;
+    		CHR_AREA_BLK_INDEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHR_AREA_BLK_INDEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHR_AREA_BLK_INDEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHR_AREA_BLK_INDEX[num] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch01kCHR_spr(int index, int where)
+    	{
+    		CHROffset_spr[(where >> 10) & 7] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch02kCHR_spr(int index, int where)
+    	{
+    		int num = (where >> 10) & 7;
+    		index <<= 1;
+    		CHROffset_spr[num] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[num + 1] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch04kCHR_spr(int index, int where)
+    	{
+    		int num = (where >> 10) & 7;
+    		index <<= 2;
+    		CHROffset_spr[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffset_spr[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffset_spr[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffset_spr[num] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch08kCHR_spr(int index)
+    	{
+    		index <<= 3;
+    		CHROffset_spr[0] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[1] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[2] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[3] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[4] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[5] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[6] = index & CHR_ROM_01KB_Mask;
+    		index++;
+    		CHROffset_spr[7] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch04kCHREX(int index, int where)
+    	{
+    		int num = (where >> 10) & 7;
+    		index <<= 2;
+    		CHROffsetEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetEX[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetEX[num] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	private void Switch04kCHRSP(int index, int where)
+    	{
+    		int num = (where >> 10) & 7;
+    		index <<= 2;
+    		CHROffsetSP[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetSP[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetSP[num] = index & CHR_ROM_01KB_Mask;
+    		num++;
+    		index++;
+    		CHROffsetSP[num] = index & CHR_ROM_01KB_Mask;
+    	}
+
+    	internal override void OnPPUScanlineTick()
+    	{
+    		irq_current_inframe = ((NesEmu.IsInRender() && NesEmu.IsRenderingOn()) ? 64 : 0);
+    		if (irq_current_inframe == 0)
+    		{
+    			irq_current_inframe = 64;
+    			irq_current_counter = 0;
+    			irq_pending = 0;
+    			NesEmu.IRQFlags &= -9;
+    			return;
+    		}
+    		irq_current_counter++;
+    		if (irq_current_counter == irq_line)
+    		{
+    			irq_pending = 128;
+    			if (irq_enable == 128)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    		}
+    	}
+
+    	internal override void OnAPUClock()
+    	{
+    		base.OnAPUClock();
+    		snd_1.Clock();
+    		snd_2.Clock();
+    	}
+
+    	internal override void OnAPUClockEnvelope()
+    	{
+    		base.OnAPUClockEnvelope();
+    		snd_1.ClockLength();
+    		snd_2.ClockLength();
+    		snd_1.ClockEnvelope();
+    		snd_2.ClockEnvelope();
+    	}
+
+    	internal override double APUGetSample()
+    	{
+    		return audio_pulse_table[snd_1.output + snd_2.output] + audio_tnd_table[snd_3.output];
+    	}
+
+    	internal override void APUApplyChannelsSettings()
+    	{
+    		base.APUApplyChannelsSettings();
+    		snd_1.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_MMC5_SQ1;
+    		snd_2.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_MMC5_SQ2;
+    		snd_3.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_MMC5_PCM;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(ram_protectA);
+    		stream.Write(ram_protectB);
+    		stream.Write(ExRAM_mode);
+    		for (int i = 0; i < CHROffset_spr.Length; i++)
+    		{
+    			stream.Write(CHROffset_spr[i]);
+    		}
+    		for (int j = 0; j < CHROffsetEX.Length; j++)
+    		{
+    			stream.Write(CHROffsetEX[j]);
+    		}
+    		for (int k = 0; k < CHROffsetSP.Length; k++)
+    		{
+    			stream.Write(CHROffsetSP[k]);
+    		}
+    		for (int l = 0; l < chrRegA.Length; l++)
+    		{
+    			stream.Write(chrRegA[l]);
+    		}
+    		for (int m = 0; m < chrRegB.Length; m++)
+    		{
+    			stream.Write(chrRegB[m]);
+    		}
+    		for (int n = 0; n < prgReg.Length; n++)
+    		{
+    			stream.Write(prgReg[n]);
+    		}
+    		stream.Write(useSRAMmirroring);
+    		stream.Write(chr_high);
+    		stream.Write(chr_mode);
+    		stream.Write(prg_mode);
+    		stream.Write(chr_setB_last);
+    		stream.Write(temp_val);
+    		stream.Write(temp_fill);
+    		stream.Write(lastAccessVRAM);
+    		stream.Write(paletteNo);
+    		stream.Write(shift);
+    		stream.Write(EXtilenumber);
+    		stream.Write(multiplicand);
+    		stream.Write(multiplier);
+    		stream.Write(product);
+    		stream.Write(split_enable);
+    		stream.Write(split_right);
+    		stream.Write(split_tile);
+    		stream.Write(split_yscroll);
+    		stream.Write(split_doit);
+    		stream.Write(split_watch_tile);
+    		stream.Write(irq_line);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_pending);
+    		stream.Write(irq_current_counter);
+    		stream.Write(irq_current_inframe);
+    		snd_1.WriteStateData(ref stream);
+    		snd_2.WriteStateData(ref stream);
+    		snd_3.SaveState(ref stream);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		ram_protectA = stream.ReadInt32();
+    		ram_protectB = stream.ReadInt32();
+    		ExRAM_mode = stream.ReadInt32();
+    		for (int i = 0; i < CHROffset_spr.Length; i++)
+    		{
+    			CHROffset_spr[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < CHROffsetEX.Length; j++)
+    		{
+    			CHROffsetEX[j] = stream.ReadInt32();
+    		}
+    		for (int k = 0; k < CHROffsetSP.Length; k++)
+    		{
+    			CHROffsetSP[k] = stream.ReadInt32();
+    		}
+    		for (int l = 0; l < chrRegA.Length; l++)
+    		{
+    			chrRegA[l] = stream.ReadInt32();
+    		}
+    		for (int m = 0; m < chrRegB.Length; m++)
+    		{
+    			chrRegB[m] = stream.ReadInt32();
+    		}
+    		for (int n = 0; n < prgReg.Length; n++)
+    		{
+    			prgReg[n] = stream.ReadInt32();
+    		}
+    		useSRAMmirroring = stream.ReadBoolean();
+    		chr_high = stream.ReadInt32();
+    		chr_mode = stream.ReadInt32();
+    		prg_mode = stream.ReadInt32();
+    		chr_setB_last = stream.ReadBoolean();
+    		temp_val = stream.ReadByte();
+    		temp_fill = stream.ReadByte();
+    		lastAccessVRAM = stream.ReadInt32();
+    		paletteNo = stream.ReadInt32();
+    		shift = stream.ReadInt32();
+    		EXtilenumber = stream.ReadInt32();
+    		multiplicand = stream.ReadByte();
+    		multiplier = stream.ReadByte();
+    		product = stream.ReadUInt16();
+    		split_enable = stream.ReadBoolean();
+    		split_right = stream.ReadBoolean();
+    		split_tile = stream.ReadInt32();
+    		split_yscroll = stream.ReadInt32();
+    		split_doit = stream.ReadBoolean();
+    		split_watch_tile = stream.ReadInt32();
+    		irq_line = stream.ReadByte();
+    		irq_enable = stream.ReadByte();
+    		irq_pending = stream.ReadInt32();
+    		irq_current_counter = stream.ReadInt32();
+    		irq_current_inframe = stream.ReadInt32();
+    		snd_1.ReadStateData(ref stream);
+    		snd_2.ReadStateData(ref stream);
+    		snd_3.LoadState(ref stream);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper006.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper006.cs
new file mode 100644
index 00000000..cc8f8287
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper006.cs
@@ -0,0 +1,21 @@
+namespace MyNes.Core
+{
+    [BoardInfo("FFE F4xxx", 6)]
+    [HassIssues]
+    internal class Mapper006 : FFE
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper6;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(7, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(data & 3);
+    		Switch16KPRG((data >> 2) & 0xF, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper007.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper007.cs
new file mode 100644
index 00000000..425a4e7f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper007.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("AxROM", 7)]
+    internal class Mapper007 : Board
+    {
+    	internal override void WritePRG(ref ushort addr, ref byte val)
+    	{
+    		Switch01KNMTFromMirroring(((val & 0x10) == 16) ? Mirroring.OneScB : Mirroring.OneScA);
+    		Switch32KPRG(val & 7, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper008.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper008.cs
new file mode 100644
index 00000000..37399342
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper008.cs
@@ -0,0 +1,15 @@
+namespace MyNes.Core
+{
+    [BoardInfo("FFE F3xxx", 8)]
+    [HassIssues]
+    internal class Mapper008 : FFE
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper8;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG((data >> 4) & 3, PRGArea.Area8000);
+    		Switch08KCHR(data & 3);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper009.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper009.cs
new file mode 100644
index 00000000..43e1ef35
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper009.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    [BoardInfo("MMC2", 9)]
+    internal class Mapper009 : MMC2
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper010.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper010.cs
new file mode 100644
index 00000000..f02be97d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper010.cs
@@ -0,0 +1,25 @@
+namespace MyNes.Core
+{
+    [BoardInfo("MMC4", 10)]
+    internal class Mapper010 : MMC2
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(0, PRGArea.Area8000);
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if ((address & 0xF000) == 40960)
+    		{
+    			Switch16KPRG(data, PRGArea.Area8000);
+    		}
+    		else
+    		{
+    			base.WritePRG(ref address, ref data);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper011.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper011.cs
new file mode 100644
index 00000000..d78fbdb4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper011.cs
@@ -0,0 +1,16 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Color Dreams", 11)]
+    internal class Mapper011 : Board
+    {
+    	private byte writeData;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		ReadPRG(ref address, out writeData);
+    		writeData &= data;
+    		Switch32KPRG(writeData & 3, PRGArea.Area8000);
+    		Switch08KCHR((writeData >> 4) & 0xF);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper013.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper013.cs
new file mode 100644
index 00000000..e89d212b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper013.cs
@@ -0,0 +1,21 @@
+namespace MyNes.Core
+{
+    [BoardInfo("CPROM", 13, 1, 16)]
+    internal class Mapper013 : Board
+    {
+    	private byte writeData;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Toggle08KCHR_RAM(ram: true);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		ReadPRG(ref address, out writeData);
+    		writeData &= data;
+    		Switch04KCHR(writeData & 3, CHRArea.Area1000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper015.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper015.cs
new file mode 100644
index 00000000..bf0959b4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper015.cs
@@ -0,0 +1,36 @@
+namespace MyNes.Core
+{
+    [BoardInfo("100-in-1 Contra Function 16", 15)]
+    internal class Mapper015 : Board
+    {
+    	private int temp;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 3)
+    		{
+    		case 0:
+    			Switch16KPRG(data & 0x3F, PRGArea.Area8000);
+    			Switch16KPRG((data & 0x3F) | 1, PRGArea.AreaC000);
+    			break;
+    		case 1:
+    			Switch16KPRG(data & 0x3F, PRGArea.Area8000);
+    			Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    			break;
+    		case 2:
+    			temp = data << 1;
+    			temp = ((data & 0x3F) << 1) | ((data >> 7) & 1);
+    			Switch08KPRG(temp, PRGArea.Area8000);
+    			Switch08KPRG(temp, PRGArea.AreaA000);
+    			Switch08KPRG(temp, PRGArea.AreaC000);
+    			Switch08KPRG(temp, PRGArea.AreaE000);
+    			break;
+    		case 3:
+    			Switch16KPRG(data & 0x3F, PRGArea.Area8000);
+    			Switch16KPRG(data & 0x3F, PRGArea.AreaC000);
+    			break;
+    		}
+    		Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper016.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper016.cs
new file mode 100644
index 00000000..aa57bea2
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper016.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Bandai", 16)]
+    internal class Mapper016 : Bandai
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper017.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper017.cs
new file mode 100644
index 00000000..648dea19
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper017.cs
@@ -0,0 +1,64 @@
+namespace MyNes.Core
+{
+    [BoardInfo("FFE F8xxx", 17)]
+    internal class Mapper017 : FFE
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 17668:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 17669:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 17670:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 17671:
+    			Switch08KPRG(data, PRGArea.AreaE000);
+    			break;
+    		case 17680:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 17681:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 17682:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 17683:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 17684:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 17685:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 17686:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 17687:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 17672:
+    		case 17673:
+    		case 17674:
+    		case 17675:
+    		case 17676:
+    		case 17677:
+    		case 17678:
+    		case 17679:
+    			break;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper018.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper018.cs
new file mode 100644
index 00000000..88c9463f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper018.cs
@@ -0,0 +1,219 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Jaleco SS8806", 18)]
+    internal class Mapper018 : Board
+    {
+    	private int[] prg_reg;
+
+    	private int[] chr_reg;
+
+    	private int irqRelaod;
+
+    	private int irqCounter;
+
+    	private bool irqEnable;
+
+    	private int irqMask;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		prg_reg = new int[3];
+    		chr_reg = new int[8];
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF003)
+    		{
+    		case 32768:
+    			prg_reg[0] = (prg_reg[0] & 0xF0) | (data & 0xF);
+    			Switch08KPRG(prg_reg[0], PRGArea.Area8000);
+    			break;
+    		case 32769:
+    			prg_reg[0] = (prg_reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch08KPRG(prg_reg[0], PRGArea.Area8000);
+    			break;
+    		case 32770:
+    			prg_reg[1] = (prg_reg[1] & 0xF0) | (data & 0xF);
+    			Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    			break;
+    		case 32771:
+    			prg_reg[1] = (prg_reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    			break;
+    		case 36864:
+    			prg_reg[2] = (prg_reg[2] & 0xF0) | (data & 0xF);
+    			Switch08KPRG(prg_reg[2], PRGArea.AreaC000);
+    			break;
+    		case 36865:
+    			prg_reg[2] = (prg_reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch08KPRG(prg_reg[2], PRGArea.AreaC000);
+    			break;
+    		case 40960:
+    			chr_reg[0] = (chr_reg[0] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[0], CHRArea.Area0000);
+    			break;
+    		case 40961:
+    			chr_reg[0] = (chr_reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[0], CHRArea.Area0000);
+    			break;
+    		case 40962:
+    			chr_reg[1] = (chr_reg[1] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[1], CHRArea.Area0400);
+    			break;
+    		case 40963:
+    			chr_reg[1] = (chr_reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[1], CHRArea.Area0400);
+    			break;
+    		case 45056:
+    			chr_reg[2] = (chr_reg[2] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0800);
+    			break;
+    		case 45057:
+    			chr_reg[2] = (chr_reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0800);
+    			break;
+    		case 45058:
+    			chr_reg[3] = (chr_reg[3] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0C00);
+    			break;
+    		case 45059:
+    			chr_reg[3] = (chr_reg[3] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0C00);
+    			break;
+    		case 49152:
+    			chr_reg[4] = (chr_reg[4] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1000);
+    			break;
+    		case 49153:
+    			chr_reg[4] = (chr_reg[4] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1000);
+    			break;
+    		case 49154:
+    			chr_reg[5] = (chr_reg[5] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1400);
+    			break;
+    		case 49155:
+    			chr_reg[5] = (chr_reg[5] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1400);
+    			break;
+    		case 53248:
+    			chr_reg[6] = (chr_reg[6] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[6], CHRArea.Area1800);
+    			break;
+    		case 53249:
+    			chr_reg[6] = (chr_reg[6] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[6], CHRArea.Area1800);
+    			break;
+    		case 53250:
+    			chr_reg[7] = (chr_reg[7] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_reg[7], CHRArea.Area1C00);
+    			break;
+    		case 53251:
+    			chr_reg[7] = (chr_reg[7] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_reg[7], CHRArea.Area1C00);
+    			break;
+    		case 57344:
+    			irqRelaod = (irqRelaod & 0xFFF0) | (data & 0xF);
+    			break;
+    		case 57345:
+    			irqRelaod = (irqRelaod & 0xFF0F) | ((data & 0xF) << 4);
+    			break;
+    		case 57346:
+    			irqRelaod = (irqRelaod & 0xF0FF) | ((data & 0xF) << 8);
+    			break;
+    		case 57347:
+    			irqRelaod = (irqRelaod & 0xFFF) | ((data & 0xF) << 12);
+    			break;
+    		case 61440:
+    			irqCounter = irqRelaod;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61441:
+    			irqEnable = (data & 1) == 1;
+    			if ((data & 8) == 8)
+    			{
+    				irqMask = 15;
+    			}
+    			else if ((data & 4) == 4)
+    			{
+    				irqMask = 255;
+    			}
+    			else if ((data & 2) == 2)
+    			{
+    				irqMask = 4095;
+    			}
+    			else
+    			{
+    				irqMask = 65535;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61442:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irqEnable && (irqCounter & irqMask) > 0 && (--irqCounter & irqMask) == 0)
+    		{
+    			irqEnable = false;
+    			NesEmu.IRQFlags |= 8;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		for (int i = 0; i < prg_reg.Length; i++)
+    		{
+    			stream.Write(prg_reg[i]);
+    		}
+    		for (int j = 0; j < chr_reg.Length; j++)
+    		{
+    			stream.Write(chr_reg[j]);
+    		}
+    		stream.Write(irqRelaod);
+    		stream.Write(irqCounter);
+    		stream.Write(irqEnable);
+    		stream.Write(irqMask);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		for (int i = 0; i < prg_reg.Length; i++)
+    		{
+    			prg_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < chr_reg.Length; j++)
+    		{
+    			chr_reg[j] = stream.ReadInt32();
+    		}
+    		irqRelaod = stream.ReadInt32();
+    		irqCounter = stream.ReadInt32();
+    		irqEnable = stream.ReadBoolean();
+    		irqMask = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper019.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper019.cs
new file mode 100644
index 00000000..4f11e09b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper019.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Namcot 106", 19, 1, 256)]
+    internal class Mapper019 : Namcot106
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper021.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper021.cs
new file mode 100644
index 00000000..141db72f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper021.cs
@@ -0,0 +1,254 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC4", 21)]
+    internal class Mapper021 : Board
+    {
+    	private bool prg_mode;
+
+    	private byte prg_reg0;
+
+    	private int[] chr_Reg;
+
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	private int prescaler;
+
+    	private bool irq_mode_cycle;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		prescaler = 341;
+    		chr_Reg = new int[8];
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32770:
+    		case 32772:
+    		case 32774:
+    		case 32832:
+    		case 32896:
+    		case 32960:
+    			prg_reg0 = data;
+    			Switch08KPRG(prg_mode ? (PRG_ROM_08KB_Mask - 1) : (prg_reg0 & 0x1F), PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? (prg_reg0 & 0x1F) : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			break;
+    		case 36864:
+    		case 36866:
+    		case 36928:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 36868:
+    		case 36870:
+    		case 36992:
+    		case 37056:
+    			prg_mode = (data & 2) == 2;
+    			Switch08KPRG(prg_mode ? (PRG_ROM_08KB_Mask - 1) : (prg_reg0 & 0x1F), PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? (prg_reg0 & 0x1F) : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			break;
+    		case 40960:
+    		case 40962:
+    		case 40964:
+    		case 40966:
+    		case 41024:
+    		case 41088:
+    		case 41152:
+    			Switch08KPRG(data & 0x1F, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45058:
+    		case 45120:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45060:
+    		case 45184:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 45062:
+    		case 45248:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 49152:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49154:
+    		case 49216:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49156:
+    		case 49280:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 49158:
+    		case 49344:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 53248:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53250:
+    		case 53312:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53252:
+    		case 53376:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 53254:
+    		case 53440:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 57344:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57346:
+    		case 57408:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57348:
+    		case 57472:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		case 57350:
+    		case 57536:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		case 61440:
+    			irq_reload = (irq_reload & 0xF0) | (data & 0xF);
+    			break;
+    		case 61442:
+    		case 61504:
+    			irq_reload = (irq_reload & 0xF) | ((data & 0xF) << 4);
+    			break;
+    		case 61444:
+    		case 61568:
+    			irq_mode_cycle = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    				prescaler = 341;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61446:
+    		case 61632:
+    			NesEmu.IRQFlags &= -9;
+    			irq_enable = irq_enable_on_ak;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (!irq_mode_cycle)
+    		{
+    			if (prescaler > 0)
+    			{
+    				prescaler -= 3;
+    				return;
+    			}
+    			prescaler = 341;
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_mode);
+    		stream.Write(prg_reg0);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			stream.Write(chr_Reg[i]);
+    		}
+    		stream.Write(irq_reload);
+    		stream.Write(irq_counter);
+    		stream.Write(prescaler);
+    		stream.Write(irq_mode_cycle);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_mode = stream.ReadBoolean();
+    		prg_reg0 = stream.ReadByte();
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			chr_Reg[i] = stream.ReadInt32();
+    		}
+    		irq_reload = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		prescaler = stream.ReadInt32();
+    		irq_mode_cycle = stream.ReadBoolean();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper022.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper022.cs
new file mode 100644
index 00000000..78daeb6f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper022.cs
@@ -0,0 +1,138 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC2", 22)]
+    internal class Mapper022 : Board
+    {
+    	private int[] chr_Reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		chr_Reg = new int[8];
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    			Switch08KPRG(data & 0xF, PRGArea.Area8000);
+    			break;
+    		case 36864:
+    		case 36865:
+    		case 36866:
+    		case 36867:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 40960:
+    		case 40961:
+    		case 40962:
+    		case 40963:
+    			Switch08KPRG(data & 0xF, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[0] >> 1, CHRArea.Area0000);
+    			break;
+    		case 45058:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[0] >> 1, CHRArea.Area0000);
+    			break;
+    		case 45057:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[1] >> 1, CHRArea.Area0400);
+    			break;
+    		case 45059:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[1] >> 1, CHRArea.Area0400);
+    			break;
+    		case 49152:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[2] >> 1, CHRArea.Area0800);
+    			break;
+    		case 49154:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[2] >> 1, CHRArea.Area0800);
+    			break;
+    		case 49153:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[3] >> 1, CHRArea.Area0C00);
+    			break;
+    		case 49155:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[3] >> 1, CHRArea.Area0C00);
+    			break;
+    		case 53248:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[4] >> 1, CHRArea.Area1000);
+    			break;
+    		case 53250:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[4] >> 1, CHRArea.Area1000);
+    			break;
+    		case 53249:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[5] >> 1, CHRArea.Area1400);
+    			break;
+    		case 53251:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[5] >> 1, CHRArea.Area1400);
+    			break;
+    		case 57344:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[6] >> 1, CHRArea.Area1800);
+    			break;
+    		case 57346:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[6] >> 1, CHRArea.Area1800);
+    			break;
+    		case 57345:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[7] >> 1, CHRArea.Area1C00);
+    			break;
+    		case 57347:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[7] >> 1, CHRArea.Area1C00);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			stream.Write(chr_Reg[i]);
+    		}
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			chr_Reg[i] = stream.ReadInt32();
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper023.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper023.cs
new file mode 100644
index 00000000..eb6e7b95
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper023.cs
@@ -0,0 +1,163 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC2", 23)]
+    internal class Mapper023 : Board
+    {
+    	private int[] chr_Reg;
+
+    	private byte security;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		chr_Reg = new int[8];
+    		security = 0;
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (address == 24576)
+    		{
+    			security = (byte)(data & 1u);
+    		}
+    	}
+
+    	internal override void ReadSRM(ref ushort address, out byte data)
+    	{
+    		if (address == 24576)
+    		{
+    			data = security;
+    		}
+    		else
+    		{
+    			data = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    			Switch08KPRG(data & 0xF, PRGArea.Area8000);
+    			break;
+    		case 36864:
+    		case 36865:
+    		case 36866:
+    		case 36867:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 40960:
+    		case 40961:
+    		case 40962:
+    		case 40963:
+    			Switch08KPRG(data & 0xF, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45057:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45058:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 45059:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 49152:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49153:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49154:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 49155:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 53248:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53249:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53250:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 53251:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 57344:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57345:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57346:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		case 57347:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			stream.Write(chr_Reg[i]);
+    		}
+    		stream.Write(security);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			chr_Reg[i] = stream.ReadInt32();
+    		}
+    		security = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper024.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper024.cs
new file mode 100644
index 00000000..703ab999
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper024.cs
@@ -0,0 +1,245 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC6", 24)]
+    [WithExternalSound]
+    internal class Mapper024 : Board
+    {
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	private int prescaler;
+
+    	private bool irq_mode_cycle;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	private VRC6Pulse snd_1;
+
+    	private VRC6Pulse snd_2;
+
+    	private VRC6Sawtooth snd_3;
+
+    	private double[] audio_pulse_table;
+
+    	private double[] audio_tnd_table;
+
+    	internal override void Initialize(IRom rom)
+    	{
+    		base.Initialize(rom);
+    		snd_1 = new VRC6Pulse();
+    		snd_2 = new VRC6Pulse();
+    		snd_3 = new VRC6Sawtooth();
+    		audio_pulse_table = new double[32];
+    		for (int i = 0; i < 32; i++)
+    		{
+    			audio_pulse_table[i] = 95.52 / (8128.0 / (double)i + 100.0);
+    		}
+    		audio_tnd_table = new double[204];
+    		for (int j = 0; j < 204; j++)
+    		{
+    			audio_tnd_table[j] = 163.67 / (24329.0 / (double)j + 100.0);
+    		}
+    	}
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		APUApplyChannelsSettings();
+    		snd_1.HardReset();
+    		snd_2.HardReset();
+    		snd_3.HardReset();
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    			Switch16KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 36864:
+    			snd_1.Write0(ref data);
+    			break;
+    		case 36865:
+    			snd_1.Write1(ref data);
+    			break;
+    		case 36866:
+    			snd_1.Write2(ref data);
+    			break;
+    		case 40960:
+    			snd_2.Write0(ref data);
+    			break;
+    		case 40961:
+    			snd_2.Write1(ref data);
+    			break;
+    		case 40962:
+    			snd_2.Write2(ref data);
+    			break;
+    		case 45056:
+    			snd_3.Write0(ref data);
+    			break;
+    		case 45057:
+    			snd_3.Write1(ref data);
+    			break;
+    		case 45058:
+    			snd_3.Write2(ref data);
+    			break;
+    		case 45059:
+    			switch ((data & 0xC) >> 2)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 49152:
+    		case 49153:
+    		case 49154:
+    		case 49155:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 53248:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 53249:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 53250:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 53251:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 57344:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 57345:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 57346:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 57347:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 61440:
+    			irq_reload = data;
+    			break;
+    		case 61441:
+    			irq_mode_cycle = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    				prescaler = 341;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61442:
+    			NesEmu.IRQFlags &= -9;
+    			irq_enable = irq_enable_on_ak;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (!irq_mode_cycle)
+    		{
+    			if (prescaler > 0)
+    			{
+    				prescaler -= 3;
+    				return;
+    			}
+    			prescaler = 341;
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void OnAPUClockSingle()
+    	{
+    		base.OnAPUClockSingle();
+    		snd_1.ClockSingle();
+    		snd_2.ClockSingle();
+    		snd_3.ClockSingle();
+    	}
+
+    	internal override void APUApplyChannelsSettings()
+    	{
+    		base.APUApplyChannelsSettings();
+    		snd_1.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SQ1;
+    		snd_2.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SQ2;
+    		snd_3.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SAW;
+    	}
+
+    	internal override double APUGetSample()
+    	{
+    		return audio_pulse_table[snd_1.output + snd_2.output] + audio_tnd_table[snd_3.output];
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_counter);
+    		stream.Write(prescaler);
+    		stream.Write(irq_mode_cycle);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    		snd_1.SaveState(ref stream);
+    		snd_2.SaveState(ref stream);
+    		snd_3.SaveState(ref stream);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_reload = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		prescaler = stream.ReadInt32();
+    		irq_mode_cycle = stream.ReadBoolean();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    		snd_1.LoadState(ref stream);
+    		snd_2.LoadState(ref stream);
+    		snd_3.LoadState(ref stream);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper025.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper025.cs
new file mode 100644
index 00000000..b2e932b1
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper025.cs
@@ -0,0 +1,254 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC4", 25)]
+    internal class Mapper025 : Board
+    {
+    	private bool prg_mode;
+
+    	private byte prg_reg0;
+
+    	private int[] chr_Reg;
+
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	private int prescaler;
+
+    	private bool irq_mode_cycle;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		prescaler = 341;
+    		chr_Reg = new int[8];
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    		case 32772:
+    		case 32776:
+    		case 32780:
+    			prg_reg0 = data;
+    			Switch08KPRG(prg_mode ? (PRG_ROM_08KB_Mask - 1) : (prg_reg0 & 0x1F), PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? (prg_reg0 & 0x1F) : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			break;
+    		case 36864:
+    		case 36866:
+    		case 36872:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 36865:
+    		case 36867:
+    		case 36868:
+    		case 36876:
+    			prg_mode = (data & 2) == 2;
+    			Switch08KPRG(prg_mode ? (PRG_ROM_08KB_Mask - 1) : (prg_reg0 & 0x1F), PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? (prg_reg0 & 0x1F) : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			break;
+    		case 40960:
+    		case 40961:
+    		case 40962:
+    		case 40963:
+    		case 40964:
+    		case 40968:
+    		case 40972:
+    			Switch08KPRG(data & 0x1F, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45058:
+    		case 45064:
+    			chr_Reg[0] = (chr_Reg[0] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[0], CHRArea.Area0000);
+    			break;
+    		case 45057:
+    		case 45060:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 45059:
+    		case 45068:
+    			chr_Reg[1] = (chr_Reg[1] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[1], CHRArea.Area0400);
+    			break;
+    		case 49152:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49154:
+    		case 49160:
+    			chr_Reg[2] = (chr_Reg[2] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[2], CHRArea.Area0800);
+    			break;
+    		case 49153:
+    		case 49156:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 49155:
+    		case 49164:
+    			chr_Reg[3] = (chr_Reg[3] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[3], CHRArea.Area0C00);
+    			break;
+    		case 53248:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53250:
+    		case 53256:
+    			chr_Reg[4] = (chr_Reg[4] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[4], CHRArea.Area1000);
+    			break;
+    		case 53249:
+    		case 53252:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 53251:
+    		case 53260:
+    			chr_Reg[5] = (chr_Reg[5] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[5], CHRArea.Area1400);
+    			break;
+    		case 57344:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57346:
+    		case 57352:
+    			chr_Reg[6] = (chr_Reg[6] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[6], CHRArea.Area1800);
+    			break;
+    		case 57345:
+    		case 57348:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF0) | (data & 0xF);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		case 57347:
+    		case 57356:
+    			chr_Reg[7] = (chr_Reg[7] & 0xF) | ((data & 0xF) << 4);
+    			Switch01KCHR(chr_Reg[7], CHRArea.Area1C00);
+    			break;
+    		case 61440:
+    			irq_reload = (irq_reload & 0xF0) | (data & 0xF);
+    			break;
+    		case 61442:
+    		case 61448:
+    			irq_reload = (irq_reload & 0xF) | ((data & 0xF) << 4);
+    			break;
+    		case 61441:
+    		case 61444:
+    			irq_mode_cycle = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    				prescaler = 341;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61443:
+    		case 61452:
+    			NesEmu.IRQFlags &= -9;
+    			irq_enable = irq_enable_on_ak;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (!irq_mode_cycle)
+    		{
+    			if (prescaler > 0)
+    			{
+    				prescaler -= 3;
+    				return;
+    			}
+    			prescaler = 341;
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_mode);
+    		stream.Write(prg_reg0);
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			stream.Write(chr_Reg[i]);
+    		}
+    		stream.Write(irq_reload);
+    		stream.Write(irq_counter);
+    		stream.Write(prescaler);
+    		stream.Write(irq_mode_cycle);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_mode = stream.ReadBoolean();
+    		prg_reg0 = stream.ReadByte();
+    		for (int i = 0; i < chr_Reg.Length; i++)
+    		{
+    			chr_Reg[i] = stream.ReadInt32();
+    		}
+    		irq_reload = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		prescaler = stream.ReadInt32();
+    		irq_mode_cycle = stream.ReadBoolean();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper026.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper026.cs
new file mode 100644
index 00000000..673488c4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper026.cs
@@ -0,0 +1,245 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC6", 26)]
+    [WithExternalSound]
+    internal class Mapper026 : Board
+    {
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	private int prescaler;
+
+    	private bool irq_mode_cycle;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	private VRC6Pulse snd_1;
+
+    	private VRC6Pulse snd_2;
+
+    	private VRC6Sawtooth snd_3;
+
+    	private double[] audio_pulse_table;
+
+    	private double[] audio_tnd_table;
+
+    	internal override void Initialize(IRom rom)
+    	{
+    		base.Initialize(rom);
+    		snd_1 = new VRC6Pulse();
+    		snd_2 = new VRC6Pulse();
+    		snd_3 = new VRC6Sawtooth();
+    		audio_pulse_table = new double[32];
+    		for (int i = 0; i < 32; i++)
+    		{
+    			audio_pulse_table[i] = 95.52 / (8128.0 / (double)i + 100.0);
+    		}
+    		audio_tnd_table = new double[204];
+    		for (int j = 0; j < 204; j++)
+    		{
+    			audio_tnd_table[j] = 163.67 / (24329.0 / (double)j + 100.0);
+    		}
+    	}
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		APUApplyChannelsSettings();
+    		snd_1.HardReset();
+    		snd_2.HardReset();
+    		snd_3.HardReset();
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    			Switch16KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 36864:
+    			snd_1.Write0(ref data);
+    			break;
+    		case 36866:
+    			snd_1.Write1(ref data);
+    			break;
+    		case 36865:
+    			snd_1.Write2(ref data);
+    			break;
+    		case 40960:
+    			snd_2.Write0(ref data);
+    			break;
+    		case 40962:
+    			snd_2.Write1(ref data);
+    			break;
+    		case 40961:
+    			snd_2.Write2(ref data);
+    			break;
+    		case 45056:
+    			snd_3.Write0(ref data);
+    			break;
+    		case 45058:
+    			snd_3.Write1(ref data);
+    			break;
+    		case 45057:
+    			snd_3.Write2(ref data);
+    			break;
+    		case 45059:
+    			switch ((data & 0xC) >> 2)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 49152:
+    		case 49153:
+    		case 49154:
+    		case 49155:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 53248:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 53250:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 53249:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 53251:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 57344:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 57346:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 57345:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 57347:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 61440:
+    			irq_reload = data;
+    			break;
+    		case 61442:
+    			irq_mode_cycle = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    				prescaler = 341;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61441:
+    			NesEmu.IRQFlags &= -9;
+    			irq_enable = irq_enable_on_ak;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (!irq_mode_cycle)
+    		{
+    			if (prescaler > 0)
+    			{
+    				prescaler -= 3;
+    				return;
+    			}
+    			prescaler = 341;
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void OnAPUClockSingle()
+    	{
+    		base.OnAPUClockSingle();
+    		snd_1.ClockSingle();
+    		snd_2.ClockSingle();
+    		snd_3.ClockSingle();
+    	}
+
+    	internal override void APUApplyChannelsSettings()
+    	{
+    		base.APUApplyChannelsSettings();
+    		snd_1.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SQ1;
+    		snd_2.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SQ2;
+    		snd_3.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_VRC6_SAW;
+    	}
+
+    	internal override double APUGetSample()
+    	{
+    		return audio_pulse_table[snd_1.output + snd_2.output] + audio_tnd_table[snd_3.output];
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_counter);
+    		stream.Write(prescaler);
+    		stream.Write(irq_mode_cycle);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    		snd_1.SaveState(ref stream);
+    		snd_2.SaveState(ref stream);
+    		snd_3.SaveState(ref stream);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_reload = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		prescaler = stream.ReadInt32();
+    		irq_mode_cycle = stream.ReadBoolean();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    		snd_1.LoadState(ref stream);
+    		snd_2.LoadState(ref stream);
+    		snd_3.LoadState(ref stream);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper032.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper032.cs
new file mode 100644
index 00000000..b7a64de8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper032.cs
@@ -0,0 +1,109 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Irem G-101", 32)]
+    internal class Mapper032 : Board
+    {
+    	private bool prg_mode;
+
+    	private byte prg_reg0;
+
+    	private bool enable_mirroring_switch;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		enable_mirroring_switch = true;
+    		if (SHA1 == "7E4180432726A433C46BA2206D9E13B32761C11E")
+    		{
+    			enable_mirroring_switch = false;
+    			Switch01KNMTFromMirroring(Mirroring.OneScA);
+    		}
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF007)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    		case 32772:
+    		case 32773:
+    		case 32774:
+    		case 32775:
+    			prg_reg0 = data;
+    			Switch08KPRG((!prg_mode) ? prg_reg0 : 0, PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? prg_reg0 : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			break;
+    		case 36864:
+    		case 36865:
+    		case 36866:
+    		case 36867:
+    		case 36868:
+    		case 36869:
+    		case 36870:
+    		case 36871:
+    			prg_mode = (data & 2) == 2;
+    			Switch08KPRG((!prg_mode) ? prg_reg0 : 0, PRGArea.Area8000);
+    			Switch08KPRG(prg_mode ? prg_reg0 : (PRG_ROM_08KB_Mask - 1), PRGArea.AreaC000);
+    			if (enable_mirroring_switch)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40960:
+    		case 40961:
+    		case 40962:
+    		case 40963:
+    		case 40964:
+    		case 40965:
+    		case 40966:
+    		case 40967:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 45057:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 45058:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 45059:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 45060:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 45061:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 45062:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 45063:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_mode);
+    		stream.Write(prg_reg0);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_mode = stream.ReadBoolean();
+    		prg_reg0 = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper033.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper033.cs
new file mode 100644
index 00000000..1be43807
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper033.cs
@@ -0,0 +1,177 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Taito TC0190/TC0350", 33)]
+    [HassIssues]
+    internal class Mapper033 : Board
+    {
+    	private bool MODE;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper33;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		MODE = true;
+    		if (IsGameFoundOnDB)
+    		{
+    			foreach (string chip in base.Chips)
+    			{
+    				if (chip.Contains("TC0190"))
+    				{
+    					MODE = false;
+    					ppuA12TogglesOnRaisingEdge = true;
+    					enabled_ppuA12ToggleTimer = true;
+    					break;
+    				}
+    			}
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		mmc3_alt_behavior = false;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (!MODE)
+    		{
+    			switch (address & 0xE003)
+    			{
+    			case 32768:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 32769:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			case 32770:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 32771:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 40960:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 40961:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 40962:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 40963:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			case 49152:
+    				irq_reload = (byte)(data ^ 0xFFu);
+    				break;
+    			case 49153:
+    				if (mmc3_alt_behavior)
+    				{
+    					irq_clear = true;
+    				}
+    				irq_counter = 0;
+    				break;
+    			case 49154:
+    				irq_enabled = false;
+    				NesEmu.IRQFlags &= -9;
+    				break;
+    			case 49155:
+    				irq_enabled = true;
+    				break;
+    			case 57344:
+    				Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Horz : Mirroring.Vert);
+    				break;
+    			}
+    		}
+    		else
+    		{
+    			switch (address & 0xA003)
+    			{
+    			case 32768:
+    				Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Horz : Mirroring.Vert);
+    				Switch08KPRG(data & 0x3F, PRGArea.Area8000);
+    				break;
+    			case 32769:
+    				Switch08KPRG(data & 0x3F, PRGArea.AreaA000);
+    				break;
+    			case 32770:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 32771:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 40960:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 40961:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 40962:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 40963:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		if (!MODE)
+    		{
+    			old_irq_counter = irq_counter;
+    			if (irq_counter == 0 || irq_clear)
+    			{
+    				irq_counter = irq_reload;
+    			}
+    			else
+    			{
+    				irq_counter--;
+    			}
+    			if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    			irq_clear = false;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper034.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper034.cs
new file mode 100644
index 00000000..6e93ecef
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper034.cs
@@ -0,0 +1,50 @@
+namespace MyNes.Core
+{
+    [BoardInfo("BxROM/NINA-001", 34)]
+    internal class Mapper034 : Board
+    {
+    	private bool BxROM;
+
+    	private byte writeData;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		BxROM = true;
+    		if (base.BoardType.Contains("NINA"))
+    		{
+    			BxROM = false;
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		base.WriteSRM(ref address, ref data);
+    		if (!BxROM)
+    		{
+    			switch (address)
+    			{
+    			case 32765:
+    				Switch32KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 32766:
+    				Switch04KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 32767:
+    				Switch04KCHR(data, CHRArea.Area1000);
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (BxROM)
+    		{
+    			ReadPRG(ref address, out writeData);
+    			writeData &= data;
+    			Switch32KPRG(writeData, PRGArea.Area8000);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper041.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper041.cs
new file mode 100644
index 00000000..cf0aa67e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper041.cs
@@ -0,0 +1,58 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Caltron 6-in-1", 41)]
+    internal class Mapper041 : Board
+    {
+    	private bool enableReg;
+
+    	private int vromReg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		vromReg = 0;
+    		enableReg = true;
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (address <= 26623)
+    		{
+    			Switch32KPRG(address & 7, PRGArea.Area8000);
+    			enableReg = (address & 4) == 4;
+    			vromReg = (vromReg & 3) | ((address >> 1) & 0xC);
+    			Switch08KCHR(vromReg);
+    			Switch01KNMTFromMirroring(((address & 0x20) == 32) ? Mirroring.Horz : Mirroring.Vert);
+    		}
+    		else
+    		{
+    			base.WriteSRM(ref address, ref data);
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (enableReg)
+    		{
+    			vromReg = (vromReg & 0xC) | (data & 3);
+    			Switch08KCHR(vromReg);
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(enableReg);
+    		stream.Write(vromReg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		enableReg = stream.ReadBoolean();
+    		vromReg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper042.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper042.cs
new file mode 100644
index 00000000..80c909be
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper042.cs
@@ -0,0 +1,94 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Mario Baby", 42)]
+    internal class Mapper042 : Board
+    {
+    	private int SRAM_PRG_Page;
+
+    	private bool irqEnable;
+
+    	private int irqCounter;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch32KPRG(PRG_ROM_32KB_Mask, PRGArea.Area8000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (address == 32768)
+    		{
+    			Switch08KCHR(data);
+    			return;
+    		}
+    		if (address == 61440)
+    		{
+    			SRAM_PRG_Page = data << 13;
+    			return;
+    		}
+    		switch (address & 0xE003)
+    		{
+    		case 57344:
+    			Switch08KPRG(data, PRGArea.Area6000);
+    			break;
+    		case 57345:
+    			if ((data & 8) == 8)
+    			{
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    			}
+    			else
+    			{
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    			}
+    			break;
+    		case 57346:
+    			irqEnable = (data & 2) == 2;
+    			if (!irqEnable)
+    			{
+    				irqCounter = 0;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irqEnable)
+    		{
+    			return;
+    		}
+    		int num = irqCounter++;
+    		if ((irqCounter & 0x6000) != (num & 0x6000))
+    		{
+    			if ((irqCounter & 0x6000) == 24576)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    			else
+    			{
+    				NesEmu.IRQFlags &= -9;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(SRAM_PRG_Page);
+    		stream.Write(irqEnable);
+    		stream.Write(irqCounter);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		SRAM_PRG_Page = stream.ReadInt32();
+    		irqEnable = stream.ReadBoolean();
+    		irqCounter = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper044.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper044.cs
new file mode 100644
index 00000000..ce5c501f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper044.cs
@@ -0,0 +1,235 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("7-in-1 MMC3 Port A001h", 44, true, true)]
+    [HassIssues]
+    internal class Mapper044 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int block;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	private int prg_and;
+
+    	private int prg_or;
+
+    	private int chr_and;
+
+    	private int chr_or;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper44;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_and = 15;
+    		prg_or = 0;
+    		chr_and = 127;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			block = data & 7;
+    			prg_and = ((block > 5) ? 31 : 15);
+    			prg_or = ((block < 5) ? (block << 4) : 96);
+    			chr_and = ((block > 5) ? 255 : 127);
+    			chr_or = ((block < 5) ? (block << 7) : 768);
+    			SetupPRG();
+    			SetupCHR();
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    		Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		stream.Write(block);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_and);
+    		stream.Write(prg_or);
+    		stream.Write(chr_and);
+    		stream.Write(chr_or);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		block = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		chr_or = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper045.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper045.cs
new file mode 100644
index 00000000..9b4bd9ee
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper045.cs
@@ -0,0 +1,294 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("X-in-1 MMC3 Port 6000hx4", 45, true, true)]
+    internal class Mapper045 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	private bool locked;
+
+    	private int regCounter;
+
+    	private int prg_and;
+
+    	private int prg_or;
+
+    	private int chr_and;
+
+    	private int chr_or;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_and = 63;
+    		prg_or = 0;
+    		chr_and = 4095;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    		locked = false;
+    		regCounter = 0;
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (locked)
+    		{
+    			base.WriteSRM(ref address, ref data);
+    			return;
+    		}
+    		switch (regCounter)
+    		{
+    		case 0:
+    			chr_or = (chr_or & 0xFF00) | data;
+    			SetupCHR();
+    			break;
+    		case 1:
+    			prg_or = data;
+    			SetupPRG();
+    			break;
+    		case 2:
+    			if ((data & 8) == 8)
+    			{
+    				chr_and = (1 << (data & 7) + 1) - 1;
+    			}
+    			else
+    			{
+    				chr_and = ((data <= 0) ? (-1) : 0);
+    			}
+    			chr_or = (chr_or & 0xFF) | ((data & 0xF0) << 4);
+    			SetupCHR();
+    			break;
+    		case 3:
+    			locked = (data & 0x40) == 64;
+    			prg_and = (data & 0x3F) ^ 0x3F;
+    			SetupPRG();
+    			break;
+    		}
+    		regCounter++;
+    		if (regCounter > 3)
+    		{
+    			regCounter = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    		Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_and);
+    		stream.Write(prg_or);
+    		stream.Write(chr_and);
+    		stream.Write(chr_or);
+    		stream.Write(locked);
+    		stream.Write(regCounter);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		chr_or = stream.ReadInt32();
+    		locked = stream.ReadBoolean();
+    		regCounter = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper046.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper046.cs
new file mode 100644
index 00000000..4b260b72
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper046.cs
@@ -0,0 +1,42 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("15-in-1 Color Dreams", 46)]
+    internal class Mapper046 : Board
+    {
+    	private int prg_reg;
+
+    	private int chr_reg;
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		prg_reg = (prg_reg & 1) | ((data << 1) & 0x1E);
+    		chr_reg = (chr_reg & 7) | ((data >> 1) & 0x78);
+    		Switch08KCHR(chr_reg);
+    		Switch32KPRG(prg_reg, PRGArea.Area8000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		prg_reg = (data & 1) | (prg_reg & 0x1E);
+    		chr_reg = ((data >> 4) & 7) | (chr_reg & 0x78);
+    		Switch08KCHR(chr_reg);
+    		Switch32KPRG(prg_reg, PRGArea.Area8000);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_reg);
+    		stream.Write(chr_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_reg = stream.ReadInt32();
+    		chr_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper047.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper047.cs
new file mode 100644
index 00000000..2405ae4b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper047.cs
@@ -0,0 +1,258 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("2-in-1 MMC3 Port 6000h", 47, true, true)]
+    internal class Mapper047 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	private int block;
+
+    	private int prg_and;
+
+    	private int prg_or;
+
+    	private int chr_and;
+
+    	private int chr_or;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_and = 15;
+    		prg_or = 0;
+    		chr_and = 127;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (PRG_RAM_ENABLED[PRG_AREA_BLK_INDEX[0]] && PRG_RAM_WRITABLE[PRG_AREA_BLK_INDEX[0]])
+    		{
+    			block = data & 1;
+    			prg_or = block << 4;
+    			chr_or = block << 7;
+    			SetupCHR();
+    			SetupPRG();
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    		Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		stream.Write(block);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_and);
+    		stream.Write(prg_or);
+    		stream.Write(chr_and);
+    		stream.Write(chr_or);
+    		stream.Write(irq_enabled);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		block = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		chr_or = stream.ReadInt32();
+    		irq_enabled = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper048.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper048.cs
new file mode 100644
index 00000000..5510695a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper048.cs
@@ -0,0 +1,172 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Taito TC0190/TC0350", 48, true, true)]
+    internal class Mapper048 : Board
+    {
+    	private bool MODE;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		MODE = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			foreach (string chip in base.Chips)
+    			{
+    				if (chip.Contains("TC0350"))
+    				{
+    					MODE = true;
+    					break;
+    				}
+    			}
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		mmc3_alt_behavior = false;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (!MODE)
+    		{
+    			switch (address & 0xE003)
+    			{
+    			case 32768:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 32769:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			case 32770:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 32771:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 40960:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 40961:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 40962:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 40963:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			case 49152:
+    				irq_reload = (byte)(data ^ 0xFFu);
+    				break;
+    			case 49153:
+    				if (mmc3_alt_behavior)
+    				{
+    					irq_clear = true;
+    				}
+    				irq_counter = 0;
+    				break;
+    			case 49154:
+    				irq_enabled = false;
+    				NesEmu.IRQFlags &= -9;
+    				break;
+    			case 49155:
+    				irq_enabled = true;
+    				break;
+    			case 57344:
+    				Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Horz : Mirroring.Vert);
+    				break;
+    			}
+    		}
+    		else
+    		{
+    			switch (address & 0xA003)
+    			{
+    			case 32768:
+    				Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Horz : Mirroring.Vert);
+    				Switch08KPRG(data & 0x3F, PRGArea.Area8000);
+    				break;
+    			case 32769:
+    				Switch08KPRG(data & 0x3F, PRGArea.AreaA000);
+    				break;
+    			case 32770:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 32771:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 40960:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 40961:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 40962:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 40963:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		if (!MODE)
+    		{
+    			old_irq_counter = irq_counter;
+    			if (irq_counter == 0 || irq_clear)
+    			{
+    				irq_counter = irq_reload;
+    			}
+    			else
+    			{
+    				irq_counter--;
+    			}
+    			if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    			irq_clear = false;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper049.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper049.cs
new file mode 100644
index 00000000..8a3453ca
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper049.cs
@@ -0,0 +1,272 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("4-in-1 MMC3 Port 6xxxh", 49, true, true)]
+    internal class Mapper049 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	private bool prg_32Mode;
+
+    	private int prg_32Page;
+
+    	private int prg_and;
+
+    	private int prg_or;
+
+    	private int chr_and;
+
+    	private int chr_or;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		prg_32Mode = false;
+    		prg_32Page = 0;
+    		address_8001 = 0;
+    		prg_and = 15;
+    		prg_or = 0;
+    		chr_and = 127;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (PRG_RAM_ENABLED[PRG_AREA_BLK_INDEX[0]] && PRG_RAM_WRITABLE[PRG_AREA_BLK_INDEX[0]])
+    		{
+    			prg_32Mode = (data & 1) == 1;
+    			prg_or = (data >> 2) & 0x30;
+    			chr_or = (data & 0xC0) << 1;
+    			prg_32Page = (data >> 4) & 3;
+    			SetupCHR();
+    			SetupPRG();
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		if (prg_32Mode)
+    		{
+    			Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    			Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    			Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    			Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(prg_32Page, PRGArea.Area8000);
+    		}
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_and);
+    		stream.Write(prg_or);
+    		stream.Write(chr_and);
+    		stream.Write(chr_or);
+    		stream.Write(prg_32Mode);
+    		stream.Write(prg_32Page);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		chr_or = stream.ReadInt32();
+    		prg_32Mode = stream.ReadBoolean();
+    		prg_32Page = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper050.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper050.cs
new file mode 100644
index 00000000..e275bfe7
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper050.cs
@@ -0,0 +1,71 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("FDS-Port - Alt. Levels", 50)]
+    internal class Mapper050 : Board
+    {
+    	private int prg_page;
+
+    	private int irq_counter;
+
+    	private bool irq_enabled;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(15, PRGArea.Area6000);
+    		Switch08KPRG(8, PRGArea.Area8000);
+    		Switch08KPRG(9, PRGArea.AreaA000);
+    		Switch08KPRG(11, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x4120)
+    		{
+    		case 16416:
+    			prg_page = (data & 8) | ((data & 1) << 2) | ((data >> 1) & 3);
+    			Switch08KPRG(prg_page, PRGArea.AreaC000);
+    			break;
+    		case 16672:
+    			irq_enabled = (data & 1) == 1;
+    			if (!irq_enabled)
+    			{
+    				irq_counter = 0;
+    				NesEmu.IRQFlags &= -9;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_enabled)
+    		{
+    			irq_counter++;
+    			if (irq_counter == 4096)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = 0;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_page);
+    		stream.Write(irq_counter);
+    		stream.Write(irq_enabled);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_page = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		irq_enabled = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper051.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper051.cs
new file mode 100644
index 00000000..b8af919f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper051.cs
@@ -0,0 +1,79 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("11-in-1", 51)]
+    internal class Mapper051 : Board
+    {
+    	private int bank;
+
+    	private int mode = 1;
+
+    	private int offset;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		bank = 0;
+    		mode = 1;
+    		offset = 0;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE000)
+    		{
+    		case 32768:
+    		case 57344:
+    			bank = data & 0xF;
+    			UpdateBanks();
+    			break;
+    		case 49152:
+    			bank = data & 0xF;
+    			mode = ((data >> 3) & 2) | (mode & 1);
+    			UpdateBanks();
+    			break;
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		mode = ((data >> 3) & 2) | ((data >> 1) & 1);
+    		UpdateBanks();
+    	}
+
+    	private void UpdateBanks()
+    	{
+    		offset = 0;
+    		if ((mode & 1) == 1)
+    		{
+    			Switch32KPRG(bank, PRGArea.Area8000);
+    			offset = 35;
+    		}
+    		else
+    		{
+    			Switch08KPRG((bank << 1) | (mode >> 1), PRGArea.Area8000);
+    			Switch08KPRG((bank << 1) | 7, PRGArea.Area8000);
+    			offset = 47;
+    		}
+    		Switch08KPRG(offset | (bank << 2), PRGArea.Area6000);
+    		Switch01KNMTFromMirroring((mode == 3) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(bank);
+    		stream.Write(mode);
+    		stream.Write(offset);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		bank = stream.ReadInt32();
+    		mode = stream.ReadInt32();
+    		offset = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper052.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper052.cs
new file mode 100644
index 00000000..8312e6e8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper052.cs
@@ -0,0 +1,273 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("7-in-1 MMC3 Port 6800h with SRAM", 52, true, true)]
+    internal class Mapper052 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	private int prg_and;
+
+    	private int prg_or;
+
+    	private int chr_and;
+
+    	private int chr_or;
+
+    	private bool locked;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		locked = false;
+    		address_8001 = 0;
+    		prg_and = 31;
+    		prg_or = 0;
+    		chr_and = 255;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		HardReset();
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (!locked)
+    		{
+    			if (PRG_RAM_ENABLED[PRG_AREA_BLK_INDEX[0]] && PRG_RAM_WRITABLE[PRG_AREA_BLK_INDEX[0]])
+    			{
+    				locked = true;
+    				prg_and = ((data << 1) & 0x10) ^ 0x1F;
+    				prg_or = ((data & 6) | ((data >> 3) & data & 1)) << 4;
+    				chr_and = ((data & 0x40) << 1) ^ 0xFF;
+    				chr_or = (((data >> 3) & 4) | ((data >> 1) & 2) | ((data >> 6) & (data >> 4) & 1)) << 7;
+    				SetupCHR();
+    				SetupPRG();
+    			}
+    		}
+    		else
+    		{
+    			base.WriteSRM(ref address, ref data);
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    		Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_and);
+    		stream.Write(prg_or);
+    		stream.Write(chr_and);
+    		stream.Write(chr_or);
+    		stream.Write(locked);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		chr_or = stream.ReadInt32();
+    		locked = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper053.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper053.cs
new file mode 100644
index 00000000..db1aaa56
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper053.cs
@@ -0,0 +1,58 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 53)]
+    [HassIssues]
+    internal class Mapper053 : Board
+    {
+    	private byte[] regs = new byte[2];
+
+    	private bool epromFirst;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper53;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		regs = new byte[2];
+    		epromFirst = true;
+    		Switch08KPRG(0, PRGArea.Area6000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		regs[1] = data;
+    		UpdatePrg();
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		regs[0] = data;
+    		UpdatePrg();
+    		Switch01KNMTFromMirroring(((data & 0x20) == 32) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+
+    	private void UpdatePrg()
+    	{
+    		int num = (regs[0] << 3) & 0x78;
+    		Switch08KPRG(((num << 1) | 0xF) + (epromFirst ? 4 : 0), PRGArea.Area6000);
+    		Switch16KPRG(((regs[0] & 0x10) == 16) ? ((num | (regs[1] & 7)) + (epromFirst ? 2 : 0)) : ((!epromFirst) ? 128 : 0), PRGArea.Area8000);
+    		Switch16KPRG(((regs[0] & 0x10) == 16) ? ((num | 7) + (epromFirst ? 2 : 0)) : (epromFirst ? 1 : 129), PRGArea.AreaC000);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(regs);
+    		stream.Write(epromFirst);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		stream.Read(regs, 0, 2);
+    		epromFirst = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper056.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper056.cs
new file mode 100644
index 00000000..7bdcdc3e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper056.cs
@@ -0,0 +1,97 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate SMB3", 56)]
+    internal class Mapper056 : Board
+    {
+    	private int irqCounter;
+
+    	private int irqLatch;
+
+    	private bool irqEnabled;
+
+    	private int irqControl;
+
+    	private int switchControl;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper56;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		irqLatch = 0;
+    		irqCounter = 0;
+    		irqControl = 0;
+    		irqEnabled = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (address < 61440)
+    		{
+    			switch (address & 0xE000)
+    			{
+    			case 32768:
+    				irqLatch = (irqLatch & 0xFFF0) | (data & 0xF);
+    				break;
+    			case 36864:
+    				irqLatch = (irqLatch & 0xFF0F) | ((data & 0xF) << 4);
+    				break;
+    			case 40960:
+    				irqLatch = (irqLatch & 0xF0FF) | ((data & 0xF) << 8);
+    				break;
+    			case 45056:
+    				irqLatch = (irqLatch & 0xFFF) | ((data & 0xF) << 12);
+    				break;
+    			case 49152:
+    				irqControl = data & 5;
+    				irqEnabled = (data & 2) == 2;
+    				if (irqEnabled)
+    				{
+    					irqCounter = irqLatch;
+    				}
+    				NesEmu.IRQFlags &= -9;
+    				break;
+    			case 53248:
+    				irqEnabled = (irqControl & 1) == 1;
+    				NesEmu.IRQFlags &= -9;
+    				break;
+    			case 57344:
+    				switchControl = data;
+    				break;
+    			}
+    			return;
+    		}
+    		int num = (switchControl & 0xF) - 1;
+    		if (num < 3)
+    		{
+    			Switch08KPRG((data & 0xF) | (PRG_AREA_BLK_INDEX[(num >> 13) + 1] & 0x10), (PRGArea)num);
+    		}
+    		switch (address & 0xC00)
+    		{
+    		case 0:
+    			address &= 3;
+    			if (address < 3)
+    			{
+    				Switch08KPRG((data & 0xF) | (PRG_AREA_BLK_INDEX[(num >> 13) + 1] & 0x10), (PRGArea)address);
+    			}
+    			break;
+    		case 2048:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Vert : Mirroring.Horz);
+    			break;
+    		case 3072:
+    			Switch01KCHR(data, (CHRArea)(address & 7u));
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irqEnabled && irqCounter++ == 65535)
+    		{
+    			irqCounter = irqLatch;
+    			NesEmu.IRQFlags |= 8;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper057.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper057.cs
new file mode 100644
index 00000000..3adefd77
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper057.cs
@@ -0,0 +1,55 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("6-in-1 (SuperGK)", 57)]
+    internal class Mapper057 : Board
+    {
+    	private int chr_aaa;
+
+    	private int chr_bbb;
+
+    	private int chr_hhh;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x8800)
+    		{
+    		case 32768:
+    			chr_aaa = data & 7;
+    			chr_hhh = (data & 0x40) >> 3;
+    			break;
+    		case 34816:
+    			chr_bbb = data & 7;
+    			if ((data & 0x10) == 16)
+    			{
+    				Switch32KPRG((data & 0xE0) >> 6, PRGArea.Area8000);
+    			}
+    			else
+    			{
+    				Switch16KPRG((data & 0xE0) >> 5, PRGArea.Area8000);
+    				Switch16KPRG((data & 0xE0) >> 5, PRGArea.AreaC000);
+    			}
+    			Switch01KNMTFromMirroring(((data & 8) == 8) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		}
+    		Switch08KCHR(chr_hhh | (chr_aaa | chr_bbb));
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr_aaa);
+    		stream.Write(chr_bbb);
+    		stream.Write(chr_hhh);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr_aaa = stream.ReadInt32();
+    		chr_bbb = stream.ReadInt32();
+    		chr_hhh = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper058.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper058.cs
new file mode 100644
index 00000000..82f11305
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper058.cs
@@ -0,0 +1,24 @@
+namespace MyNes.Core
+{
+    [BoardInfo("68-in-1 (Game Star)", 58)]
+    [HassIssues]
+    internal class Mapper058 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper58;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR((address >> 3) & 7);
+    		if ((address & 0x40) == 0)
+    		{
+    			Switch32KPRG((address & 7) >> 1, PRGArea.Area8000);
+    		}
+    		else
+    		{
+    			Switch16KPRG(address & 7, PRGArea.Area8000);
+    			Switch16KPRG(address & 7, PRGArea.AreaC000);
+    		}
+    		Switch01KNMTFromMirroring(((address & 0x80) == 128) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper060.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper060.cs
new file mode 100644
index 00000000..ff0b122c
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper060.cs
@@ -0,0 +1,67 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 60)]
+    [HassIssues]
+    internal class Mapper060 : Board
+    {
+    	private int latch;
+
+    	private byte menu;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper60;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		latch = 0;
+    		menu = 0;
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		base.SoftReset();
+    		latch = 0;
+    		menu = (byte)((uint)(menu + 1) & 3u);
+    		Switch08KCHR(menu);
+    		Switch16KPRG(menu, PRGArea.Area8000);
+    		Switch16KPRG(menu, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		latch = address & 0x100;
+    		Switch01KNMTFromMirroring(((address & 8) == 8) ? Mirroring.Horz : Mirroring.Vert);
+    		Switch16KPRG((address >> 4) & ~((~address >> 7) & 1), PRGArea.Area8000);
+    		Switch16KPRG((address >> 4) | ((~address >> 7) & 1), PRGArea.AreaC000);
+    		Switch08KCHR(address);
+    	}
+
+    	internal override void ReadPRG(ref ushort address, out byte data)
+    	{
+    		if (latch == 0)
+    		{
+    			base.ReadPRG(ref address, out data);
+    		}
+    		else
+    		{
+    			data = menu;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(latch);
+    		stream.Write(menu);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		latch = stream.ReadInt32();
+    		menu = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper061.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper061.cs
new file mode 100644
index 00000000..dec1605d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper061.cs
@@ -0,0 +1,20 @@
+namespace MyNes.Core
+{
+    [BoardInfo("20-in-1", 61)]
+    internal class Mapper061 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if ((address & 0x10) == 0)
+    		{
+    			Switch32KPRG(address & 0xF, PRGArea.Area8000);
+    		}
+    		else
+    		{
+    			Switch16KPRG(((address & 0xF) << 1) | ((address & 0x20) >> 5), PRGArea.Area8000);
+    			Switch16KPRG(((address & 0xF) << 1) | ((address & 0x20) >> 5), PRGArea.AreaC000);
+    		}
+    		Switch01KNMTFromMirroring(((address & 0x80) == 128) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper062.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper062.cs
new file mode 100644
index 00000000..e1cf08b0
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper062.cs
@@ -0,0 +1,24 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Super 700-in-1", 62)]
+    internal class Mapper062 : Board
+    {
+    	private int prg_page;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		prg_page = ((address & 0x3F00) >> 8) | (address & 0x40);
+    		Switch08KCHR(((address & 0x1F) << 2) | (data & 3));
+    		if ((address & 0x20) == 32)
+    		{
+    			Switch16KPRG(prg_page, PRGArea.Area8000);
+    			Switch16KPRG(prg_page, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(prg_page >> 1, PRGArea.Area8000);
+    		}
+    		Switch01KNMTFromMirroring(((address & 0x80) == 128) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper064.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper064.cs
new file mode 100644
index 00000000..1c60bf8c
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper064.cs
@@ -0,0 +1,258 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Tengen RAMBO-1", 64, true, true)]
+    internal class Mapper064 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private bool flag_k;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_mode;
+
+    	private bool irq_clear;
+
+    	private int irq_prescaler;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = (flag_k = false));
+    		address_8001 = 0;
+    		prg_reg = new int[3];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = 2;
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		SetupPRG();
+    		chr_reg = new int[8];
+    		for (int i = 0; i < 8; i++)
+    		{
+    			chr_reg[i] = i;
+    		}
+    		SetupCHR();
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_prescaler = 0;
+    		irq_mode = false;
+    		irq_reload = byte.MaxValue;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 0xF;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			flag_k = (data & 0x20) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data;
+    				SetupPRG();
+    				break;
+    			case 8:
+    				chr_reg[6] = data;
+    				SetupCHR();
+    				break;
+    			case 9:
+    				chr_reg[7] = data;
+    				SetupCHR();
+    				break;
+    			case 15:
+    				prg_reg[2] = data;
+    				SetupPRG();
+    				break;
+    			case 10:
+    			case 11:
+    			case 12:
+    			case 13:
+    			case 14:
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			irq_mode = (data & 1) == 1;
+    			irq_clear = true;
+    			irq_prescaler = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			if (!flag_k)
+    			{
+    				Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    				Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			}
+    			else
+    			{
+    				Switch01KCHR(chr_reg[0], CHRArea.Area0000);
+    				Switch01KCHR(chr_reg[6], CHRArea.Area0400);
+    				Switch01KCHR(chr_reg[1], CHRArea.Area0800);
+    				Switch01KCHR(chr_reg[7], CHRArea.Area0C00);
+    			}
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			if (!flag_k)
+    			{
+    				Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    				Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			}
+    			else
+    			{
+    				Switch01KCHR(chr_reg[0], CHRArea.Area1000);
+    				Switch01KCHR(chr_reg[6], CHRArea.Area1400);
+    				Switch01KCHR(chr_reg[1], CHRArea.Area1800);
+    				Switch01KCHR(chr_reg[7], CHRArea.Area1C00);
+    			}
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 1u : 0u], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[flag_p ? 1 : 2], PRGArea.AreaC000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		ClockIRQ();
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_mode)
+    		{
+    			irq_prescaler++;
+    			if (irq_prescaler == 4)
+    			{
+    				irq_prescaler = 0;
+    				ClockIRQ();
+    			}
+    		}
+    	}
+
+    	private void ClockIRQ()
+    	{
+    		if (irq_clear)
+    		{
+    			irq_counter = (byte)(irq_reload + 1);
+    			irq_clear = false;
+    		}
+    		else if (irq_counter == 0)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else if (--irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(irq_prescaler);
+    		stream.Write(irq_mode);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		irq_prescaler = stream.ReadInt32();
+    		irq_mode = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper065.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper065.cs
new file mode 100644
index 00000000..91addf80
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper065.cs
@@ -0,0 +1,94 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Irem H-3001", 65)]
+    internal class Mapper065 : Board
+    {
+    	private bool irq_enable;
+
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(0, PRGArea.Area8000);
+    		Switch08KPRG(1, PRGArea.AreaA000);
+    		Switch08KPRG(254, PRGArea.AreaC000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 36865:
+    			Switch01KNMTFromMirroring(((data & 0x80) == 128) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		case 36867:
+    			irq_enable = (data & 0x80) == 128;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 36868:
+    			irq_counter = irq_reload;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 36869:
+    			irq_reload = (irq_reload & 0xFF) | (data << 8);
+    			break;
+    		case 36870:
+    			irq_reload = (irq_reload & 0xFF00) | data;
+    			break;
+    		case 40960:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 49152:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 45056:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 45057:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 45058:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 45059:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 45060:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 45061:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 45062:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 45063:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_enable)
+    		{
+    			if (irq_counter > 0)
+    			{
+    				irq_counter--;
+    			}
+    			else if (irq_counter == 0)
+    			{
+    				irq_counter = -1;
+    				NesEmu.IRQFlags |= 8;
+    			}
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper066.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper066.cs
new file mode 100644
index 00000000..d746d3cd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper066.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("GxROM", 66)]
+    internal class Mapper066 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG((data >> 4) & 3, PRGArea.Area8000);
+    		Switch08KCHR(data & 3);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper067.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper067.cs
new file mode 100644
index 00000000..cb746193
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper067.cs
@@ -0,0 +1,108 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Sunsoft 3", 67)]
+    internal class Mapper067 : Board
+    {
+    	private bool irq_enabled;
+
+    	private int irq_counter;
+
+    	private bool odd;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		irq_enabled = false;
+    		irq_counter = 65535;
+    		odd = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF800)
+    		{
+    		case 34816:
+    			Switch02KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 38912:
+    			Switch02KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 43008:
+    			Switch02KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 47104:
+    			Switch02KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 51200:
+    			if (!odd)
+    			{
+    				irq_counter = (irq_counter & 0xFF) | (data << 8);
+    			}
+    			else
+    			{
+    				irq_counter = (irq_counter & 0xFF00) | data;
+    			}
+    			odd = !odd;
+    			break;
+    		case 55296:
+    			irq_enabled = (data & 0x10) == 16;
+    			odd = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 59392:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 63488:
+    			Switch16KPRG(data, PRGArea.Area8000);
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_enabled)
+    		{
+    			irq_counter--;
+    			if (irq_counter == 0)
+    			{
+    				irq_counter = 65535;
+    				NesEmu.IRQFlags |= 8;
+    				irq_enabled = false;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(odd);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadInt32();
+    		odd = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper068.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper068.cs
new file mode 100644
index 00000000..ebb61e39
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper068.cs
@@ -0,0 +1,112 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Sunsoft 4", 68)]
+    internal class Mapper068 : Board
+    {
+    	private bool flag_r;
+
+    	private bool flag_m;
+
+    	private int nt_reg0;
+
+    	private int nt_reg1;
+
+    	private int temp;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF000)
+    		{
+    		case 32768:
+    			Switch02KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 36864:
+    			Switch02KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 40960:
+    			Switch02KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 45056:
+    			Switch02KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 49152:
+    			nt_reg0 = (data & 0x7F) | 0x80;
+    			break;
+    		case 53248:
+    			nt_reg1 = (data & 0x7F) | 0x80;
+    			break;
+    		case 57344:
+    			flag_r = (data & 0x10) == 16;
+    			flag_m = (data & 1) == 1;
+    			Switch01KNMTFromMirroring(flag_m ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		case 61440:
+    			Switch16KPRG(data, PRGArea.Area8000);
+    			break;
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte data)
+    	{
+    		if (!flag_r)
+    		{
+    			data = NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF];
+    			return;
+    		}
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    			data = CHR_ROM[nt_reg0][address & 0x3FF];
+    			break;
+    		case 1:
+    			data = CHR_ROM[flag_m ? nt_reg0 : nt_reg1][address & 0x3FF];
+    			break;
+    		case 2:
+    			data = CHR_ROM[flag_m ? nt_reg1 : nt_reg0][address & 0x3FF];
+    			break;
+    		case 3:
+    			data = CHR_ROM[nt_reg1][address & 0x3FF];
+    			break;
+    		default:
+    			data = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		if (!flag_r)
+    		{
+    			base.WriteNMT(ref address, ref data);
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_r);
+    		stream.Write(flag_m);
+    		stream.Write(nt_reg0);
+    		stream.Write(nt_reg1);
+    		stream.Write(temp);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_r = stream.ReadBoolean();
+    		flag_m = stream.ReadBoolean();
+    		nt_reg0 = stream.ReadInt32();
+    		nt_reg1 = stream.ReadInt32();
+    		temp = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper069.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper069.cs
new file mode 100644
index 00000000..65867f02
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper069.cs
@@ -0,0 +1,259 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("FME-7/Sunsoft 5B", 69)]
+    [WithExternalSound]
+    internal class Mapper069 : Board
+    {
+    	private int address_A000;
+
+    	private int address_E000;
+
+    	private int irq_counter;
+
+    	private bool irq_count_enabled;
+
+    	private bool irq_trigger_enabled;
+
+    	private Sunsoft5BChnl snd_1;
+
+    	private Sunsoft5BChnl snd_2;
+
+    	private Sunsoft5BChnl snd_3;
+
+    	private double[] audio_pulse_table;
+
+    	private double[] audio_tnd_table;
+
+    	internal override void Initialize(IRom rom)
+    	{
+    		base.Initialize(rom);
+    		snd_1 = new Sunsoft5BChnl();
+    		snd_2 = new Sunsoft5BChnl();
+    		snd_3 = new Sunsoft5BChnl();
+    		audio_pulse_table = new double[32];
+    		for (int i = 0; i < 32; i++)
+    		{
+    			audio_pulse_table[i] = 95.52 / (8128.0 / (double)i + 100.0);
+    		}
+    		audio_tnd_table = new double[204];
+    		for (int j = 0; j < 204; j++)
+    		{
+    			audio_tnd_table[j] = 163.67 / (24329.0 / (double)j + 100.0);
+    		}
+    	}
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		address_A000 = 0;
+    		irq_counter = 65535;
+    		irq_count_enabled = false;
+    		irq_trigger_enabled = false;
+    		APUApplyChannelsSettings();
+    		snd_1.HardReset();
+    		snd_2.HardReset();
+    		snd_3.HardReset();
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE000)
+    		{
+    		case 32768:
+    			address_A000 = data & 0xF;
+    			break;
+    		case 40960:
+    			switch (address_A000)
+    			{
+    			case 0:
+    				Switch01KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 1:
+    				Switch01KCHR(data, CHRArea.Area0400);
+    				break;
+    			case 2:
+    				Switch01KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 3:
+    				Switch01KCHR(data, CHRArea.Area0C00);
+    				break;
+    			case 4:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 5:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 6:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 7:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			case 8:
+    				TogglePRGRAMEnable((data & 0x80) == 128);
+    				if ((data & 0x40u) != 0)
+    				{
+    					Toggle08KPRG_RAM(ram: true, PRGArea.Area6000);
+    					Switch08KPRG(data & 0x3F & PRG_RAM_08KB_Mask, PRGArea.Area6000);
+    				}
+    				else
+    				{
+    					Toggle08KPRG_RAM(ram: false, PRGArea.Area6000);
+    					Switch08KPRG(data & 0x3F, PRGArea.Area6000);
+    				}
+    				break;
+    			case 9:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 10:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			case 11:
+    				Switch08KPRG(data, PRGArea.AreaC000);
+    				break;
+    			case 12:
+    				switch (data & 3)
+    				{
+    				case 0:
+    					Switch01KNMTFromMirroring(Mirroring.Vert);
+    					break;
+    				case 1:
+    					Switch01KNMTFromMirroring(Mirroring.Horz);
+    					break;
+    				case 2:
+    					Switch01KNMTFromMirroring(Mirroring.OneScA);
+    					break;
+    				case 3:
+    					Switch01KNMTFromMirroring(Mirroring.OneScB);
+    					break;
+    				}
+    				break;
+    			case 13:
+    				irq_count_enabled = (data & 0x80) == 128;
+    				irq_trigger_enabled = (data & 1) == 1;
+    				if (!irq_trigger_enabled)
+    				{
+    					NesEmu.IRQFlags &= -9;
+    				}
+    				break;
+    			case 14:
+    				irq_counter = (irq_counter & 0xFF00) | data;
+    				break;
+    			case 15:
+    				irq_counter = (irq_counter & 0xFF) | (data << 8);
+    				break;
+    			}
+    			break;
+    		case 49152:
+    			address_E000 = data & 0xF;
+    			break;
+    		case 57344:
+    			switch (address_E000)
+    			{
+    			case 0:
+    				snd_1.Write0(ref data);
+    				break;
+    			case 1:
+    				snd_1.Write1(ref data);
+    				break;
+    			case 2:
+    				snd_2.Write0(ref data);
+    				break;
+    			case 3:
+    				snd_2.Write1(ref data);
+    				break;
+    			case 4:
+    				snd_3.Write0(ref data);
+    				break;
+    			case 5:
+    				snd_3.Write1(ref data);
+    				break;
+    			case 7:
+    				snd_1.Enabled = (data & 1) == 0;
+    				snd_2.Enabled = (data & 2) == 0;
+    				snd_3.Enabled = (data & 4) == 0;
+    				break;
+    			case 8:
+    				snd_1.Volume = (byte)(data & 0xFu);
+    				break;
+    			case 9:
+    				snd_2.Volume = (byte)(data & 0xFu);
+    				break;
+    			case 10:
+    				snd_3.Volume = (byte)(data & 0xFu);
+    				break;
+    			case 6:
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_count_enabled)
+    		{
+    			return;
+    		}
+    		irq_counter--;
+    		if (irq_counter <= 0)
+    		{
+    			irq_counter = 65535;
+    			if (irq_trigger_enabled)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    			}
+    		}
+    	}
+
+    	internal override double APUGetSample()
+    	{
+    		return audio_pulse_table[snd_1.output + snd_2.output] + audio_tnd_table[snd_3.output];
+    	}
+
+    	internal override void OnAPUClockSingle()
+    	{
+    		base.OnAPUClockSingle();
+    		snd_1.ClockSingle();
+    		snd_2.ClockSingle();
+    		snd_3.ClockSingle();
+    	}
+
+    	internal override void APUApplyChannelsSettings()
+    	{
+    		base.APUApplyChannelsSettings();
+    		snd_1.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_SUN1;
+    		snd_2.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_SUN2;
+    		snd_3.Outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_SUN3;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(address_A000);
+    		stream.Write(address_E000);
+    		stream.Write(irq_counter);
+    		stream.Write(irq_count_enabled);
+    		stream.Write(irq_trigger_enabled);
+    		snd_1.SaveState(ref stream);
+    		snd_2.SaveState(ref stream);
+    		snd_3.SaveState(ref stream);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		address_A000 = stream.ReadInt32();
+    		address_E000 = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		irq_count_enabled = stream.ReadBoolean();
+    		irq_trigger_enabled = stream.ReadBoolean();
+    		snd_1.LoadState(ref stream);
+    		snd_2.LoadState(ref stream);
+    		snd_3.LoadState(ref stream);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper070.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper070.cs
new file mode 100644
index 00000000..de108bac
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper070.cs
@@ -0,0 +1,18 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Bandai", 70)]
+    internal class Mapper070 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG((data >> 4) & 0xF, PRGArea.Area8000);
+    		Switch08KCHR(data & 0xF);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper071.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper071.cs
new file mode 100644
index 00000000..7137fa15
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper071.cs
@@ -0,0 +1,30 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Camerica", 71)]
+    internal class Mapper071 : Board
+    {
+    	private bool fireHawk;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		fireHawk = SHA1.ToUpper() == "334781C830F135CF30A33E392D8AAA4AFDC223F9";
+    	}
+
+    	internal override void WritePRG(ref ushort addr, ref byte val)
+    	{
+    		if (addr < 40960)
+    		{
+    			if (fireHawk)
+    			{
+    				Switch01KNMTFromMirroring(((val & 0x10) == 16) ? Mirroring.OneScB : Mirroring.OneScA);
+    			}
+    		}
+    		else if (addr >= 49152)
+    		{
+    			Switch16KPRG(val, PRGArea.Area8000);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper072.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper072.cs
new file mode 100644
index 00000000..02f6771a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper072.cs
@@ -0,0 +1,53 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Jaleco Early Mapper 0", 72)]
+    internal class Mapper072 : Board
+    {
+    	private byte writeData;
+
+    	private int chr_reg;
+
+    	private int prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		writeData = 0;
+    		chr_reg = (prg_reg = 0);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch ((data >> 6) & 3)
+    		{
+    		case 0:
+    			Switch08KCHR(chr_reg);
+    			Switch16KPRG(prg_reg, PRGArea.Area8000);
+    			break;
+    		case 1:
+    			chr_reg = data & 0xF;
+    			break;
+    		case 2:
+    			prg_reg = data & 0xF;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr_reg);
+    		stream.Write(prg_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr_reg = stream.ReadInt32();
+    		prg_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper073.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper073.cs
new file mode 100644
index 00000000..a3b71ecf
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper073.cs
@@ -0,0 +1,111 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC3", 73)]
+    internal class Mapper073 : Board
+    {
+    	private bool irq_mode_8;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		irq_mode_8 = false;
+    		irq_enable = false;
+    		irq_enable_on_ak = false;
+    		irq_reload = 0;
+    		irq_counter = 0;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF000)
+    		{
+    		case 32768:
+    			irq_reload = (irq_reload & 0xFFF0) | (data & 0xF);
+    			break;
+    		case 36864:
+    			irq_reload = (irq_reload & 0xFF0F) | ((data & 0xF) << 4);
+    			break;
+    		case 40960:
+    			irq_reload = (irq_reload & 0xF0FF) | ((data & 0xF) << 8);
+    			break;
+    		case 45056:
+    			irq_reload = (irq_reload & 0xFFF) | ((data & 0xF) << 12);
+    			break;
+    		case 49152:
+    			irq_mode_8 = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 53248:
+    			irq_enable = irq_enable_on_ak;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61440:
+    			Switch16KPRG(data & 0xF, PRGArea.Area8000);
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (irq_mode_8)
+    		{
+    			irq_counter = (irq_counter & 0xFF00) | (byte)((irq_counter & 0xFF) + 1);
+    			if ((byte)(irq_counter & 0xFF) == byte.MaxValue)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = (irq_counter & 0xFF00) | (irq_reload & 0xFF);
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 65535)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_mode_8);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_counter);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_mode_8 = stream.ReadBoolean();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    		irq_reload = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper074.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper074.cs
new file mode 100644
index 00000000..f42f193f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper074.cs
@@ -0,0 +1,234 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC3 variant", 74, true, true)]
+    internal class Mapper074 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Toggle02KCHR_RAM(chr_reg[0] != 8 && chr_reg[0] != 9, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Toggle02KCHR_RAM(chr_reg[1] != 8 && chr_reg[1] != 9, CHRArea.Area0800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Toggle02KCHR_RAM(chr_reg[2] != 8 && chr_reg[2] != 9, CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Toggle02KCHR_RAM(chr_reg[3] != 8 && chr_reg[3] != 9, CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Toggle02KCHR_RAM(chr_reg[4] != 8 && chr_reg[4] != 9, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Toggle02KCHR_RAM(chr_reg[5] != 8 && chr_reg[5] != 9, CHRArea.Area1C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Toggle02KCHR_RAM(chr_reg[0] != 8 && chr_reg[0] != 9, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Toggle02KCHR_RAM(chr_reg[1] != 8 && chr_reg[1] != 9, CHRArea.Area1800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Toggle02KCHR_RAM(chr_reg[2] != 8 && chr_reg[2] != 9, CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Toggle02KCHR_RAM(chr_reg[3] != 8 && chr_reg[3] != 9, CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Toggle02KCHR_RAM(chr_reg[4] != 8 && chr_reg[4] != 9, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Toggle02KCHR_RAM(chr_reg[5] != 8 && chr_reg[5] != 9, CHRArea.Area0C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper075.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper075.cs
new file mode 100644
index 00000000..5942e8f3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper075.cs
@@ -0,0 +1,63 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC1", 75)]
+    internal class Mapper075 : Board
+    {
+    	private int chr0_reg;
+
+    	private int chr1_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF000)
+    		{
+    		case 32768:
+    			Switch08KPRG(data & 0xF, PRGArea.Area8000);
+    			break;
+    		case 40960:
+    			Switch08KPRG(data & 0xF, PRGArea.AreaA000);
+    			break;
+    		case 49152:
+    			Switch08KPRG(data & 0xF, PRGArea.AreaC000);
+    			break;
+    		case 36864:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			chr0_reg = (chr0_reg & 0xF) | ((data & 2) << 3);
+    			Switch04KCHR(chr0_reg, CHRArea.Area0000);
+    			chr1_reg = (chr1_reg & 0xF) | ((data & 4) << 2);
+    			Switch04KCHR(chr1_reg, CHRArea.Area1000);
+    			break;
+    		case 57344:
+    			chr0_reg = (chr0_reg & 0x10) | (data & 0xF);
+    			Switch04KCHR(chr0_reg, CHRArea.Area0000);
+    			break;
+    		case 61440:
+    			chr1_reg = (chr1_reg & 0x10) | (data & 0xF);
+    			Switch04KCHR(chr1_reg, CHRArea.Area1000);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr0_reg);
+    		stream.Write(chr1_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr0_reg = stream.ReadInt32();
+    		chr1_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper076.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper076.cs
new file mode 100644
index 00000000..8d68b937
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper076.cs
@@ -0,0 +1,77 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Namco 109", 76)]
+    internal class Mapper076 : Board
+    {
+    	private int address_8001;
+
+    	private bool prg_a;
+
+    	private byte prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask - 1, PRGArea.AreaC000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		address_8001 = 0;
+    		prg_a = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			prg_a = (data & 0x40) == 64;
+    			Switch08KPRG(prg_reg, prg_a ? PRGArea.AreaC000 : PRGArea.Area8000);
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 2:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 3:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 4:
+    				Switch02KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 5:
+    				Switch02KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 6:
+    				Switch08KPRG(prg_reg = data, prg_a ? PRGArea.AreaC000 : PRGArea.Area8000);
+    				break;
+    			case 7:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(address_8001);
+    		stream.Write(prg_a);
+    		stream.Write(prg_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		address_8001 = stream.ReadInt32();
+    		prg_a = stream.ReadBoolean();
+    		prg_reg = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper077.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper077.cs
new file mode 100644
index 00000000..f4295815
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper077.cs
@@ -0,0 +1,23 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Irem", 77)]
+    internal class Mapper077 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Toggle02KCHR_RAM(ram: true, CHRArea.Area0800);
+    		Switch02KCHR(0, CHRArea.Area0800);
+    		Toggle02KCHR_RAM(ram: true, CHRArea.Area1000);
+    		Switch02KCHR(1, CHRArea.Area1000);
+    		Toggle02KCHR_RAM(ram: true, CHRArea.Area1800);
+    		Switch02KCHR(2, CHRArea.Area1800);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch02KCHR((data >> 4) & 0xF, CHRArea.Area0000);
+    		Switch32KPRG(data & 0xF, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper078.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper078.cs
new file mode 100644
index 00000000..31ee1410
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper078.cs
@@ -0,0 +1,33 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Irem 74HC161/32", 78)]
+    internal class Mapper078 : Board
+    {
+    	private bool mirroring_mode_single;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    		mirroring_mode_single = false;
+    		if (base.BoardType == "JALECO-JF-16")
+    		{
+    			mirroring_mode_single = true;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR((data >> 4) & 0xF);
+    		Switch16KPRG(data & 7, PRGArea.Area8000);
+    		if (mirroring_mode_single)
+    		{
+    			Switch01KNMTFromMirroring(((data & 8) == 8) ? Mirroring.OneScB : Mirroring.OneScA);
+    		}
+    		else
+    		{
+    			Switch01KNMTFromMirroring(((data & 8) == 8) ? Mirroring.Vert : Mirroring.Horz);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper079.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper079.cs
new file mode 100644
index 00000000..a70f64ef
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper079.cs
@@ -0,0 +1,15 @@
+namespace MyNes.Core
+{
+    [BoardInfo("AVE Nina-3", 79)]
+    internal class Mapper079 : Board
+    {
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if ((address ^ 0x4100) == 0)
+    		{
+    			Switch32KPRG((data >> 3) & 7, PRGArea.Area8000);
+    			Switch08KCHR((data & 7) | ((data >> 3) & 8));
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper080.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper080.cs
new file mode 100644
index 00000000..547cf60d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper080.cs
@@ -0,0 +1,56 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Taito X-005", 80)]
+    internal class Mapper080 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32496:
+    			Switch02KCHR(data >> 1, CHRArea.Area0000);
+    			break;
+    		case 32497:
+    			Switch02KCHR(data >> 1, CHRArea.Area0800);
+    			break;
+    		case 32498:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 32499:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 32500:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 32501:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 32502:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Vert : Mirroring.Horz);
+    			break;
+    		case 32506:
+    		case 32507:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 32508:
+    		case 32509:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 32510:
+    		case 32511:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 32503:
+    		case 32504:
+    		case 32505:
+    			break;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper082.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper082.cs
new file mode 100644
index 00000000..92dc70a4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper082.cs
@@ -0,0 +1,70 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Taito X1-17 ", 82)]
+    internal class Mapper082 : Board
+    {
+    	private bool chr_mode;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32496:
+    			Switch02KCHR(data >> 1, chr_mode ? CHRArea.Area1000 : CHRArea.Area0000);
+    			break;
+    		case 32497:
+    			Switch02KCHR(data >> 1, chr_mode ? CHRArea.Area1800 : CHRArea.Area0800);
+    			break;
+    		case 32498:
+    			Switch01KCHR(data, (!chr_mode) ? CHRArea.Area1000 : CHRArea.Area0000);
+    			break;
+    		case 32499:
+    			Switch01KCHR(data, chr_mode ? CHRArea.Area0400 : CHRArea.Area1400);
+    			break;
+    		case 32500:
+    			Switch01KCHR(data, chr_mode ? CHRArea.Area0800 : CHRArea.Area1800);
+    			break;
+    		case 32501:
+    			Switch01KCHR(data, chr_mode ? CHRArea.Area0C00 : CHRArea.Area1C00);
+    			break;
+    		case 32502:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Vert : Mirroring.Horz);
+    			chr_mode = (data & 2) == 2;
+    			break;
+    		case 32506:
+    			Switch08KPRG(data >> 2, PRGArea.Area8000);
+    			break;
+    		case 32507:
+    			Switch08KPRG(data >> 2, PRGArea.AreaA000);
+    			break;
+    		case 32508:
+    			Switch08KPRG(data >> 2, PRGArea.AreaC000);
+    			break;
+    		case 32503:
+    		case 32504:
+    		case 32505:
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr_mode);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr_mode = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper085.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper085.cs
new file mode 100644
index 00000000..06aabf8f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper085.cs
@@ -0,0 +1,171 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("VRC7", 85)]
+    [HassIssues]
+    internal class Mapper085 : Board
+    {
+    	private int irq_reload;
+
+    	private int irq_counter;
+
+    	private int prescaler;
+
+    	private bool irq_mode_cycle;
+
+    	private bool irq_enable;
+
+    	private bool irq_enable_on_ak;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper85;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		irq_reload = 0;
+    		prescaler = 341;
+    		irq_counter = 0;
+    		irq_mode_cycle = false;
+    		irq_enable = false;
+    		irq_enable_on_ak = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32768:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 32776:
+    		case 32784:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 36864:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 40960:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 40968:
+    		case 40976:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 45056:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 45064:
+    		case 45072:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 49152:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 49160:
+    		case 49168:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 53248:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 53256:
+    		case 53264:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 57344:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 57352:
+    		case 57360:
+    			irq_reload = data;
+    			break;
+    		case 61440:
+    			irq_mode_cycle = (data & 4) == 4;
+    			irq_enable = (data & 2) == 2;
+    			irq_enable_on_ak = (data & 1) == 1;
+    			if (irq_enable)
+    			{
+    				irq_counter = irq_reload;
+    				prescaler = 341;
+    			}
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 61448:
+    		case 61456:
+    			NesEmu.IRQFlags &= -9;
+    			irq_enable = irq_enable_on_ak;
+    			break;
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_enable)
+    		{
+    			return;
+    		}
+    		if (!irq_mode_cycle)
+    		{
+    			if (prescaler > 0)
+    			{
+    				prescaler -= 3;
+    				return;
+    			}
+    			prescaler = 341;
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    		else
+    		{
+    			irq_counter++;
+    			if (irq_counter == 255)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = irq_reload;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prescaler);
+    		stream.Write(irq_counter);
+    		stream.Write(irq_mode_cycle);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_enable);
+    		stream.Write(irq_enable_on_ak);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prescaler = stream.ReadInt32();
+    		irq_counter = stream.ReadInt32();
+    		irq_mode_cycle = stream.ReadBoolean();
+    		irq_reload = stream.ReadInt32();
+    		irq_enable = stream.ReadBoolean();
+    		irq_enable_on_ak = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper086.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper086.cs
new file mode 100644
index 00000000..e34ebdf3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper086.cs
@@ -0,0 +1,15 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Jaleco Early Mapper 2", 86)]
+    internal class Mapper086 : Board
+    {
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (address < 28672)
+    		{
+    			Switch32KPRG((data >> 4) & 3, PRGArea.Area8000);
+    			Switch08KCHR((data & 7) | ((data >> 4) & 4));
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper087.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper087.cs
new file mode 100644
index 00000000..d58c181a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper087.cs
@@ -0,0 +1,11 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Jaleco/Konami", 87)]
+    internal class Mapper087 : Board
+    {
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(((data & 2) >> 1) | ((data & 1) << 1));
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper088.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper088.cs
new file mode 100644
index 00000000..76dece0b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper088.cs
@@ -0,0 +1,67 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Namco 118", 88)]
+    internal class Mapper088 : Board
+    {
+    	private int address_8001;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x8001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    				Switch02KCHR((data & 0x3F) >> 1, CHRArea.Area0000);
+    				break;
+    			case 1:
+    				Switch02KCHR((data & 0x3F) >> 1, CHRArea.Area0800);
+    				break;
+    			case 2:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1000);
+    				break;
+    			case 3:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1400);
+    				break;
+    			case 4:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1800);
+    				break;
+    			case 5:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1C00);
+    				break;
+    			case 6:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 7:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(address_8001);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		address_8001 = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper089.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper089.cs
new file mode 100644
index 00000000..94fddf54
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper089.cs
@@ -0,0 +1,19 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Sunsoft Early", 89)]
+    internal class Mapper089 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR((data & 7) | ((data >> 4) & 8));
+    		Switch16KPRG((data >> 4) & 7, PRGArea.Area8000);
+    		Switch01KNMTFromMirroring(((data & 8) == 8) ? Mirroring.OneScB : Mirroring.OneScA);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper090.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper090.cs
new file mode 100644
index 00000000..d2e4bec2
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper090.cs
@@ -0,0 +1,634 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC5-style", 90)]
+    [HassIssues]
+    internal class Mapper090 : Board
+    {
+    	protected bool MAPPER90MODE;
+
+    	private int[] prg_reg;
+
+    	private int[] chr_reg;
+
+    	private int[] nt_reg;
+
+    	private int prg_mode;
+
+    	private int chr_mode;
+
+    	private bool chr_block_mode;
+
+    	private int chr_block;
+
+    	private bool chr_m;
+
+    	private bool flag_s;
+
+    	private int irqCounter;
+
+    	private bool IrqEnable;
+
+    	private bool irqCountDownMode;
+
+    	private bool irqCountUpMode;
+
+    	private bool irqFunkyMode;
+
+    	private bool irqPrescalerSize;
+
+    	private int irqSource;
+
+    	private int irqPrescaler;
+
+    	private int irqPrescalerXOR;
+
+    	private byte irqFunkyModeReg;
+
+    	private byte Dipswitch;
+
+    	private byte multiplication_a;
+
+    	private byte multiplication_b;
+
+    	private ushort multiplication;
+
+    	private byte RAM5803;
+
+    	private bool nt_advanced_enable;
+
+    	private bool nt_rom_only;
+
+    	private int nt_ram_select;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper90;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		MAPPER90MODE = true;
+    		prg_reg = new int[4];
+    		chr_reg = new int[8];
+    		nt_reg = new int[4];
+    		prg_mode = (chr_mode = 0);
+    		for (int i = 0; i < 4; i++)
+    		{
+    			prg_reg[i] = i;
+    			nt_reg[i] = i;
+    		}
+    		for (int j = 0; j < 8; j++)
+    		{
+    			chr_reg[j] = j;
+    		}
+    		SetupPRG();
+    		SetupCHR();
+    		Dipswitch = 0;
+    		irqCounter = 0;
+    		IrqEnable = false;
+    		irqCountDownMode = false;
+    		irqCountUpMode = false;
+    		irqFunkyMode = false;
+    		irqPrescalerSize = false;
+    		irqSource = 0;
+    		irqPrescaler = 0;
+    		irqPrescalerXOR = 0;
+    		irqFunkyModeReg = 0;
+    		RAM5803 = 0;
+    		flag_s = false;
+    		multiplication_a = 0;
+    		multiplication_b = 0;
+    		multiplication = 0;
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		base.SoftReset();
+    		if (Dipswitch == 0)
+    		{
+    			Dipswitch = byte.MaxValue;
+    		}
+    		else
+    		{
+    			Dipswitch = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF007)
+    		{
+    		case 32768:
+    		case 32769:
+    		case 32770:
+    		case 32771:
+    		case 32772:
+    		case 32773:
+    		case 32774:
+    		case 32775:
+    			prg_reg[address & 3] = data & 0x7F;
+    			SetupPRG();
+    			break;
+    		case 36864:
+    		case 36865:
+    		case 36866:
+    		case 36867:
+    		case 36868:
+    		case 36869:
+    		case 36870:
+    		case 36871:
+    			chr_reg[address & 7] = (chr_reg[address & 7] & 0xFF00) | data;
+    			SetupCHR();
+    			break;
+    		case 40960:
+    		case 40961:
+    		case 40962:
+    		case 40963:
+    		case 40964:
+    		case 40965:
+    		case 40966:
+    		case 40967:
+    			chr_reg[address & 7] = (chr_reg[address & 7] & 0xFF) | (data << 8);
+    			SetupCHR();
+    			break;
+    		case 45056:
+    		case 45057:
+    		case 45058:
+    		case 45059:
+    			nt_reg[address & 3] = (nt_reg[address & 3] & 0xFF00) | data;
+    			break;
+    		case 45060:
+    		case 45061:
+    		case 45062:
+    		case 45063:
+    			nt_reg[address & 3] = (nt_reg[address & 3] & 0xFF) | (data << 8);
+    			break;
+    		case 49152:
+    			IrqEnable = (data & 1) == 1;
+    			if (!IrqEnable)
+    			{
+    				NesEmu.IRQFlags &= -9;
+    			}
+    			break;
+    		case 49153:
+    			irqCountDownMode = (data & 0x80) == 128;
+    			irqCountUpMode = (data & 0x40) == 64;
+    			irqFunkyMode = (data & 8) == 8;
+    			irqPrescalerSize = (data & 4) == 4;
+    			irqSource = data & 3;
+    			break;
+    		case 49154:
+    			IrqEnable = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 49155:
+    			IrqEnable = true;
+    			break;
+    		case 49156:
+    			irqPrescaler = data ^ irqPrescalerXOR;
+    			break;
+    		case 49157:
+    			irqCounter = data ^ irqPrescalerXOR;
+    			break;
+    		case 49158:
+    			irqPrescalerXOR = data;
+    			break;
+    		case 49159:
+    			irqFunkyModeReg = data;
+    			break;
+    		case 53248:
+    			flag_s = (data & 0x80) == 128;
+    			prg_mode = data & 7;
+    			chr_mode = (data >> 3) & 3;
+    			nt_advanced_enable = (data & 0x20) == 32;
+    			nt_rom_only = (data & 0x40) == 64;
+    			SetupPRG();
+    			SetupCHR();
+    			break;
+    		case 53249:
+    			switch (data & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			}
+    			break;
+    		case 53250:
+    			nt_ram_select = data & 0x80;
+    			break;
+    		case 53251:
+    			chr_m = (data & 0x80) == 128;
+    			chr_block_mode = (data & 0x20) == 32;
+    			chr_block = (data & 0x1F) << 8;
+    			SetupCHR();
+    			break;
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    	}
+
+    	internal override void ReadSRM(ref ushort address, out byte data)
+    	{
+    		if (flag_s)
+    		{
+    			base.ReadSRM(ref address, out data);
+    		}
+    		else
+    		{
+    			data = 0;
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte data)
+    	{
+    		switch (address)
+    		{
+    		case 20480:
+    			data = Dipswitch;
+    			break;
+    		case 22528:
+    			data = (byte)(multiplication & 0xFFu);
+    			break;
+    		case 22529:
+    			data = (byte)((multiplication & 0xFF00) >> 8);
+    			break;
+    		case 22531:
+    			data = RAM5803;
+    			break;
+    		default:
+    			data = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 22528:
+    			multiplication_a = data;
+    			multiplication = (ushort)(multiplication_a * multiplication_b);
+    			break;
+    		case 22529:
+    			multiplication_b = data;
+    			multiplication = (ushort)(multiplication_a * multiplication_b);
+    			break;
+    		case 22531:
+    			RAM5803 = data;
+    			break;
+    		case 22530:
+    			break;
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte data)
+    	{
+    		if (MAPPER90MODE)
+    		{
+    			data = NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF];
+    		}
+    		if (!nt_advanced_enable)
+    		{
+    			data = NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF];
+    		}
+    		else if (nt_rom_only)
+    		{
+    			data = CHR_ROM[nt_reg[(address >> 10) & 3]][address & 0x3FF];
+    		}
+    		else if ((nt_reg[(address >> 10) & 3] & 0x80) != nt_ram_select)
+    		{
+    			data = CHR_ROM[nt_reg[(address >> 10) & 3]][address & 0x3FF];
+    		}
+    		else
+    		{
+    			data = NMT_RAM[nt_reg[(address >> 10) & 3] & 1][address & 0x3FF];
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		if (MAPPER90MODE)
+    		{
+    			NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF] = data;
+    		}
+    		else if (!nt_advanced_enable)
+    		{
+    			NMT_RAM[NMT_AREA_BLK_INDEX[(address >> 10) & 3]][address & 0x3FF] = data;
+    		}
+    		else if (!nt_rom_only && (nt_reg[(address >> 10) & 3] & 0x80) == nt_ram_select)
+    		{
+    			NMT_RAM[nt_reg[(address >> 10) & 3] & 1][address & 0x3FF] = data;
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		switch (prg_mode)
+    		{
+    		case 0:
+    			Switch08KPRG(prg_reg[3] * 4 + 3, PRGArea.Area6000);
+    			Switch32KPRG(PRG_ROM_32KB_Mask, PRGArea.Area8000);
+    			break;
+    		case 1:
+    			Switch08KPRG(prg_reg[3] * 2 + 1, PRGArea.Area6000);
+    			Switch16KPRG(prg_reg[1], PRGArea.Area8000);
+    			Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    			break;
+    		case 2:
+    			Switch08KPRG(prg_reg[3], PRGArea.Area6000);
+    			Switch08KPRG(prg_reg[0], PRGArea.Area8000);
+    			Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    			Switch08KPRG(prg_reg[2], PRGArea.AreaC000);
+    			Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    			break;
+    		case 3:
+    			Switch08KPRG(ReverseByte(prg_reg[3]), PRGArea.Area6000);
+    			Switch08KPRG(ReverseByte(prg_reg[0]), PRGArea.Area8000);
+    			Switch08KPRG(ReverseByte(prg_reg[1]), PRGArea.AreaA000);
+    			Switch08KPRG(ReverseByte(prg_reg[2]), PRGArea.AreaC000);
+    			Switch08KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaE000);
+    			break;
+    		case 4:
+    			Switch08KPRG(prg_reg[3] * 4 + 3, PRGArea.Area6000);
+    			Switch32KPRG(prg_reg[3], PRGArea.Area8000);
+    			break;
+    		case 5:
+    			Switch08KPRG(prg_reg[3] * 2 + 1, PRGArea.Area6000);
+    			Switch16KPRG(prg_reg[1], PRGArea.Area8000);
+    			Switch16KPRG(prg_reg[3], PRGArea.AreaC000);
+    			break;
+    		case 6:
+    			Switch08KPRG(prg_reg[3], PRGArea.Area6000);
+    			Switch08KPRG(prg_reg[0], PRGArea.Area8000);
+    			Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    			Switch08KPRG(prg_reg[2], PRGArea.AreaC000);
+    			Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    			break;
+    		case 7:
+    			Switch08KPRG(ReverseByte(prg_reg[3]), PRGArea.Area6000);
+    			Switch08KPRG(ReverseByte(prg_reg[0]), PRGArea.Area8000);
+    			Switch08KPRG(ReverseByte(prg_reg[1]), PRGArea.AreaA000);
+    			Switch08KPRG(ReverseByte(prg_reg[2]), PRGArea.AreaC000);
+    			Switch08KPRG(ReverseByte(prg_reg[3]), PRGArea.AreaE000);
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		switch (chr_mode)
+    		{
+    		case 0:
+    			if (chr_block_mode)
+    			{
+    				Switch08KCHR(chr_reg[0]);
+    			}
+    			else
+    			{
+    				Switch08KCHR((chr_reg[0] & 0xFF) | chr_block);
+    			}
+    			break;
+    		case 1:
+    			if (chr_block_mode)
+    			{
+    				Switch04KCHR(chr_reg[0], CHRArea.Area0000);
+    				Switch04KCHR(chr_reg[4], CHRArea.Area1000);
+    			}
+    			else
+    			{
+    				Switch04KCHR((chr_reg[0] & 0xFF) | chr_block, CHRArea.Area0000);
+    				Switch04KCHR((chr_reg[4] & 0xFF) | chr_block, CHRArea.Area1000);
+    			}
+    			break;
+    		case 2:
+    			if (chr_block_mode)
+    			{
+    				Switch02KCHR(chr_reg[0], CHRArea.Area0000);
+    				Switch02KCHR(chr_m ? chr_reg[0] : chr_reg[2], CHRArea.Area0800);
+    				Switch02KCHR(chr_reg[4], CHRArea.Area1000);
+    				Switch02KCHR(chr_reg[6], CHRArea.Area1800);
+    			}
+    			else
+    			{
+    				Switch02KCHR((chr_reg[0] & 0xFF) | chr_block, CHRArea.Area0000);
+    				Switch02KCHR(((chr_m ? chr_reg[0] : chr_reg[2]) & 0xFF) | chr_block, CHRArea.Area0800);
+    				Switch02KCHR((chr_reg[4] & 0xFF) | chr_block, CHRArea.Area1000);
+    				Switch02KCHR((chr_reg[6] & 0xFF) | chr_block, CHRArea.Area1800);
+    			}
+    			break;
+    		case 3:
+    			if (chr_block_mode)
+    			{
+    				Switch01KCHR(chr_reg[0], CHRArea.Area0000);
+    				Switch01KCHR(chr_reg[1], CHRArea.Area0400);
+    				Switch01KCHR(chr_m ? chr_reg[0] : chr_reg[2], CHRArea.Area0800);
+    				Switch01KCHR(chr_m ? chr_reg[1] : chr_reg[3], CHRArea.Area0C00);
+    				Switch01KCHR(chr_reg[4], CHRArea.Area1000);
+    				Switch01KCHR(chr_reg[5], CHRArea.Area1400);
+    				Switch01KCHR(chr_reg[6], CHRArea.Area1800);
+    				Switch01KCHR(chr_reg[7], CHRArea.Area1C00);
+    			}
+    			else
+    			{
+    				Switch01KCHR((chr_reg[0] & 0xFF) | chr_block, CHRArea.Area0000);
+    				Switch01KCHR((chr_reg[1] & 0xFF) | chr_block, CHRArea.Area0400);
+    				Switch01KCHR(((chr_m ? chr_reg[0] : chr_reg[2]) & 0xFF) | chr_block, CHRArea.Area0800);
+    				Switch01KCHR(((chr_m ? chr_reg[1] : chr_reg[3]) & 0xFF) | chr_block, CHRArea.Area0C00);
+    				Switch01KCHR((chr_reg[4] & 0xFF) | chr_block, CHRArea.Area1000);
+    				Switch01KCHR((chr_reg[5] & 0xFF) | chr_block, CHRArea.Area1400);
+    				Switch01KCHR((chr_reg[6] & 0xFF) | chr_block, CHRArea.Area1800);
+    				Switch01KCHR((chr_reg[7] & 0xFF) | chr_block, CHRArea.Area1C00);
+    			}
+    			break;
+    		}
+    	}
+
+    	private byte ReverseByte(int value)
+    	{
+    		return (byte)((uint)(((value & 0x40) >> 6) | ((value & 0x20) >> 4) | ((value & 0x10) >> 2)) | ((uint)value & 8u) | (uint)((value & 4) << 2) | (uint)((value & 2) << 4) | (uint)((value & 1) << 6));
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irqSource != 0)
+    		{
+    			return;
+    		}
+    		if (irqPrescalerSize)
+    		{
+    			irqPrescaler = (irqPrescaler & 0xF8) | (((irqPrescaler & 7) + 1) & 7);
+    			if ((irqPrescaler & 7) == 7)
+    			{
+    				ClockIRQCounter();
+    			}
+    		}
+    		else
+    		{
+    			irqPrescaler++;
+    			if (irqPrescaler == 255)
+    			{
+    				ClockIRQCounter();
+    			}
+    		}
+    	}
+
+    	internal override void OnPPUAddressUpdate(ref ushort address)
+    	{
+    		if (irqSource != 1)
+    		{
+    			return;
+    		}
+    		old_vram_address = new_vram_address;
+    		new_vram_address = address & 0x1000;
+    		if (old_vram_address >= new_vram_address)
+    		{
+    			return;
+    		}
+    		if (irqPrescalerSize)
+    		{
+    			irqPrescaler = (irqPrescaler & 0xF8) | (((irqPrescaler & 7) + 1) & 7);
+    			if ((irqPrescaler & 7) == 7)
+    			{
+    				ClockIRQCounter();
+    			}
+    		}
+    		else
+    		{
+    			irqPrescaler++;
+    			if (irqPrescaler == 255)
+    			{
+    				ClockIRQCounter();
+    			}
+    		}
+    	}
+
+    	private void ClockIRQCounter()
+    	{
+    		if (irqCountDownMode && irqCountUpMode)
+    		{
+    			return;
+    		}
+    		if (irqCountDownMode)
+    		{
+    			irqCounter--;
+    			if (irqCounter == 0)
+    			{
+    				irqCounter = 255;
+    				if (IrqEnable)
+    				{
+    					NesEmu.IRQFlags |= 8;
+    				}
+    			}
+    		}
+    		else
+    		{
+    			if (!irqCountUpMode)
+    			{
+    				return;
+    			}
+    			irqCounter++;
+    			if (irqCounter == 255)
+    			{
+    				irqCounter = 0;
+    				if (IrqEnable)
+    				{
+    					NesEmu.IRQFlags |= 8;
+    				}
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		for (int i = 0; i < prg_reg.Length; i++)
+    		{
+    			stream.Write(prg_reg[i]);
+    		}
+    		for (int j = 0; j < chr_reg.Length; j++)
+    		{
+    			stream.Write(chr_reg[j]);
+    		}
+    		for (int k = 0; k < nt_reg.Length; k++)
+    		{
+    			stream.Write(nt_reg[k]);
+    		}
+    		stream.Write(prg_mode);
+    		stream.Write(chr_mode);
+    		stream.Write(chr_block_mode);
+    		stream.Write(chr_block);
+    		stream.Write(chr_m);
+    		stream.Write(flag_s);
+    		stream.Write(irqCounter);
+    		stream.Write(IrqEnable);
+    		stream.Write(irqCountDownMode);
+    		stream.Write(irqCountUpMode);
+    		stream.Write(irqFunkyMode);
+    		stream.Write(irqPrescalerSize);
+    		stream.Write(irqSource);
+    		stream.Write(irqPrescaler);
+    		stream.Write(irqPrescalerXOR);
+    		stream.Write(irqFunkyModeReg);
+    		stream.Write(Dipswitch);
+    		stream.Write(multiplication_a);
+    		stream.Write(multiplication_b);
+    		stream.Write(multiplication);
+    		stream.Write(RAM5803);
+    		stream.Write(nt_advanced_enable);
+    		stream.Write(nt_rom_only);
+    		stream.Write(nt_ram_select);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		for (int i = 0; i < prg_reg.Length; i++)
+    		{
+    			prg_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < chr_reg.Length; j++)
+    		{
+    			chr_reg[j] = stream.ReadInt32();
+    		}
+    		for (int k = 0; k < nt_reg.Length; k++)
+    		{
+    			nt_reg[k] = stream.ReadInt32();
+    		}
+    		prg_mode = stream.ReadInt32();
+    		chr_mode = stream.ReadInt32();
+    		chr_block_mode = stream.ReadBoolean();
+    		chr_block = stream.ReadInt32();
+    		chr_m = stream.ReadBoolean();
+    		flag_s = stream.ReadBoolean();
+    		irqCounter = stream.ReadInt32();
+    		IrqEnable = stream.ReadBoolean();
+    		irqCountDownMode = stream.ReadBoolean();
+    		irqCountUpMode = stream.ReadBoolean();
+    		irqFunkyMode = stream.ReadBoolean();
+    		irqPrescalerSize = stream.ReadBoolean();
+    		irqSource = stream.ReadInt32();
+    		irqPrescaler = stream.ReadInt32();
+    		irqPrescalerXOR = stream.ReadInt32();
+    		irqFunkyModeReg = stream.ReadByte();
+    		Dipswitch = stream.ReadByte();
+    		multiplication_a = stream.ReadByte();
+    		multiplication_b = stream.ReadByte();
+    		multiplication = stream.ReadUInt16();
+    		RAM5803 = stream.ReadByte();
+    		nt_advanced_enable = stream.ReadBoolean();
+    		nt_rom_only = stream.ReadBoolean();
+    		nt_ram_select = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper091.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper091.cs
new file mode 100644
index 00000000..b9390451
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper091.cs
@@ -0,0 +1,96 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("HK-SF3", 91, true, true)]
+    internal class Mapper091 : Board
+    {
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x7003)
+    		{
+    		case 24576:
+    			Switch02KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 24577:
+    			Switch02KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 24578:
+    			Switch02KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 24579:
+    			Switch02KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 28672:
+    			Switch08KPRG(data & 0xF, PRGArea.Area8000);
+    			break;
+    		case 28673:
+    			Switch08KPRG(data & 0xF, PRGArea.AreaA000);
+    			break;
+    		case 28674:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 28675:
+    			irq_enabled = true;
+    			irq_reload = 7;
+    			irq_counter = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper092.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper092.cs
new file mode 100644
index 00000000..86b29ebe
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper092.cs
@@ -0,0 +1,50 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Jaleco Early Mapper 1", 92)]
+    internal class Mapper092 : Board
+    {
+    	private int chr_reg;
+
+    	private int prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(0, PRGArea.Area8000);
+    		chr_reg = (prg_reg = 0);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch ((data >> 6) & 3)
+    		{
+    		case 0:
+    			Switch08KCHR(chr_reg);
+    			Switch16KPRG(prg_reg, PRGArea.AreaC000);
+    			break;
+    		case 1:
+    			chr_reg = data & 0xF;
+    			break;
+    		case 2:
+    			prg_reg = data & 0xF;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(chr_reg);
+    		stream.Write(prg_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		chr_reg = stream.ReadInt32();
+    		prg_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper093.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper093.cs
new file mode 100644
index 00000000..8cbf049c
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper093.cs
@@ -0,0 +1,18 @@
+namespace MyNes.Core
+{
+    [BoardInfo("74161/32", 93)]
+    internal class Mapper093 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG((data >> 4) & 0xF, PRGArea.Area8000);
+    		Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper094.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper094.cs
new file mode 100644
index 00000000..3f425258
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper094.cs
@@ -0,0 +1,17 @@
+namespace MyNes.Core
+{
+    [BoardInfo("74161/32", 94)]
+    internal class Mapper094 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG((data >> 2) & 7, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper095.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper095.cs
new file mode 100644
index 00000000..ee5f1899
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper095.cs
@@ -0,0 +1,265 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Namcot MMC3-Style", 95, true, true)]
+    internal class Mapper095 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte value)
+    	{
+    		if (flag_c)
+    		{
+    			value = NMT_RAM[(chr_reg[((address >> 10) & 3) + 2] & 0x20) >> 5][address & 0x3FF];
+    			return;
+    		}
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    		case 1:
+    			value = NMT_RAM[(chr_reg[0] & 0x20) >> 5][address & 0x3FF];
+    			break;
+    		case 2:
+    		case 3:
+    			value = NMT_RAM[(chr_reg[1] & 0x20) >> 5][address & 0x3FF];
+    			break;
+    		default:
+    			value = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		if (flag_c)
+    		{
+    			NMT_RAM[(chr_reg[((address >> 10) & 3) + 2] & 0x20) >> 5][address & 0x3FF] = data;
+    			return;
+    		}
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    		case 1:
+    			NMT_RAM[(chr_reg[0] & 0x20) >> 5][address & 0x3FF] = data;
+    			break;
+    		case 2:
+    		case 3:
+    			NMT_RAM[(chr_reg[1] & 0x20) >> 5][address & 0x3FF] = data;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper096.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper096.cs
new file mode 100644
index 00000000..50709f6f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper096.cs
@@ -0,0 +1,46 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("74161/32", 96, 1, 32)]
+    internal class Mapper096 : Board
+    {
+    	private int flag_c;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper96;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = 0;
+    		Switch04KCHR(3, CHRArea.Area1000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG(data & 3, PRGArea.Area8000);
+    		flag_c = (((data & 4) == 4) ? 1 : 0);
+    		Switch04KCHR(3, CHRArea.Area1000);
+    	}
+
+    	internal override void OnPPUAddressUpdate(ref ushort address)
+    	{
+    		if ((address & 0x3FF) < 960 && (address & 0x1000) == 0)
+    		{
+    			Switch04KCHR(((address & 0x300) >> 8) | flag_c, CHRArea.Area0000);
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper097.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper097.cs
new file mode 100644
index 00000000..8dfa81ff
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper097.cs
@@ -0,0 +1,32 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Irem - PRG HI", 97)]
+    internal class Mapper097 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.Area8000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG(data & 0xF, PRGArea.AreaC000);
+    		switch ((address >> 6) & 3)
+    		{
+    		case 0:
+    			Switch01KNMTFromMirroring(Mirroring.OneScA);
+    			break;
+    		case 1:
+    			Switch01KNMTFromMirroring(Mirroring.Horz);
+    			break;
+    		case 2:
+    			Switch01KNMTFromMirroring(Mirroring.Vert);
+    			break;
+    		case 3:
+    			Switch01KNMTFromMirroring(Mirroring.OneScB);
+    			break;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper105.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper105.cs
new file mode 100644
index 00000000..7adc71ae
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper105.cs
@@ -0,0 +1,200 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("NES-EVENT", 105)]
+    [HassIssues]
+    internal class Mapper105 : Board
+    {
+    	private int DipSwitchNumber;
+
+    	private byte[] reg = new byte[4];
+
+    	private byte shift;
+
+    	private byte buffer;
+
+    	private bool flag_p;
+
+    	private bool flag_s;
+
+    	private bool flag_o;
+
+    	private int reg_a;
+
+    	private int reg_b;
+
+    	private bool irq_control;
+
+    	private bool initialized;
+
+    	private int irq_counter;
+
+    	private int dipswitches;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper105;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		TogglePRGRAMEnable(enable: true);
+    		reg = new byte[4];
+    		reg[0] = 12;
+    		flag_s = (flag_p = true);
+    		reg[1] = (reg[2] = (reg[3] = 0));
+    		buffer = 0;
+    		shift = 0;
+    		initialized = false;
+    		DipSwitchNumber = 0;
+    		dipswitches = 0x20000000 | (DipSwitchNumber << 22);
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		DipSwitchNumber = (DipSwitchNumber + 1) & 0xF;
+    		dipswitches = 0x20000000 | (DipSwitchNumber << 22);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte value)
+    	{
+    		if ((value & 0x80) == 128)
+    		{
+    			reg[0] |= 12;
+    			flag_s = (flag_p = true);
+    			shift = (buffer = 0);
+    			return;
+    		}
+    		if ((value & 1) == 1)
+    		{
+    			buffer |= (byte)(1 << (int)shift);
+    		}
+    		if (++shift < 5)
+    		{
+    			return;
+    		}
+    		address = (ushort)((address & 0x7FFF) >> 13);
+    		reg[address] = buffer;
+    		shift = (buffer = 0);
+    		switch (address)
+    		{
+    		case 0:
+    			flag_p = (reg[0] & 8) != 0;
+    			flag_s = (reg[0] & 4) != 0;
+    			UpdatePRG();
+    			switch (reg[0] & 3)
+    			{
+    			case 0:
+    				Switch01KNMTFromMirroring(Mirroring.OneScA);
+    				break;
+    			case 1:
+    				Switch01KNMTFromMirroring(Mirroring.OneScB);
+    				break;
+    			case 2:
+    				Switch01KNMTFromMirroring(Mirroring.Vert);
+    				break;
+    			case 3:
+    				Switch01KNMTFromMirroring(Mirroring.Horz);
+    				break;
+    			}
+    			break;
+    		case 1:
+    			irq_control = (reg[1] & 0x10) == 16;
+    			if (irq_control)
+    			{
+    				initialized = true;
+    				irq_counter = 0;
+    				NesEmu.IRQFlags &= -9;
+    			}
+    			else
+    			{
+    				Switch32KPRG(0, PRGArea.Area8000);
+    			}
+    			flag_o = (reg[1] & 8) == 8;
+    			reg_a = (reg[1] >> 1) & 3;
+    			UpdatePRG();
+    			break;
+    		case 3:
+    			TogglePRGRAMEnable((reg[3] & 0x10) == 0);
+    			reg_b = reg[3] & 0xF;
+    			UpdatePRG();
+    			break;
+    		case 2:
+    			break;
+    		}
+    	}
+
+    	private void UpdatePRG()
+    	{
+    		if (initialized)
+    		{
+    			if (!flag_o)
+    			{
+    				Switch32KPRG(reg_a, PRGArea.Area8000);
+    			}
+    			else if (!flag_p)
+    			{
+    				Switch32KPRG((reg_b >> 1) + 4, PRGArea.Area8000);
+    			}
+    			else if (!flag_s)
+    			{
+    				Switch16KPRG(8, PRGArea.Area8000);
+    				Switch16KPRG(reg_b + 8, PRGArea.AreaC000);
+    			}
+    			else
+    			{
+    				Switch16KPRG(reg_b + 8, PRGArea.Area8000);
+    				Switch16KPRG(15, PRGArea.AreaC000);
+    			}
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (!irq_control)
+    		{
+    			irq_counter++;
+    			if (irq_counter == dipswitches)
+    			{
+    				irq_counter = 0;
+    				NesEmu.IRQFlags |= 8;
+    			}
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(DipSwitchNumber);
+    		stream.Write(reg);
+    		stream.Write(shift);
+    		stream.Write(buffer);
+    		stream.Write(flag_p);
+    		stream.Write(flag_s);
+    		stream.Write(flag_o);
+    		stream.Write(reg_a);
+    		stream.Write(reg_b);
+    		stream.Write(irq_control);
+    		stream.Write(initialized);
+    		stream.Write(irq_counter);
+    		stream.Write(dipswitches);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		DipSwitchNumber = stream.ReadInt32();
+    		stream.Read(reg, 0, reg.Length);
+    		shift = stream.ReadByte();
+    		buffer = stream.ReadByte();
+    		flag_p = stream.ReadBoolean();
+    		flag_s = stream.ReadBoolean();
+    		flag_o = stream.ReadBoolean();
+    		reg_a = stream.ReadInt32();
+    		reg_b = stream.ReadInt32();
+    		irq_control = stream.ReadBoolean();
+    		initialized = stream.ReadBoolean();
+    		irq_counter = stream.ReadInt32();
+    		dipswitches = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper107.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper107.cs
new file mode 100644
index 00000000..162d9788
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper107.cs
@@ -0,0 +1,11 @@
+namespace MyNes.Core
+{
+    internal class Mapper107 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG(data >> 1, PRGArea.Area8000);
+    		Switch08KCHR(data);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper112.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper112.cs
new file mode 100644
index 00000000..44047fab
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper112.cs
@@ -0,0 +1,70 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Asder", 112)]
+    internal class Mapper112 : Board
+    {
+    	private int address_A000;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_A000 = data & 7;
+    			break;
+    		case 40960:
+    			switch (address_A000)
+    			{
+    			case 0:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 1:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			case 2:
+    				Switch02KCHR(data >> 1, CHRArea.Area0000);
+    				break;
+    			case 3:
+    				Switch02KCHR(data >> 1, CHRArea.Area0800);
+    				break;
+    			case 4:
+    				Switch01KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 5:
+    				Switch01KCHR(data, CHRArea.Area1400);
+    				break;
+    			case 6:
+    				Switch01KCHR(data, CHRArea.Area1800);
+    				break;
+    			case 7:
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    				break;
+    			}
+    			break;
+    		case 57344:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(address_A000);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		address_A000 = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper113.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper113.cs
new file mode 100644
index 00000000..edce7761
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper113.cs
@@ -0,0 +1,16 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Sachen/Hacker/Nina", 113)]
+    internal class Mapper113 : Board
+    {
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if ((address & 0x4100) == 16640)
+    		{
+    			Switch08KCHR((data & 7) | ((data & 0x40) >> 3));
+    			Switch32KPRG((data >> 3) & 7, PRGArea.Area8000);
+    			Switch01KNMTFromMirroring(((data & 0x80) == 128) ? Mirroring.Vert : Mirroring.Horz);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper115.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper115.cs
new file mode 100644
index 00000000..cec9d8bf
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper115.cs
@@ -0,0 +1,259 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC3 Cart Saint", 115, true, true)]
+    internal class Mapper115 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private bool flag_o;
+
+    	private int chr_block;
+
+    	private int prg_secreg;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_o = (flag_c = (flag_p = false));
+    		address_8001 = 0;
+    		chr_block = 0;
+    		prg_secreg = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x6001)
+    		{
+    		case 24576:
+    			flag_o = (data & 0x80) == 128;
+    			prg_secreg = data & 0xF;
+    			SetupPRG();
+    			break;
+    		case 24577:
+    			chr_block = (data & 1) << 8;
+    			SetupCHR();
+    			break;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR((chr_reg[0] >> 1) | chr_block, CHRArea.Area0000);
+    			Switch02KCHR((chr_reg[1] >> 1) | chr_block, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2] | chr_block, CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3] | chr_block, CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4] | chr_block, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5] | chr_block, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR((chr_reg[0] >> 1) | chr_block, CHRArea.Area1000);
+    			Switch02KCHR((chr_reg[1] >> 1) | chr_block, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2] | chr_block, CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3] | chr_block, CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4] | chr_block, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5] | chr_block, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		if (!flag_o)
+    		{
+    			Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    			Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		}
+    		else
+    		{
+    			Switch16KPRG(prg_secreg, PRGArea.Area8000);
+    		}
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(flag_o);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(chr_block);
+    		stream.Write(prg_secreg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		flag_o = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		chr_block = stream.ReadInt32();
+    		prg_secreg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper118.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper118.cs
new file mode 100644
index 00000000..79e9e528
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper118.cs
@@ -0,0 +1,263 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC3 TLSROM", 118, true, true)]
+    internal class Mapper118 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte value)
+    	{
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    			value = NMT_RAM[(chr_reg[flag_c ? 2 : 0] >> 7) & 1][address & 0x3FF];
+    			break;
+    		case 1:
+    			value = NMT_RAM[(chr_reg[flag_c ? 3 : 0] >> 7) & 1][address & 0x3FF];
+    			break;
+    		case 2:
+    			value = NMT_RAM[(chr_reg[(!flag_c) ? 1 : 4] >> 7) & 1][address & 0x3FF];
+    			break;
+    		case 3:
+    			value = NMT_RAM[(chr_reg[(!flag_c) ? 1 : 5] >> 7) & 1][address & 0x3FF];
+    			break;
+    		default:
+    			value = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    			NMT_RAM[(chr_reg[flag_c ? 2 : 0] >> 7) & 1][address & 0x3FF] = data;
+    			break;
+    		case 1:
+    			NMT_RAM[(chr_reg[flag_c ? 3 : 0] >> 7) & 1][address & 0x3FF] = data;
+    			break;
+    		case 2:
+    			NMT_RAM[(chr_reg[(!flag_c) ? 1 : 4] >> 7) & 1][address & 0x3FF] = data;
+    			break;
+    		case 3:
+    			NMT_RAM[(chr_reg[(!flag_c) ? 1 : 5] >> 7) & 1][address & 0x3FF] = data;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper119.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper119.cs
new file mode 100644
index 00000000..42d91593
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper119.cs
@@ -0,0 +1,236 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("TQROM", 119, 1, 8, true, true)]
+    internal class Mapper119 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper119;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Toggle02KCHR_RAM((chr_reg[0] & 0x40) != 0, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Toggle02KCHR_RAM((chr_reg[1] & 0x40) != 0, CHRArea.Area0800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Toggle02KCHR_RAM((chr_reg[2] & 0x40) != 0, CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Toggle02KCHR_RAM((chr_reg[3] & 0x40) != 0, CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Toggle02KCHR_RAM((chr_reg[4] & 0x40) != 0, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Toggle02KCHR_RAM((chr_reg[5] & 0x40) != 0, CHRArea.Area1C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Toggle02KCHR_RAM((chr_reg[0] & 0x40) != 0, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Toggle02KCHR_RAM((chr_reg[1] & 0x40) != 0, CHRArea.Area1800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Toggle02KCHR_RAM((chr_reg[2] & 0x40) != 0, CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Toggle02KCHR_RAM((chr_reg[3] & 0x40) != 0, CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Toggle02KCHR_RAM((chr_reg[4] & 0x40) != 0, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Toggle02KCHR_RAM((chr_reg[5] & 0x40) != 0, CHRArea.Area0C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper133.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper133.cs
new file mode 100644
index 00000000..7416d1c5
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper133.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Sachen", 133)]
+    internal class Mapper133 : Board
+    {
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(data & 3);
+    		Switch32KPRG(data >> 2, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper140.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper140.cs
new file mode 100644
index 00000000..1be085ef
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper140.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 140)]
+    internal class Mapper140 : Board
+    {
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(data & 0xF);
+    		Switch32KPRG((data >> 4) & 3, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper152.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper152.cs
new file mode 100644
index 00000000..562043a8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper152.cs
@@ -0,0 +1,19 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 152)]
+    internal class Mapper152 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(data & 0xF);
+    		Switch16KPRG((data >> 4) & 7, PRGArea.Area8000);
+    		Switch01KNMTFromMirroring(((data & 0x80) == 128) ? Mirroring.OneScB : Mirroring.OneScA);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper154.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper154.cs
new file mode 100644
index 00000000..29b02ac6
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper154.cs
@@ -0,0 +1,72 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("NAMCOT-3453", 154)]
+    [HassIssues]
+    internal class Mapper154 : Board
+    {
+    	private int address_8001;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper154;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		address_8001 = 0;
+    		Switch16KPRG(PRG_ROM_16KB_Mask, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x8001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.OneScB : Mirroring.OneScA);
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    				Switch02KCHR((data & 0x3F) >> 1, CHRArea.Area0000);
+    				break;
+    			case 1:
+    				Switch02KCHR((data & 0x3F) >> 1, CHRArea.Area0800);
+    				break;
+    			case 2:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1000);
+    				break;
+    			case 3:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1400);
+    				break;
+    			case 4:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1800);
+    				break;
+    			case 5:
+    				Switch01KCHR(data | 0x40, CHRArea.Area1C00);
+    				break;
+    			case 6:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 7:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(address_8001);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		address_8001 = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper163.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper163.cs
new file mode 100644
index 00000000..180d9fbc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper163.cs
@@ -0,0 +1,109 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 163)]
+    internal class Mapper163 : Board
+    {
+    	internal byte prg_reg;
+
+    	internal byte security_reg;
+
+    	internal bool security_trigger;
+
+    	internal byte security_reg101;
+
+    	internal bool do_chr_ram;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		security_reg101 = 1;
+    		security_trigger = false;
+    		do_chr_ram = true;
+    		Switch32KPRG(15, PRGArea.Area8000);
+    		Toggle08KCHR_RAM(ram: true);
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if (address == 20737)
+    		{
+    			if (security_reg101 != 0 && data == 0)
+    			{
+    				security_trigger = true;
+    			}
+    			security_reg101 = data;
+    		}
+    		else
+    		{
+    			if (address < 20480)
+    			{
+    				return;
+    			}
+    			switch (address & 0x7300)
+    			{
+    			case 20480:
+    				prg_reg = (byte)((prg_reg & 0xF0u) | (data & 0xFu));
+    				Switch32KPRG(prg_reg, PRGArea.Area8000);
+    				do_chr_ram = (data & 0x80) != 0;
+    				if (!do_chr_ram && NesEmu.ppu_clock_v < 128)
+    				{
+    					Switch08KCHR(0);
+    				}
+    				break;
+    			case 20736:
+    				if (data == 6)
+    				{
+    					Switch32KPRG(3, PRGArea.Area8000);
+    				}
+    				break;
+    			case 20992:
+    				prg_reg = (byte)((prg_reg & 0xFu) | (uint)((data & 0xF) << 4));
+    				Switch32KPRG(prg_reg, PRGArea.Area8000);
+    				break;
+    			case 21248:
+    				security_reg = data;
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort addr, out byte val)
+    	{
+    		val = 0;
+    		if (addr < 20480)
+    		{
+    			return;
+    		}
+    		switch (addr & 0x1E14)
+    		{
+    		case 20736:
+    			val = security_reg;
+    			break;
+    		case 21760:
+    			if (security_trigger)
+    			{
+    				val = security_reg;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void OnPPUScanlineTick()
+    	{
+    		base.OnPPUScanlineTick();
+    		if (do_chr_ram && NesEmu.IsRenderingOn())
+    		{
+    			if (NesEmu.ppu_clock_v == 127)
+    			{
+    				Switch04KCHR(1, CHRArea.Area0000);
+    				Switch04KCHR(1, CHRArea.Area1000);
+    			}
+    			if (NesEmu.ppu_clock_v == 237)
+    			{
+    				Switch04KCHR(0, CHRArea.Area0000);
+    				Switch04KCHR(0, CHRArea.Area1000);
+    			}
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper164.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper164.cs
new file mode 100644
index 00000000..0e6188bc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper164.cs
@@ -0,0 +1,28 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 164)]
+    internal class Mapper164 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch32KPRG(255, PRGArea.Area8000);
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if (address >= 20480 && (address & 0xF000) == 20480)
+    		{
+    			Switch32KPRG(data, PRGArea.Area8000);
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if ((address & 0xF000) == 53248)
+    		{
+    			Switch32KPRG(data, PRGArea.Area8000);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper165.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper165.cs
new file mode 100644
index 00000000..606f5973
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper165.cs
@@ -0,0 +1,253 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 165, true, true)]
+    internal class Mapper165 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private byte latch_a = 254;
+
+    	private byte latch_b = 254;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	internal override void ReadCHR(ref ushort address, out byte data)
+    	{
+    		if ((address & 0x1FF0) == 4048 && latch_a != 253)
+    		{
+    			latch_a = 253;
+    			Switch04KCHR(chr_reg[0] >> 2, CHRArea.Area0000);
+    		}
+    		else if ((address & 0x1FF0) == 4064 && latch_a != 254)
+    		{
+    			latch_a = 254;
+    			Switch04KCHR(chr_reg[1] >> 2, CHRArea.Area0000);
+    		}
+    		else if ((address & 0x1FF0) == 8144 && latch_b != 253)
+    		{
+    			latch_b = 253;
+    			Switch04KCHR(chr_reg[2] >> 2, CHRArea.Area1000);
+    		}
+    		else if ((address & 0x1FF0) == 8160 && latch_b != 254)
+    		{
+    			latch_b = 254;
+    			Switch04KCHR(chr_reg[4] >> 2, CHRArea.Area1000);
+    		}
+    		base.ReadCHR(ref address, out data);
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (latch_a == 253)
+    		{
+    			Switch04KCHR(chr_reg[0] >> 2, CHRArea.Area0000);
+    		}
+    		if (latch_a == 254)
+    		{
+    			Switch04KCHR(chr_reg[1] >> 2, CHRArea.Area0000);
+    		}
+    		if (latch_b == 253)
+    		{
+    			Switch04KCHR(chr_reg[2] >> 2, CHRArea.Area1000);
+    		}
+    		if (latch_b == 254)
+    		{
+    			Switch04KCHR(chr_reg[4] >> 2, CHRArea.Area1000);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(latch_a);
+    		stream.Write(latch_b);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		latch_a = stream.ReadByte();
+    		latch_b = stream.ReadByte();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper180.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper180.cs
new file mode 100644
index 00000000..99634858
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper180.cs
@@ -0,0 +1,14 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Nihon Bussan", 180)]
+    [HassIssues]
+    internal class Mapper180 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper180;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG(data & 7, PRGArea.AreaC000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper182.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper182.cs
new file mode 100644
index 00000000..9c2f5823
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper182.cs
@@ -0,0 +1,227 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 182, true, true)]
+    internal class Mapper182 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		mmc3_alt_behavior = false;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		int num = address & 0xE001;
+    		if (num <= 40961)
+    		{
+    			if (num <= 32769)
+    			{
+    				if (num != 32768 && num == 32769 && NMT_DEFAULT_MIRROR != Mirroring.Full)
+    				{
+    					Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    				}
+    			}
+    			else if (num != 40960)
+    			{
+    				_ = 40961;
+    			}
+    			else
+    			{
+    				address_8001 = data & 7;
+    				flag_c = (data & 0x80) != 0;
+    				flag_p = (data & 0x40) != 0;
+    				SetupCHR();
+    				SetupPRG();
+    			}
+    			return;
+    		}
+    		switch (num)
+    		{
+    		case 49152:
+    			switch (address_8001)
+    			{
+    			case 0:
+    				chr_reg[0] = data;
+    				SetupCHR();
+    				break;
+    			case 1:
+    				chr_reg[3] = data;
+    				SetupCHR();
+    				break;
+    			case 2:
+    				chr_reg[1] = data;
+    				SetupCHR();
+    				break;
+    			case 3:
+    				chr_reg[5] = data;
+    				SetupCHR();
+    				break;
+    			case 4:
+    				prg_reg[0] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			case 5:
+    				prg_reg[1] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			case 6:
+    				chr_reg[2] = data;
+    				SetupCHR();
+    				break;
+    			case 7:
+    				chr_reg[4] = data;
+    				SetupCHR();
+    				break;
+    			}
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			irq_reload = data;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper184.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper184.cs
new file mode 100644
index 00000000..27573142
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper184.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Sunsoft", 184)]
+    internal class Mapper184 : Board
+    {
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		Switch04KCHR(data & 7, CHRArea.Area0000);
+    		Switch04KCHR((data >> 4) & 7, CHRArea.Area1000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper185.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper185.cs
new file mode 100644
index 00000000..1eee6868
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper185.cs
@@ -0,0 +1,45 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 185)]
+    internal class Mapper185 : Board
+    {
+    	private bool lockchr;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		lockchr = false;
+    	}
+
+    	internal override void ReadCHR(ref ushort address, out byte data)
+    	{
+    		if (!lockchr)
+    		{
+    			base.ReadCHR(ref address, out data);
+    		}
+    		else
+    		{
+    			data = byte.MaxValue;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		lockchr = (data & 0xF) == 0 || data == 19;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(lockchr);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		lockchr = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper189.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper189.cs
new file mode 100644
index 00000000..eb68aaca
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper189.cs
@@ -0,0 +1,184 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("MMC3 Variant", 189, true, true)]
+    internal class Mapper189 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = 0;
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG(((data & 0xF0) >> 4) | (data & 0xF), PRGArea.Area8000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG(((data & 0xF0) >> 4) | (data & 0xF), PRGArea.Area8000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			break;
+    		case 32769:
+    		{
+    			int num = address_8001;
+    			if ((uint)num <= 5u)
+    			{
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    			}
+    			break;
+    		}
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		stream.Write(prg_reg);
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		prg_reg = stream.ReadInt32();
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper191.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper191.cs
new file mode 100644
index 00000000..270c8103
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper191.cs
@@ -0,0 +1,212 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC3 variant", 191, true, true)]
+    [HassIssues]
+    internal class Mapper191 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper191;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Toggle02KCHR_RAM((chr_reg[0] & 0x80) == 0, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Toggle02KCHR_RAM((chr_reg[1] & 0x80) == 0, CHRArea.Area0800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Toggle02KCHR_RAM((chr_reg[2] & 0x80) == 0, CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Toggle02KCHR_RAM((chr_reg[3] & 0x80) == 0, CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Toggle02KCHR_RAM((chr_reg[4] & 0x80) == 0, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Toggle02KCHR_RAM((chr_reg[5] & 0x80) == 0, CHRArea.Area1C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Toggle02KCHR_RAM((chr_reg[0] & 0x80) == 0, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Toggle02KCHR_RAM((chr_reg[1] & 0x80) == 0, CHRArea.Area1800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Toggle02KCHR_RAM((chr_reg[2] & 0x80) == 0, CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Toggle02KCHR_RAM((chr_reg[3] & 0x80) == 0, CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Toggle02KCHR_RAM((chr_reg[4] & 0x80) == 0, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Toggle02KCHR_RAM((chr_reg[5] & 0x80) == 0, CHRArea.Area0C00);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper192.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper192.cs
new file mode 100644
index 00000000..4f21ab58
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper192.cs
@@ -0,0 +1,225 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC3 variant", 192, true, true)]
+    internal class Mapper192 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool isRam;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			isRam = chr_reg[0] >= 8 && chr_reg[0] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0000);
+    			Switch02KCHR(isRam ? (chr_reg[0] - 8 >> 1) : (chr_reg[0] >> 1), CHRArea.Area0000);
+    			isRam = chr_reg[1] >= 8 && chr_reg[1] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0000);
+    			Switch02KCHR(isRam ? (chr_reg[1] - 8 >> 1) : (chr_reg[1] >> 1), CHRArea.Area0800);
+    			isRam = chr_reg[2] >= 8 && chr_reg[2] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1000);
+    			Switch01KCHR(isRam ? (chr_reg[2] - 8) : chr_reg[2], CHRArea.Area1000);
+    			isRam = chr_reg[3] >= 8 && chr_reg[3] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1400);
+    			Switch01KCHR(isRam ? (chr_reg[3] - 8) : chr_reg[3], CHRArea.Area1400);
+    			isRam = chr_reg[4] >= 8 && chr_reg[4] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1800);
+    			Switch01KCHR(isRam ? (chr_reg[4] - 8) : chr_reg[4], CHRArea.Area1800);
+    			isRam = chr_reg[5] >= 8 && chr_reg[5] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1C00);
+    			Switch01KCHR(isRam ? (chr_reg[5] - 8) : chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			isRam = chr_reg[0] >= 8 && chr_reg[0] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1000);
+    			Switch02KCHR(isRam ? (chr_reg[0] - 8 >> 1) : (chr_reg[0] >> 1), CHRArea.Area1000);
+    			isRam = chr_reg[1] >= 8 && chr_reg[1] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area1800);
+    			Switch02KCHR(isRam ? (chr_reg[1] - 8 >> 1) : (chr_reg[1] >> 1), CHRArea.Area1800);
+    			isRam = chr_reg[2] >= 8 && chr_reg[2] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0000);
+    			Switch01KCHR(isRam ? (chr_reg[2] - 8) : chr_reg[2], CHRArea.Area0000);
+    			isRam = chr_reg[3] >= 8 && chr_reg[3] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0400);
+    			Switch01KCHR(isRam ? (chr_reg[3] - 8) : chr_reg[3], CHRArea.Area0400);
+    			isRam = chr_reg[4] >= 8 && chr_reg[4] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0800);
+    			Switch01KCHR(isRam ? (chr_reg[4] - 8) : chr_reg[4], CHRArea.Area0800);
+    			isRam = chr_reg[5] >= 8 && chr_reg[5] <= 11;
+    			Toggle02KCHR_RAM(isRam, CHRArea.Area0C00);
+    			Switch01KCHR(isRam ? (chr_reg[5] - 8) : chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(isRam);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		isRam = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper193.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper193.cs
new file mode 100644
index 00000000..c5da814a
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper193.cs
@@ -0,0 +1,36 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 193, 1, 32)]
+    [HassIssues]
+    internal class Mapper193 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper193;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask - 2, PRGArea.AreaA000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask - 1, PRGArea.AreaC000);
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x6003)
+    		{
+    		case 24576:
+    			Switch04KCHR(data >> 2, CHRArea.Area0000);
+    			break;
+    		case 24577:
+    			Switch02KCHR(data >> 1, CHRArea.Area1000);
+    			break;
+    		case 24578:
+    			Switch02KCHR(data >> 1, CHRArea.Area1800);
+    			break;
+    		case 24579:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper194.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper194.cs
new file mode 100644
index 00000000..81ef017d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper194.cs
@@ -0,0 +1,209 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC3 variant", 194, true, true)]
+    internal class Mapper194 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Toggle02KCHR_RAM(chr_reg[0] > 1, CHRArea.Area0000);
+    			Switch02KCHR((chr_reg[0] > 1) ? (chr_reg[0] - 1 >> 1) : (chr_reg[0] >> 1), CHRArea.Area0000);
+    			Toggle02KCHR_RAM(chr_reg[1] > 1, CHRArea.Area0800);
+    			Switch02KCHR((chr_reg[1] > 1) ? (chr_reg[1] - 1 >> 1) : (chr_reg[1] >> 1), CHRArea.Area0800);
+    			Toggle02KCHR_RAM(chr_reg[2] > 1, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[2] > 1) ? (chr_reg[2] - 1) : chr_reg[2], CHRArea.Area1000);
+    			Toggle02KCHR_RAM(chr_reg[3] > 1, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[3] > 1) ? (chr_reg[3] - 1) : chr_reg[3], CHRArea.Area1400);
+    			Toggle02KCHR_RAM(chr_reg[4] > 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[4] > 1) ? (chr_reg[4] - 1) : chr_reg[4], CHRArea.Area1800);
+    			Toggle02KCHR_RAM(chr_reg[5] > 1, CHRArea.Area1C00);
+    			Switch01KCHR((chr_reg[5] > 1) ? (chr_reg[5] - 1) : chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Toggle02KCHR_RAM(chr_reg[0] > 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Toggle02KCHR_RAM(chr_reg[1] > 1, CHRArea.Area1800);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Toggle02KCHR_RAM(chr_reg[2] > 1, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[2] > 1) ? (chr_reg[2] - 1) : chr_reg[2], CHRArea.Area0000);
+    			Toggle02KCHR_RAM(chr_reg[3] > 1, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[3] > 1) ? (chr_reg[3] - 1) : chr_reg[3], CHRArea.Area0400);
+    			Toggle02KCHR_RAM(chr_reg[4] > 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[4] > 1) ? (chr_reg[4] - 1) : chr_reg[4], CHRArea.Area0800);
+    			Toggle02KCHR_RAM(chr_reg[5] > 1, CHRArea.Area0C00);
+    			Switch01KCHR((chr_reg[5] > 1) ? (chr_reg[5] - 1) : chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper200.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper200.cs
new file mode 100644
index 00000000..574fd691
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper200.cs
@@ -0,0 +1,14 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 200)]
+    internal class Mapper200 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(address & 7);
+    		Switch16KPRG(address & 7, PRGArea.Area8000);
+    		Switch16KPRG(address & 7, PRGArea.AreaC000);
+    		Switch01KNMTFromMirroring(((address & 8) == 8) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper201.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper201.cs
new file mode 100644
index 00000000..859a6de1
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper201.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 201)]
+    internal class Mapper201 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(address & 0xFF);
+    		Switch32KPRG(address & 0xFF, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper202.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper202.cs
new file mode 100644
index 00000000..813dffd4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper202.cs
@@ -0,0 +1,22 @@
+namespace MyNes.Core
+{
+    [BoardInfo("150-in-1", 202)]
+    [HassIssues]
+    internal class Mapper202 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper202;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch01KNMTFromMirroring(((address & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    		Switch08KCHR((address >> 1) & 7);
+    		if ((address & 0xC) == 12)
+    		{
+    			Switch32KPRG(3, PRGArea.Area8000);
+    			return;
+    		}
+    		Switch16KPRG((address >> 1) & 7, PRGArea.Area8000);
+    		Switch16KPRG((address >> 1) & 7, PRGArea.AreaC000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper203.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper203.cs
new file mode 100644
index 00000000..05b6622f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper203.cs
@@ -0,0 +1,16 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 203)]
+    [HassIssues]
+    internal class Mapper203 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper203;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(data & 3);
+    		Switch16KPRG(data & 0x3F, PRGArea.Area8000);
+    		Switch16KPRG(data & 0x3F, PRGArea.AreaC000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper204.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper204.cs
new file mode 100644
index 00000000..89cb0b7b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper204.cs
@@ -0,0 +1,19 @@
+namespace MyNes.Core
+{
+    [BoardInfo("64-in-1", 204)]
+    internal class Mapper204 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch01KNMTFromMirroring(((address & 0x10) == 16) ? Mirroring.Horz : Mirroring.Vert);
+    		Switch08KCHR(address & 7);
+    		if ((address & 6) == 6)
+    		{
+    			Switch32KPRG(3, PRGArea.Area8000);
+    			return;
+    		}
+    		Switch16KPRG(address & 7, PRGArea.Area8000);
+    		Switch16KPRG(address & 7, PRGArea.AreaC000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper205.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper205.cs
new file mode 100644
index 00000000..d4eaedce
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper205.cs
@@ -0,0 +1,275 @@
+using System;
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 205, true, true)]
+    internal class Mapper205 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private int chr_or;
+
+    	private int chr_and;
+
+    	private int prg_or;
+
+    	private int prg_and;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_and = 31;
+    		prg_or = 0;
+    		chr_and = 255;
+    		chr_or = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    		if (IsGameFoundOnDB)
+    		{
+    			switch (GameCartInfo.chip_type[0].ToLower())
+    			{
+    			case "mmc3a":
+    				mmc3_alt_behavior = true;
+    				Console.WriteLine("Chip= MMC3 A, MMC3 IQR mode switched to RevA");
+    				break;
+    			case "mmc3b":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 B, MMC3 IQR mode switched to RevB");
+    				break;
+    			case "mmc3c":
+    				mmc3_alt_behavior = false;
+    				Console.WriteLine("Chip= MMC3 C, MMC3 IQR mode switched to RevB");
+    				break;
+    			}
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (data & 3)
+    		{
+    		case 0:
+    			prg_and = 31;
+    			prg_or = 0;
+    			chr_and = 255;
+    			chr_or = 0;
+    			break;
+    		case 1:
+    			prg_and = 31;
+    			prg_or = 16;
+    			chr_and = 255;
+    			chr_or = 128;
+    			break;
+    		case 2:
+    			prg_and = 15;
+    			prg_or = 32;
+    			chr_and = 127;
+    			chr_or = 256;
+    			break;
+    		case 3:
+    			prg_and = 15;
+    			prg_or = 48;
+    			chr_and = 127;
+    			chr_or = 384;
+    			break;
+    		}
+    		SetupCHR();
+    		SetupPRG();
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area0000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area1000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area1400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(((chr_reg[0] & chr_and) | chr_or) >> 1, CHRArea.Area1000);
+    			Switch02KCHR(((chr_reg[1] & chr_and) | chr_or) >> 1, CHRArea.Area1800);
+    			Switch01KCHR((chr_reg[2] & chr_and) | chr_or, CHRArea.Area0000);
+    			Switch01KCHR((chr_reg[3] & chr_and) | chr_or, CHRArea.Area0400);
+    			Switch01KCHR((chr_reg[4] & chr_and) | chr_or, CHRArea.Area0800);
+    			Switch01KCHR((chr_reg[5] & chr_and) | chr_or, CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG((prg_reg[flag_p ? 2 : 0] & prg_and) | prg_or, PRGArea.Area8000);
+    		Switch08KPRG((prg_reg[1] & prg_and) | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG((prg_reg[(!flag_p) ? 2 : 0] & prg_and) | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG((prg_reg[3] & prg_and) | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(chr_or);
+    		stream.Write(chr_and);
+    		stream.Write(prg_or);
+    		stream.Write(prg_and);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		chr_or = stream.ReadInt32();
+    		chr_and = stream.ReadInt32();
+    		prg_or = stream.ReadInt32();
+    		prg_and = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper206.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper206.cs
new file mode 100644
index 00000000..04b18bd4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper206.cs
@@ -0,0 +1,131 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 206)]
+    internal class Mapper206 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		SetupPRG();
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    			case 7:
+    				prg_reg[address_8001 - 6] = data & PRG_ROM_08KB_Mask;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (!flag_c)
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    		}
+    		else
+    		{
+    			Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    			Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    			Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    			Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    			Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    			Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0], PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1], PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0], PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3], PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper207.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper207.cs
new file mode 100644
index 00000000..f013b8ff
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper207.cs
@@ -0,0 +1,112 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 207)]
+    [HassIssues]
+    internal class Mapper207 : Board
+    {
+    	private int mirroring0;
+
+    	private int mirroring1;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper207;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		switch (address)
+    		{
+    		case 32496:
+    			Switch02KCHR(data & 0x3F, CHRArea.Area0000);
+    			mirroring0 = (data >> 7) & 1;
+    			break;
+    		case 32497:
+    			Switch02KCHR(data & 0x3F, CHRArea.Area0800);
+    			mirroring1 = (data >> 7) & 1;
+    			break;
+    		case 32498:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 32499:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 32500:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 32501:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		case 32506:
+    		case 32507:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 32508:
+    		case 32509:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 32510:
+    		case 32511:
+    			Switch08KPRG(data, PRGArea.AreaC000);
+    			break;
+    		case 32502:
+    		case 32503:
+    		case 32504:
+    		case 32505:
+    			break;
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte data)
+    	{
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    		case 1:
+    			data = NMT_RAM[mirroring0][address & 0x3FF];
+    			break;
+    		case 2:
+    		case 3:
+    			data = NMT_RAM[mirroring1][address & 0x3FF];
+    			break;
+    		default:
+    			data = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		switch ((address >> 10) & 3)
+    		{
+    		case 0:
+    		case 1:
+    			NMT_RAM[mirroring0][address & 0x3FF] = data;
+    			break;
+    		case 2:
+    		case 3:
+    			NMT_RAM[mirroring1][address & 0x3FF] = data;
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(mirroring0);
+    		stream.Write(mirroring1);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		mirroring0 = stream.ReadInt32();
+    		mirroring1 = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper209.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper209.cs
new file mode 100644
index 00000000..f9bd34fd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper209.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Pirate MMC5-style", 209)]
+    internal class Mapper209 : Mapper090
+    {
+    	internal override void HardReset()
+    	{
+    		MAPPER90MODE = false;
+    		base.HardReset();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper212.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper212.cs
new file mode 100644
index 00000000..b92b87fa
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper212.cs
@@ -0,0 +1,19 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Super HIK 300-in-1 (1994)", 212)]
+    internal class Mapper212 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(address & 7);
+    		Switch01KNMTFromMirroring(((address & 8) == 8) ? Mirroring.Horz : Mirroring.Vert);
+    		if ((address & 0x4000) == 16384)
+    		{
+    			Switch32KPRG((address >> 1) & 3, PRGArea.Area8000);
+    			return;
+    		}
+    		Switch16KPRG(address & 7, PRGArea.Area8000);
+    		Switch16KPRG(address & 7, PRGArea.AreaC000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper213.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper213.cs
new file mode 100644
index 00000000..221aacce
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper213.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("9999999-in-1", 213)]
+    internal class Mapper213 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR((address >> 3) & 7);
+    		Switch32KPRG((address >> 1) & 3, PRGArea.Area8000);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper214.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper214.cs
new file mode 100644
index 00000000..8c942820
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper214.cs
@@ -0,0 +1,13 @@
+namespace MyNes.Core
+{
+    [BoardInfo("X-in-1", 214)]
+    internal class Mapper214 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG(address >> 2, PRGArea.Area8000);
+    		Switch16KPRG(address >> 2, PRGArea.AreaC000);
+    		Switch08KCHR(address);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper216.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper216.cs
new file mode 100644
index 00000000..050a37fa
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper216.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 216)]
+    internal class Mapper216 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG(address, PRGArea.Area8000);
+    		Switch08KCHR(address >> 1);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper222.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper222.cs
new file mode 100644
index 00000000..3f05444e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper222.cs
@@ -0,0 +1,48 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 222)]
+    internal class Mapper222 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper222;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF003)
+    		{
+    		case 32768:
+    			Switch08KPRG(data, PRGArea.Area8000);
+    			break;
+    		case 36864:
+    			Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			break;
+    		case 40960:
+    			Switch08KPRG(data, PRGArea.AreaA000);
+    			break;
+    		case 45056:
+    			Switch01KCHR(data, CHRArea.Area0000);
+    			break;
+    		case 45058:
+    			Switch01KCHR(data, CHRArea.Area0400);
+    			break;
+    		case 49152:
+    			Switch01KCHR(data, CHRArea.Area0800);
+    			break;
+    		case 49154:
+    			Switch01KCHR(data, CHRArea.Area0C00);
+    			break;
+    		case 53248:
+    			Switch01KCHR(data, CHRArea.Area1000);
+    			break;
+    		case 53250:
+    			Switch01KCHR(data, CHRArea.Area1400);
+    			break;
+    		case 57344:
+    			Switch01KCHR(data, CHRArea.Area1800);
+    			break;
+    		case 57346:
+    			Switch01KCHR(data, CHRArea.Area1C00);
+    			break;
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper225.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper225.cs
new file mode 100644
index 00000000..f07329db
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper225.cs
@@ -0,0 +1,63 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 225)]
+    internal class Mapper225 : Board
+    {
+    	private byte[] RAM;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		RAM = new byte[4];
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if (address >= 22528)
+    		{
+    			RAM[address & 3] = (byte)(data & 0xFu);
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte value)
+    	{
+    		if (address >= 22528)
+    		{
+    			value = RAM[address & 3];
+    		}
+    		else
+    		{
+    			value = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(address & 0x3F);
+    		if ((address & 0x1000) == 4096)
+    		{
+    			Switch16KPRG((address >> 6) & 0x3F, PRGArea.Area8000);
+    			Switch16KPRG((address >> 6) & 0x3F, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(((address >> 6) & 0x3F) >> 1, PRGArea.Area8000);
+    		}
+    		Switch01KNMTFromMirroring(((address & 0x2000) == 8192) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(RAM);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		stream.Read(RAM, 0, RAM.Length);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper226.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper226.cs
new file mode 100644
index 00000000..4703b793
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper226.cs
@@ -0,0 +1,66 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 226)]
+    internal class Mapper226 : Board
+    {
+    	private int prg_reg;
+
+    	private bool prg_mode;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		prg_reg = 0;
+    		prg_mode = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0x8001)
+    		{
+    		case 32768:
+    			prg_reg = (data & 0x1F) | ((data & 0x80) >> 2) | (prg_reg & 0xC0);
+    			prg_mode = (data & 0x20) == 32;
+    			Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Vert : Mirroring.Horz);
+    			if (prg_mode)
+    			{
+    				Switch16KPRG(prg_reg, PRGArea.Area8000);
+    				Switch16KPRG(prg_reg, PRGArea.AreaC000);
+    			}
+    			else
+    			{
+    				Switch32KPRG(prg_reg >> 1, PRGArea.Area8000);
+    			}
+    			break;
+    		case 32769:
+    			prg_reg = ((data & 1) << 6) | (prg_reg & 0x3F);
+    			if (prg_mode)
+    			{
+    				Switch16KPRG(prg_reg, PRGArea.Area8000);
+    				Switch16KPRG(prg_reg, PRGArea.AreaC000);
+    			}
+    			else
+    			{
+    				Switch32KPRG(prg_reg >> 1, PRGArea.Area8000);
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_reg);
+    		stream.Write(prg_mode);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_reg = stream.ReadInt32();
+    		prg_mode = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper227.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper227.cs
new file mode 100644
index 00000000..ec287f93
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper227.cs
@@ -0,0 +1,90 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 227)]
+    internal class Mapper227 : Board
+    {
+    	private bool flag_o;
+
+    	private bool flag_s;
+
+    	private bool flag_l;
+
+    	private int prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(0, PRGArea.AreaC000);
+    		flag_o = false;
+    		flag_s = false;
+    		flag_l = false;
+    		prg_reg = 0;
+    		ToggleCHRRAMWritableEnable(enable: true);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		flag_s = (address & 1) == 1;
+    		flag_o = (address & 0x80) == 128;
+    		flag_l = (address & 0x200) == 512;
+    		prg_reg = ((address >> 2) & 0x1F) | ((address >> 3) & 0x20);
+    		Switch01KNMTFromMirroring(((address & 2) == 2) ? Mirroring.Horz : Mirroring.Vert);
+    		ToggleCHRRAMWritableEnable(!flag_o);
+    		if (flag_o)
+    		{
+    			if (!flag_s)
+    			{
+    				Switch16KPRG(prg_reg, PRGArea.Area8000);
+    				Switch16KPRG(prg_reg, PRGArea.AreaC000);
+    			}
+    			else
+    			{
+    				Switch32KPRG(prg_reg >> 1, PRGArea.Area8000);
+    			}
+    		}
+    		else if (!flag_l)
+    		{
+    			if (!flag_s)
+    			{
+    				Switch16KPRG(prg_reg, PRGArea.Area8000);
+    				Switch16KPRG(prg_reg & 0x38, PRGArea.AreaC000);
+    			}
+    			else
+    			{
+    				Switch16KPRG(prg_reg & 0x3E, PRGArea.Area8000);
+    				Switch16KPRG(prg_reg & 0x38, PRGArea.AreaC000);
+    			}
+    		}
+    		else if (!flag_s)
+    		{
+    			Switch16KPRG(prg_reg, PRGArea.Area8000);
+    			Switch16KPRG(prg_reg | 7, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch16KPRG(prg_reg & 0x3E, PRGArea.Area8000);
+    			Switch16KPRG(prg_reg | 7, PRGArea.AreaC000);
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_o);
+    		stream.Write(flag_s);
+    		stream.Write(flag_l);
+    		stream.Write(prg_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_o = stream.ReadBoolean();
+    		flag_s = stream.ReadBoolean();
+    		flag_l = stream.ReadBoolean();
+    		prg_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper228.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper228.cs
new file mode 100644
index 00000000..40952eab
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper228.cs
@@ -0,0 +1,61 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 228)]
+    [HassIssues]
+    internal class Mapper228 : Board
+    {
+    	private byte[] RAM;
+
+    	private int bank;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper228;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		RAM = new byte[4];
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		RAM[address & 3] = (byte)(data & 0xFu);
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte data)
+    	{
+    		data = RAM[address & 3];
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(((address & 0xF) << 2) | (data & 3));
+    		Switch01KNMTFromMirroring(((address & 0x2000) == 8192) ? Mirroring.Horz : Mirroring.Vert);
+    		bank = ((address >> 7) & 0x1F) + ((address >> 7) & (address >> 8) & 0x10);
+    		if ((address & 0x20) == 32)
+    		{
+    			Switch16KPRG((bank << 2) | ((address >> 5) & 2), PRGArea.Area8000);
+    			Switch16KPRG((bank << 2) | ((address >> 5) & 2), PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(bank, PRGArea.Area8000);
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(RAM);
+    		stream.Write(bank);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		stream.Read(RAM, 0, RAM.Length);
+    		bank = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper229.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper229.cs
new file mode 100644
index 00000000..7c3b059b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper229.cs
@@ -0,0 +1,17 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 229)]
+    [HassIssues]
+    internal class Mapper229 : Board
+    {
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper229;
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch01KNMTFromMirroring(((address & 0x20) == 32) ? Mirroring.Horz : Mirroring.Vert);
+    		Switch16KPRG(((address & 0x1E) == 30) ? (address & 0x1F) : 0, PRGArea.Area8000);
+    		Switch16KPRG(((address & 0x1E) != 30) ? 1 : (address & 0x1F), PRGArea.AreaC000);
+    		Switch08KCHR(address);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper230.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper230.cs
new file mode 100644
index 00000000..1c2d1047
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper230.cs
@@ -0,0 +1,58 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 230)]
+    [HassIssues]
+    internal class Mapper230 : Board
+    {
+    	private bool contraMode;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper230;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		contraMode = true;
+    		Switch16KPRG(0, PRGArea.Area8000);
+    		Switch16KPRG(7, PRGArea.AreaC000);
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		base.SoftReset();
+    		contraMode = !contraMode;
+    		if (contraMode)
+    		{
+    			Switch16KPRG(0, PRGArea.Area8000);
+    			Switch16KPRG(7, PRGArea.AreaC000);
+    			Switch01KNMTFromMirroring(Mirroring.Vert);
+    		}
+    		else
+    		{
+    			Switch08KCHR(0);
+    			Switch16KPRG(8, PRGArea.Area8000);
+    			Switch16KPRG(39, PRGArea.AreaC000);
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (contraMode)
+    		{
+    			Switch16KPRG(data & 7, PRGArea.Area8000);
+    			Switch16KPRG(7, PRGArea.AreaC000);
+    			Switch01KNMTFromMirroring(Mirroring.Vert);
+    			return;
+    		}
+    		Switch01KNMTFromMirroring(((data & 0x40) == 64) ? Mirroring.Vert : Mirroring.Horz);
+    		if ((data & 0x20) == 32)
+    		{
+    			Switch16KPRG((data & 0x1F) + 8, PRGArea.Area8000);
+    			Switch16KPRG((data & 0x1F) + 8, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(((data & 0x1F) >> 1) + 4, PRGArea.Area8000);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper231.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper231.cs
new file mode 100644
index 00000000..b9dde8c4
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper231.cs
@@ -0,0 +1,13 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 231)]
+    internal class Mapper231 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch16KPRG(address & 0x1E, PRGArea.Area8000);
+    		Switch16KPRG((address & 0x1E) | ((address >> 5) & 1), PRGArea.AreaC000);
+    		Switch01KNMTFromMirroring(((address & 0x80) == 128) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper232.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper232.cs
new file mode 100644
index 00000000..25328fca
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper232.cs
@@ -0,0 +1,42 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 232)]
+    internal class Mapper232 : Board
+    {
+    	private int prg_reg;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch16KPRG(3, PRGArea.AreaC000);
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		if (address < 49152)
+    		{
+    			prg_reg = ((data & 0x18) >> 1) | (prg_reg & 3);
+    		}
+    		else
+    		{
+    			prg_reg = (prg_reg & 0xC) | (data & 3);
+    		}
+    		Switch16KPRG(prg_reg, PRGArea.Area8000);
+    		Switch16KPRG(3 | (prg_reg & 0xC), PRGArea.AreaC000);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(prg_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		prg_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper233.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper233.cs
new file mode 100644
index 00000000..b33f5041
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper233.cs
@@ -0,0 +1,68 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 233)]
+    internal class Mapper233 : Board
+    {
+    	private int title;
+
+    	private int bank;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		bank = (title = 0);
+    	}
+
+    	internal override void SoftReset()
+    	{
+    		base.SoftReset();
+    		bank = 0;
+    		title ^= 32;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		bank = data & 0x1F;
+    		if ((data & 0x20) == 32)
+    		{
+    			Switch16KPRG(title | bank, PRGArea.Area8000);
+    			Switch16KPRG(title | bank, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG((title >> 1) | (bank >> 1), PRGArea.Area8000);
+    		}
+    		switch ((data >> 6) & 3)
+    		{
+    		case 0:
+    			Switch01KNMT(128);
+    			break;
+    		case 1:
+    			Switch01KNMTFromMirroring(Mirroring.Vert);
+    			break;
+    		case 2:
+    			Switch01KNMTFromMirroring(Mirroring.Horz);
+    			break;
+    		case 3:
+    			Switch01KNMTFromMirroring(Mirroring.OneScB);
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(title);
+    		stream.Write(bank);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		title = stream.ReadInt32();
+    		bank = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper240.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper240.cs
new file mode 100644
index 00000000..f06d1fa9
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper240.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 240)]
+    internal class Mapper240 : Board
+    {
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG((data >> 4) & 0xF, PRGArea.Area8000);
+    		Switch08KCHR(data & 0xF);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper242.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper242.cs
new file mode 100644
index 00000000..13c18202
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper242.cs
@@ -0,0 +1,12 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 242)]
+    internal class Mapper242 : Board
+    {
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch32KPRG((address >> 3) & 0xF, PRGArea.Area8000);
+    		Switch01KNMTFromMirroring(((address & 2) == 2) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper243.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper243.cs
new file mode 100644
index 00000000..c1d64ab8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper243.cs
@@ -0,0 +1,88 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Sachen Poker", 243)]
+    [HassIssues]
+    internal class Mapper243 : Board
+    {
+    	private int addr;
+
+    	private int chr_reg;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper243;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		addr = (chr_reg = 0);
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if (address >= 20480 || address < 16416)
+    		{
+    			return;
+    		}
+    		switch (address & 0x4101)
+    		{
+    		case 16640:
+    			addr = data & 7;
+    			break;
+    		case 16641:
+    			switch (addr)
+    			{
+    			case 2:
+    				chr_reg = ((data << 3) & 8) | (chr_reg & 7);
+    				Switch08KCHR(chr_reg);
+    				break;
+    			case 4:
+    				chr_reg = (data & 1) | (chr_reg & 0xE);
+    				Switch08KCHR(chr_reg);
+    				break;
+    			case 5:
+    				Switch32KPRG(data & 7, PRGArea.Area8000);
+    				break;
+    			case 6:
+    				chr_reg = ((data & 3) << 1) | (chr_reg & 9);
+    				Switch08KCHR(chr_reg);
+    				break;
+    			case 7:
+    				switch ((data >> 1) & 3)
+    				{
+    				case 0:
+    					Switch01KNMTFromMirroring(Mirroring.Horz);
+    					break;
+    				case 1:
+    					Switch01KNMTFromMirroring(Mirroring.Vert);
+    					break;
+    				case 2:
+    					Switch01KNMT(14);
+    					break;
+    				case 3:
+    					Switch01KNMTFromMirroring(Mirroring.OneScB);
+    					break;
+    				}
+    				break;
+    			case 3:
+    				break;
+    			}
+    			break;
+    		}
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(addr);
+    		stream.Write(chr_reg);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		addr = stream.ReadInt32();
+    		chr_reg = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper245.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper245.cs
new file mode 100644
index 00000000..d74364af
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper245.cs
@@ -0,0 +1,229 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("C&E", 245, true, true)]
+    [HassIssues]
+    internal class Mapper245 : Board
+    {
+    	private bool flag_c;
+
+    	private bool flag_p;
+
+    	private int address_8001;
+
+    	private int[] chr_reg;
+
+    	private int[] prg_reg;
+
+    	private int prg_or;
+
+    	private bool irq_enabled;
+
+    	private byte irq_counter;
+
+    	private int old_irq_counter;
+
+    	private byte irq_reload;
+
+    	private bool irq_clear;
+
+    	private bool mmc3_alt_behavior;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper245;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		flag_c = (flag_p = false);
+    		address_8001 = 0;
+    		prg_reg = new int[4];
+    		prg_or = 0;
+    		prg_reg[0] = 0;
+    		prg_reg[1] = 1;
+    		prg_reg[2] = PRG_ROM_08KB_Mask - 1;
+    		prg_reg[3] = PRG_ROM_08KB_Mask;
+    		chr_reg = new int[6];
+    		for (int i = 0; i < 6; i++)
+    		{
+    			chr_reg[i] = 0;
+    		}
+    		SetupPRG();
+    		SetupCHR();
+    		irq_enabled = false;
+    		irq_counter = 0;
+    		irq_reload = byte.MaxValue;
+    		old_irq_counter = 0;
+    		irq_clear = false;
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xE001)
+    		{
+    		case 32768:
+    			address_8001 = data & 7;
+    			flag_c = (data & 0x80) != 0;
+    			flag_p = (data & 0x40) != 0;
+    			SetupCHR();
+    			SetupPRG();
+    			break;
+    		case 32769:
+    			switch (address_8001)
+    			{
+    			case 0:
+    			case 1:
+    			case 2:
+    			case 3:
+    			case 4:
+    			case 5:
+    				chr_reg[address_8001] = data;
+    				SetupCHR();
+    				break;
+    			case 6:
+    				prg_reg[0] = data & 0x3F;
+    				SetupPRG();
+    				break;
+    			case 7:
+    				prg_reg[1] = data & 0x3F;
+    				SetupPRG();
+    				break;
+    			}
+    			break;
+    		case 40960:
+    			if (NMT_DEFAULT_MIRROR != Mirroring.Full)
+    			{
+    				Switch01KNMTFromMirroring(((data & 1) == 1) ? Mirroring.Horz : Mirroring.Vert);
+    			}
+    			break;
+    		case 40961:
+    			TogglePRGRAMEnable((data & 0x80) != 0);
+    			TogglePRGRAMWritableEnable((data & 0x40) == 0);
+    			break;
+    		case 49152:
+    			irq_reload = data;
+    			break;
+    		case 49153:
+    			if (mmc3_alt_behavior)
+    			{
+    				irq_clear = true;
+    			}
+    			irq_counter = 0;
+    			break;
+    		case 57344:
+    			irq_enabled = false;
+    			NesEmu.IRQFlags &= -9;
+    			break;
+    		case 57345:
+    			irq_enabled = true;
+    			break;
+    		}
+    	}
+
+    	private void SetupCHR()
+    	{
+    		if (CHR_ROM_01KB_Count > 0)
+    		{
+    			if (!flag_c)
+    			{
+    				Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area0000);
+    				Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area0800);
+    				Switch01KCHR(chr_reg[2], CHRArea.Area1000);
+    				Switch01KCHR(chr_reg[3], CHRArea.Area1400);
+    				Switch01KCHR(chr_reg[4], CHRArea.Area1800);
+    				Switch01KCHR(chr_reg[5], CHRArea.Area1C00);
+    			}
+    			else
+    			{
+    				Switch02KCHR(chr_reg[0] >> 1, CHRArea.Area1000);
+    				Switch02KCHR(chr_reg[1] >> 1, CHRArea.Area1800);
+    				Switch01KCHR(chr_reg[2], CHRArea.Area0000);
+    				Switch01KCHR(chr_reg[3], CHRArea.Area0400);
+    				Switch01KCHR(chr_reg[4], CHRArea.Area0800);
+    				Switch01KCHR(chr_reg[5], CHRArea.Area0C00);
+    			}
+    		}
+    		else if (!flag_c)
+    		{
+    			Switch04KCHR(0, CHRArea.Area0000);
+    			Switch04KCHR(1, CHRArea.Area1000);
+    		}
+    		else
+    		{
+    			Switch04KCHR(1, CHRArea.Area0000);
+    			Switch04KCHR(0, CHRArea.Area1000);
+    		}
+    	}
+
+    	private void SetupPRG()
+    	{
+    		prg_or = (chr_reg[0] & 2) << 5;
+    		Switch08KPRG(prg_reg[flag_p ? 2 : 0] | prg_or, PRGArea.Area8000);
+    		Switch08KPRG(prg_reg[1] | prg_or, PRGArea.AreaA000);
+    		Switch08KPRG(prg_reg[(!flag_p) ? 2 : 0] | prg_or, PRGArea.AreaC000);
+    		Switch08KPRG(prg_reg[3] | prg_or, PRGArea.AreaE000);
+    	}
+
+    	internal override void OnPPUA12RaisingEdge()
+    	{
+    		old_irq_counter = irq_counter;
+    		if (irq_counter == 0 || irq_clear)
+    		{
+    			irq_counter = irq_reload;
+    		}
+    		else
+    		{
+    			irq_counter--;
+    		}
+    		if ((!mmc3_alt_behavior || old_irq_counter != 0 || irq_clear) && irq_counter == 0 && irq_enabled)
+    		{
+    			NesEmu.IRQFlags |= 8;
+    		}
+    		irq_clear = false;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(flag_c);
+    		stream.Write(flag_p);
+    		stream.Write(address_8001);
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			stream.Write(chr_reg[i]);
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			stream.Write(prg_reg[j]);
+    		}
+    		stream.Write(irq_enabled);
+    		stream.Write(irq_counter);
+    		stream.Write(old_irq_counter);
+    		stream.Write(irq_reload);
+    		stream.Write(irq_clear);
+    		stream.Write(prg_or);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		flag_c = stream.ReadBoolean();
+    		flag_p = stream.ReadBoolean();
+    		address_8001 = stream.ReadInt32();
+    		for (int i = 0; i < chr_reg.Length; i++)
+    		{
+    			chr_reg[i] = stream.ReadInt32();
+    		}
+    		for (int j = 0; j < prg_reg.Length; j++)
+    		{
+    			prg_reg[j] = stream.ReadInt32();
+    		}
+    		irq_enabled = stream.ReadBoolean();
+    		irq_counter = stream.ReadByte();
+    		old_irq_counter = stream.ReadInt32();
+    		irq_reload = stream.ReadByte();
+    		irq_clear = stream.ReadBoolean();
+    		prg_or = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper246.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper246.cs
new file mode 100644
index 00000000..af6088cd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper246.cs
@@ -0,0 +1,50 @@
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 246)]
+    internal class Mapper246 : Board
+    {
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		Switch08KPRG(255, PRGArea.AreaE000);
+    	}
+
+    	internal override void WriteSRM(ref ushort address, ref byte data)
+    	{
+    		if (address < 26624)
+    		{
+    			switch (address)
+    			{
+    			case 24576:
+    				Switch08KPRG(data, PRGArea.Area8000);
+    				break;
+    			case 24577:
+    				Switch08KPRG(data, PRGArea.AreaA000);
+    				break;
+    			case 24578:
+    				Switch08KPRG(data, PRGArea.AreaC000);
+    				break;
+    			case 24579:
+    				Switch08KPRG(data, PRGArea.AreaE000);
+    				break;
+    			case 24580:
+    				Switch02KCHR(data, CHRArea.Area0000);
+    				break;
+    			case 24581:
+    				Switch02KCHR(data, CHRArea.Area0800);
+    				break;
+    			case 24582:
+    				Switch02KCHR(data, CHRArea.Area1000);
+    				break;
+    			case 24583:
+    				Switch02KCHR(data, CHRArea.Area1800);
+    				break;
+    			}
+    		}
+    		else
+    		{
+    			base.WriteSRM(ref address, ref data);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mapper255.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper255.cs
new file mode 100644
index 00000000..da4cf0fc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mapper255.cs
@@ -0,0 +1,66 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [BoardInfo("Unknown", 255)]
+    [HassIssues]
+    internal class Mapper255 : Board
+    {
+    	private byte[] RAM;
+
+    	internal override string Issues => MNInterfaceLanguage.IssueMapper255;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		RAM = new byte[4];
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		if (address >= 22528)
+    		{
+    			RAM[address & 3] = (byte)(data & 0xFu);
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte data)
+    	{
+    		if (address >= 22528)
+    		{
+    			data = RAM[address & 3];
+    		}
+    		else
+    		{
+    			data = 0;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		Switch08KCHR(address & 0x3F);
+    		if ((address & 0x1000) == 4096)
+    		{
+    			Switch16KPRG((address >> 6) & 0x3F, PRGArea.Area8000);
+    			Switch16KPRG((address >> 6) & 0x3F, PRGArea.AreaC000);
+    		}
+    		else
+    		{
+    			Switch32KPRG(((address >> 6) & 0x3F) >> 1, PRGArea.Area8000);
+    		}
+    		Switch01KNMTFromMirroring(((address & 0x2000) == 8192) ? Mirroring.Horz : Mirroring.Vert);
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(RAM);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		stream.Read(RAM, 0, RAM.Length);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MemReadAccess.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MemReadAccess.cs
new file mode 100644
index 00000000..48e964a3
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MemReadAccess.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void MemReadAccess(ref ushort addr, out byte value);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MemWriteAccess.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MemWriteAccess.cs
new file mode 100644
index 00000000..ea7a8d1d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MemWriteAccess.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void MemWriteAccess(ref ushort addr, ref byte value);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Mirroring.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Mirroring.cs
new file mode 100644
index 00000000..bddc25f6
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Mirroring.cs
@@ -0,0 +1,11 @@
+namespace MyNes.Core
+{
+    public enum Mirroring : byte
+    {
+    	Horz = 80,
+    	Vert = 68,
+    	OneScA = 0,
+    	OneScB = 85,
+    	Full = 228
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/MyNesMain.cs b/OtherCore/MyNes.Standard2/MyNes.Core/MyNesMain.cs
new file mode 100644
index 00000000..f82d4fb0
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/MyNesMain.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace MyNes.Core
+{
+    public class MyNesMain
+    {
+        public static EmuSettings EmuSettings { get; private set; }
+        public static RendererSettings RendererSettings { get; private set; }
+        public static IExternalSupporter Supporter { get; private set; }
+        public static string WorkingFolder { get; private set; }
+
+        internal static List<Board> Boards { get; private set; }
+
+        public static IVideoProvider VideoProvider { get; private set; }
+
+        public static IAudioProvider AudioProvider { get; private set; }
+
+        public static WaveRecorder WaveRecorder { get; private set; }
+
+        public static void Initialize(IExternalSupporter fileManager, IVideoProvider videoProvider, IAudioProvider audioProvider)
+        {
+            Tracer.WriteLine("Initializing My Nes Core ....");
+            Supporter = fileManager;
+            WorkingFolder = fileManager.GetWorkingFolderPath();
+            Tracer.WriteLine("Loading emu settings ...");
+            EmuSettings = new EmuSettings(Path.Combine(WorkingFolder, "emusettings.ini"));
+            EmuSettings.LoadSettings();
+            Tracer.WriteLine("Emu settings loaded successfully.");
+            Tracer.WriteLine("Loading renderer settings ...");
+            RendererSettings = new RendererSettings(Path.Combine(WorkingFolder, "renderersettings.ini"));
+            RendererSettings.LoadSettings();
+            Tracer.WriteLine("Renderer settings loaded successfully.");
+            Tracer.WriteLine("Locating boards and providers ...");
+            WaveRecorder = new WaveRecorder();
+            Boards = new List<Board>();
+
+            var allTypes = typeof(Board).Assembly.GetTypes();
+            VideoProvider = videoProvider;
+            AudioProvider = audioProvider;
+
+            Boards.Add(new Mapper004());
+
+            foreach (var type in allTypes)
+            {
+                if (type.IsSubclassOf(typeof(Board)) && !type.IsAbstract)
+                {
+                    Board board = Activator.CreateInstance(type) as Board;
+                    Boards.Add(board);
+                    Tracer.WriteLine("Board added: " + board.Name + " [ Mapper " + board.MapperNumber + "]");
+                }
+            }
+
+            Tracer.WriteInformation("Done.");
+            Tracer.WriteInformation("Total of " + Boards.Count + " board found.");
+            SetVideoProvider();
+            SetAudioProvider();
+            SetRenderingMethods();
+
+            NesEmu.Initialize();
+        }
+
+        public static void Shutdown()
+        {
+            if (NesEmu.ON)
+            {
+                NesEmu.ShutDown();
+            }
+            if (VideoProvider != null)
+            {
+                VideoProvider.ShutDown();
+            }
+            if (AudioProvider != null)
+            {
+                AudioProvider.ShutDown();
+            }
+            Tracer.WriteLine("Saving settings ...");
+            EmuSettings.SaveSettings();
+            RendererSettings.SaveSettings();
+            Tracer.WriteLine("Settings saved successfully.");
+            Tracer.WriteLine("Exiting My Nes.");
+        }
+
+        internal static bool IsBoardExist(int mapper)
+        {
+            foreach (Board board in Boards)
+            {
+                if (board.MapperNumber == mapper)
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        internal static Board GetBoard(int mapper)
+        {
+            foreach (Board board in Boards)
+            {
+                if (board.MapperNumber == mapper)
+                {
+                    return board;
+                }
+            }
+            return null;
+        }
+
+        public static void MakeWorkingFolder()
+        {
+            WorkingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "MyNes");
+            Directory.CreateDirectory(WorkingFolder);
+        }
+
+        public static BoardInfoObject[] GetBoardsList(bool includeUnsupportedMappers)
+        {
+            List<BoardInfoObject> list = new List<BoardInfoObject>();
+            if (includeUnsupportedMappers)
+            {
+                for (int i = 0; i < 256; i++)
+                {
+                    bool flag = false;
+                    foreach (Board board in Boards)
+                    {
+                        if (board.MapperNumber == i)
+                        {
+                            BoardInfoObject boardInfoObject = new BoardInfoObject();
+                            boardInfoObject.Name = board.Name;
+                            boardInfoObject.MapperNumber = board.MapperNumber;
+                            boardInfoObject.IsSupported = true;
+                            boardInfoObject.HasIssues = board.HasIssues;
+                            boardInfoObject.Issues = board.Issues;
+                            list.Add(boardInfoObject);
+                            flag = true;
+                            break;
+                        }
+                    }
+                    if (!flag)
+                    {
+                        BoardInfoObject boardInfoObject2 = new BoardInfoObject();
+                        boardInfoObject2.Name = "N/A";
+                        boardInfoObject2.MapperNumber = i;
+                        boardInfoObject2.IsSupported = false;
+                        boardInfoObject2.HasIssues = false;
+                        boardInfoObject2.Issues = "";
+                        list.Add(boardInfoObject2);
+                    }
+                }
+            }
+            else
+            {
+                foreach (Board board2 in Boards)
+                {
+                    if (board2.MapperNumber >= 0)
+                    {
+                        BoardInfoObject boardInfoObject3 = new BoardInfoObject();
+                        boardInfoObject3.Name = board2.Name;
+                        boardInfoObject3.MapperNumber = board2.MapperNumber;
+                        boardInfoObject3.IsSupported = true;
+                        boardInfoObject3.HasIssues = board2.HasIssues;
+                        boardInfoObject3.Issues = board2.Issues;
+                        list.Add(boardInfoObject3);
+                    }
+                }
+            }
+            return list.ToArray();
+        }
+
+        static void SetVideoProvider()
+        {
+            if (VideoProvider != null) VideoProvider.Initialize();
+            else Tracer.WriteError("VideoProvider is null");
+        }
+
+        static void SetAudioProvider()
+        {
+            Tracer.WriteLine("Looking for the audio provider that set in the settings...");
+            if (AudioProvider != null) AudioProvider.Initialize();
+            else Tracer.WriteError("AudioProvider is null");
+        }
+
+        static void SetRenderingMethods()
+        {
+            if (VideoProvider != null && AudioProvider != null)
+            {
+                NesEmu.SetupRenderingMethods(VideoProvider.SubmitFrame, AudioProvider.SubmitSamples, AudioProvider.TogglePause, AudioProvider.GetIsPlaying);
+            }
+            else
+            {
+                Tracer.WriteError("ERROR: unable to setup rendering methods, one (or both) of the providers is not set (video and/or audio provider)");
+            }
+        }
+
+        public static void RecordWave()
+        {
+            if (NesEmu.ON && NesEmu.SoundEnabled)
+            {
+                string text = Path.Combine(EmuSettings.WavesFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath) + ".wav");
+                int num = 0;
+                while (File.Exists(text))
+                {
+                    text = Path.Combine(EmuSettings.WavesFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath) + "_" + num + ".wav");
+                    num++;
+                }
+                WaveRecorder.Record(text, 1, 16, RendererSettings.Audio_Frequency);
+            }
+            else if (VideoProvider != null)
+            {
+                VideoProvider.WriteErrorNotification("Cannot record sound when the emu is off/sound is not enabled.", instant: false);
+            }
+        }
+    }
+
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NTArea.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NTArea.cs
new file mode 100644
index 00000000..407c0dea
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NTArea.cs
@@ -0,0 +1,10 @@
+namespace MyNes.Core
+{
+    internal enum NTArea : byte
+    {
+    	Area2000NT0,
+    	Area2400NT1,
+    	Area2800NT2,
+    	Area2C00NT3
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NTSCPaletteGenerator.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NTSCPaletteGenerator.cs
new file mode 100644
index 00000000..778be2b7
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NTSCPaletteGenerator.cs
@@ -0,0 +1,109 @@
+using System;
+
+namespace MyNes.Core
+{
+    public class NTSCPaletteGenerator
+    {
+    	public const float default_saturation = 1.496f;
+
+    	public const float default_hue_tweak = 0f;
+
+    	public const float default_contrast = 1.016f;
+
+    	public const float default_brightness = 1.075f;
+
+    	public const float default_gamma = 1.975f;
+
+    	private const float black = 0.518f;
+
+    	private const float white = 1.962f;
+
+    	private const float attenuation = 0.746f;
+
+    	public static float saturation = 2f;
+
+    	public static float hue_tweak = 0f;
+
+    	public static float contrast = 1.4f;
+
+    	public static float brightness = 1.07f;
+
+    	public static float gamma = 2f;
+
+    	private static float[] levels = new float[8] { 0.35f, 0.518f, 0.962f, 1.55f, 1.094f, 1.506f, 1.962f, 1.962f };
+
+    	private static int wave(int p, int color)
+    	{
+    		if ((color + p + 8) % 12 >= 6)
+    		{
+    			return 0;
+    		}
+    		return 1;
+    	}
+
+    	private static float gammafix(float f, float gamma)
+    	{
+    		return (float)((f < 0f) ? 0.0 : Math.Pow(f, 2.2f / gamma));
+    	}
+
+    	private static int clamp(float v)
+    	{
+    		return (int)((v < 0f) ? 0f : ((v > 255f) ? 255f : v));
+    	}
+
+    	public static int MakeRGBcolor(int pixel)
+    	{
+    		int num = pixel & 0xF;
+    		int num2 = ((num >= 14) ? 1 : ((pixel >> 4) & 3));
+    		float[] array = new float[2]
+    		{
+    			levels[num2 + ((num == 0) ? 4 : 0)],
+    			levels[num2 + ((num <= 12) ? 4 : 0)]
+    		};
+    		float num3 = 0f;
+    		float num4 = 0f;
+    		float num5 = 0f;
+    		for (int i = 0; i < 12; i++)
+    		{
+    			float num6 = array[wave(i, num)];
+    			if ((((uint)pixel & 0x40u) != 0 && wave(i, 12) == 1) || (((uint)pixel & 0x80u) != 0 && wave(i, 4) == 1) || (((uint)pixel & 0x100u) != 0 && wave(i, 8) == 1))
+    			{
+    				num6 *= 0.746f;
+    			}
+    			float num7 = (num6 - 0.518f) / 1.444f;
+    			num7 = (num7 - 0.5f) * contrast + 0.5f;
+    			num7 *= brightness / 12f;
+    			num3 += num7;
+    			num4 += (float)((double)num7 * Math.Cos(Math.PI / 6.0 * (double)((float)i + hue_tweak)));
+    			num5 += (float)((double)num7 * Math.Sin(Math.PI / 6.0 * (double)((float)i + hue_tweak)));
+    		}
+    		num4 *= saturation;
+    		num5 *= saturation;
+    		return 65536 * clamp(255f * gammafix(num3 + 0.946882f * num4 + 0.623557f * num5, gamma)) + 256 * clamp(255f * gammafix(num3 - 245f / (328f * (float)Math.E) * num4 - 0.635691f * num5, gamma)) + clamp(255f * gammafix(num3 - 1.108545f * num4 + 1.709007f * num5, gamma));
+    	}
+
+    	public static int[] GeneratePalette()
+    	{
+    		int[] array = new int[512];
+    		for (int i = 0; i < 512; i++)
+    		{
+    			array[i] = MakeRGBcolor(i) | -16777216;
+    		}
+    		return array;
+    	}
+
+    	public static int[] GeneratePaletteGBR()
+    	{
+    		int[] array = new int[512];
+    		for (int i = 0; i < 512; i++)
+    		{
+    			int num = MakeRGBcolor(i);
+    			byte b = (byte)((num & 0xFF0000) >> 16);
+    			byte b2 = (byte)((num & 0xFF00) >> 8);
+    			byte b3 = (byte)((uint)num & 0xFFu);
+    			array[i] = -16777216 | (b3 << 16) | (b2 << 8) | b;
+    		}
+    		return array;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106.cs
new file mode 100644
index 00000000..787809f0
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106.cs
@@ -0,0 +1,553 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    [WithExternalSound]
+    internal abstract class Namcot106 : Board
+    {
+    	private int irq_counter;
+
+    	private bool irq_enable;
+
+    	private bool disables_chr_ram_A;
+
+    	private bool disables_chr_ram_B;
+
+    	private bool enable_mirroring_switch;
+
+    	private bool enable_N106_sound;
+
+    	private int temp_nmt;
+
+    	private Namcot106Chnl[] sound_channels;
+
+    	private byte soundReg;
+
+    	public int enabledChannels;
+
+    	private int enabledChannels1;
+
+    	private int channelIndex;
+
+    	private byte temp_val;
+
+    	private byte temp_i;
+
+    	public byte[] EXRAM;
+
+    	private bool[] sound_channels_enable;
+
+    	private double soundOut;
+
+    	private int sound_out_div;
+
+    	internal override void HardReset()
+    	{
+    		base.HardReset();
+    		EXRAM = new byte[128];
+    		Switch08KPRG(PRG_ROM_08KB_Mask, PRGArea.AreaE000);
+    		enable_mirroring_switch = (enable_N106_sound = base.MapperNumber == 19);
+    		switch (SHA1.ToUpper())
+    		{
+    		case "97E7E61EECB73CB1EA0C15AE51E65EA56301A685":
+    		case "3D554F55411AB2DDD1A87E7583E643970DB784F3":
+    		case "7FA51058307DB50825C2D3A3A98C0DA554BC3C92":
+    		case "1C476C795CFC17E987C22FFD6F09BAF1396ED2C9":
+    			enable_mirroring_switch = false;
+    			enable_N106_sound = false;
+    			break;
+    		}
+    		if (enable_N106_sound)
+    		{
+    			sound_channels = new Namcot106Chnl[8];
+    			sound_channels_enable = new bool[8];
+    			for (int i = 0; i < 8; i++)
+    			{
+    				sound_channels[i] = new Namcot106Chnl(this);
+    				sound_channels[i].HardReset();
+    			}
+    			soundReg = 0;
+    			enabledChannels = 0;
+    			channelIndex = 0;
+    			APUApplyChannelsSettings();
+    		}
+    	}
+
+    	internal override void WriteEX(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF800)
+    		{
+    		case 18432:
+    			if (soundReg >= 64)
+    			{
+    				switch (soundReg & 0x7F)
+    				{
+    				case 64:
+    					sound_channels[0].WriteA(ref data);
+    					break;
+    				case 66:
+    					sound_channels[0].WriteB(ref data);
+    					break;
+    				case 68:
+    					sound_channels[0].WriteC(ref data);
+    					break;
+    				case 70:
+    					sound_channels[0].WriteD(ref data);
+    					break;
+    				case 71:
+    					sound_channels[0].WriteE(ref data);
+    					break;
+    				case 72:
+    					sound_channels[1].WriteA(ref data);
+    					break;
+    				case 74:
+    					sound_channels[1].WriteB(ref data);
+    					break;
+    				case 76:
+    					sound_channels[1].WriteC(ref data);
+    					break;
+    				case 78:
+    					sound_channels[1].WriteD(ref data);
+    					break;
+    				case 79:
+    					sound_channels[1].WriteE(ref data);
+    					break;
+    				case 80:
+    					sound_channels[2].WriteA(ref data);
+    					break;
+    				case 82:
+    					sound_channels[2].WriteB(ref data);
+    					break;
+    				case 84:
+    					sound_channels[2].WriteC(ref data);
+    					break;
+    				case 86:
+    					sound_channels[2].WriteD(ref data);
+    					break;
+    				case 87:
+    					sound_channels[2].WriteE(ref data);
+    					break;
+    				case 88:
+    					sound_channels[3].WriteA(ref data);
+    					break;
+    				case 90:
+    					sound_channels[3].WriteB(ref data);
+    					break;
+    				case 92:
+    					sound_channels[3].WriteC(ref data);
+    					break;
+    				case 94:
+    					sound_channels[3].WriteD(ref data);
+    					break;
+    				case 95:
+    					sound_channels[3].WriteE(ref data);
+    					break;
+    				case 96:
+    					sound_channels[4].WriteA(ref data);
+    					break;
+    				case 98:
+    					sound_channels[4].WriteB(ref data);
+    					break;
+    				case 100:
+    					sound_channels[4].WriteC(ref data);
+    					break;
+    				case 102:
+    					sound_channels[4].WriteD(ref data);
+    					break;
+    				case 103:
+    					sound_channels[4].WriteE(ref data);
+    					break;
+    				case 104:
+    					sound_channels[5].WriteA(ref data);
+    					break;
+    				case 106:
+    					sound_channels[5].WriteB(ref data);
+    					break;
+    				case 108:
+    					sound_channels[5].WriteC(ref data);
+    					break;
+    				case 110:
+    					sound_channels[5].WriteD(ref data);
+    					break;
+    				case 111:
+    					sound_channels[5].WriteE(ref data);
+    					break;
+    				case 112:
+    					sound_channels[6].WriteA(ref data);
+    					break;
+    				case 114:
+    					sound_channels[6].WriteB(ref data);
+    					break;
+    				case 116:
+    					sound_channels[6].WriteC(ref data);
+    					break;
+    				case 118:
+    					sound_channels[6].WriteD(ref data);
+    					break;
+    				case 119:
+    					sound_channels[6].WriteE(ref data);
+    					break;
+    				case 120:
+    					sound_channels[7].WriteA(ref data);
+    					break;
+    				case 122:
+    					sound_channels[7].WriteB(ref data);
+    					break;
+    				case 124:
+    					sound_channels[7].WriteC(ref data);
+    					break;
+    				case 126:
+    					sound_channels[7].WriteD(ref data);
+    					break;
+    				case 127:
+    					sound_channels[7].WriteE(ref data);
+    					enabledChannels = (data & 0x70) >> 4;
+    					channelIndex = 0;
+    					enabledChannels1 = enabledChannels + 1;
+    					temp_i = 7;
+    					while (temp_i >= 0 && enabledChannels1 > 0)
+    					{
+    						sound_channels[temp_i].Enabled = true;
+    						enabledChannels1--;
+    						temp_i--;
+    					}
+    					break;
+    				}
+    			}
+    			EXRAM[soundReg & 0x7F] = data;
+    			if ((soundReg & 0x80) == 128)
+    			{
+    				soundReg = (byte)(((uint)(soundReg + 1) & 0x7Fu) | 0x80u);
+    			}
+    			break;
+    		case 20480:
+    			NesEmu.IRQFlags &= -9;
+    			irq_counter = (irq_counter & 0x7F00) | data;
+    			break;
+    		case 22528:
+    			NesEmu.IRQFlags &= -9;
+    			irq_counter = (irq_counter & 0xFF) | ((data & 0x7F) << 8);
+    			irq_enable = (data & 0x80) == 128;
+    			break;
+    		}
+    	}
+
+    	internal override void ReadEX(ref ushort address, out byte value)
+    	{
+    		switch (address & 0xF800)
+    		{
+    		case 18432:
+    			value = EXRAM[soundReg & 0x7F];
+    			if ((soundReg & 0x80) == 128)
+    			{
+    				soundReg = (byte)(((uint)(soundReg + 1) & 0x7Fu) | 0x80u);
+    			}
+    			break;
+    		case 20480:
+    			NesEmu.IRQFlags &= -9;
+    			value = (byte)((uint)irq_counter & 0xFFu);
+    			break;
+    		case 22528:
+    			NesEmu.IRQFlags &= -9;
+    			value = (byte)((irq_enable ? 128u : 0u) | (uint)((irq_counter & 0x7F00) >> 8));
+    			break;
+    		default:
+    			value = 0;
+    			break;
+    		}
+    	}
+
+    	internal override void WritePRG(ref ushort address, ref byte data)
+    	{
+    		switch (address & 0xF800)
+    		{
+    		case 32768:
+    			if (!disables_chr_ram_A)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area0000);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area0000);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area0000);
+    				Switch01KCHR(data, CHRArea.Area0000);
+    			}
+    			break;
+    		case 34816:
+    			if (!disables_chr_ram_A)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area0400);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area0400);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area0400);
+    				Switch01KCHR(data, CHRArea.Area0400);
+    			}
+    			break;
+    		case 36864:
+    			if (!disables_chr_ram_A)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area0800);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area0800);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area0800);
+    				Switch01KCHR(data, CHRArea.Area0800);
+    			}
+    			break;
+    		case 38912:
+    			if (!disables_chr_ram_A)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area0C00);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area0C00);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area0C00);
+    				Switch01KCHR(data, CHRArea.Area0C00);
+    			}
+    			break;
+    		case 40960:
+    			if (!disables_chr_ram_B)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area1000);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area1000);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area1000);
+    				Switch01KCHR(data, CHRArea.Area1000);
+    			}
+    			break;
+    		case 43008:
+    			if (!disables_chr_ram_B)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area1400);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area1400);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area1400);
+    				Switch01KCHR(data, CHRArea.Area1400);
+    			}
+    			break;
+    		case 45056:
+    			if (!disables_chr_ram_B)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area1800);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area1800);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area1800);
+    				Switch01KCHR(data, CHRArea.Area1800);
+    			}
+    			break;
+    		case 47104:
+    			if (!disables_chr_ram_B)
+    			{
+    				Toggle01KCHR_RAM(data >= 224, CHRArea.Area1C00);
+    				Switch01KCHR((data >= 224) ? (data - 224) : data, CHRArea.Area1C00);
+    			}
+    			else
+    			{
+    				Toggle01KCHR_RAM(ram: false, CHRArea.Area1C00);
+    				Switch01KCHR(data, CHRArea.Area1C00);
+    			}
+    			break;
+    		case 49152:
+    			if (enable_mirroring_switch)
+    			{
+    				NMT_AREA_BLK_INDEX[0] = data;
+    			}
+    			break;
+    		case 51200:
+    			if (enable_mirroring_switch)
+    			{
+    				NMT_AREA_BLK_INDEX[1] = data;
+    			}
+    			break;
+    		case 53248:
+    			if (enable_mirroring_switch)
+    			{
+    				NMT_AREA_BLK_INDEX[2] = data;
+    			}
+    			break;
+    		case 55296:
+    			if (enable_mirroring_switch)
+    			{
+    				NMT_AREA_BLK_INDEX[3] = data;
+    			}
+    			break;
+    		case 57344:
+    			Switch08KPRG(data & 0x3F, PRGArea.Area8000);
+    			break;
+    		case 59392:
+    			Switch08KPRG(data & 0x3F, PRGArea.AreaA000);
+    			disables_chr_ram_A = (data & 0x40) == 64;
+    			disables_chr_ram_B = (data & 0x80) == 128;
+    			break;
+    		case 61440:
+    			Switch08KPRG(data & 0x3F, PRGArea.AreaC000);
+    			break;
+    		case 63488:
+    			soundReg = data;
+    			break;
+    		}
+    	}
+
+    	internal override void ReadNMT(ref ushort address, out byte data)
+    	{
+    		if (enable_mirroring_switch)
+    		{
+    			temp_nmt = NMT_AREA_BLK_INDEX[(address >> 10) & 3];
+    			if (temp_nmt >= 224)
+    			{
+    				data = NMT_RAM[(temp_nmt - 224) & 1][address & 0x3FF];
+    			}
+    			else
+    			{
+    				data = CHR_ROM[temp_nmt][address & 0x3FF];
+    			}
+    		}
+    		else
+    		{
+    			base.ReadNMT(ref address, out data);
+    		}
+    	}
+
+    	internal override void WriteNMT(ref ushort address, ref byte data)
+    	{
+    		if (enable_mirroring_switch)
+    		{
+    			temp_nmt = NMT_AREA_BLK_INDEX[(address >> 10) & 3];
+    			if (temp_nmt >= 224)
+    			{
+    				NMT_RAM[(temp_nmt - 224) & 1][address & 0x3FF] = data;
+    			}
+    		}
+    		else
+    		{
+    			base.WriteNMT(ref address, ref data);
+    		}
+    	}
+
+    	internal override void OnCPUClock()
+    	{
+    		if (irq_enable)
+    		{
+    			if (irq_counter == 32767)
+    			{
+    				NesEmu.IRQFlags |= 8;
+    				irq_counter = 0;
+    			}
+    			else
+    			{
+    				irq_counter++;
+    			}
+    		}
+    	}
+
+    	internal override void OnAPUClockSingle()
+    	{
+    		if (sound_channels != null)
+    		{
+    			for (int i = 0; i < sound_channels.Length; i++)
+    			{
+    				sound_channels[i].ClockSingle();
+    			}
+    		}
+    	}
+
+    	internal override double APUGetSample()
+    	{
+    		soundOut = 0.0;
+    		sound_out_div = 0;
+    		if (enabledChannels > 0)
+    		{
+    			for (int i = 0; i < sound_channels.Length; i++)
+    			{
+    				if (sound_channels[i].Enabled && sound_channels_enable[i])
+    				{
+    					if (sound_channels[i].clocks > 0)
+    					{
+    						sound_channels[i].output = sound_channels[i].output_av / sound_channels[i].clocks;
+    					}
+    					sound_channels[i].clocks = (sound_channels[i].output_av = 0);
+    					soundOut += sound_channels[i].output;
+    					sound_out_div++;
+    				}
+    			}
+    			soundOut = soundOut / 8.0 / 225.0;
+    		}
+    		return soundOut;
+    	}
+
+    	internal override void APUApplyChannelsSettings()
+    	{
+    		base.APUApplyChannelsSettings();
+    		sound_channels_enable[0] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT1;
+    		sound_channels_enable[1] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT2;
+    		sound_channels_enable[2] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT3;
+    		sound_channels_enable[3] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT4;
+    		sound_channels_enable[4] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT5;
+    		sound_channels_enable[5] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT6;
+    		sound_channels_enable[6] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT7;
+    		sound_channels_enable[7] = MyNesMain.RendererSettings.Audio_ChannelEnabled_NMT8;
+    	}
+
+    	internal override void WriteStateData(ref BinaryWriter stream)
+    	{
+    		base.WriteStateData(ref stream);
+    		stream.Write(irq_counter);
+    		stream.Write(irq_enable);
+    		stream.Write(disables_chr_ram_A);
+    		stream.Write(disables_chr_ram_B);
+    		stream.Write(enable_mirroring_switch);
+    		stream.Write(enable_N106_sound);
+    		stream.Write(temp_nmt);
+    		if (enable_N106_sound)
+    		{
+    			for (int i = 0; i < sound_channels.Length; i++)
+    			{
+    				sound_channels[i].SaveState(stream);
+    			}
+    		}
+    		stream.Write(soundReg);
+    		stream.Write(enabledChannels);
+    		stream.Write(enabledChannels1);
+    		stream.Write(channelIndex);
+    		stream.Write(temp_val);
+    		stream.Write(temp_i);
+    		stream.Write(EXRAM);
+    	}
+
+    	internal override void ReadStateData(ref BinaryReader stream)
+    	{
+    		base.ReadStateData(ref stream);
+    		irq_counter = stream.ReadInt32();
+    		irq_enable = stream.ReadBoolean();
+    		disables_chr_ram_A = stream.ReadBoolean();
+    		disables_chr_ram_B = stream.ReadBoolean();
+    		enable_mirroring_switch = stream.ReadBoolean();
+    		enable_N106_sound = stream.ReadBoolean();
+    		temp_nmt = stream.ReadInt32();
+    		if (enable_N106_sound)
+    		{
+    			for (int i = 0; i < sound_channels.Length; i++)
+    			{
+    				sound_channels[i].LoadState(stream);
+    			}
+    		}
+    		soundReg = stream.ReadByte();
+    		enabledChannels = stream.ReadInt32();
+    		enabledChannels1 = stream.ReadInt32();
+    		channelIndex = stream.ReadInt32();
+    		temp_val = stream.ReadByte();
+    		temp_i = stream.ReadByte();
+    		stream.Read(EXRAM, 0, EXRAM.Length);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106Chnl.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106Chnl.cs
new file mode 100644
index 00000000..f7c5b99f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Namcot106Chnl.cs
@@ -0,0 +1,157 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class Namcot106Chnl
+    {
+    	private Namcot106 namcot;
+
+    	private int freqTimer;
+
+    	private int frequency;
+
+    	public int output;
+
+    	public int output_av;
+
+    	public int clocks;
+
+    	private int cycles;
+
+    	private int InstrumentLength;
+
+    	private byte InstrumentAddress;
+
+    	private int startPoint;
+
+    	private int endPoint;
+
+    	private int readPoint;
+
+    	public int volume;
+
+    	private bool freez;
+
+    	public bool Enabled { get; set; }
+
+    	public Namcot106Chnl(Namcot106 namcot)
+    	{
+    		this.namcot = namcot;
+    	}
+
+    	public void HardReset()
+    	{
+    	}
+
+    	private void UpdateFrequency()
+    	{
+    		if (frequency > 0)
+    		{
+    			freqTimer = 983040 * (namcot.enabledChannels + 1) / frequency;
+    			freez = false;
+    		}
+    		else
+    		{
+    			freez = true;
+    			output_av = 0;
+    		}
+    	}
+
+    	private void UpdatePlaybackParameters()
+    	{
+    		startPoint = InstrumentAddress;
+    		endPoint = InstrumentAddress + 4 * (8 - InstrumentLength);
+    		readPoint = InstrumentAddress;
+    	}
+
+    	public void WriteA(ref byte data)
+    	{
+    		frequency = (frequency & 0xFFFF00) | data;
+    		UpdateFrequency();
+    	}
+
+    	public void WriteB(ref byte data)
+    	{
+    		frequency = (frequency & 0xFF00FF) | (data << 8);
+    		UpdateFrequency();
+    	}
+
+    	public void WriteC(ref byte data)
+    	{
+    		frequency = (frequency & 0xFFFF) | ((data & 3) << 12);
+    		InstrumentLength = (data >> 2) & 7;
+    		UpdateFrequency();
+    		UpdatePlaybackParameters();
+    	}
+
+    	public void WriteD(ref byte data)
+    	{
+    		InstrumentAddress = data;
+    		UpdatePlaybackParameters();
+    	}
+
+    	public void WriteE(ref byte data)
+    	{
+    		volume = data & 0xF;
+    	}
+
+    	public void ClockSingle()
+    	{
+    		if (freez || --cycles > 0)
+    		{
+    			return;
+    		}
+    		cycles = freqTimer;
+    		if (readPoint >= startPoint && readPoint <= endPoint)
+    		{
+    			if (Enabled && !freez)
+    			{
+    				if ((readPoint & 1) == 0)
+    				{
+    					output_av += (namcot.EXRAM[readPoint] & 0xF) * volume;
+    				}
+    				else
+    				{
+    					output_av += ((namcot.EXRAM[readPoint] >> 4) & 0xF) * volume;
+    				}
+    			}
+    			readPoint++;
+    		}
+    		else
+    		{
+    			readPoint = startPoint;
+    		}
+    		clocks++;
+    	}
+
+    	public void SaveState(BinaryWriter stream)
+    	{
+    		stream.Write(freqTimer);
+    		stream.Write(frequency);
+    		stream.Write(output);
+    		stream.Write(cycles);
+    		stream.Write(InstrumentLength);
+    		stream.Write(InstrumentAddress);
+    		stream.Write(startPoint);
+    		stream.Write(endPoint);
+    		stream.Write(readPoint);
+    		stream.Write(volume);
+    		stream.Write(freez);
+    	}
+
+    	public void LoadState(BinaryReader stream)
+    	{
+    		freqTimer = stream.ReadInt32();
+    		frequency = stream.ReadInt32();
+    		output = stream.ReadByte();
+    		cycles = stream.ReadInt32();
+    		InstrumentLength = stream.ReadInt32();
+    		InstrumentAddress = stream.ReadByte();
+    		startPoint = stream.ReadInt32();
+    		endPoint = stream.ReadInt32();
+    		readPoint = stream.ReadInt32();
+    		volume = stream.ReadInt32();
+    		freez = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabase.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabase.cs
new file mode 100644
index 00000000..6794210e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabase.cs
@@ -0,0 +1,327 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+namespace MyNes.Core
+{
+    public class NesCartDatabase
+    {
+        private static List<NesCartDatabaseGameInfo> _databaseRoms = new List<NesCartDatabaseGameInfo>();
+
+        public static string DBVersion = "";
+
+        public static string DBConformance = "";
+
+        public static string DBAgent = "";
+
+        public static string DBAuthor = "";
+
+        public static string DBTimeStamp = "";
+
+        public static bool Ready = false;
+
+        public static List<NesCartDatabaseGameInfo> DatabaseRoms => _databaseRoms;
+
+        public static void LoadDatabase(out bool success)
+        {
+            success = false;
+            Ready = false;
+            _databaseRoms.Clear();
+
+            var stream = MyNesMain.Supporter.OpenDatabaseFile();
+            XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
+            xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;
+            xmlReaderSettings.IgnoreWhitespace = true;
+            XmlReader xmlReader = XmlReader.Create(stream, xmlReaderSettings);
+            NesCartDatabaseGameInfo nesCartDatabaseGameInfo = default(NesCartDatabaseGameInfo);
+            nesCartDatabaseGameInfo.Cartridges = new List<NesCartDatabaseCartridgeInfo>();
+            nesCartDatabaseGameInfo.Game_AltName = "";
+            nesCartDatabaseGameInfo.Game_Catalog = "";
+            nesCartDatabaseGameInfo.Game_Class = "";
+            nesCartDatabaseGameInfo.Game_Developer = "";
+            nesCartDatabaseGameInfo.Game_Name = "";
+            nesCartDatabaseGameInfo.Game_Players = "";
+            nesCartDatabaseGameInfo.Game_Publisher = "";
+            nesCartDatabaseGameInfo.Game_Region = "";
+            nesCartDatabaseGameInfo.Game_ReleaseDate = "";
+            while (xmlReader.Read())
+            {
+                if ((xmlReader.Name == "xml") & xmlReader.IsStartElement())
+                {
+                    if (xmlReader.MoveToAttribute("version"))
+                    {
+                        DBVersion = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("conformance"))
+                    {
+                        DBConformance = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("agent"))
+                    {
+                        DBAgent = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("author"))
+                    {
+                        DBAuthor = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("timestamp"))
+                    {
+                        DBTimeStamp = xmlReader.Value;
+                    }
+                }
+                else
+                {
+                    if (!((xmlReader.Name == "game") & xmlReader.IsStartElement()))
+                    {
+                        continue;
+                    }
+                    nesCartDatabaseGameInfo = default(NesCartDatabaseGameInfo);
+                    if (xmlReader.MoveToAttribute("name"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Name = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("altname"))
+                    {
+                        nesCartDatabaseGameInfo.Game_AltName = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("class"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Class = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("catalog"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Catalog = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("publisher"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Publisher = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("developer"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Developer = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("region"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Region = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("players"))
+                    {
+                        nesCartDatabaseGameInfo.Game_Players = xmlReader.Value;
+                    }
+                    if (xmlReader.MoveToAttribute("date"))
+                    {
+                        nesCartDatabaseGameInfo.Game_ReleaseDate = xmlReader.Value;
+                    }
+                    NesCartDatabaseCartridgeInfo nesCartDatabaseCartridgeInfo = new NesCartDatabaseCartridgeInfo();
+                    nesCartDatabaseCartridgeInfo.PAD_h = "";
+                    nesCartDatabaseCartridgeInfo.PAD_v = "";
+                    nesCartDatabaseCartridgeInfo.PRG_crc = "";
+                    nesCartDatabaseCartridgeInfo.PRG_name = "";
+                    nesCartDatabaseCartridgeInfo.PRG_sha1 = "";
+                    nesCartDatabaseCartridgeInfo.PRG_size = "";
+                    nesCartDatabaseCartridgeInfo.chip_type = new List<string>();
+                    nesCartDatabaseCartridgeInfo.CHR_crc = "";
+                    nesCartDatabaseCartridgeInfo.CHR_name = "";
+                    nesCartDatabaseCartridgeInfo.CHR_sha1 = "";
+                    nesCartDatabaseCartridgeInfo.CHR_size = "";
+                    nesCartDatabaseCartridgeInfo.CIC_type = "";
+                    nesCartDatabaseCartridgeInfo.Board_Mapper = "";
+                    nesCartDatabaseCartridgeInfo.Board_Pcb = "";
+                    nesCartDatabaseCartridgeInfo.Board_Type = "";
+                    nesCartDatabaseCartridgeInfo.VRAM_sizes = new List<string>();
+                    nesCartDatabaseCartridgeInfo.WRAMBanks = new List<SRAMBankInfo>();
+                    while (xmlReader.Read())
+                    {
+                        if ((xmlReader.Name == "game") & !xmlReader.IsStartElement())
+                        {
+                            _databaseRoms.Add(nesCartDatabaseGameInfo);
+                            break;
+                        }
+                        if ((xmlReader.Name == "cartridge") & xmlReader.IsStartElement())
+                        {
+                            if (nesCartDatabaseGameInfo.Cartridges == null)
+                            {
+                                nesCartDatabaseGameInfo.Cartridges = new List<NesCartDatabaseCartridgeInfo>();
+                            }
+                            nesCartDatabaseCartridgeInfo = new NesCartDatabaseCartridgeInfo();
+                            nesCartDatabaseCartridgeInfo.PAD_h = "";
+                            nesCartDatabaseCartridgeInfo.PAD_v = "";
+                            nesCartDatabaseCartridgeInfo.PRG_crc = "";
+                            nesCartDatabaseCartridgeInfo.PRG_name = "";
+                            nesCartDatabaseCartridgeInfo.PRG_sha1 = "";
+                            nesCartDatabaseCartridgeInfo.PRG_size = "";
+                            nesCartDatabaseCartridgeInfo.chip_type = new List<string>();
+                            nesCartDatabaseCartridgeInfo.CHR_crc = "";
+                            nesCartDatabaseCartridgeInfo.CHR_name = "";
+                            nesCartDatabaseCartridgeInfo.CHR_sha1 = "";
+                            nesCartDatabaseCartridgeInfo.CHR_size = "";
+                            nesCartDatabaseCartridgeInfo.CIC_type = "";
+                            nesCartDatabaseCartridgeInfo.Board_Mapper = "";
+                            nesCartDatabaseCartridgeInfo.Board_Pcb = "";
+                            nesCartDatabaseCartridgeInfo.Board_Type = "";
+                            nesCartDatabaseCartridgeInfo.VRAM_sizes = new List<string>();
+                            nesCartDatabaseCartridgeInfo.WRAMBanks = new List<SRAMBankInfo>();
+                            if (xmlReader.MoveToAttribute("system"))
+                            {
+                                nesCartDatabaseCartridgeInfo.System = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("crc"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CRC = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("sha1"))
+                            {
+                                nesCartDatabaseCartridgeInfo.SHA1 = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("dump"))
+                            {
+                                nesCartDatabaseCartridgeInfo.Dump = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("dumper"))
+                            {
+                                nesCartDatabaseCartridgeInfo.Dumper = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("datedumped"))
+                            {
+                                nesCartDatabaseCartridgeInfo.DateDumped = xmlReader.Value;
+                            }
+                        }
+                        else if ((xmlReader.Name == "cartridge") & !xmlReader.IsStartElement())
+                        {
+                            nesCartDatabaseGameInfo.Cartridges.Add(nesCartDatabaseCartridgeInfo);
+                        }
+                        else if ((xmlReader.Name == "board") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("type"))
+                            {
+                                nesCartDatabaseCartridgeInfo.Board_Type = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("pcb"))
+                            {
+                                nesCartDatabaseCartridgeInfo.Board_Pcb = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("mapper"))
+                            {
+                                nesCartDatabaseCartridgeInfo.Board_Mapper = xmlReader.Value;
+                            }
+                        }
+                        else if ((xmlReader.Name == "prg") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("name"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PRG_name = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("size"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PRG_size = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("crc"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PRG_crc = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("sha1"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PRG_sha1 = xmlReader.Value;
+                            }
+                        }
+                        else if ((xmlReader.Name == "chr") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("name"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CHR_name = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("size"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CHR_size = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("crc"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CHR_crc = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("sha1"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CHR_sha1 = xmlReader.Value;
+                            }
+                        }
+                        else if ((xmlReader.Name == "vram") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("size"))
+                            {
+                                nesCartDatabaseCartridgeInfo.VRAM_sizes.Add(xmlReader.Value);
+                            }
+                        }
+                        else if ((xmlReader.Name == "wram") & xmlReader.IsStartElement())
+                        {
+                            string sIZE = "";
+                            bool bATTERY = false;
+                            int result = 0;
+                            if (xmlReader.MoveToAttribute("size"))
+                            {
+                                sIZE = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("battery"))
+                            {
+                                bATTERY = xmlReader.Value == "1";
+                            }
+                            if (xmlReader.MoveToAttribute("id"))
+                            {
+                                int.TryParse(xmlReader.Value, out result);
+                            }
+                            nesCartDatabaseCartridgeInfo.WRAMBanks.Add(new SRAMBankInfo(result, sIZE, bATTERY));
+                        }
+                        else if ((xmlReader.Name == "chip") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("type"))
+                            {
+                                if (nesCartDatabaseCartridgeInfo.chip_type == null)
+                                {
+                                    nesCartDatabaseCartridgeInfo.chip_type = new List<string>();
+                                }
+                                nesCartDatabaseCartridgeInfo.chip_type.Add(xmlReader.Value);
+                            }
+                        }
+                        else if ((xmlReader.Name == "cic") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("type"))
+                            {
+                                nesCartDatabaseCartridgeInfo.CIC_type = xmlReader.Value;
+                            }
+                        }
+                        else if ((xmlReader.Name == "pad") & xmlReader.IsStartElement())
+                        {
+                            if (xmlReader.MoveToAttribute("h"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PAD_h = xmlReader.Value;
+                            }
+                            if (xmlReader.MoveToAttribute("v"))
+                            {
+                                nesCartDatabaseCartridgeInfo.PAD_v = xmlReader.Value;
+                            }
+                        }
+                    }
+                }
+            }
+            Ready = true;
+            success = true;
+            xmlReader.Close();
+            stream.Close();
+        }
+
+        public static NesCartDatabaseGameInfo Find(string Cart_sha1, out bool found)
+        {
+            found = false;
+            foreach (NesCartDatabaseGameInfo databaseRom in _databaseRoms)
+            {
+                foreach (NesCartDatabaseCartridgeInfo cartridge in databaseRom.Cartridges)
+                {
+                    if (cartridge.SHA1.ToLower() == Cart_sha1.ToLower())
+                    {
+                        found = true;
+                        return databaseRom;
+                    }
+                }
+            }
+            return default(NesCartDatabaseGameInfo);
+        }
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseCartridgeInfo.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseCartridgeInfo.cs
new file mode 100644
index 00000000..39d347cd
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseCartridgeInfo.cs
@@ -0,0 +1,53 @@
+using System.Collections.Generic;
+
+namespace MyNes.Core
+{
+    public class NesCartDatabaseCartridgeInfo
+    {
+    	public string System;
+
+    	public string CRC;
+
+    	public string SHA1;
+
+    	public string Dump;
+
+    	public string Dumper;
+
+    	public string DateDumped;
+
+    	public string Board_Type;
+
+    	public string Board_Pcb;
+
+    	public string Board_Mapper;
+
+    	public List<string> VRAM_sizes;
+
+    	public List<SRAMBankInfo> WRAMBanks;
+
+    	public string PRG_name;
+
+    	public string PRG_size;
+
+    	public string PRG_crc;
+
+    	public string PRG_sha1;
+
+    	public string CHR_name;
+
+    	public string CHR_size;
+
+    	public string CHR_crc;
+
+    	public string CHR_sha1;
+
+    	public List<string> chip_type;
+
+    	public string CIC_type;
+
+    	public string PAD_h;
+
+    	public string PAD_v;
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseGameInfo.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseGameInfo.cs
new file mode 100644
index 00000000..72ff1bb0
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NesCartDatabaseGameInfo.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+
+namespace MyNes.Core
+{
+    public struct NesCartDatabaseGameInfo
+    {
+    	public string Game_Name;
+
+    	public string Game_AltName;
+
+    	public string Game_Class;
+
+    	public string Game_Catalog;
+
+    	public string Game_Publisher;
+
+    	public string Game_Developer;
+
+    	public string Game_Region;
+
+    	public string Game_Players;
+
+    	public string Game_ReleaseDate;
+
+    	public List<NesCartDatabaseCartridgeInfo> Cartridges;
+
+    	public static NesCartDatabaseGameInfo Empty => default(NesCartDatabaseGameInfo);
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/NesEmu.cs b/OtherCore/MyNes.Standard2/MyNes.Core/NesEmu.cs
new file mode 100644
index 00000000..171b148e
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/NesEmu.cs
@@ -0,0 +1,5740 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Xml;
+
+namespace MyNes.Core
+{
+    public class NesEmu
+    {
+        [StructLayout(LayoutKind.Explicit)]
+        private struct CPURegister
+        {
+            [FieldOffset(0)]
+            internal byte l;
+
+            [FieldOffset(1)]
+            internal byte h;
+
+            [FieldOffset(0)]
+            internal ushort v;
+        }
+
+        private enum RequestMode
+        {
+            None,
+            HardReset,
+            SoftReset,
+            LoadState,
+            SaveState,
+            TakeSnapshot
+        }
+
+        private static int[][] dmc_freq_table = new int[3][]
+        {
+            new int[16]
+            {
+                428, 380, 340, 320, 286, 254, 226, 214, 190, 160,
+                142, 128, 106, 84, 72, 54
+            },
+            new int[16]
+            {
+                398, 354, 316, 298, 276, 236, 210, 198, 176, 148,
+                132, 118, 98, 78, 66, 50
+            },
+            new int[16]
+            {
+                428, 380, 340, 320, 286, 254, 226, 214, 190, 160,
+                142, 128, 106, 84, 72, 54
+            }
+        };
+
+        private static int dmc_output_a;
+
+        private static int dmc_output;
+
+        private static int dmc_period_devider;
+
+        private static bool dmc_irq_enabled;
+
+        private static bool dmc_loop_flag;
+
+        private static byte dmc_rate_index;
+
+        private static ushort dmc_addr_refresh;
+
+        private static int dmc_size_refresh;
+
+        private static bool dmc_dmaEnabled;
+
+        private static byte dmc_dmaByte;
+
+        private static int dmc_dmaBits;
+
+        private static bool dmc_bufferFull;
+
+        private static byte dmc_dmaBuffer;
+
+        private static int dmc_dmaSize;
+
+        private static ushort dmc_dmaAddr;
+
+        private static ushort[][] nos_freq_table = new ushort[3][]
+        {
+            new ushort[16]
+            {
+                4, 8, 16, 32, 64, 96, 128, 160, 202, 254,
+                380, 508, 762, 1016, 2034, 4068
+            },
+            new ushort[16]
+            {
+                4, 7, 14, 30, 60, 88, 118, 148, 188, 236,
+                354, 472, 708, 944, 1890, 3778
+            },
+            new ushort[16]
+            {
+                4, 8, 16, 32, 64, 96, 128, 160, 202, 254,
+                380, 508, 762, 1016, 2034, 4068
+            }
+        };
+
+        private static bool nos_length_halt;
+
+        private static bool nos_constant_volume_envelope;
+
+        private static byte nos_volume_devider_period;
+
+        private static ushort nos_timer;
+
+        private static bool nos_mode;
+
+        private static int nos_period_devider;
+
+        private static bool nos_length_enabled;
+
+        private static int nos_length_counter;
+
+        private static bool nos_envelope_start_flag;
+
+        private static byte nos_envelope_devider;
+
+        private static byte nos_envelope_decay_level_counter;
+
+        private static byte nos_envelope;
+
+        private static int nos_output;
+
+        private static int nos_shift_reg;
+
+        private static int nos_feedback;
+
+        private static bool nos_ignore_reload;
+
+        private static readonly byte[][] sq_duty_cycle_sequences = new byte[4][]
+        {
+            new byte[8] { 0, 0, 0, 0, 0, 0, 0, 1 },
+            new byte[8] { 0, 0, 0, 0, 0, 0, 1, 1 },
+            new byte[8] { 0, 0, 0, 0, 1, 1, 1, 1 },
+            new byte[8] { 1, 1, 1, 1, 1, 1, 0, 0 }
+        };
+
+        private static readonly byte[] sq_duration_table = new byte[32]
+        {
+            10, 254, 20, 2, 40, 4, 80, 6, 160, 8,
+            60, 10, 14, 12, 26, 14, 12, 16, 24, 18,
+            48, 20, 96, 22, 192, 24, 72, 26, 16, 28,
+            32, 30
+        };
+
+        private static byte sq1_duty_cycle;
+
+        private static bool sq1_length_halt;
+
+        private static bool sq1_constant_volume_envelope;
+
+        private static byte sq1_volume_devider_period;
+
+        private static bool sq1_sweep_enable;
+
+        private static byte sq1_sweep_devider_period;
+
+        private static bool sq1_sweep_negate;
+
+        private static byte sq1_sweep_shift_count;
+
+        private static int sq1_timer;
+
+        private static int sq1_period_devider;
+
+        private static byte sq1_seqencer;
+
+        private static bool sq1_length_enabled;
+
+        private static int sq1_length_counter;
+
+        private static bool sq1_envelope_start_flag;
+
+        private static byte sq1_envelope_devider;
+
+        private static byte sq1_envelope_decay_level_counter;
+
+        private static byte sq1_envelope;
+
+        private static int sq1_sweep_counter;
+
+        private static bool sq1_sweep_reload;
+
+        private static int sq1_sweep_change;
+
+        private static bool sq1_valid_freq;
+
+        private static int sq1_output;
+
+        private static bool sq1_ignore_reload;
+
+        private static readonly byte[] trl_step_seq = new byte[32]
+        {
+            15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+            5, 4, 3, 2, 1, 0, 0, 1, 2, 3,
+            4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+            14, 15
+        };
+
+        private static bool trl_liner_control_flag;
+
+        private static byte trl_liner_control_reload;
+
+        private static ushort trl_timer;
+
+        private static bool trl_length_enabled;
+
+        private static byte trl_length_counter;
+
+        private static bool trl_liner_control_reload_flag;
+
+        private static byte trl_liner_counter;
+
+        private static int trl_output;
+
+        private static int trl_period_devider;
+
+        private static int trl_step;
+
+        private static bool trl_ignore_reload;
+
+        private static byte apu_reg_io_db;
+
+        private static byte apu_reg_io_addr;
+
+        private static bool apu_reg_access_happened;
+
+        private static bool apu_reg_access_w;
+
+        private static Action[] apu_reg_update_func;
+
+        private static Action[] apu_reg_read_func;
+
+        private static Action[] apu_reg_write_func;
+
+        private static Action apu_update_playback_func;
+
+        private static bool apu_odd_cycle;
+
+        private static bool apu_irq_enabled;
+
+        private static bool apu_irq_flag;
+
+        internal static bool apu_irq_delta_occur;
+
+        private static bool apu_seq_mode;
+
+        private static int apu_ferq_f;
+
+        private static int apu_ferq_l;
+
+        private static int apu_ferq_e;
+
+        private static int apu_cycle_f;
+
+        private static int apu_cycle_f_t;
+
+        private static int apu_cycle_e;
+
+        private static int apu_cycle_l;
+
+        private static bool apu_odd_l;
+
+        private static bool apu_check_irq;
+
+        private static bool apu_do_env;
+
+        private static bool apu_do_length;
+
+        public static bool SoundEnabled;
+
+        public static double audio_playback_amplitude = 1.5;
+
+        public static int audio_playback_peek_limit = 124;
+
+        private static bool audio_playback_dac_initialized;
+
+        public static int cpu_speed;
+
+        private static short[] audio_samples;
+
+        private static int audio_w_pos;
+
+        private static int audio_samples_added;
+
+        internal static int audio_samples_count;
+
+        private static int[][][][][] mix_table;
+
+        private static double audio_x;
+
+        private static double audio_y;
+
+        private static double audio_y_av;
+
+        private static double audio_y_timer;
+
+        public static double audio_timer_ratio = 40.0;
+
+        private static double audio_timer;
+
+        private static SoundLowPassFilter audio_low_pass_filter_14K;
+
+        private static SoundHighPassFilter audio_high_pass_filter_90;
+
+        private static SoundHighPassFilter audio_high_pass_filter_440;
+
+        private static bool audio_sq1_outputable;
+
+        private static bool audio_sq2_outputable;
+
+        private static bool audio_nos_outputable;
+
+        private static bool audio_trl_outputable;
+
+        private static bool audio_dmc_outputable;
+
+        private static bool audio_signal_outputed;
+
+        private static bool apu_use_external_sound;
+
+        private static CPURegister cpu_reg_pc;
+
+        private static CPURegister cpu_reg_sp;
+
+        private static CPURegister cpu_reg_ea;
+
+        private static byte cpu_reg_a;
+
+        private static byte cpu_reg_x;
+
+        private static byte cpu_reg_y;
+
+        private static bool cpu_flag_n;
+
+        private static bool cpu_flag_v;
+
+        private static bool cpu_flag_d;
+
+        private static bool cpu_flag_i;
+
+        private static bool cpu_flag_z;
+
+        private static bool cpu_flag_c;
+
+        private static byte cpu_m;
+
+        private static byte cpu_opcode;
+
+        private static byte cpu_byte_temp;
+
+        private static int cpu_int_temp;
+
+        private static int cpu_int_temp1;
+
+        private static byte cpu_dummy;
+
+        private static bool cpu_bool_tmp;
+
+        private static CPURegister temp_add;
+
+        private static bool CPU_IRQ_PIN;
+
+        private static bool CPU_NMI_PIN;
+
+        private static bool cpu_suspend_nmi;
+
+        private static bool cpu_suspend_irq;
+
+        private static Action[] cpu_addressings;
+
+        private static Action[] cpu_instructions;
+
+        private static int dma_DMCDMAWaitCycles;
+
+        private static int dma_OAMDMAWaitCycles;
+
+        private static bool dma_isOamDma;
+
+        private static int dma_oamdma_i;
+
+        private static bool dma_DMCOn;
+
+        private static bool dma_OAMOn;
+
+        private static bool dma_DMC_occurring;
+
+        private static bool dma_OAM_occurring;
+
+        private static int dma_OAMFinishCounter;
+
+        private static ushort dma_Oamaddress;
+
+        private static int dma_OAMCYCLE;
+
+        private static byte dma_latch;
+
+        private static byte dma_dummy;
+
+        private static ushort reg_2004;
+
+        internal static int IRQFlags = 0;
+
+        private static bool PPU_NMI_Current;
+
+        private static bool PPU_NMI_Old;
+
+        private const int IRQ_APU = 1;
+
+        internal const int IRQ_DMC = 2;
+
+        internal const int IRQ_BOARD = 8;
+
+        private static ushort InterruptVector;
+
+        private static byte[] mem_wram;
+
+        internal static Board mem_board;
+
+        private static MemReadAccess[] mem_read_accesses;
+
+        private static MemWriteAccess[] mem_write_accesses;
+
+        private static bool BUS_RW;
+
+        private static ushort BUS_ADDRESS;
+
+        private static string SRAMFileName;
+
+        public static string GMFileName;
+
+        private static int PORT0;
+
+        private static int PORT1;
+
+        private static int inputStrobe;
+
+        private static IJoypadConnecter joypad1;
+
+        private static IJoypadConnecter joypad2;
+
+        private static IJoypadConnecter joypad3;
+
+        private static IJoypadConnecter joypad4;
+
+        public static bool IsFourPlayers;
+
+        private static readonly byte[] reverseLookup = new byte[256]
+        {
+            0, 128, 64, 192, 32, 160, 96, 224, 16, 144,
+            80, 208, 48, 176, 112, 240, 8, 136, 72, 200,
+            40, 168, 104, 232, 24, 152, 88, 216, 56, 184,
+            120, 248, 4, 132, 68, 196, 36, 164, 100, 228,
+            20, 148, 84, 212, 52, 180, 116, 244, 12, 140,
+            76, 204, 44, 172, 108, 236, 28, 156, 92, 220,
+            60, 188, 124, 252, 2, 130, 66, 194, 34, 162,
+            98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+            10, 138, 74, 202, 42, 170, 106, 234, 26, 154,
+            90, 218, 58, 186, 122, 250, 6, 134, 70, 198,
+            38, 166, 102, 230, 22, 150, 86, 214, 54, 182,
+            118, 246, 14, 142, 78, 206, 46, 174, 110, 238,
+            30, 158, 94, 222, 62, 190, 126, 254, 1, 129,
+            65, 193, 33, 161, 97, 225, 17, 145, 81, 209,
+            49, 177, 113, 241, 9, 137, 73, 201, 41, 169,
+            105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+            5, 133, 69, 197, 37, 165, 101, 229, 21, 149,
+            85, 213, 53, 181, 117, 245, 13, 141, 77, 205,
+            45, 173, 109, 237, 29, 157, 93, 221, 61, 189,
+            125, 253, 3, 131, 67, 195, 35, 163, 99, 227,
+            19, 147, 83, 211, 51, 179, 115, 243, 11, 139,
+            75, 203, 43, 171, 107, 235, 27, 155, 91, 219,
+            59, 187, 123, 251, 7, 135, 71, 199, 39, 167,
+            103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+            15, 143, 79, 207, 47, 175, 111, 239, 31, 159,
+            95, 223, 63, 191, 127, 255
+        };
+
+        private static Action[] ppu_v_clocks;
+
+        private static Action[] ppu_h_clocks;
+
+        private static Action[] ppu_bkg_fetches;
+
+        private static Action[] ppu_spr_fetches;
+
+        private static Action[] ppu_oam_phases;
+
+        private static int[] ppu_bkg_pixels;
+
+        private static int[] ppu_spr_pixels;
+
+        private static int[] ppu_screen_pixels;
+
+        private static int[] ppu_palette;
+
+        private static int ppu_clock_h;
+
+        internal static ushort ppu_clock_v;
+
+        private static ushort ppu_clock_vblank_start;
+
+        private static ushort ppu_clock_vblank_end;
+
+        private static bool ppu_use_odd_cycle;
+
+        private static bool ppu_use_odd_swap;
+
+        private static bool ppu_odd_swap_done;
+
+        private static bool ppu_is_nmi_time;
+
+        private static bool ppu_frame_finished;
+
+        private static byte[] ppu_oam_bank;
+
+        private static byte[] ppu_oam_bank_secondary;
+
+        private static byte[] ppu_palette_bank;
+
+        private static byte ppu_reg_io_db;
+
+        private static byte ppu_reg_io_addr;
+
+        private static bool ppu_reg_access_happened;
+
+        private static bool ppu_reg_access_w;
+
+        private static Action[] ppu_reg_update_func;
+
+        private static Action[] ppu_reg_read_func;
+
+        private static byte ppu_reg_2000_vram_address_increament;
+
+        private static ushort ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites;
+
+        private static ushort ppu_reg_2000_background_pattern_table_address;
+
+        internal static byte ppu_reg_2000_Sprite_size;
+
+        private static bool ppu_reg_2000_VBI;
+
+        private static bool ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen;
+
+        private static bool ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen;
+
+        private static bool ppu_reg_2001_show_background;
+
+        private static bool ppu_reg_2001_show_sprites;
+
+        private static int ppu_reg_2001_grayscale;
+
+        private static int ppu_reg_2001_emphasis;
+
+        private static bool ppu_reg_2002_SpriteOverflow;
+
+        private static bool ppu_reg_2002_Sprite0Hit;
+
+        private static bool ppu_reg_2002_VblankStartedFlag;
+
+        private static byte ppu_reg_2003_oam_addr;
+
+        private static ushort ppu_vram_addr;
+
+        private static byte ppu_vram_data;
+
+        private static ushort ppu_vram_addr_temp;
+
+        private static ushort ppu_vram_addr_access_temp;
+
+        private static bool ppu_vram_flip_flop;
+
+        private static byte ppu_vram_finex;
+
+        private static ushort ppu_bkgfetch_nt_addr;
+
+        private static byte ppu_bkgfetch_nt_data;
+
+        private static ushort ppu_bkgfetch_at_addr;
+
+        private static byte ppu_bkgfetch_at_data;
+
+        private static ushort ppu_bkgfetch_lb_addr;
+
+        private static byte ppu_bkgfetch_lb_data;
+
+        private static ushort ppu_bkgfetch_hb_addr;
+
+        private static byte ppu_bkgfetch_hb_data;
+
+        private static int ppu_sprfetch_slot;
+
+        private static byte ppu_sprfetch_y_data;
+
+        private static byte ppu_sprfetch_t_data;
+
+        private static byte ppu_sprfetch_at_data;
+
+        private static byte ppu_sprfetch_x_data;
+
+        private static ushort ppu_sprfetch_lb_addr;
+
+        private static byte ppu_sprfetch_lb_data;
+
+        private static ushort ppu_sprfetch_hb_addr;
+
+        private static byte ppu_sprfetch_hb_data;
+
+        internal static bool ppu_is_sprfetch;
+
+        private static int ppu_bkg_render_i;
+
+        private static int ppu_bkg_render_pos;
+
+        private static int ppu_bkg_render_tmp_val;
+
+        private static int ppu_bkg_current_pixel;
+
+        private static int ppu_spr_current_pixel;
+
+        private static int ppu_current_pixel;
+
+        private static int ppu_render_x;
+
+        private static int ppu_render_y;
+
+        private static byte ppu_oamev_n;
+
+        private static byte ppu_oamev_m;
+
+        private static bool ppu_oamev_compare;
+
+        private static byte ppu_oamev_slot;
+
+        private static byte ppu_fetch_data;
+
+        private static byte ppu_phase_index;
+
+        private static bool ppu_sprite0_should_hit;
+
+        private static int ppu_temp_comparator;
+
+        public static bool ON;
+
+        public static bool PAUSED;
+
+        public static bool isPaused;
+
+        public static string CurrentFilePath;
+
+        public static bool FrameLimiterEnabled;
+
+        private static Thread mainThread;
+
+        private static double fps_time_period;
+
+        private static double emu_time_target_fps = 60.0;
+
+        private static bool render_initialized;
+
+        private static RenderVideoFrame render_video;
+
+        private static RenderAudioSamples render_audio;
+
+        private static TogglePause render_audio_toggle_pause;
+
+        private static GetIsPlaying render_audio_get_is_playing;
+
+        private static bool render_audio_is_playing;
+
+        public static EmuRegion Region;
+
+        private static int SystemIndex;
+
+        private static RequestMode emu_request_mode = RequestMode.None;
+
+        public static bool FrameSkipEnabled;
+
+        public static int FrameSkipInterval;
+
+        private static int FrameSkipCounter;
+
+        private static byte sq2_duty_cycle;
+
+        private static bool sq2_length_halt;
+
+        private static bool sq2_constant_volume_envelope;
+
+        private static byte sq2_volume_devider_period;
+
+        private static bool sq2_sweep_enable;
+
+        private static byte sq2_sweep_devider_period;
+
+        private static bool sq2_sweep_negate;
+
+        private static byte sq2_sweep_shift_count;
+
+        private static int sq2_timer;
+
+        private static int sq2_period_devider;
+
+        private static byte sq2_seqencer;
+
+        private static bool sq2_length_enabled;
+
+        private static int sq2_length_counter;
+
+        private static bool sq2_envelope_start_flag;
+
+        private static byte sq2_envelope_devider;
+
+        private static byte sq2_envelope_decay_level_counter;
+
+        private static byte sq2_envelope;
+
+        private static int sq2_sweep_counter;
+
+        private static bool sq2_sweep_reload;
+
+        private static int sq2_sweep_change;
+
+        private static bool sq2_valid_freq;
+
+        private static int sq2_output;
+
+        private static bool sq2_ignore_reload;
+
+        private static byte register_p
+        {
+            get
+            {
+                return (byte)((cpu_flag_n ? 128u : 0u) | (cpu_flag_v ? 64u : 0u) | (cpu_flag_d ? 8u : 0u) | (cpu_flag_i ? 4u : 0u) | (cpu_flag_z ? 2u : 0u) | (cpu_flag_c ? 1u : 0u) | 0x20u);
+            }
+            set
+            {
+                cpu_flag_n = (value & 0x80) != 0;
+                cpu_flag_v = (value & 0x40) != 0;
+                cpu_flag_d = (value & 8) != 0;
+                cpu_flag_i = (value & 4) != 0;
+                cpu_flag_z = (value & 2) != 0;
+                cpu_flag_c = (value & 1) != 0;
+            }
+        }
+
+        public static GameGenieCode[] GameGenieCodes
+        {
+            get
+            {
+                if (mem_board != null)
+                {
+                    return mem_board.GameGenieCodes;
+                }
+                return null;
+            }
+        }
+
+        public static bool IsGameGenieActive
+        {
+            get
+            {
+                if (mem_board != null)
+                {
+                    return mem_board.IsGameGenieActive;
+                }
+                return false;
+            }
+            set
+            {
+                if (mem_board != null)
+                {
+                    mem_board.IsGameGenieActive = value;
+                }
+            }
+        }
+
+        public static bool IsGameFoundOnDB
+        {
+            get
+            {
+                if (mem_board != null)
+                {
+                    return mem_board.IsGameFoundOnDB;
+                }
+                return false;
+            }
+        }
+
+        public static NesCartDatabaseGameInfo GameInfo
+        {
+            get
+            {
+                if (mem_board != null)
+                {
+                    return mem_board.GameInfo;
+                }
+                return NesCartDatabaseGameInfo.Empty;
+            }
+        }
+
+        public static NesCartDatabaseCartridgeInfo GameCartInfo
+        {
+            get
+            {
+                if (mem_board != null)
+                {
+                    return mem_board.GameCartInfo;
+                }
+                return new NesCartDatabaseCartridgeInfo();
+            }
+        }
+
+        public static string SHA1 => mem_board.SHA1;
+
+        public static event EventHandler EmuShutdown;
+
+        private static void DMCHardReset()
+        {
+            dmc_output_a = 0;
+            dmc_output = 0;
+            dmc_period_devider = 0;
+            dmc_loop_flag = false;
+            dmc_rate_index = 0;
+            dmc_irq_enabled = false;
+            dmc_dmaAddr = 49152;
+            dmc_addr_refresh = 49152;
+            dmc_size_refresh = 0;
+            dmc_dmaBits = 1;
+            dmc_dmaByte = 1;
+            dmc_period_devider = 0;
+            dmc_dmaEnabled = false;
+            dmc_bufferFull = false;
+            dmc_dmaSize = 0;
+        }
+
+        private static void DMCSoftReset()
+        {
+            DMCHardReset();
+        }
+
+        private static void DMCClock()
+        {
+            dmc_period_devider--;
+            if (dmc_period_devider > 0)
+            {
+                return;
+            }
+            dmc_period_devider = dmc_freq_table[SystemIndex][dmc_rate_index];
+            if (dmc_dmaEnabled)
+            {
+                if (((uint)dmc_dmaByte & (true ? 1u : 0u)) != 0)
+                {
+                    if (dmc_output_a <= 125)
+                    {
+                        dmc_output_a += 2;
+                    }
+                }
+                else if (dmc_output_a >= 2)
+                {
+                    dmc_output_a -= 2;
+                }
+                dmc_dmaByte >>= 1;
+            }
+            dmc_dmaBits--;
+            if (dmc_dmaBits == 0)
+            {
+                dmc_dmaBits = 8;
+                if (dmc_bufferFull)
+                {
+                    dmc_bufferFull = false;
+                    dmc_dmaEnabled = true;
+                    dmc_dmaByte = dmc_dmaBuffer;
+                    if (dmc_dmaSize > 0)
+                    {
+                        AssertDMCDMA();
+                    }
+                }
+                else
+                {
+                    dmc_dmaEnabled = false;
+                }
+            }
+            if (audio_dmc_outputable)
+            {
+                dmc_output = dmc_output_a;
+            }
+            audio_signal_outputed = true;
+        }
+
+        private static void DMCDoDMA()
+        {
+            dmc_bufferFull = true;
+            Read(ref dmc_dmaAddr, out dmc_dmaBuffer);
+            if (dmc_dmaAddr == ushort.MaxValue)
+            {
+                dmc_dmaAddr = 32768;
+            }
+            else
+            {
+                dmc_dmaAddr++;
+            }
+            if (dmc_dmaSize > 0)
+            {
+                dmc_dmaSize--;
+            }
+            if (dmc_dmaSize == 0)
+            {
+                if (dmc_loop_flag)
+                {
+                    dmc_dmaSize = dmc_size_refresh;
+                    dmc_dmaAddr = dmc_addr_refresh;
+                }
+                else if (dmc_irq_enabled)
+                {
+                    IRQFlags |= 2;
+                    apu_irq_delta_occur = true;
+                }
+            }
+        }
+
+        private static void APUOnRegister4010()
+        {
+            if (apu_reg_access_w)
+            {
+                dmc_irq_enabled = (apu_reg_io_db & 0x80) != 0;
+                dmc_loop_flag = (apu_reg_io_db & 0x40) != 0;
+                if (!dmc_irq_enabled)
+                {
+                    apu_irq_delta_occur = false;
+                    IRQFlags &= -3;
+                }
+                dmc_rate_index = (byte)(apu_reg_io_db & 0xFu);
+            }
+        }
+
+        private static void APUOnRegister4011()
+        {
+            if (apu_reg_access_w)
+            {
+                dmc_output_a = (byte)(apu_reg_io_db & 0x7F);
+            }
+        }
+
+        private static void APUOnRegister4012()
+        {
+            if (apu_reg_access_w)
+            {
+                dmc_addr_refresh = (ushort)((uint)(apu_reg_io_db << 6) | 0xC000u);
+            }
+        }
+
+        private static void APUOnRegister4013()
+        {
+            if (apu_reg_access_w)
+            {
+                dmc_size_refresh = (apu_reg_io_db << 4) | 1;
+            }
+        }
+
+        private static void DMCOn4015()
+        {
+            apu_irq_delta_occur = false;
+            IRQFlags &= -3;
+        }
+
+        private static void DMCRead4015()
+        {
+            if (dmc_dmaSize > 0)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xEFu) | 0x10u);
+            }
+        }
+
+        private static void DMCWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(dmc_output_a);
+            bin.Write(dmc_output);
+            bin.Write(dmc_period_devider);
+            bin.Write(dmc_irq_enabled);
+            bin.Write(dmc_loop_flag);
+            bin.Write(dmc_rate_index);
+            bin.Write(dmc_addr_refresh);
+            bin.Write(dmc_size_refresh);
+            bin.Write(dmc_dmaEnabled);
+            bin.Write(dmc_dmaByte);
+            bin.Write(dmc_dmaBits);
+            bin.Write(dmc_bufferFull);
+            bin.Write(dmc_dmaBuffer);
+            bin.Write(dmc_dmaSize);
+            bin.Write(dmc_dmaAddr);
+        }
+
+        private static void DMCReadState(ref BinaryReader bin)
+        {
+            dmc_output_a = bin.ReadInt32();
+            dmc_output = bin.ReadInt32();
+            dmc_period_devider = bin.ReadInt32();
+            dmc_irq_enabled = bin.ReadBoolean();
+            dmc_loop_flag = bin.ReadBoolean();
+            dmc_rate_index = bin.ReadByte();
+            dmc_addr_refresh = bin.ReadUInt16();
+            dmc_size_refresh = bin.ReadInt32();
+            dmc_dmaEnabled = bin.ReadBoolean();
+            dmc_dmaByte = bin.ReadByte();
+            dmc_dmaBits = bin.ReadInt32();
+            dmc_bufferFull = bin.ReadBoolean();
+            dmc_dmaBuffer = bin.ReadByte();
+            dmc_dmaSize = bin.ReadInt32();
+            dmc_dmaAddr = bin.ReadUInt16();
+        }
+
+        private static void NOSHardReset()
+        {
+            nos_length_halt = false;
+            nos_constant_volume_envelope = false;
+            nos_volume_devider_period = 0;
+            nos_shift_reg = 1;
+            nos_timer = 0;
+            nos_mode = false;
+            nos_period_devider = 0;
+            nos_length_enabled = false;
+            nos_length_counter = 0;
+            nos_envelope_start_flag = false;
+            nos_envelope_devider = 0;
+            nos_envelope_decay_level_counter = 0;
+            nos_envelope = 0;
+            nos_output = 0;
+            nos_feedback = 0;
+            nos_ignore_reload = false;
+        }
+
+        private static void NOSSoftReset()
+        {
+            NOSHardReset();
+        }
+
+        private static void NOSClock()
+        {
+            nos_period_devider--;
+            if (nos_period_devider > 0)
+            {
+                return;
+            }
+            nos_period_devider = nos_timer;
+            if (nos_mode)
+            {
+                nos_feedback = ((nos_shift_reg >> 6) & 1) ^ (nos_shift_reg & 1);
+            }
+            else
+            {
+                nos_feedback = ((nos_shift_reg >> 1) & 1) ^ (nos_shift_reg & 1);
+            }
+            nos_shift_reg >>= 1;
+            nos_shift_reg = (nos_shift_reg & 0x3FFF) | ((nos_feedback & 1) << 14);
+            if (nos_length_counter > 0 && (nos_shift_reg & 1) == 0)
+            {
+                if (audio_nos_outputable)
+                {
+                    nos_output = nos_envelope;
+                }
+            }
+            else
+            {
+                nos_output = 0;
+            }
+            audio_signal_outputed = true;
+        }
+
+        private static void NOSClockLength()
+        {
+            if (nos_length_counter > 0 && !nos_length_halt)
+            {
+                nos_length_counter--;
+                if (apu_reg_access_happened && apu_reg_io_addr == 15 && apu_reg_access_w)
+                {
+                    nos_ignore_reload = true;
+                }
+            }
+        }
+
+        private static void NOSClockEnvelope()
+        {
+            if (nos_envelope_start_flag)
+            {
+                nos_envelope_start_flag = false;
+                nos_envelope_decay_level_counter = 15;
+                nos_envelope_devider = (byte)(nos_volume_devider_period + 1);
+            }
+            else if (nos_envelope_devider > 0)
+            {
+                nos_envelope_devider--;
+            }
+            else
+            {
+                nos_envelope_devider = (byte)(nos_volume_devider_period + 1);
+                if (nos_envelope_decay_level_counter > 0)
+                {
+                    nos_envelope_decay_level_counter--;
+                }
+                else if (nos_length_halt)
+                {
+                    nos_envelope_decay_level_counter = 15;
+                }
+            }
+            nos_envelope = (nos_constant_volume_envelope ? nos_volume_devider_period : nos_envelope_decay_level_counter);
+        }
+
+        private static void APUOnRegister400C()
+        {
+            if (apu_reg_access_w)
+            {
+                nos_volume_devider_period = (byte)(apu_reg_io_db & 0xFu);
+                nos_length_halt = (apu_reg_io_db & 0x20) != 0;
+                nos_constant_volume_envelope = (apu_reg_io_db & 0x10) != 0;
+                nos_envelope = (nos_constant_volume_envelope ? nos_volume_devider_period : nos_envelope_decay_level_counter);
+            }
+        }
+
+        private static void APUOnRegister400D()
+        {
+        }
+
+        private static void APUOnRegister400E()
+        {
+            if (apu_reg_access_w)
+            {
+                nos_timer = (ushort)(nos_freq_table[SystemIndex][apu_reg_io_db & 0xF] / 2);
+                nos_mode = (apu_reg_io_db & 0x80) == 128;
+            }
+        }
+
+        private static void APUOnRegister400F()
+        {
+            if (apu_reg_access_w)
+            {
+                if (nos_length_enabled && !nos_ignore_reload)
+                {
+                    nos_length_counter = sq_duration_table[apu_reg_io_db >> 3];
+                }
+                if (nos_ignore_reload)
+                {
+                    nos_ignore_reload = false;
+                }
+                nos_envelope_start_flag = true;
+            }
+        }
+
+        private static void NOSOn4015()
+        {
+            nos_length_enabled = (apu_reg_io_db & 8) != 0;
+            if (!nos_length_enabled)
+            {
+                nos_length_counter = 0;
+            }
+        }
+
+        private static void NOSRead4015()
+        {
+            if (nos_length_counter > 0)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xF7u) | 8u);
+            }
+        }
+
+        private static void NOSWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(nos_length_halt);
+            bin.Write(nos_constant_volume_envelope);
+            bin.Write(nos_volume_devider_period);
+            bin.Write(nos_timer);
+            bin.Write(nos_mode);
+            bin.Write(nos_period_devider);
+            bin.Write(nos_length_enabled);
+            bin.Write(nos_length_counter);
+            bin.Write(nos_envelope_start_flag);
+            bin.Write(nos_envelope_devider);
+            bin.Write(nos_envelope_decay_level_counter);
+            bin.Write(nos_envelope);
+            bin.Write(nos_output);
+            bin.Write(nos_shift_reg);
+            bin.Write(nos_feedback);
+            bin.Write(nos_ignore_reload);
+        }
+
+        private static void NOSReadState(ref BinaryReader bin)
+        {
+            nos_length_halt = bin.ReadBoolean();
+            nos_constant_volume_envelope = bin.ReadBoolean();
+            nos_volume_devider_period = bin.ReadByte();
+            nos_timer = bin.ReadUInt16();
+            nos_mode = bin.ReadBoolean();
+            nos_period_devider = bin.ReadInt32();
+            nos_length_enabled = bin.ReadBoolean();
+            nos_length_counter = bin.ReadInt32();
+            nos_envelope_start_flag = bin.ReadBoolean();
+            nos_envelope_devider = bin.ReadByte();
+            nos_envelope_decay_level_counter = bin.ReadByte();
+            nos_envelope = bin.ReadByte();
+            nos_output = bin.ReadInt32();
+            nos_shift_reg = bin.ReadInt32();
+            nos_feedback = bin.ReadInt32();
+            nos_ignore_reload = bin.ReadBoolean();
+        }
+
+        private static void SQ1HardReset()
+        {
+            sq1_duty_cycle = 0;
+            sq1_length_halt = false;
+            sq1_constant_volume_envelope = false;
+            sq1_volume_devider_period = 0;
+            sq1_sweep_enable = false;
+            sq1_sweep_devider_period = 0;
+            sq1_sweep_negate = false;
+            sq1_sweep_shift_count = 0;
+            sq1_timer = 0;
+            sq1_period_devider = 0;
+            sq1_seqencer = 0;
+            sq1_length_enabled = false;
+            sq1_length_counter = 0;
+            sq1_envelope_start_flag = false;
+            sq1_envelope_devider = 0;
+            sq1_envelope_decay_level_counter = 0;
+            sq1_envelope = 0;
+            sq1_sweep_counter = 0;
+            sq1_sweep_reload = false;
+            sq1_sweep_change = 0;
+            sq1_valid_freq = false;
+            sq1_output = 0;
+            sq1_ignore_reload = false;
+        }
+
+        private static void SQ1SoftReset()
+        {
+            SQ1HardReset();
+        }
+
+        private static void SQ1Clock()
+        {
+            sq1_period_devider--;
+            if (sq1_period_devider > 0)
+            {
+                return;
+            }
+            sq1_period_devider = sq1_timer + 1;
+            sq1_seqencer = (byte)((uint)(sq1_seqencer + 1) & 7u);
+            if (sq1_length_counter > 0 && sq1_valid_freq)
+            {
+                if (audio_sq1_outputable)
+                {
+                    sq1_output = sq_duty_cycle_sequences[sq1_duty_cycle][sq1_seqencer] * sq1_envelope;
+                }
+            }
+            else
+            {
+                sq1_output = 0;
+            }
+            audio_signal_outputed = true;
+        }
+
+        private static void SQ1ClockLength()
+        {
+            if (sq1_length_counter > 0 && !sq1_length_halt)
+            {
+                sq1_length_counter--;
+                if (apu_reg_access_happened && apu_reg_io_addr == 3 && apu_reg_access_w)
+                {
+                    sq1_ignore_reload = true;
+                }
+            }
+            sq1_sweep_counter--;
+            if (sq1_sweep_counter == 0)
+            {
+                sq1_sweep_counter = sq1_sweep_devider_period + 1;
+                if (sq1_sweep_enable && sq1_sweep_shift_count > 0 && sq1_valid_freq)
+                {
+                    sq1_sweep_change = sq1_timer >> (int)sq1_sweep_shift_count;
+                    sq1_timer += (sq1_sweep_negate ? (~sq1_sweep_change) : sq1_sweep_change);
+                    SQ1CalculateValidFreq();
+                }
+            }
+            if (sq1_sweep_reload)
+            {
+                sq1_sweep_counter = sq1_sweep_devider_period + 1;
+                sq1_sweep_reload = false;
+            }
+        }
+
+        private static void SQ1ClockEnvelope()
+        {
+            if (sq1_envelope_start_flag)
+            {
+                sq1_envelope_start_flag = false;
+                sq1_envelope_decay_level_counter = 15;
+                sq1_envelope_devider = (byte)(sq1_volume_devider_period + 1);
+            }
+            else if (sq1_envelope_devider > 0)
+            {
+                sq1_envelope_devider--;
+            }
+            else
+            {
+                sq1_envelope_devider = (byte)(sq1_volume_devider_period + 1);
+                if (sq1_envelope_decay_level_counter > 0)
+                {
+                    sq1_envelope_decay_level_counter--;
+                }
+                else if (sq1_length_halt)
+                {
+                    sq1_envelope_decay_level_counter = 15;
+                }
+            }
+            sq1_envelope = (sq1_constant_volume_envelope ? sq1_volume_devider_period : sq1_envelope_decay_level_counter);
+        }
+
+        private static void APUOnRegister4000()
+        {
+            if (apu_reg_access_w)
+            {
+                sq1_duty_cycle = (byte)((apu_reg_io_db & 0xC0) >> 6);
+                sq1_volume_devider_period = (byte)(apu_reg_io_db & 0xFu);
+                sq1_length_halt = (apu_reg_io_db & 0x20) != 0;
+                sq1_constant_volume_envelope = (apu_reg_io_db & 0x10) != 0;
+                sq1_envelope = (sq1_constant_volume_envelope ? sq1_volume_devider_period : sq1_envelope_decay_level_counter);
+            }
+        }
+
+        private static void APUOnRegister4001()
+        {
+            if (apu_reg_access_w)
+            {
+                sq1_sweep_enable = (apu_reg_io_db & 0x80) == 128;
+                sq1_sweep_devider_period = (byte)((uint)(apu_reg_io_db >> 4) & 7u);
+                sq1_sweep_negate = (apu_reg_io_db & 8) == 8;
+                sq1_sweep_shift_count = (byte)(apu_reg_io_db & 7u);
+                sq1_sweep_reload = true;
+                SQ1CalculateValidFreq();
+            }
+        }
+
+        private static void APUOnRegister4002()
+        {
+            if (apu_reg_access_w)
+            {
+                sq1_timer = (sq1_timer & 0xFF00) | apu_reg_io_db;
+                SQ1CalculateValidFreq();
+            }
+        }
+
+        private static void APUOnRegister4003()
+        {
+            if (apu_reg_access_w)
+            {
+                sq1_timer = (sq1_timer & 0xFF) | ((apu_reg_io_db & 7) << 8);
+                if (sq1_length_enabled && !sq1_ignore_reload)
+                {
+                    sq1_length_counter = sq_duration_table[apu_reg_io_db >> 3];
+                }
+                if (sq1_ignore_reload)
+                {
+                    sq1_ignore_reload = false;
+                }
+                sq1_seqencer = 0;
+                sq1_envelope_start_flag = true;
+                SQ1CalculateValidFreq();
+            }
+        }
+
+        private static void SQ1On4015()
+        {
+            sq1_length_enabled = (apu_reg_io_db & 1) != 0;
+            if (!sq1_length_enabled)
+            {
+                sq1_length_counter = 0;
+            }
+        }
+
+        private static void SQ1Read4015()
+        {
+            if (sq1_length_counter > 0)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xFEu) | 1u);
+            }
+        }
+
+        private static void SQ1CalculateValidFreq()
+        {
+            sq1_valid_freq = sq1_timer >= 8 && (sq1_sweep_negate || ((sq1_timer + (sq1_timer >> (int)sq1_sweep_shift_count)) & 0x800) == 0);
+        }
+
+        private static void SQ1WriteState(ref BinaryWriter bin)
+        {
+            bin.Write(sq1_duty_cycle);
+            bin.Write(sq1_length_halt);
+            bin.Write(sq1_constant_volume_envelope);
+            bin.Write(sq1_volume_devider_period);
+            bin.Write(sq1_sweep_enable);
+            bin.Write(sq1_sweep_devider_period);
+            bin.Write(sq1_sweep_negate);
+            bin.Write(sq1_sweep_shift_count);
+            bin.Write(sq1_timer);
+            bin.Write(sq1_period_devider);
+            bin.Write(sq1_seqencer);
+            bin.Write(sq1_length_enabled);
+            bin.Write(sq1_length_counter);
+            bin.Write(sq1_envelope_start_flag);
+            bin.Write(sq1_envelope_devider);
+            bin.Write(sq1_envelope_decay_level_counter);
+            bin.Write(sq1_envelope);
+            bin.Write(sq1_sweep_counter);
+            bin.Write(sq1_sweep_reload);
+            bin.Write(sq1_sweep_change);
+            bin.Write(sq1_valid_freq);
+            bin.Write(sq1_output);
+            bin.Write(sq1_ignore_reload);
+        }
+
+        private static void SQ1ReadState(ref BinaryReader bin)
+        {
+            sq1_duty_cycle = bin.ReadByte();
+            sq1_length_halt = bin.ReadBoolean();
+            sq1_constant_volume_envelope = bin.ReadBoolean();
+            sq1_volume_devider_period = bin.ReadByte();
+            sq1_sweep_enable = bin.ReadBoolean();
+            sq1_sweep_devider_period = bin.ReadByte();
+            sq1_sweep_negate = bin.ReadBoolean();
+            sq1_sweep_shift_count = bin.ReadByte();
+            sq1_timer = bin.ReadInt32();
+            sq1_period_devider = bin.ReadInt32();
+            sq1_seqencer = bin.ReadByte();
+            sq1_length_enabled = bin.ReadBoolean();
+            sq1_length_counter = bin.ReadInt32();
+            sq1_envelope_start_flag = bin.ReadBoolean();
+            sq1_envelope_devider = bin.ReadByte();
+            sq1_envelope_decay_level_counter = bin.ReadByte();
+            sq1_envelope = bin.ReadByte();
+            sq1_sweep_counter = bin.ReadInt32();
+            sq1_sweep_reload = bin.ReadBoolean();
+            sq1_sweep_change = bin.ReadInt32();
+            sq1_valid_freq = bin.ReadBoolean();
+            sq1_output = bin.ReadInt32();
+            sq1_ignore_reload = bin.ReadBoolean();
+        }
+
+        private static void TRLHardReset()
+        {
+            trl_liner_control_flag = false;
+            trl_liner_control_reload = 0;
+            trl_timer = 0;
+            trl_length_enabled = false;
+            trl_length_counter = 0;
+            trl_liner_control_reload_flag = false;
+            trl_liner_counter = 0;
+            trl_output = 0;
+            trl_period_devider = 0;
+            trl_step = 0;
+            trl_ignore_reload = false;
+        }
+
+        private static void TRLSoftReset()
+        {
+            TRLHardReset();
+        }
+
+        private static void TRLClock()
+        {
+            trl_period_devider--;
+            if (trl_period_devider > 0)
+            {
+                return;
+            }
+            trl_period_devider = trl_timer + 1;
+            if (trl_length_counter > 0 && trl_liner_counter > 0 && trl_timer >= 4)
+            {
+                trl_step++;
+                trl_step &= 31;
+                if (audio_trl_outputable)
+                {
+                    trl_output = trl_step_seq[trl_step];
+                }
+            }
+            audio_signal_outputed = true;
+        }
+
+        private static void TRLClockLength()
+        {
+            if (trl_length_counter > 0 && !trl_liner_control_flag)
+            {
+                trl_length_counter--;
+                if (apu_reg_access_happened && apu_reg_io_addr == 11 && apu_reg_access_w)
+                {
+                    trl_ignore_reload = true;
+                }
+            }
+        }
+
+        private static void TRLClockEnvelope()
+        {
+            if (trl_liner_control_reload_flag)
+            {
+                trl_liner_counter = trl_liner_control_reload;
+            }
+            else if (trl_liner_counter > 0)
+            {
+                trl_liner_counter--;
+            }
+            if (!trl_liner_control_flag)
+            {
+                trl_liner_control_reload_flag = false;
+            }
+        }
+
+        private static void APUOnRegister4008()
+        {
+            if (apu_reg_access_w)
+            {
+                trl_liner_control_flag = (apu_reg_io_db & 0x80) == 128;
+                trl_liner_control_reload = (byte)(apu_reg_io_db & 0x7Fu);
+            }
+        }
+
+        private static void APUOnRegister4009()
+        {
+        }
+
+        private static void APUOnRegister400A()
+        {
+            if (apu_reg_access_w)
+            {
+                trl_timer = (ushort)((trl_timer & 0x7F00u) | apu_reg_io_db);
+            }
+        }
+
+        private static void APUOnRegister400B()
+        {
+            if (apu_reg_access_w)
+            {
+                trl_timer = (ushort)((trl_timer & 0xFFu) | (uint)((apu_reg_io_db & 7) << 8));
+                if (trl_length_enabled && !trl_ignore_reload)
+                {
+                    trl_length_counter = sq_duration_table[apu_reg_io_db >> 3];
+                }
+                if (trl_ignore_reload)
+                {
+                    trl_ignore_reload = false;
+                }
+                trl_liner_control_reload_flag = true;
+            }
+        }
+
+        private static void TRLOn4015()
+        {
+            trl_length_enabled = (apu_reg_io_db & 4) != 0;
+            if (!trl_length_enabled)
+            {
+                trl_length_counter = 0;
+            }
+        }
+
+        private static void TRLRead4015()
+        {
+            if (trl_length_counter > 0)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xFBu) | 4u);
+            }
+        }
+
+        private static void TRLWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(trl_liner_control_flag);
+            bin.Write(trl_liner_control_reload);
+            bin.Write(trl_timer);
+            bin.Write(trl_length_enabled);
+            bin.Write(trl_length_counter);
+            bin.Write(trl_liner_control_reload_flag);
+            bin.Write(trl_liner_counter);
+            bin.Write(trl_output);
+            bin.Write(trl_period_devider);
+            bin.Write(trl_step);
+            bin.Write(trl_ignore_reload);
+        }
+
+        private static void TRLReadState(ref BinaryReader bin)
+        {
+            trl_liner_control_flag = bin.ReadBoolean();
+            trl_liner_control_reload = bin.ReadByte();
+            trl_timer = bin.ReadUInt16();
+            trl_length_enabled = bin.ReadBoolean();
+            trl_length_counter = bin.ReadByte();
+            trl_liner_control_reload_flag = bin.ReadBoolean();
+            trl_liner_counter = bin.ReadByte();
+            trl_output = bin.ReadInt32();
+            trl_period_devider = bin.ReadInt32();
+            trl_step = bin.ReadInt32();
+            trl_ignore_reload = bin.ReadBoolean();
+        }
+
+        private static void APUInitialize()
+        {
+            apu_reg_update_func = new Action[32];
+            apu_reg_read_func = new Action[32];
+            apu_reg_write_func = new Action[32];
+            for (int i = 0; i < 32; i++)
+            {
+                apu_reg_update_func[i] = APUBlankAccess;
+                apu_reg_read_func[i] = APUBlankAccess;
+                apu_reg_write_func[i] = APUBlankAccess;
+            }
+            apu_reg_update_func[0] = APUOnRegister4000;
+            apu_reg_update_func[1] = APUOnRegister4001;
+            apu_reg_update_func[2] = APUOnRegister4002;
+            apu_reg_update_func[3] = APUOnRegister4003;
+            apu_reg_update_func[4] = APUOnRegister4004;
+            apu_reg_update_func[5] = APUOnRegister4005;
+            apu_reg_update_func[6] = APUOnRegister4006;
+            apu_reg_update_func[7] = APUOnRegister4007;
+            apu_reg_update_func[8] = APUOnRegister4008;
+            apu_reg_update_func[9] = APUOnRegister4009;
+            apu_reg_update_func[10] = APUOnRegister400A;
+            apu_reg_update_func[11] = APUOnRegister400B;
+            apu_reg_update_func[12] = APUOnRegister400C;
+            apu_reg_update_func[13] = APUOnRegister400D;
+            apu_reg_update_func[14] = APUOnRegister400E;
+            apu_reg_update_func[15] = APUOnRegister400F;
+            apu_reg_update_func[16] = APUOnRegister4010;
+            apu_reg_update_func[17] = APUOnRegister4011;
+            apu_reg_update_func[18] = APUOnRegister4012;
+            apu_reg_update_func[19] = APUOnRegister4013;
+            apu_reg_update_func[21] = APUOnRegister4015;
+            apu_reg_update_func[22] = APUOnRegister4016;
+            apu_reg_update_func[23] = APUOnRegister4017;
+            apu_reg_read_func[21] = APURead4015;
+            apu_reg_read_func[22] = APURead4016;
+            apu_reg_read_func[23] = APURead4017;
+            apu_reg_write_func[20] = APUWrite4014;
+            apu_reg_write_func[21] = APUWrite4015;
+            audio_low_pass_filter_14K = new SoundLowPassFilter(0.00815686);
+            audio_high_pass_filter_90 = new SoundHighPassFilter(0.999835);
+            audio_high_pass_filter_440 = new SoundHighPassFilter(0.996039);
+            apu_update_playback_func = APUUpdatePlaybackWithFilters;
+        }
+
+        public static void ApplyAudioSettings(bool all = true)
+        {
+            SoundEnabled = MyNesMain.RendererSettings.Audio_SoundEnabled;
+            audio_sq1_outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_SQ1;
+            audio_sq2_outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_SQ2;
+            audio_nos_outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_NOZ;
+            audio_trl_outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_TRL;
+            audio_dmc_outputable = MyNesMain.RendererSettings.Audio_ChannelEnabled_DMC;
+            if (apu_use_external_sound)
+            {
+                mem_board.APUApplyChannelsSettings();
+            }
+            if (all)
+            {
+                CalculateAudioPlaybackValues();
+            }
+        }
+
+        private static void APUHardReset()
+        {
+            apu_reg_io_db = 0;
+            apu_reg_io_addr = 0;
+            apu_reg_access_happened = false;
+            apu_reg_access_w = false;
+            apu_seq_mode = false;
+            apu_odd_cycle = true;
+            apu_cycle_f_t = 0;
+            apu_cycle_e = 4;
+            apu_cycle_f = 4;
+            apu_cycle_l = 4;
+            apu_odd_l = false;
+            apu_check_irq = false;
+            apu_do_env = false;
+            apu_do_length = false;
+            switch (Region)
+            {
+                case EmuRegion.NTSC:
+                    cpu_speed = 1789773;
+                    apu_ferq_f = 14914;
+                    apu_ferq_e = 3728;
+                    apu_ferq_l = 7456;
+                    break;
+                case EmuRegion.PALB:
+                    cpu_speed = 1662607;
+                    apu_ferq_f = 14914;
+                    apu_ferq_e = 3728;
+                    apu_ferq_l = 7456;
+                    break;
+                case EmuRegion.DENDY:
+                    cpu_speed = 1773448;
+                    apu_ferq_f = 14914;
+                    apu_ferq_e = 3728;
+                    apu_ferq_l = 7456;
+                    break;
+            }
+            Tracer.WriteLine("NES: cpu speed = " + cpu_speed);
+            SQ1HardReset();
+            SQ2HardReset();
+            NOSHardReset();
+            DMCHardReset();
+            TRLHardReset();
+            apu_irq_enabled = true;
+            apu_irq_flag = false;
+            reg_2004 = 8196;
+            CalculateAudioPlaybackValues();
+            apu_use_external_sound = mem_board.enable_external_sound;
+            if (apu_use_external_sound)
+            {
+                Tracer.WriteInformation("External sound channels has been enabled on apu.");
+            }
+        }
+
+        private static void APUSoftReset()
+        {
+            apu_reg_io_db = 0;
+            apu_reg_io_addr = 0;
+            apu_reg_access_happened = false;
+            apu_reg_access_w = false;
+            apu_seq_mode = false;
+            apu_odd_cycle = false;
+            apu_cycle_f_t = 0;
+            apu_cycle_e = 4;
+            apu_cycle_f = 4;
+            apu_cycle_l = 4;
+            apu_odd_l = false;
+            apu_check_irq = false;
+            apu_do_env = false;
+            apu_do_length = false;
+            apu_irq_enabled = true;
+            apu_irq_flag = false;
+            SQ1SoftReset();
+            SQ2SoftReset();
+            TRLSoftReset();
+            NOSSoftReset();
+            DMCSoftReset();
+        }
+
+        private static void APUIORead(ref ushort addr, out byte value)
+        {
+            if (addr >= 16416)
+            {
+                mem_board.ReadEX(ref addr, out value);
+                return;
+            }
+            apu_reg_io_addr = (byte)(addr & 0x1Fu);
+            apu_reg_access_happened = true;
+            apu_reg_access_w = false;
+            apu_reg_read_func[apu_reg_io_addr]();
+            value = apu_reg_io_db;
+        }
+
+        private static void APUIOWrite(ref ushort addr, ref byte value)
+        {
+            if (addr >= 16416)
+            {
+                mem_board.WriteEX(ref addr, ref value);
+                return;
+            }
+            apu_reg_io_addr = (byte)(addr & 0x1Fu);
+            apu_reg_io_db = value;
+            apu_reg_access_w = true;
+            apu_reg_access_happened = true;
+            apu_reg_write_func[apu_reg_io_addr]();
+        }
+
+        private static void APUBlankAccess()
+        {
+        }
+
+        private static void APUWrite4014()
+        {
+            dma_Oamaddress = (ushort)(apu_reg_io_db << 8);
+            AssertOAMDMA();
+        }
+
+        private static void APUWrite4015()
+        {
+            if ((apu_reg_io_db & 0x10u) != 0)
+            {
+                if (dmc_dmaSize == 0)
+                {
+                    dmc_dmaSize = dmc_size_refresh;
+                    dmc_dmaAddr = dmc_addr_refresh;
+                }
+            }
+            else
+            {
+                dmc_dmaSize = 0;
+            }
+            if (!dmc_bufferFull && dmc_dmaSize > 0)
+            {
+                AssertDMCDMA();
+            }
+        }
+
+        private static void APUOnRegister4015()
+        {
+            if (apu_reg_access_w)
+            {
+                SQ1On4015();
+                SQ2On4015();
+                NOSOn4015();
+                TRLOn4015();
+                DMCOn4015();
+            }
+            else
+            {
+                apu_irq_flag = false;
+                IRQFlags &= -2;
+            }
+        }
+
+        private static void APUOnRegister4016()
+        {
+            if (!apu_reg_access_w)
+            {
+                return;
+            }
+            if (inputStrobe > (apu_reg_io_db & 1))
+            {
+                if (IsFourPlayers)
+                {
+                    PORT0 = (joypad3.GetData() << 8) | joypad1.GetData() | 0x1010000;
+                    PORT1 = (joypad4.GetData() << 8) | joypad2.GetData() | 0x2020000;
+                }
+                else
+                {
+                    PORT0 = joypad1.GetData() | 0x1010100;
+                    PORT1 = joypad2.GetData() | 0x2020200;
+                }
+            }
+            inputStrobe = apu_reg_io_db & 1;
+        }
+
+        private static void APUOnRegister4017()
+        {
+            if (apu_reg_access_w)
+            {
+                apu_seq_mode = (apu_reg_io_db & 0x80) != 0;
+                apu_irq_enabled = (apu_reg_io_db & 0x40) == 0;
+                apu_cycle_e = -1;
+                apu_cycle_l = -1;
+                apu_cycle_f = -1;
+                apu_odd_l = false;
+                apu_do_length = apu_seq_mode;
+                apu_do_env = apu_seq_mode;
+                apu_check_irq = false;
+                if (!apu_irq_enabled)
+                {
+                    apu_irq_flag = false;
+                    IRQFlags &= -2;
+                }
+            }
+        }
+
+        private static void APURead4015()
+        {
+            apu_reg_io_db &= 32;
+            SQ1Read4015();
+            SQ2Read4015();
+            NOSRead4015();
+            TRLRead4015();
+            DMCRead4015();
+            if (apu_irq_flag)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xBFu) | 0x40u);
+            }
+            if (apu_irq_delta_occur)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0x7Fu) | 0x80u);
+            }
+        }
+
+        private static void APURead4016()
+        {
+            apu_reg_io_db = (byte)((uint)PORT0 & 1u);
+            PORT0 >>= 1;
+        }
+
+        private static void APURead4017()
+        {
+            apu_reg_io_db = (byte)((uint)PORT1 & 1u);
+            PORT1 >>= 1;
+        }
+
+        private static void APUClock()
+        {
+            apu_odd_cycle = !apu_odd_cycle;
+            if (apu_do_env)
+            {
+                APUClockEnvelope();
+            }
+            if (apu_do_length)
+            {
+                APUClockDuration();
+            }
+            if (apu_odd_cycle)
+            {
+                apu_cycle_f++;
+                if (apu_cycle_f >= apu_ferq_f)
+                {
+                    apu_cycle_f = -1;
+                    apu_check_irq = true;
+                    apu_cycle_f_t = 3;
+                }
+                apu_cycle_e++;
+                if (apu_cycle_e >= apu_ferq_e)
+                {
+                    apu_cycle_e = -1;
+                    if (apu_check_irq)
+                    {
+                        if (!apu_seq_mode)
+                        {
+                            apu_do_env = true;
+                        }
+                        else
+                        {
+                            apu_cycle_e = 4;
+                        }
+                    }
+                    else
+                    {
+                        apu_do_env = true;
+                    }
+                }
+                apu_cycle_l++;
+                if (apu_cycle_l >= apu_ferq_l)
+                {
+                    apu_odd_l = !apu_odd_l;
+                    apu_cycle_l = (apu_odd_l ? (-2) : (-1));
+                    if (apu_check_irq && apu_seq_mode)
+                    {
+                        apu_cycle_l = 3730;
+                        apu_odd_l = true;
+                    }
+                    else
+                    {
+                        apu_do_length = true;
+                    }
+                }
+                SQ1Clock();
+                SQ2Clock();
+                NOSClock();
+                if (apu_use_external_sound)
+                {
+                    mem_board.OnAPUClock();
+                }
+                if (apu_reg_access_happened)
+                {
+                    apu_reg_access_happened = false;
+                    apu_reg_update_func[apu_reg_io_addr]();
+                }
+            }
+            TRLClock();
+            DMCClock();
+            if (apu_check_irq)
+            {
+                if (!apu_seq_mode)
+                {
+                    APUCheckIRQ();
+                }
+                apu_cycle_f_t--;
+                if (apu_cycle_f_t == 0)
+                {
+                    apu_check_irq = false;
+                }
+            }
+            if (apu_use_external_sound)
+            {
+                mem_board.OnAPUClockSingle();
+            }
+            apu_update_playback_func();
+        }
+
+        private static void APUClockDuration()
+        {
+            SQ1ClockLength();
+            SQ2ClockLength();
+            NOSClockLength();
+            TRLClockLength();
+            if (apu_use_external_sound)
+            {
+                mem_board.OnAPUClockDuration();
+            }
+            apu_do_length = false;
+        }
+
+        private static void APUClockEnvelope()
+        {
+            SQ1ClockEnvelope();
+            SQ2ClockEnvelope();
+            NOSClockEnvelope();
+            TRLClockEnvelope();
+            if (apu_use_external_sound)
+            {
+                mem_board.OnAPUClockEnvelope();
+            }
+            apu_do_env = false;
+        }
+
+        private static void APUCheckIRQ()
+        {
+            if (apu_irq_enabled)
+            {
+                apu_irq_flag = true;
+            }
+            if (apu_irq_flag)
+            {
+                IRQFlags |= 1;
+            }
+        }
+
+        private static void CalculateAudioPlaybackValues()
+        {
+            audio_timer_ratio = (double)cpu_speed / (double)MyNesMain.RendererSettings.Audio_Frequency;
+            audio_playback_peek_limit = MyNesMain.RendererSettings.Audio_InternalPeekLimit;
+            audio_samples_count = MyNesMain.RendererSettings.Audio_InternalSamplesCount;
+            audio_playback_amplitude = MyNesMain.RendererSettings.Audio_PlaybackAmplitude;
+            audio_samples = new short[audio_samples_count];
+            audio_w_pos = 0;
+            audio_samples_added = 0;
+            audio_timer = 0.0;
+            audio_x = (audio_y = 0.0);
+            Tracer.WriteLine("AUDIO: frequency = " + MyNesMain.RendererSettings.Audio_Frequency);
+            Tracer.WriteLine("AUDIO: timer ratio = " + audio_timer_ratio);
+            Tracer.WriteLine("AUDIO: internal samples count = " + audio_samples_count);
+            Tracer.WriteLine("AUDIO: amplitude = " + audio_playback_amplitude);
+            if (MyNesMain.RendererSettings.Audio_EnableFilters)
+            {
+                apu_update_playback_func = APUUpdatePlaybackWithFilters;
+                audio_low_pass_filter_14K = new SoundLowPassFilter(SoundLowPassFilter.GetK((double)cpu_speed / 14000.0, 14000.0));
+                audio_high_pass_filter_90 = new SoundHighPassFilter(SoundHighPassFilter.GetK((double)cpu_speed / 90.0, 90.0));
+                audio_high_pass_filter_440 = new SoundHighPassFilter(SoundHighPassFilter.GetK((double)cpu_speed / 440.0, 440.0));
+            }
+            else
+            {
+                apu_update_playback_func = APUUpdatePlaybackWithoutFilters;
+            }
+            InitializeDACTables(force_intitialize: false);
+        }
+
+        public static void InitializeDACTables(bool force_intitialize)
+        {
+            if (audio_playback_dac_initialized && !force_intitialize)
+            {
+                return;
+            }
+            int[] array = new int[5];
+            mix_table = new int[16][][][][];
+            for (int i = 0; i < 16; i++)
+            {
+                mix_table[i] = new int[16][][][];
+                for (int j = 0; j < 16; j++)
+                {
+                    mix_table[i][j] = new int[16][][];
+                    for (int k = 0; k < 16; k++)
+                    {
+                        mix_table[i][j][k] = new int[16][];
+                        for (int l = 0; l < 16; l++)
+                        {
+                            mix_table[i][j][k][l] = new int[128];
+                            for (int m = 0; m < 128; m++)
+                            {
+                                if (MyNesMain.RendererSettings.Audio_UseDefaultMixer)
+                                {
+                                    double num = 95.88 / (8128.0 / (double)(i + j) + 100.0);
+                                    double num2 = 159.79 / (1.0 / ((double)k / 8227.0 + (double)l / 12241.0 + (double)m / 22638.0) + 100.0);
+                                    mix_table[i][j][k][l][m] = (int)Math.Ceiling((num + num2) * audio_playback_amplitude);
+                                    continue;
+                                }
+                                GetPrec(i, 255, 2048, out array[0]);
+                                GetPrec(j, 255, 2048, out array[1]);
+                                GetPrec(l, 255, 2048, out array[2]);
+                                GetPrec(k, 255, 2048, out array[3]);
+                                GetPrec(m, 255, 2048, out array[4]);
+                                array[4] /= 2;
+                                int num3 = array[0] + array[1] + array[2] + array[3] + array[4];
+                                num3 /= 5;
+                                mix_table[i][j][k][l][m] = num3;
+                            }
+                        }
+                    }
+                }
+            }
+            audio_playback_dac_initialized = true;
+        }
+
+        private static void APUUpdatePlaybackWithFilters()
+        {
+            if (!SoundEnabled)
+            {
+                return;
+            }
+            audio_x = mix_table[sq1_output][sq2_output][trl_output][nos_output][dmc_output];
+            if (apu_use_external_sound)
+            {
+                audio_x = (audio_x + mem_board.APUGetSample() * audio_playback_amplitude) / 2.0;
+            }
+            audio_high_pass_filter_90.DoFiltering(audio_x, out audio_y);
+            audio_high_pass_filter_440.DoFiltering(audio_y, out audio_y);
+            audio_low_pass_filter_14K.DoFiltering(audio_y, out audio_y);
+            audio_y_av += audio_y;
+            audio_y_timer += 1.0;
+            audio_timer += 1.0;
+            if (!(audio_timer >= audio_timer_ratio))
+            {
+                return;
+            }
+            if (audio_y_timer > 0.0)
+            {
+                audio_y = audio_y_av / audio_y_timer;
+            }
+            else
+            {
+                audio_y = 0.0;
+            }
+            audio_y_av = 0.0;
+            audio_y_timer = 0.0;
+            audio_timer -= audio_timer_ratio;
+            if (audio_w_pos < audio_samples_count)
+            {
+                if (audio_y > (double)audio_playback_peek_limit)
+                {
+                    audio_y = audio_playback_peek_limit;
+                }
+                if (audio_y < (double)(-audio_playback_peek_limit))
+                {
+                    audio_y = -audio_playback_peek_limit;
+                }
+                audio_samples[audio_w_pos] = (short)audio_y;
+                if (MyNesMain.WaveRecorder.IsRecording)
+                {
+                    MyNesMain.WaveRecorder.AddSample((short)audio_y);
+                }
+                audio_w_pos++;
+                audio_samples_added++;
+            }
+            audio_y = 0.0;
+        }
+
+        private static void APUUpdatePlaybackWithoutFilters()
+        {
+            if (!SoundEnabled)
+            {
+                return;
+            }
+            audio_y = mix_table[sq1_output][sq2_output][trl_output][nos_output][dmc_output] / 2;
+            if (apu_use_external_sound)
+            {
+                audio_y = (audio_y + mem_board.APUGetSample() * audio_playback_amplitude) / 2.0;
+            }
+            audio_y_av += audio_y;
+            audio_y_timer += 1.0;
+            audio_timer += 1.0;
+            if (!(audio_timer >= audio_timer_ratio))
+            {
+                return;
+            }
+            if (audio_y_timer > 0.0)
+            {
+                audio_y = audio_y_av / audio_y_timer;
+            }
+            else
+            {
+                audio_y = 0.0;
+            }
+            audio_y_av = 0.0;
+            audio_y_timer = 0.0;
+            audio_timer -= audio_timer_ratio;
+            if (audio_w_pos < audio_samples_count)
+            {
+                if (audio_y > (double)audio_playback_peek_limit)
+                {
+                    audio_y = audio_playback_peek_limit;
+                }
+                if (audio_y < (double)(-audio_playback_peek_limit))
+                {
+                    audio_y = -audio_playback_peek_limit;
+                }
+                audio_samples[audio_w_pos] = (short)audio_y;
+                if (MyNesMain.WaveRecorder.IsRecording)
+                {
+                    MyNesMain.WaveRecorder.AddSample((short)audio_y);
+                }
+                audio_w_pos++;
+                audio_samples_added++;
+            }
+            audio_y = 0.0;
+        }
+
+        private static void GetPrec(int inVal, int inMax, int outMax, out int val)
+        {
+            val = outMax * inVal / inMax;
+        }
+
+        private static void APUWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(apu_reg_io_db);
+            bin.Write(apu_reg_io_addr);
+            bin.Write(apu_reg_access_happened);
+            bin.Write(apu_reg_access_w);
+            bin.Write(apu_odd_cycle);
+            bin.Write(apu_irq_enabled);
+            bin.Write(apu_irq_flag);
+            bin.Write(apu_irq_delta_occur);
+            bin.Write(apu_seq_mode);
+            bin.Write(apu_ferq_f);
+            bin.Write(apu_ferq_l);
+            bin.Write(apu_ferq_e);
+            bin.Write(apu_cycle_f);
+            bin.Write(apu_cycle_e);
+            bin.Write(apu_cycle_l);
+            bin.Write(apu_odd_l);
+            bin.Write(apu_cycle_f_t);
+            bin.Write(apu_check_irq);
+            bin.Write(apu_do_env);
+            bin.Write(apu_do_length);
+            SQ1WriteState(ref bin);
+            SQ2WriteState(ref bin);
+            NOSWriteState(ref bin);
+            TRLWriteState(ref bin);
+            DMCWriteState(ref bin);
+        }
+
+        private static void APUReadState(ref BinaryReader bin)
+        {
+            apu_reg_io_db = bin.ReadByte();
+            apu_reg_io_addr = bin.ReadByte();
+            apu_reg_access_happened = bin.ReadBoolean();
+            apu_reg_access_w = bin.ReadBoolean();
+            apu_odd_cycle = bin.ReadBoolean();
+            apu_irq_enabled = bin.ReadBoolean();
+            apu_irq_flag = bin.ReadBoolean();
+            apu_irq_delta_occur = bin.ReadBoolean();
+            apu_seq_mode = bin.ReadBoolean();
+            apu_ferq_f = bin.ReadInt32();
+            apu_ferq_l = bin.ReadInt32();
+            apu_ferq_e = bin.ReadInt32();
+            apu_cycle_f = bin.ReadInt32();
+            apu_cycle_e = bin.ReadInt32();
+            apu_cycle_l = bin.ReadInt32();
+            apu_odd_l = bin.ReadBoolean();
+            apu_cycle_f_t = bin.ReadInt32();
+            apu_check_irq = bin.ReadBoolean();
+            apu_do_env = bin.ReadBoolean();
+            apu_do_length = bin.ReadBoolean();
+            SQ1ReadState(ref bin);
+            SQ2ReadState(ref bin);
+            NOSReadState(ref bin);
+            TRLReadState(ref bin);
+            DMCReadState(ref bin);
+        }
+
+        private static byte register_pb()
+        {
+            return (byte)((cpu_flag_n ? 128u : 0u) | (cpu_flag_v ? 64u : 0u) | (cpu_flag_d ? 8u : 0u) | (cpu_flag_i ? 4u : 0u) | (cpu_flag_z ? 2u : 0u) | (cpu_flag_c ? 1u : 0u) | 0x30u);
+        }
+
+        private static void CPUInitialize()
+        {
+            cpu_addressings = new Action[256]
+            {
+                Imp____, IndX_R_, ImA____, IndX_W_, Zpg_R__, Zpg_R__, Zpg_RW_, Zpg_W__, ImA____, Imm____,
+                ImA____, Imm____, Abs_R__, Abs_R__, Abs_RW_, Abs_W__, Imp____, IndY_R_, Imp____, IndY_W_,
+                ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_W_, ImA____, AbsY_R_, ImA____, AbsY_W_, AbsX_R_, AbsX_R_,
+                AbsX_RW, AbsX_W_, Imp____, IndX_R_, ImA____, IndX_W_, Zpg_R__, Zpg_R__, Zpg_RW_, Zpg_W__,
+                ImA____, Imm____, ImA____, Imm____, Abs_R__, Abs_R__, Abs_RW_, Abs_W__, Imp____, IndY_R_,
+                Imp____, IndY_W_, ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_W_, ImA____, AbsY_R_, ImA____, AbsY_W_,
+                AbsX_R_, AbsX_R_, AbsX_RW, AbsX_W_, ImA____, IndX_R_, ImA____, IndX_W_, Zpg_R__, Zpg_R__,
+                Zpg_RW_, Zpg_W__, ImA____, Imm____, ImA____, Imm____, Abs_W__, Abs_R__, Abs_RW_, Abs_W__,
+                Imp____, IndY_R_, Imp____, IndY_W_, ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_W_, ImA____, AbsY_R_,
+                ImA____, AbsY_W_, AbsX_R_, AbsX_R_, AbsX_RW, AbsX_W_, ImA____, IndX_R_, ImA____, IndX_W_,
+                Zpg_R__, Zpg_R__, Zpg_RW_, Zpg_W__, ImA____, Imm____, ImA____, Imm____, Imp____, Abs_R__,
+                Abs_RW_, Abs_W__, Imp____, IndY_R_, Imp____, IndY_W_, ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_W_,
+                ImA____, AbsY_R_, ImA____, AbsY_W_, AbsX_R_, AbsX_R_, AbsX_RW, AbsX_W_, Imm____, IndX_W_,
+                Imm____, IndX_W_, Zpg_W__, Zpg_W__, Zpg_W__, Zpg_W__, ImA____, Imm____, ImA____, Imm____,
+                Abs_W__, Abs_W__, Abs_W__, Abs_W__, Imp____, IndY_W_, Imp____, IndY_W_, ZpgX_W_, ZpgX_W_,
+                ZpgY_W_, ZpgY_W_, ImA____, AbsY_W_, ImA____, AbsY_W_, Abs_W__, AbsX_W_, Abs_W__, AbsY_W_,
+                Imm____, IndX_R_, Imm____, IndX_R_, Zpg_R__, Zpg_R__, Zpg_R__, Zpg_R__, ImA____, Imm____,
+                ImA____, Imm____, Abs_R__, Abs_R__, Abs_R__, Abs_R__, Imp____, IndY_R_, Imp____, IndY_R_,
+                ZpgX_R_, ZpgX_R_, ZpgY_R_, ZpgY_R_, ImA____, AbsY_R_, ImA____, AbsY_R_, AbsX_R_, AbsX_R_,
+                AbsY_R_, AbsY_R_, Imm____, IndX_R_, Imm____, IndX_R_, Zpg_R__, Zpg_R__, Zpg_RW_, Zpg_R__,
+                ImA____, Imm____, ImA____, Imm____, Abs_R__, Abs_R__, Abs_RW_, Abs_R__, Imp____, IndY_R_,
+                Imp____, IndY_RW, ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_RW, ImA____, AbsY_R_, ImA____, AbsY_RW,
+                AbsX_R_, AbsX_R_, AbsX_RW, AbsX_RW, Imm____, IndX_R_, Imm____, IndX_W_, Zpg_R__, Zpg_R__,
+                Zpg_RW_, Zpg_W__, ImA____, Imm____, ImA____, Imm____, Abs_R__, Abs_R__, Abs_RW_, Abs_W__,
+                Imp____, IndY_R_, Imp____, IndY_W_, ZpgX_R_, ZpgX_R_, ZpgX_RW, ZpgX_W_, ImA____, AbsY_R_,
+                ImA____, AbsY_W_, AbsX_R_, AbsX_R_, AbsX_RW, AbsX_W_
+            };
+            cpu_instructions = new Action[256]
+            {
+                BRK__, ORA__, NOP__, SLO__, NOP__, ORA__, ASL_M, SLO__, PHP__, ORA__,
+                ASL_A, ANC__, NOP__, ORA__, ASL_M, SLO__, BPL__, ORA__, NOP__, SLO__,
+                NOP__, ORA__, ASL_M, SLO__, CLC__, ORA__, NOP__, SLO__, NOP__, ORA__,
+                ASL_M, SLO__, JSR__, AND__, NOP__, RLA__, BIT__, AND__, ROL_M, RLA__,
+                PLP__, AND__, ROL_A, ANC__, BIT__, AND__, ROL_M, RLA__, BMI__, AND__,
+                NOP__, RLA__, NOP__, AND__, ROL_M, RLA__, SEC__, AND__, NOP__, RLA__,
+                NOP__, AND__, ROL_M, RLA__, RTI__, EOR__, NOP__, SRE__, NOP__, EOR__,
+                LSR_M, SRE__, PHA__, EOR__, LSR_A, ALR__, JMP__, EOR__, LSR_M, SRE__,
+                BVC__, EOR__, NOP__, SRE__, NOP__, EOR__, LSR_M, SRE__, CLI__, EOR__,
+                NOP__, SRE__, NOP__, EOR__, LSR_M, SRE__, RTS__, ADC__, NOP__, RRA__,
+                NOP__, ADC__, ROR_M, RRA__, PLA__, ADC__, ROR_A, ARR__, JMP_I, ADC__,
+                ROR_M, RRA__, BVS__, ADC__, NOP__, RRA__, NOP__, ADC__, ROR_M, RRA__,
+                SEI__, ADC__, NOP__, RRA__, NOP__, ADC__, ROR_M, RRA__, NOP__, STA__,
+                NOP__, SAX__, STY__, STA__, STX__, SAX__, DEY__, NOP__, TXA__, XAA__,
+                STY__, STA__, STX__, SAX__, BCC__, STA__, NOP__, AHX__, STY__, STA__,
+                STX__, SAX__, TYA__, STA__, TXS__, XAS__, SHY__, STA__, SHX__, AHX__,
+                LDY__, LDA__, LDX__, LAX__, LDY__, LDA__, LDX__, LAX__, TAY__, LDA__,
+                TAX__, LAX__, LDY__, LDA__, LDX__, LAX__, BCS__, LDA__, NOP__, LAX__,
+                LDY__, LDA__, LDX__, LAX__, CLV__, LDA__, TSX__, LAR__, LDY__, LDA__,
+                LDX__, LAX__, CPY__, CMP__, NOP__, DCP__, CPY__, CMP__, DEC__, DCP__,
+                INY__, CMP__, DEX__, AXS__, CPY__, CMP__, DEC__, DCP__, BNE__, CMP__,
+                NOP__, DCP__, NOP__, CMP__, DEC__, DCP__, CLD__, CMP__, NOP__, DCP__,
+                NOP__, CMP__, DEC__, DCP__, CPX__, SBC__, NOP__, ISC__, CPX__, SBC__,
+                INC__, ISC__, INX__, SBC__, NOP__, SBC__, CPX__, SBC__, INC__, ISC__,
+                BEQ__, SBC__, NOP__, ISC__, NOP__, SBC__, INC__, ISC__, SED__, SBC__,
+                NOP__, ISC__, NOP__, SBC__, INC__, ISC__
+            };
+        }
+
+        private static void CPUClock()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_opcode);
+            cpu_reg_pc.v++;
+            cpu_addressings[cpu_opcode]();
+            cpu_instructions[cpu_opcode]();
+            if (CPU_IRQ_PIN || CPU_NMI_PIN)
+            {
+                Read(ref cpu_reg_pc.v, out cpu_dummy);
+                Read(ref cpu_reg_pc.v, out cpu_dummy);
+                Interrupt();
+            }
+        }
+
+        private static void CPUHardReset()
+        {
+            cpu_reg_a = 0;
+            cpu_reg_x = 0;
+            cpu_reg_y = 0;
+            cpu_reg_sp.l = 253;
+            cpu_reg_sp.h = 1;
+            ushort addr = 65532;
+            mem_board.ReadPRG(ref addr, out cpu_reg_pc.l);
+            addr++;
+            mem_board.ReadPRG(ref addr, out cpu_reg_pc.h);
+            register_p = 0;
+            cpu_flag_i = true;
+            cpu_reg_ea.v = 0;
+            cpu_opcode = 0;
+            CPU_IRQ_PIN = false;
+            CPU_NMI_PIN = false;
+            cpu_suspend_nmi = false;
+            cpu_suspend_irq = false;
+            IRQFlags = 0;
+        }
+
+        private static void CPUSoftReset()
+        {
+            cpu_flag_i = true;
+            cpu_reg_sp.v -= 3;
+            ushort addr = 65532;
+            Read(ref addr, out cpu_reg_pc.l);
+            addr++;
+            Read(ref addr, out cpu_reg_pc.h);
+        }
+
+        private static void Imp____()
+        {
+        }
+
+        private static void IndX_R_()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_dummy);
+            temp_add.l += cpu_reg_x;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void IndX_W_()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_dummy);
+            temp_add.l += cpu_reg_x;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+        }
+
+        private static void IndX_RW()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_dummy);
+            temp_add.l += cpu_reg_x;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void IndY_R_()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+                Read(ref cpu_reg_ea.v, out cpu_m);
+            }
+        }
+
+        private static void IndY_W_()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+            }
+        }
+
+        private static void IndY_RW()
+        {
+            temp_add.h = 0;
+            Read(ref cpu_reg_pc.v, out temp_add.l);
+            cpu_reg_pc.v++;
+            Read(ref temp_add.v, out cpu_reg_ea.l);
+            temp_add.l++;
+            Read(ref temp_add.v, out cpu_reg_ea.h);
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+            }
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void Zpg_R__()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void Zpg_W__()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+        }
+
+        private static void Zpg_RW_()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void ZpgX_R_()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_x;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void ZpgX_W_()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_x;
+        }
+
+        private static void ZpgX_RW()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_x;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void ZpgY_R_()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void ZpgY_W_()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_y;
+        }
+
+        private static void ZpgY_RW()
+        {
+            cpu_reg_ea.h = 0;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void Imm____()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_m);
+            cpu_reg_pc.v++;
+        }
+
+        private static void ImA____()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_dummy);
+        }
+
+        private static void Abs_R__()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void Abs_W__()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+        }
+
+        private static void Abs_RW_()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void AbsX_R_()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_x;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_x)
+            {
+                cpu_reg_ea.h++;
+                Read(ref cpu_reg_ea.v, out cpu_m);
+            }
+        }
+
+        private static void AbsX_W_()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_x;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_x)
+            {
+                cpu_reg_ea.h++;
+            }
+        }
+
+        private static void AbsX_RW()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_x;
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            if (cpu_reg_ea.l < cpu_reg_x)
+            {
+                cpu_reg_ea.h++;
+            }
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void AbsY_R_()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+                Read(ref cpu_reg_ea.v, out cpu_m);
+            }
+        }
+
+        private static void AbsY_W_()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+            }
+        }
+
+        private static void AbsY_RW()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v++;
+            cpu_reg_ea.l += cpu_reg_y;
+            Read(ref cpu_reg_ea.v, out cpu_m);
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h++;
+            }
+            Read(ref cpu_reg_ea.v, out cpu_m);
+        }
+
+        private static void Interrupt()
+        {
+            Push(ref cpu_reg_pc.h);
+            Push(ref cpu_reg_pc.l);
+            cpu_dummy = ((cpu_opcode == 0) ? register_pb() : register_p);
+            Push(ref cpu_dummy);
+            temp_add.v = InterruptVector;
+            cpu_suspend_nmi = true;
+            cpu_flag_i = true;
+            CPU_NMI_PIN = false;
+            Read(ref temp_add.v, out cpu_reg_pc.l);
+            temp_add.v++;
+            Read(ref temp_add.v, out cpu_reg_pc.h);
+            cpu_suspend_nmi = false;
+        }
+
+        private static void Branch(ref bool condition)
+        {
+            Read(ref cpu_reg_pc.v, out cpu_byte_temp);
+            cpu_reg_pc.v++;
+            if (!condition)
+            {
+                return;
+            }
+            cpu_suspend_irq = true;
+            Read(ref cpu_reg_pc.v, out cpu_dummy);
+            cpu_reg_pc.l += cpu_byte_temp;
+            cpu_suspend_irq = false;
+            if (cpu_byte_temp >= 128)
+            {
+                if (cpu_reg_pc.l >= cpu_byte_temp)
+                {
+                    Read(ref cpu_reg_pc.v, out cpu_dummy);
+                    cpu_reg_pc.h--;
+                }
+            }
+            else if (cpu_reg_pc.l < cpu_byte_temp)
+            {
+                Read(ref cpu_reg_pc.v, out cpu_dummy);
+                cpu_reg_pc.h++;
+            }
+        }
+
+        private static void Push(ref byte val)
+        {
+            Write(ref cpu_reg_sp.v, ref val);
+            cpu_reg_sp.l--;
+        }
+
+        private static void Pull(out byte val)
+        {
+            cpu_reg_sp.l++;
+            Read(ref cpu_reg_sp.v, out val);
+        }
+
+        private static void ADC__()
+        {
+            cpu_int_temp = cpu_reg_a + cpu_m + (cpu_flag_c ? 1 : 0);
+            cpu_flag_v = ((cpu_int_temp ^ cpu_reg_a) & (cpu_int_temp ^ cpu_m) & 0x80) != 0;
+            cpu_flag_n = (cpu_int_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_int_temp & 0xFF) == 0;
+            cpu_flag_c = cpu_int_temp >> 8 != 0;
+            cpu_reg_a = (byte)((uint)cpu_int_temp & 0xFFu);
+        }
+
+        private static void AHX__()
+        {
+            cpu_byte_temp = (byte)((uint)(cpu_reg_a & cpu_reg_x) & 7u);
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+        }
+
+        private static void ALR__()
+        {
+            cpu_reg_a &= cpu_m;
+            cpu_flag_c = (cpu_reg_a & 1) != 0;
+            cpu_reg_a >>= 1;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void ANC__()
+        {
+            cpu_reg_a &= cpu_m;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = cpu_reg_a == 0;
+            cpu_flag_c = (cpu_reg_a & 0x80) != 0;
+        }
+
+        private static void AND__()
+        {
+            cpu_reg_a &= cpu_m;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void ARR__()
+        {
+            cpu_reg_a = (byte)((uint)((cpu_m & cpu_reg_a) >> 1) | (cpu_flag_c ? 128u : 0u));
+            cpu_flag_z = (cpu_reg_a & 0xFF) == 0;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_c = (cpu_reg_a & 0x40) != 0;
+            cpu_flag_v = (((cpu_reg_a << 1) ^ cpu_reg_a) & 0x40) != 0;
+        }
+
+        private static void AXS__()
+        {
+            cpu_int_temp = (cpu_reg_a & cpu_reg_x) - cpu_m;
+            cpu_flag_n = (cpu_int_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_int_temp & 0xFF) == 0;
+            cpu_flag_c = ~cpu_int_temp >> 8 != 0;
+            cpu_reg_x = (byte)((uint)cpu_int_temp & 0xFFu);
+        }
+
+        private static void ASL_M()
+        {
+            cpu_flag_c = (cpu_m & 0x80) == 128;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_m = (byte)((uint)(cpu_m << 1) & 0xFEu);
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_flag_n = (cpu_m & 0x80) == 128;
+            cpu_flag_z = cpu_m == 0;
+        }
+
+        private static void ASL_A()
+        {
+            cpu_flag_c = (cpu_reg_a & 0x80) == 128;
+            cpu_reg_a = (byte)((uint)(cpu_reg_a << 1) & 0xFEu);
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void BCC__()
+        {
+            cpu_bool_tmp = !cpu_flag_c;
+            Branch(ref cpu_bool_tmp);
+        }
+
+        private static void BCS__()
+        {
+            Branch(ref cpu_flag_c);
+        }
+
+        private static void BEQ__()
+        {
+            Branch(ref cpu_flag_z);
+        }
+
+        private static void BIT__()
+        {
+            cpu_flag_n = (cpu_m & 0x80) != 0;
+            cpu_flag_v = (cpu_m & 0x40) != 0;
+            cpu_flag_z = (cpu_m & cpu_reg_a) == 0;
+        }
+
+        private static void BRK__()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_dummy);
+            cpu_reg_pc.v++;
+            Interrupt();
+        }
+
+        private static void BPL__()
+        {
+            cpu_bool_tmp = !cpu_flag_n;
+            Branch(ref cpu_bool_tmp);
+        }
+
+        private static void BNE__()
+        {
+            cpu_bool_tmp = !cpu_flag_z;
+            Branch(ref cpu_bool_tmp);
+        }
+
+        private static void BMI__()
+        {
+            Branch(ref cpu_flag_n);
+        }
+
+        private static void BVC__()
+        {
+            cpu_bool_tmp = !cpu_flag_v;
+            Branch(ref cpu_bool_tmp);
+        }
+
+        private static void BVS__()
+        {
+            Branch(ref cpu_flag_v);
+        }
+
+        private static void SED__()
+        {
+            cpu_flag_d = true;
+        }
+
+        private static void CLC__()
+        {
+            cpu_flag_c = false;
+        }
+
+        private static void CLD__()
+        {
+            cpu_flag_d = false;
+        }
+
+        private static void CLV__()
+        {
+            cpu_flag_v = false;
+        }
+
+        private static void CMP__()
+        {
+            cpu_int_temp = cpu_reg_a - cpu_m;
+            cpu_flag_n = (cpu_int_temp & 0x80) == 128;
+            cpu_flag_c = cpu_reg_a >= cpu_m;
+            cpu_flag_z = cpu_int_temp == 0;
+        }
+
+        private static void CPX__()
+        {
+            cpu_int_temp = cpu_reg_x - cpu_m;
+            cpu_flag_n = (cpu_int_temp & 0x80) == 128;
+            cpu_flag_c = cpu_reg_x >= cpu_m;
+            cpu_flag_z = cpu_int_temp == 0;
+        }
+
+        private static void CPY__()
+        {
+            cpu_int_temp = cpu_reg_y - cpu_m;
+            cpu_flag_n = (cpu_int_temp & 0x80) == 128;
+            cpu_flag_c = cpu_reg_y >= cpu_m;
+            cpu_flag_z = cpu_int_temp == 0;
+        }
+
+        private static void CLI__()
+        {
+            cpu_flag_i = false;
+        }
+
+        private static void DCP__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_m--;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_int_temp = cpu_reg_a - cpu_m;
+            cpu_flag_n = (cpu_int_temp & 0x80) != 0;
+            cpu_flag_z = cpu_int_temp == 0;
+            cpu_flag_c = ~cpu_int_temp >> 8 != 0;
+        }
+
+        private static void DEC__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_m--;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_flag_n = (cpu_m & 0x80) == 128;
+            cpu_flag_z = cpu_m == 0;
+        }
+
+        private static void DEY__()
+        {
+            cpu_reg_y--;
+            cpu_flag_z = cpu_reg_y == 0;
+            cpu_flag_n = (cpu_reg_y & 0x80) == 128;
+        }
+
+        private static void DEX__()
+        {
+            cpu_reg_x--;
+            cpu_flag_z = cpu_reg_x == 0;
+            cpu_flag_n = (cpu_reg_x & 0x80) == 128;
+        }
+
+        private static void EOR__()
+        {
+            cpu_reg_a ^= cpu_m;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void INC__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_m++;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_flag_n = (cpu_m & 0x80) == 128;
+            cpu_flag_z = cpu_m == 0;
+        }
+
+        private static void INX__()
+        {
+            cpu_reg_x++;
+            cpu_flag_z = cpu_reg_x == 0;
+            cpu_flag_n = (cpu_reg_x & 0x80) == 128;
+        }
+
+        private static void INY__()
+        {
+            cpu_reg_y++;
+            cpu_flag_n = (cpu_reg_y & 0x80) == 128;
+            cpu_flag_z = cpu_reg_y == 0;
+        }
+
+        private static void ISC__()
+        {
+            Read(ref cpu_reg_ea.v, out cpu_byte_temp);
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_byte_temp++;
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_int_temp = cpu_byte_temp ^ 0xFF;
+            cpu_int_temp1 = cpu_reg_a + cpu_int_temp + (cpu_flag_c ? 1 : 0);
+            cpu_flag_n = (cpu_int_temp1 & 0x80) != 0;
+            cpu_flag_v = ((cpu_int_temp1 ^ cpu_reg_a) & (cpu_int_temp1 ^ cpu_int_temp) & 0x80) != 0;
+            cpu_flag_z = (cpu_int_temp1 & 0xFF) == 0;
+            cpu_flag_c = cpu_int_temp1 >> 8 != 0;
+            cpu_reg_a = (byte)((uint)cpu_int_temp1 & 0xFFu);
+        }
+
+        private static void JMP__()
+        {
+            cpu_reg_pc.v = cpu_reg_ea.v;
+        }
+
+        private static void JMP_I()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            Read(ref cpu_reg_ea.v, out cpu_reg_pc.l);
+            cpu_reg_ea.l++;
+            Read(ref cpu_reg_ea.v, out cpu_reg_pc.h);
+        }
+
+        private static void JSR__()
+        {
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.l);
+            cpu_reg_pc.v++;
+            Write(ref cpu_reg_sp.v, ref cpu_reg_ea.l);
+            Push(ref cpu_reg_pc.h);
+            Push(ref cpu_reg_pc.l);
+            Read(ref cpu_reg_pc.v, out cpu_reg_ea.h);
+            cpu_reg_pc.v = cpu_reg_ea.v;
+        }
+
+        private static void LAR__()
+        {
+            cpu_reg_sp.l &= cpu_m;
+            cpu_reg_a = cpu_reg_sp.l;
+            cpu_reg_x = cpu_reg_sp.l;
+            cpu_flag_n = (cpu_reg_sp.l & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_sp.l & 0xFF) == 0;
+        }
+
+        private static void LAX__()
+        {
+            cpu_reg_x = (cpu_reg_a = cpu_m);
+            cpu_flag_n = (cpu_reg_x & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_x & 0xFF) == 0;
+        }
+
+        private static void LDA__()
+        {
+            cpu_reg_a = cpu_m;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void LDX__()
+        {
+            cpu_reg_x = cpu_m;
+            cpu_flag_n = (cpu_reg_x & 0x80) == 128;
+            cpu_flag_z = cpu_reg_x == 0;
+        }
+
+        private static void LDY__()
+        {
+            cpu_reg_y = cpu_m;
+            cpu_flag_n = (cpu_reg_y & 0x80) == 128;
+            cpu_flag_z = cpu_reg_y == 0;
+        }
+
+        private static void LSR_A()
+        {
+            cpu_flag_c = (cpu_reg_a & 1) == 1;
+            cpu_reg_a >>= 1;
+            cpu_flag_z = cpu_reg_a == 0;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+        }
+
+        private static void LSR_M()
+        {
+            cpu_flag_c = (cpu_m & 1) == 1;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_m >>= 1;
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_flag_z = cpu_m == 0;
+            cpu_flag_n = (cpu_m & 0x80) != 0;
+        }
+
+        private static void NOP__()
+        {
+        }
+
+        private static void ORA__()
+        {
+            cpu_reg_a |= cpu_m;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void PHA__()
+        {
+            Push(ref cpu_reg_a);
+        }
+
+        private static void PHP__()
+        {
+            cpu_dummy = register_pb();
+            Push(ref cpu_dummy);
+        }
+
+        private static void PLA__()
+        {
+            Read(ref cpu_reg_sp.v, out cpu_dummy);
+            Pull(out cpu_reg_a);
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void PLP__()
+        {
+            Read(ref cpu_reg_sp.v, out cpu_dummy);
+            Pull(out cpu_dummy);
+            register_p = cpu_dummy;
+        }
+
+        private static void RLA__()
+        {
+            Read(ref cpu_reg_ea.v, out cpu_byte_temp);
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_dummy = (byte)((uint)(cpu_byte_temp << 1) | (cpu_flag_c ? 1u : 0u));
+            Write(ref cpu_reg_ea.v, ref cpu_dummy);
+            cpu_flag_n = (cpu_dummy & 0x80) != 0;
+            cpu_flag_z = (cpu_dummy & 0xFF) == 0;
+            cpu_flag_c = (cpu_byte_temp & 0x80) != 0;
+            cpu_reg_a &= cpu_dummy;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_a & 0xFF) == 0;
+        }
+
+        private static void ROL_A()
+        {
+            cpu_byte_temp = (byte)((uint)(cpu_reg_a << 1) | (cpu_flag_c ? 1u : 0u));
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_flag_c = (cpu_reg_a & 0x80) != 0;
+            cpu_reg_a = cpu_byte_temp;
+        }
+
+        private static void ROL_M()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_byte_temp = (byte)((uint)(cpu_m << 1) | (cpu_flag_c ? 1u : 0u));
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_flag_c = (cpu_m & 0x80) != 0;
+        }
+
+        private static void ROR_A()
+        {
+            cpu_byte_temp = (byte)((uint)(cpu_reg_a >> 1) | (cpu_flag_c ? 128u : 0u));
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_flag_c = (cpu_reg_a & 1) != 0;
+            cpu_reg_a = cpu_byte_temp;
+        }
+
+        private static void ROR_M()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_m);
+            cpu_byte_temp = (byte)((uint)(cpu_m >> 1) | (cpu_flag_c ? 128u : 0u));
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_flag_c = (cpu_m & 1) != 0;
+        }
+
+        private static void RRA__()
+        {
+            Read(ref cpu_reg_ea.v, out cpu_byte_temp);
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_dummy = (byte)((uint)(cpu_byte_temp >> 1) | (cpu_flag_c ? 128u : 0u));
+            Write(ref cpu_reg_ea.v, ref cpu_dummy);
+            cpu_flag_n = (cpu_dummy & 0x80) != 0;
+            cpu_flag_z = (cpu_dummy & 0xFF) == 0;
+            cpu_flag_c = (cpu_byte_temp & 1) != 0;
+            cpu_byte_temp = cpu_dummy;
+            cpu_int_temp = cpu_reg_a + cpu_byte_temp + (cpu_flag_c ? 1 : 0);
+            cpu_flag_n = (cpu_int_temp & 0x80) != 0;
+            cpu_flag_v = ((cpu_int_temp ^ cpu_reg_a) & (cpu_int_temp ^ cpu_byte_temp) & 0x80) != 0;
+            cpu_flag_z = (cpu_int_temp & 0xFF) == 0;
+            cpu_flag_c = cpu_int_temp >> 8 != 0;
+            cpu_reg_a = (byte)cpu_int_temp;
+        }
+
+        private static void RTI__()
+        {
+            Read(ref cpu_reg_sp.v, out cpu_dummy);
+            Pull(out cpu_dummy);
+            register_p = cpu_dummy;
+            Pull(out cpu_reg_pc.l);
+            Pull(out cpu_reg_pc.h);
+        }
+
+        private static void RTS__()
+        {
+            Read(ref cpu_reg_sp.v, out cpu_dummy);
+            Pull(out cpu_reg_pc.l);
+            Pull(out cpu_reg_pc.h);
+            cpu_reg_pc.v++;
+            Read(ref cpu_reg_pc.v, out cpu_dummy);
+        }
+
+        private static void SAX__()
+        {
+            cpu_dummy = (byte)(cpu_reg_x & cpu_reg_a);
+            Write(ref cpu_reg_ea.v, ref cpu_dummy);
+        }
+
+        private static void SBC__()
+        {
+            cpu_m ^= byte.MaxValue;
+            cpu_int_temp = cpu_reg_a + cpu_m + (cpu_flag_c ? 1 : 0);
+            cpu_flag_n = (cpu_int_temp & 0x80) != 0;
+            cpu_flag_v = ((cpu_int_temp ^ cpu_reg_a) & (cpu_int_temp ^ cpu_m) & 0x80) != 0;
+            cpu_flag_z = (cpu_int_temp & 0xFF) == 0;
+            cpu_flag_c = cpu_int_temp >> 8 != 0;
+            cpu_reg_a = (byte)cpu_int_temp;
+        }
+
+        private static void SEC__()
+        {
+            cpu_flag_c = true;
+        }
+
+        private static void SEI__()
+        {
+            cpu_flag_i = true;
+        }
+
+        private static void SHX__()
+        {
+            cpu_byte_temp = (byte)(cpu_reg_x & (cpu_reg_ea.h + 1));
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_y;
+            if (cpu_reg_ea.l < cpu_reg_y)
+            {
+                cpu_reg_ea.h = cpu_byte_temp;
+            }
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+        }
+
+        private static void SHY__()
+        {
+            cpu_byte_temp = (byte)(cpu_reg_y & (cpu_reg_ea.h + 1));
+            Read(ref cpu_reg_ea.v, out cpu_dummy);
+            cpu_reg_ea.l += cpu_reg_x;
+            if (cpu_reg_ea.l < cpu_reg_x)
+            {
+                cpu_reg_ea.h = cpu_byte_temp;
+            }
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+        }
+
+        private static void SLO__()
+        {
+            Read(ref cpu_reg_ea.v, out cpu_byte_temp);
+            cpu_flag_c = (cpu_byte_temp & 0x80) != 0;
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_byte_temp <<= 1;
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_reg_a |= cpu_byte_temp;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_a & 0xFF) == 0;
+        }
+
+        private static void SRE__()
+        {
+            Read(ref cpu_reg_ea.v, out cpu_byte_temp);
+            cpu_flag_c = (cpu_byte_temp & 1) != 0;
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_byte_temp >>= 1;
+            Write(ref cpu_reg_ea.v, ref cpu_byte_temp);
+            cpu_flag_n = (cpu_byte_temp & 0x80) != 0;
+            cpu_flag_z = (cpu_byte_temp & 0xFF) == 0;
+            cpu_reg_a ^= cpu_byte_temp;
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_a & 0xFF) == 0;
+        }
+
+        private static void STA__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_reg_a);
+        }
+
+        private static void STX__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_reg_x);
+        }
+
+        private static void STY__()
+        {
+            Write(ref cpu_reg_ea.v, ref cpu_reg_y);
+        }
+
+        private static void TAX__()
+        {
+            cpu_reg_x = cpu_reg_a;
+            cpu_flag_n = (cpu_reg_x & 0x80) == 128;
+            cpu_flag_z = cpu_reg_x == 0;
+        }
+
+        private static void TAY__()
+        {
+            cpu_reg_y = cpu_reg_a;
+            cpu_flag_n = (cpu_reg_y & 0x80) == 128;
+            cpu_flag_z = cpu_reg_y == 0;
+        }
+
+        private static void TSX__()
+        {
+            cpu_reg_x = cpu_reg_sp.l;
+            cpu_flag_n = (cpu_reg_x & 0x80) != 0;
+            cpu_flag_z = cpu_reg_x == 0;
+        }
+
+        private static void TXA__()
+        {
+            cpu_reg_a = cpu_reg_x;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void TXS__()
+        {
+            cpu_reg_sp.l = cpu_reg_x;
+        }
+
+        private static void TYA__()
+        {
+            cpu_reg_a = cpu_reg_y;
+            cpu_flag_n = (cpu_reg_a & 0x80) == 128;
+            cpu_flag_z = cpu_reg_a == 0;
+        }
+
+        private static void XAA__()
+        {
+            cpu_reg_a = (byte)(cpu_reg_x & cpu_m);
+            cpu_flag_n = (cpu_reg_a & 0x80) != 0;
+            cpu_flag_z = (cpu_reg_a & 0xFF) == 0;
+        }
+
+        private static void XAS__()
+        {
+            cpu_reg_sp.l = (byte)(cpu_reg_a & cpu_reg_x);
+            Write(ref cpu_reg_ea.v, ref cpu_reg_sp.l);
+        }
+
+        private static void CPUWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(cpu_reg_pc.v);
+            bin.Write(cpu_reg_sp.v);
+            bin.Write(cpu_reg_ea.v);
+            bin.Write(cpu_reg_a);
+            bin.Write(cpu_reg_x);
+            bin.Write(cpu_reg_y);
+            bin.Write(cpu_flag_n);
+            bin.Write(cpu_flag_v);
+            bin.Write(cpu_flag_d);
+            bin.Write(cpu_flag_i);
+            bin.Write(cpu_flag_z);
+            bin.Write(cpu_flag_c);
+            bin.Write(cpu_m);
+            bin.Write(cpu_opcode);
+            bin.Write(cpu_byte_temp);
+            bin.Write(cpu_int_temp);
+            bin.Write(cpu_int_temp1);
+            bin.Write(cpu_dummy);
+            bin.Write(cpu_bool_tmp);
+            bin.Write(temp_add.v);
+            bin.Write(CPU_IRQ_PIN);
+            bin.Write(CPU_NMI_PIN);
+            bin.Write(cpu_suspend_nmi);
+            bin.Write(cpu_suspend_irq);
+        }
+
+        private static void CPUReadState(ref BinaryReader bin)
+        {
+            cpu_reg_pc.v = bin.ReadUInt16();
+            cpu_reg_sp.v = bin.ReadUInt16();
+            cpu_reg_ea.v = bin.ReadUInt16();
+            cpu_reg_a = bin.ReadByte();
+            cpu_reg_x = bin.ReadByte();
+            cpu_reg_y = bin.ReadByte();
+            cpu_flag_n = bin.ReadBoolean();
+            cpu_flag_v = bin.ReadBoolean();
+            cpu_flag_d = bin.ReadBoolean();
+            cpu_flag_i = bin.ReadBoolean();
+            cpu_flag_z = bin.ReadBoolean();
+            cpu_flag_c = bin.ReadBoolean();
+            cpu_m = bin.ReadByte();
+            cpu_opcode = bin.ReadByte();
+            cpu_byte_temp = bin.ReadByte();
+            cpu_int_temp = bin.ReadInt32();
+            cpu_int_temp1 = bin.ReadInt32();
+            cpu_dummy = bin.ReadByte();
+            cpu_bool_tmp = bin.ReadBoolean();
+            temp_add.v = bin.ReadUInt16();
+            CPU_IRQ_PIN = bin.ReadBoolean();
+            CPU_NMI_PIN = bin.ReadBoolean();
+            cpu_suspend_nmi = bin.ReadBoolean();
+            cpu_suspend_irq = bin.ReadBoolean();
+        }
+
+        private static void DMAHardReset()
+        {
+            dma_DMCDMAWaitCycles = 0;
+            dma_OAMDMAWaitCycles = 0;
+            dma_isOamDma = false;
+            dma_oamdma_i = 0;
+            dma_DMCOn = false;
+            dma_OAMOn = false;
+            dma_DMC_occurring = false;
+            dma_OAM_occurring = false;
+            dma_OAMFinishCounter = 0;
+            dma_Oamaddress = 0;
+            dma_OAMCYCLE = 0;
+            dma_latch = 0;
+            reg_2004 = 8196;
+        }
+
+        private static void DMASoftReset()
+        {
+            dma_DMCDMAWaitCycles = 0;
+            dma_OAMDMAWaitCycles = 0;
+            dma_isOamDma = false;
+            dma_oamdma_i = 0;
+            dma_DMCOn = false;
+            dma_OAMOn = false;
+            dma_DMC_occurring = false;
+            dma_OAM_occurring = false;
+            dma_OAMFinishCounter = 0;
+            dma_Oamaddress = 0;
+            dma_OAMCYCLE = 0;
+            dma_latch = 0;
+        }
+
+        internal static void AssertDMCDMA()
+        {
+            if (dma_OAM_occurring)
+            {
+                if (dma_OAMCYCLE < 508)
+                {
+                    dma_DMCDMAWaitCycles = (BUS_RW ? 1 : 0);
+                }
+                else
+                {
+                    dma_DMCDMAWaitCycles = 4 - (512 - dma_OAMCYCLE);
+                }
+            }
+            else
+            {
+                if (dma_DMC_occurring)
+                {
+                    return;
+                }
+                dma_DMCDMAWaitCycles = (BUS_RW ? 3 : 2);
+                if (dma_OAMFinishCounter == 3)
+                {
+                    dma_DMCDMAWaitCycles++;
+                }
+            }
+            dma_isOamDma = false;
+            dma_DMCOn = true;
+        }
+
+        private static void AssertOAMDMA()
+        {
+            if (!dma_OAM_occurring)
+            {
+                dma_OAMDMAWaitCycles = (apu_odd_cycle ? 1 : 2);
+                dma_isOamDma = true;
+                dma_OAMOn = true;
+            }
+        }
+
+        private static void DMAClock()
+        {
+            if (dma_OAMFinishCounter > 0)
+            {
+                dma_OAMFinishCounter--;
+            }
+            if (!BUS_RW)
+            {
+                if (dma_DMCDMAWaitCycles > 0)
+                {
+                    dma_DMCDMAWaitCycles--;
+                }
+                if (dma_OAMDMAWaitCycles > 0)
+                {
+                    dma_OAMDMAWaitCycles--;
+                }
+                return;
+            }
+            if (dma_DMCOn)
+            {
+                dma_DMC_occurring = true;
+                dma_DMCOn = false;
+                if (dma_DMCDMAWaitCycles > 0)
+                {
+                    if (BUS_ADDRESS == 16406 || BUS_ADDRESS == 16407)
+                    {
+                        Read(ref BUS_ADDRESS, out dma_dummy);
+                        dma_DMCDMAWaitCycles--;
+                        while (dma_DMCDMAWaitCycles > 0)
+                        {
+                            EmuClockComponents();
+                            dma_DMCDMAWaitCycles--;
+                        }
+                    }
+                    else
+                    {
+                        if (dma_DMCDMAWaitCycles > 0)
+                        {
+                            EmuClockComponents();
+                            dma_DMCDMAWaitCycles--;
+                        }
+                        while (dma_DMCDMAWaitCycles > 0)
+                        {
+                            Read(ref BUS_ADDRESS, out dma_dummy);
+                            dma_DMCDMAWaitCycles--;
+                        }
+                    }
+                }
+                DMCDoDMA();
+                dma_DMC_occurring = false;
+            }
+            if (!dma_OAMOn)
+            {
+                return;
+            }
+            dma_OAM_occurring = true;
+            dma_OAMOn = false;
+            if (dma_OAMDMAWaitCycles > 0)
+            {
+                if (BUS_ADDRESS == 16406 || BUS_ADDRESS == 16407)
+                {
+                    Read(ref BUS_ADDRESS, out dma_dummy);
+                    dma_OAMDMAWaitCycles--;
+                    while (dma_OAMDMAWaitCycles > 0)
+                    {
+                        EmuClockComponents();
+                        dma_OAMDMAWaitCycles--;
+                    }
+                }
+                else
+                {
+                    if (dma_OAMDMAWaitCycles > 0)
+                    {
+                        EmuClockComponents();
+                        dma_OAMDMAWaitCycles--;
+                    }
+                    while (dma_OAMDMAWaitCycles > 0)
+                    {
+                        Read(ref BUS_ADDRESS, out dma_dummy);
+                        dma_OAMDMAWaitCycles--;
+                    }
+                }
+            }
+            dma_OAMCYCLE = 0;
+            for (dma_oamdma_i = 0; dma_oamdma_i < 256; dma_oamdma_i++)
+            {
+                Read(ref dma_Oamaddress, out dma_latch);
+                dma_OAMCYCLE++;
+                Write(ref reg_2004, ref dma_latch);
+                dma_OAMCYCLE++;
+                dma_Oamaddress = (ushort)(++dma_Oamaddress & 0xFFFFu);
+            }
+            dma_OAMCYCLE = 0;
+            dma_OAMFinishCounter = 5;
+            dma_OAM_occurring = false;
+        }
+
+        private static void DMAWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(dma_DMCDMAWaitCycles);
+            bin.Write(dma_OAMDMAWaitCycles);
+            bin.Write(dma_isOamDma);
+            bin.Write(dma_oamdma_i);
+            bin.Write(dma_DMCOn);
+            bin.Write(dma_OAMOn);
+            bin.Write(dma_DMC_occurring);
+            bin.Write(dma_OAM_occurring);
+            bin.Write(dma_OAMFinishCounter);
+            bin.Write(dma_Oamaddress);
+            bin.Write(dma_OAMCYCLE);
+            bin.Write(dma_latch);
+            bin.Write(dma_dummy);
+        }
+
+        private static void DMAReadState(ref BinaryReader bin)
+        {
+            dma_DMCDMAWaitCycles = bin.ReadInt32();
+            dma_OAMDMAWaitCycles = bin.ReadInt32();
+            dma_isOamDma = bin.ReadBoolean();
+            dma_oamdma_i = bin.ReadInt32();
+            dma_DMCOn = bin.ReadBoolean();
+            dma_OAMOn = bin.ReadBoolean();
+            dma_DMC_occurring = bin.ReadBoolean();
+            dma_OAM_occurring = bin.ReadBoolean();
+            dma_OAMFinishCounter = bin.ReadInt32();
+            dma_Oamaddress = bin.ReadUInt16();
+            dma_OAMCYCLE = bin.ReadInt32();
+            dma_latch = bin.ReadByte();
+            dma_dummy = bin.ReadByte();
+        }
+
+        private static void PollInterruptStatus()
+        {
+            if (!cpu_suspend_nmi)
+            {
+                if (PPU_NMI_Current & !PPU_NMI_Old)
+                {
+                    CPU_NMI_PIN = true;
+                }
+                PPU_NMI_Old = (PPU_NMI_Current = false);
+            }
+            if (!cpu_suspend_irq)
+            {
+                CPU_IRQ_PIN = !cpu_flag_i && IRQFlags != 0;
+            }
+            if (CPU_NMI_PIN)
+            {
+                InterruptVector = 65530;
+            }
+            else
+            {
+                InterruptVector = 65534;
+            }
+        }
+
+        private static void InterruptsWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(IRQFlags);
+            bin.Write(PPU_NMI_Current);
+            bin.Write(PPU_NMI_Old);
+            bin.Write(InterruptVector);
+        }
+
+        private static void InterruptsReadState(ref BinaryReader bin)
+        {
+            IRQFlags = bin.ReadInt32();
+            PPU_NMI_Current = bin.ReadBoolean();
+            PPU_NMI_Old = bin.ReadBoolean();
+            InterruptVector = bin.ReadUInt16();
+        }
+
+        public static void SetupGameGenie(bool IsGameGenieActive, GameGenieCode[] GameGenieCodes)
+        {
+            if (mem_board != null)
+            {
+                mem_board.SetupGameGenie(IsGameGenieActive, GameGenieCodes);
+            }
+        }
+
+        private static void MEMInitialize(IRom rom)
+        {
+            Tracer.WriteLine("Looking for mapper # " + rom.MapperNumber + "....");
+            if (MyNesMain.IsBoardExist(rom.MapperNumber))
+            {
+                Tracer.WriteLine("Mapper # " + rom.MapperNumber + " located, assigning...");
+                mem_board = MyNesMain.GetBoard(rom.MapperNumber);
+                Tracer.WriteInformation("Mapper # " + rom.MapperNumber + " assigned successfully.");
+                if (mem_board.HasIssues)
+                {
+                    Tracer.WriteWarning(MNInterfaceLanguage.Mapper + " # " + mem_board.MapperNumber + " [" + mem_board.Name + "] " + MNInterfaceLanguage.Message_Error17);
+                    MyNesMain.VideoProvider.WriteWarningNotification(MNInterfaceLanguage.Mapper + " # " + mem_board.MapperNumber + " [" + mem_board.Name + "] " + MNInterfaceLanguage.Message_Error17, instant: false);
+                }
+            }
+            else
+            {
+                Tracer.WriteError("Mapper # " + rom.MapperNumber + " IS NOT LOCATED, mapper is not supported or unable to find it.");
+                MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Mapper + " # " + rom.MapperNumber + " " + MNInterfaceLanguage.Message_Error14, instant: false);
+                mem_board = MyNesMain.GetBoard(0);
+                Tracer.WriteWarning("Mapper # 0 [NROM] will be used instead, assigned successfully.");
+                MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Mapper + " # 0 [NROM] " + MNInterfaceLanguage.Message_Error15, instant: false);
+            }
+            mem_read_accesses = new MemReadAccess[65536];
+            mem_write_accesses = new MemWriteAccess[65536];
+            MEMMap(MEMReadWRAM, new ushort[2] { 0, 4096 });
+            MEMMap(MEMWriteWRAM, new ushort[2] { 0, 4096 });
+            MEMMap(PPUIORead, new ushort[2] { 8192, 12288 });
+            MEMMap(PPUIOWrite, new ushort[2] { 8192, 12288 });
+            MEMMap(APUIORead, new ushort[1] { 16384 });
+            MEMMap(APUIOWrite, new ushort[1] { 16384 });
+            MEMMap(mem_board.ReadEX, new ushort[1] { 20480 });
+            MEMMap(mem_board.WriteEX, new ushort[1] { 20480 });
+            MEMMap(mem_board.ReadSRM, new ushort[2] { 24576, 28672 });
+            MEMMap(mem_board.WriteSRM, new ushort[2] { 24576, 28672 });
+            MEMMap(mem_board.ReadPRG, new ushort[8] { 32768, 36864, 40960, 45056, 49152, 53248, 57344, 61440 });
+            MEMMap(mem_board.WritePRG, new ushort[8] { 32768, 36864, 40960, 45056, 49152, 53248, 57344, 61440 });
+            mem_board.Initialize(rom);
+            mem_wram = new byte[2048];
+        }
+
+        private static void MEMHardReset()
+        {
+            mem_wram = new byte[2048];
+            mem_wram[8] = 247;
+            mem_wram[9] = 239;
+            mem_wram[10] = 223;
+            mem_wram[15] = 191;
+            Tracer.WriteLine("Reading SRAM ...");
+            SRAMFileName = Path.Combine(MyNesMain.EmuSettings.SRAMFolder, Path.GetFileNameWithoutExtension(CurrentFilePath) + ".srm");
+            if (File.Exists(SRAMFileName))
+            {
+                FileStream fileStream = new FileStream(SRAMFileName, FileMode.Open, FileAccess.Read);
+                byte[] array = new byte[fileStream.Length];
+                fileStream.Read(array, 0, array.Length);
+                fileStream.Flush();
+                fileStream.Close();
+                byte[] outData = new byte[0];
+                ZlipWrapper.DecompressData(array, out outData);
+                mem_board.LoadSRAM(outData);
+                Tracer.WriteLine("SRAM read successfully.");
+            }
+            else
+            {
+                Tracer.WriteLine("SRAM file not found; rom has no SRAM or file not exist.");
+            }
+            ReloadGameGenieCodes();
+            mem_board.HardReset();
+        }
+
+        public static void ReloadGameGenieCodes()
+        {
+            Tracer.WriteLine("Reading game genie codes (if available)....");
+            GMFileName = Path.Combine(MyNesMain.EmuSettings.GameGenieFolder, Path.GetFileNameWithoutExtension(CurrentFilePath) + ".txt");
+            mem_board.GameGenieCodes = new GameGenieCode[0];
+            if (File.Exists(GMFileName))
+            {
+                XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
+                xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;
+                xmlReaderSettings.IgnoreWhitespace = true;
+                XmlReader xmlReader = XmlReader.Create(GMFileName, xmlReaderSettings);
+                xmlReader.Read();
+                xmlReader.Read();
+                if (xmlReader.Name != "MyNesGameGenieCodesList")
+                {
+                    xmlReader.Close();
+                    return;
+                }
+                GameGenie gameGenie = new GameGenie();
+                List<GameGenieCode> list = new List<GameGenieCode>();
+                while (xmlReader.Read())
+                {
+                    if (xmlReader.Name == "Code")
+                    {
+                        GameGenieCode item = default(GameGenieCode);
+                        item.Enabled = true;
+                        xmlReader.MoveToAttribute("code");
+                        item.Name = xmlReader.Value.ToString();
+                        if (item.Name.Length == 6)
+                        {
+                            item.Address = gameGenie.GetGGAddress(gameGenie.GetCodeAsHEX(item.Name), 6) | 0x8000;
+                            item.Value = gameGenie.GetGGValue(gameGenie.GetCodeAsHEX(item.Name), 6);
+                            item.IsCompare = false;
+                        }
+                        else
+                        {
+                            item.Address = gameGenie.GetGGAddress(gameGenie.GetCodeAsHEX(item.Name), 8) | 0x8000;
+                            item.Value = gameGenie.GetGGValue(gameGenie.GetCodeAsHEX(item.Name), 8);
+                            item.Compare = gameGenie.GetGGCompareValue(gameGenie.GetCodeAsHEX(item.Name));
+                            item.IsCompare = true;
+                        }
+                        list.Add(item);
+                    }
+                }
+                xmlReader.Close();
+                if (list.Count > 0)
+                {
+                    mem_board.GameGenieCodes = list.ToArray();
+                    Tracer.WriteInformation("Game Genie codes loaded successfully, total of " + list.Count);
+                }
+                else
+                {
+                    Tracer.WriteError("There is no Game Genie code in the file to load.");
+                }
+            }
+            else
+            {
+                Tracer.WriteWarning("No Game Genie file found for this game.");
+            }
+        }
+
+        private static void MEMMap(MemReadAccess readAccess, ushort[] addresses)
+        {
+            for (int i = 0; i < addresses.Length; i++)
+            {
+                mem_read_accesses[(addresses[i] & 0xF000) >> 12] = readAccess;
+            }
+        }
+
+        private static void MEMMap(MemWriteAccess writeAccess, ushort[] addresses)
+        {
+            for (int i = 0; i < addresses.Length; i++)
+            {
+                mem_write_accesses[(addresses[i] & 0xF000) >> 12] = writeAccess;
+            }
+        }
+
+        private static void MEMReadWRAM(ref ushort addr, out byte value)
+        {
+            value = mem_wram[addr & 0x7FF];
+        }
+
+        private static void MEMWriteWRAM(ref ushort addr, ref byte value)
+        {
+            mem_wram[addr & 0x7FF] = value;
+        }
+
+        internal static void Read(ref ushort addr, out byte value)
+        {
+            BUS_RW = true;
+            BUS_ADDRESS = addr;
+            EmuClockComponents();
+            mem_read_accesses[(addr & 0xF000) >> 12](ref addr, out value);
+        }
+
+        private static void Write(ref ushort addr, ref byte value)
+        {
+            BUS_RW = false;
+            BUS_ADDRESS = addr;
+            EmuClockComponents();
+            mem_write_accesses[(addr & 0xF000) >> 12](ref addr, ref value);
+        }
+
+        internal static void SaveSRAM()
+        {
+            if (mem_board != null && MyNesMain.EmuSettings.SaveSRAMAtEmuShutdown && mem_board.SRAMSaveRequired)
+            {
+                Tracer.WriteLine("Saving SRAM ...");
+                byte[] outData = new byte[0];
+                ZlipWrapper.CompressData(mem_board.GetSRAMBuffer(), out outData);
+                FileStream fileStream = new FileStream(SRAMFileName, FileMode.Create, FileAccess.Write);
+                fileStream.Write(outData, 0, outData.Length);
+                fileStream.Flush();
+                fileStream.Close();
+                Tracer.WriteLine("SRAM saved successfully.");
+            }
+        }
+
+        private static void MEMWriteState(ref BinaryWriter bin)
+        {
+            mem_board.WriteStateData(ref bin);
+            bin.Write(mem_wram);
+            bin.Write(BUS_RW);
+            bin.Write(BUS_ADDRESS);
+        }
+
+        private static void MEMReadState(ref BinaryReader bin)
+        {
+            mem_board.ReadStateData(ref bin);
+            bin.Read(mem_wram, 0, mem_wram.Length);
+            BUS_RW = bin.ReadBoolean();
+            BUS_ADDRESS = bin.ReadUInt16();
+        }
+
+        private static void PORTSInitialize()
+        {
+            if (joypad1 == null)
+            {
+                joypad1 = new BlankJoypad();
+            }
+            if (joypad2 == null)
+            {
+                joypad2 = new BlankJoypad();
+            }
+            if (joypad3 == null)
+            {
+                joypad3 = new BlankJoypad();
+            }
+            if (joypad4 == null)
+            {
+                joypad4 = new BlankJoypad();
+            }
+        }
+
+        public static void SetupControllers(IJoypadConnecter joy1, IJoypadConnecter joy2, IJoypadConnecter joy3, IJoypadConnecter joy4)
+        {
+            joypad1 = joy1;
+            joypad2 = joy2;
+            joypad3 = joy3;
+            joypad4 = joy4;
+        }
+
+        public static void SetupVSUnisystemDIP(IVSUnisystemDIPConnecter uni)
+        {
+        }
+
+        public static void SetupControllersP1(IJoypadConnecter joy)
+        {
+            joypad1 = joy;
+        }
+
+        public static void SetupControllersP2(IJoypadConnecter joy)
+        {
+            joypad2 = joy;
+        }
+
+        public static void SetupControllersP3(IJoypadConnecter joy)
+        {
+            joypad3 = joy;
+        }
+
+        public static void SetupControllersP4(IJoypadConnecter joy)
+        {
+            joypad4 = joy;
+        }
+
+        public static void DestroyJoypads()
+        {
+            if (joypad1 == null)
+            {
+                joypad1 = new BlankJoypad();
+            }
+            else
+            {
+                joypad1.Destroy();
+            }
+            if (joypad2 == null)
+            {
+                joypad2 = new BlankJoypad();
+            }
+            else
+            {
+                joypad1.Destroy();
+            }
+            if (joypad3 == null)
+            {
+                joypad3 = new BlankJoypad();
+            }
+            else
+            {
+                joypad1.Destroy();
+            }
+            if (joypad4 == null)
+            {
+                joypad4 = new BlankJoypad();
+            }
+            else
+            {
+                joypad1.Destroy();
+            }
+        }
+
+        private static void PORTWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(PORT0);
+            bin.Write(PORT1);
+            bin.Write(inputStrobe);
+        }
+
+        private static void PORTReadState(ref BinaryReader bin)
+        {
+            PORT0 = bin.ReadInt32();
+            PORT1 = bin.ReadInt32();
+            inputStrobe = bin.ReadInt32();
+        }
+
+        public static void SetupPalette(int[] pal)
+        {
+            ppu_palette = pal;
+        }
+
+        private static void PPUInitialize()
+        {
+            ppu_reg_update_func = new Action[8] { PPUOnRegister2000, PPUOnRegister2001, PPUOnRegister2002, PPUOnRegister2003, PPUOnRegister2004, PPUOnRegister2005, PPUOnRegister2006, PPUOnRegister2007 };
+            ppu_reg_read_func = new Action[8] { PPURead2000, PPURead2001, PPURead2002, PPURead2003, PPURead2004, PPURead2005, PPURead2006, PPURead2007 };
+            ppu_bkg_fetches = new Action[8] { PPUBKFetch0, PPUBKFetch1, PPUBKFetch2, PPUBKFetch3, PPUBKFetch4, PPUBKFetch5, PPUBKFetch6, PPUBKFetch7 };
+            ppu_spr_fetches = new Action[8] { PPUBKFetch0, PPUBKFetch1, PPUBKFetch2, PPUBKFetch3, PPUSPRFetch0, PPUSPRFetch1, PPUSPRFetch2, PPUSPRFetch3 };
+            ppu_oam_phases = new Action[9] { PPUOamPhase0, PPUOamPhase1, PPUOamPhase2, PPUOamPhase3, PPUOamPhase4, PPUOamPhase5, PPUOamPhase6, PPUOamPhase7, PPUOamPhase8 };
+            ppu_h_clocks = new Action[341];
+            ppu_h_clocks[0] = PPUHClock_000_Idle;
+            for (int i = 1; i < 257; i++)
+            {
+                ppu_h_clocks[i] = PPUHClock_1_256_BKGClocks;
+            }
+            for (int j = 257; j < 321; j++)
+            {
+                ppu_h_clocks[j] = PPUHClock_257_320_SPRClocks;
+            }
+            for (int k = 321; k < 337; k++)
+            {
+                ppu_h_clocks[k] = PPUHClock_321_336_DUMClocks;
+            }
+            for (int l = 337; l < 341; l++)
+            {
+                ppu_h_clocks[l] = PPUHClock_337_340_DUMClocks;
+            }
+            ppu_v_clocks = new Action[320];
+            for (int m = 0; m < 240; m++)
+            {
+                ppu_v_clocks[m] = PPUScanlineRender;
+            }
+            ppu_v_clocks[240] = PPUScanlineVBLANK;
+            ppu_oam_bank = new byte[256];
+            ppu_oam_bank_secondary = new byte[32];
+            ppu_palette_bank = new byte[32];
+            ppu_bkg_pixels = new int[512];
+            ppu_spr_pixels = new int[512];
+            ppu_screen_pixels = new int[61440];
+            ppu_palette = NTSCPaletteGenerator.GeneratePalette();
+        }
+
+        private static void PPUHardReset()
+        {
+            ppu_reg_2001_grayscale = 243;
+            switch (Region)
+            {
+                case EmuRegion.NTSC:
+                    ppu_clock_vblank_start = 241;
+                    ppu_clock_vblank_end = 261;
+                    ppu_use_odd_cycle = true;
+                    break;
+                case EmuRegion.PALB:
+                    ppu_clock_vblank_start = 241;
+                    ppu_clock_vblank_end = 311;
+                    ppu_use_odd_cycle = false;
+                    break;
+                case EmuRegion.DENDY:
+                    {
+                        ppu_clock_vblank_start = 291;
+                        ppu_clock_vblank_end = 311;
+                        for (int i = 241; i <= 290; i++)
+                        {
+                            ppu_v_clocks[i] = PPUScanlineVBLANK;
+                        }
+                        ppu_use_odd_cycle = false;
+                        break;
+                    }
+            }
+            ppu_v_clocks[ppu_clock_vblank_start] = PPUScanlineVBLANKStart;
+            for (int j = ppu_clock_vblank_start + 1; j <= ppu_clock_vblank_end - 1; j++)
+            {
+                ppu_v_clocks[j] = PPUScanlineVBLANK;
+            }
+            ppu_v_clocks[ppu_clock_vblank_end] = PPUScanlineVBLANKEnd;
+            ppu_oam_bank = new byte[256];
+            ppu_oam_bank_secondary = new byte[32];
+            PPUOamReset();
+            ppu_palette_bank = new byte[32]
+            {
+                9, 1, 0, 1, 0, 2, 2, 13, 8, 16,
+                8, 36, 0, 0, 4, 44, 9, 1, 52, 3,
+                0, 4, 0, 20, 8, 58, 0, 2, 0, 32,
+                44, 8
+            };
+            ppu_reg_io_db = 0;
+            ppu_reg_io_addr = 0;
+            ppu_reg_access_happened = false;
+            ppu_reg_access_w = false;
+            ppu_reg_2000_vram_address_increament = 1;
+            ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites = 0;
+            ppu_reg_2000_background_pattern_table_address = 0;
+            ppu_reg_2000_Sprite_size = 0;
+            ppu_reg_2000_VBI = false;
+            ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen = false;
+            ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen = false;
+            ppu_reg_2001_show_background = false;
+            ppu_reg_2001_show_sprites = false;
+            ppu_reg_2001_grayscale = 63;
+            ppu_reg_2001_emphasis = 0;
+            ppu_reg_2002_SpriteOverflow = false;
+            ppu_reg_2002_Sprite0Hit = false;
+            ppu_reg_2002_VblankStartedFlag = false;
+            ppu_reg_2003_oam_addr = 0;
+            ppu_is_sprfetch = false;
+            ppu_use_odd_swap = false;
+            ppu_clock_h = 0;
+            ppu_clock_v = 0;
+        }
+
+        private static void PPUClock()
+        {
+            mem_board.OnPPUClock();
+            ppu_v_clocks[ppu_clock_v]();
+            ppu_clock_h++;
+            if (ppu_clock_h >= 341)
+            {
+                mem_board.OnPPUScanlineTick();
+                if (ppu_clock_v == ppu_clock_vblank_end)
+                {
+                    ppu_clock_v = 0;
+                    ppu_frame_finished = true;
+                }
+                else
+                {
+                    ppu_clock_v++;
+                }
+                ppu_clock_h -= 341;
+            }
+            if (ppu_reg_access_happened)
+            {
+                ppu_reg_access_happened = false;
+                ppu_reg_update_func[ppu_reg_io_addr]();
+            }
+        }
+
+        public static int GetPixel(int x, int y)
+        {
+            return ppu_screen_pixels[y * 256 + x];
+        }
+
+        private static void PPUScanlineRender()
+        {
+            ppu_h_clocks[ppu_clock_h]();
+        }
+
+        private static void PPUScanlineVBLANKStart()
+        {
+            ppu_is_nmi_time = (ppu_clock_h >= 1) & (ppu_clock_h <= 3);
+            if (ppu_is_nmi_time)
+            {
+                if (ppu_clock_h == 1)
+                {
+                    ppu_reg_2002_VblankStartedFlag = true;
+                }
+                PPU_NMI_Current = ppu_reg_2002_VblankStartedFlag & ppu_reg_2000_VBI;
+            }
+        }
+
+        private static void PPUScanlineVBLANKEnd()
+        {
+            ppu_is_nmi_time = (ppu_clock_h >= 1) & (ppu_clock_h <= 3);
+            if (ppu_clock_h == 1)
+            {
+                ppu_reg_2002_Sprite0Hit = false;
+                ppu_reg_2002_VblankStartedFlag = false;
+                ppu_reg_2002_SpriteOverflow = false;
+            }
+            PPUScanlineRender();
+            if (ppu_use_odd_cycle && ppu_clock_h == 339)
+            {
+                ppu_use_odd_swap = !ppu_use_odd_swap;
+                if (!ppu_use_odd_swap & (ppu_reg_2001_show_background || ppu_reg_2001_show_sprites))
+                {
+                    ppu_odd_swap_done = true;
+                    ppu_clock_h++;
+                }
+            }
+        }
+
+        private static void PPUScanlineVBLANK()
+        {
+        }
+
+        private static void PPUHClock_000_Idle()
+        {
+            if (ppu_odd_swap_done)
+            {
+                ppu_bkg_fetches[1]();
+                ppu_odd_swap_done = false;
+            }
+        }
+
+        private static void PPUHClock_1_256_BKGClocks()
+        {
+            if (ppu_reg_2001_show_background || ppu_reg_2001_show_sprites)
+            {
+                if (ppu_clock_v != ppu_clock_vblank_end)
+                {
+                    if (ppu_clock_h > 0 && ppu_clock_h < 65)
+                    {
+                        ppu_oam_bank_secondary[(ppu_clock_h - 1) & 0x1F] = byte.MaxValue;
+                    }
+                    else
+                    {
+                        if (ppu_clock_h == 65)
+                        {
+                            PPUOamReset();
+                        }
+                        if (((ppu_clock_h - 1) & 1) == 0)
+                        {
+                            PPUOamEvFetch();
+                        }
+                        else
+                        {
+                            ppu_oam_phases[ppu_phase_index]();
+                        }
+                        if (ppu_clock_h == 256)
+                        {
+                            PPUOamClear();
+                        }
+                    }
+                }
+                ppu_bkg_fetches[(ppu_clock_h - 1) & 7]();
+                if (ppu_clock_v < 240)
+                {
+                    RenderPixel();
+                }
+            }
+            else
+            {
+                if (ppu_clock_v >= 240)
+                {
+                    return;
+                }
+                if ((ppu_vram_addr & 0x3F00) == 16128)
+                {
+                    if ((ppu_vram_addr & 3) == 0)
+                    {
+                        ppu_screen_pixels[ppu_clock_h - 1 + ppu_clock_v * 256] = ppu_palette[(ppu_palette_bank[ppu_vram_addr & 0xC] & ppu_reg_2001_grayscale) | ppu_reg_2001_emphasis];
+                    }
+                    else
+                    {
+                        ppu_screen_pixels[ppu_clock_h - 1 + ppu_clock_v * 256] = ppu_palette[(ppu_palette_bank[ppu_vram_addr & 0x1F] & ppu_reg_2001_grayscale) | ppu_reg_2001_emphasis];
+                    }
+                }
+                else
+                {
+                    ppu_screen_pixels[ppu_clock_h - 1 + ppu_clock_v * 256] = ppu_palette[(ppu_palette_bank[0] & ppu_reg_2001_grayscale) | ppu_reg_2001_emphasis];
+                }
+            }
+        }
+
+        private static void PPUHClock_257_320_SPRClocks()
+        {
+            if (ppu_reg_2001_show_background || ppu_reg_2001_show_sprites)
+            {
+                ppu_spr_fetches[(ppu_clock_h - 1) & 7]();
+                if (ppu_clock_h == 257)
+                {
+                    ppu_vram_addr = (ushort)((ppu_vram_addr & 0x7BE0u) | (ppu_vram_addr_temp & 0x41Fu));
+                }
+                if (ppu_clock_v == ppu_clock_vblank_end && ppu_clock_h >= 280 && ppu_clock_h <= 304)
+                {
+                    ppu_vram_addr = (ushort)((ppu_vram_addr & 0x41Fu) | (ppu_vram_addr_temp & 0x7BE0u));
+                }
+            }
+        }
+
+        private static void PPUHClock_321_336_DUMClocks()
+        {
+            if (ppu_reg_2001_show_background || ppu_reg_2001_show_sprites)
+            {
+                ppu_bkg_fetches[(ppu_clock_h - 1) & 7]();
+            }
+        }
+
+        private static void PPUHClock_337_340_DUMClocks()
+        {
+            if (ppu_reg_2001_show_background || ppu_reg_2001_show_sprites)
+            {
+                ppu_bkg_fetches[(ppu_clock_h - 1) & 1]();
+            }
+        }
+
+        private static void PPUBKFetch0()
+        {
+            ppu_bkgfetch_nt_addr = (ushort)(0x2000u | (ppu_vram_addr & 0xFFFu));
+            mem_board.OnPPUAddressUpdate(ref ppu_bkgfetch_nt_addr);
+        }
+
+        private static void PPUBKFetch1()
+        {
+            mem_board.ReadNMT(ref ppu_bkgfetch_nt_addr, out ppu_bkgfetch_nt_data);
+        }
+
+        private static void PPUBKFetch2()
+        {
+            ppu_bkgfetch_at_addr = (ushort)(0x23C0u | (ppu_vram_addr & 0xC00u) | ((uint)(ppu_vram_addr >> 4) & 0x38u) | ((uint)(ppu_vram_addr >> 2) & 7u));
+            mem_board.OnPPUAddressUpdate(ref ppu_bkgfetch_at_addr);
+        }
+
+        private static void PPUBKFetch3()
+        {
+            mem_board.ReadNMT(ref ppu_bkgfetch_at_addr, out ppu_bkgfetch_at_data);
+            ppu_bkgfetch_at_data = (byte)(ppu_bkgfetch_at_data >> (((ppu_vram_addr >> 4) & 4) | (ppu_vram_addr & 2)));
+        }
+
+        private static void PPUBKFetch4()
+        {
+            ppu_bkgfetch_lb_addr = (ushort)((uint)(ppu_reg_2000_background_pattern_table_address | (ppu_bkgfetch_nt_data << 4)) | ((uint)(ppu_vram_addr >> 12) & 7u));
+            mem_board.OnPPUAddressUpdate(ref ppu_bkgfetch_lb_addr);
+        }
+
+        private static void PPUBKFetch5()
+        {
+            mem_board.ReadCHR(ref ppu_bkgfetch_lb_addr, out ppu_bkgfetch_lb_data);
+        }
+
+        private static void PPUBKFetch6()
+        {
+            ppu_bkgfetch_hb_addr = (ushort)((uint)(ppu_reg_2000_background_pattern_table_address | (ppu_bkgfetch_nt_data << 4)) | 8u | ((uint)(ppu_vram_addr >> 12) & 7u));
+            mem_board.OnPPUAddressUpdate(ref ppu_bkgfetch_hb_addr);
+        }
+
+        private static void PPUBKFetch7()
+        {
+            mem_board.ReadCHR(ref ppu_bkgfetch_hb_addr, out ppu_bkgfetch_hb_data);
+            ppu_bkg_render_pos = ppu_clock_h + 8;
+            ppu_bkg_render_pos %= 336;
+            if (ppu_clock_h == 256)
+            {
+                if ((ppu_vram_addr & 0x7000) != 28672)
+                {
+                    ppu_vram_addr += 4096;
+                }
+                else
+                {
+                    ppu_vram_addr ^= 28672;
+                    switch (ppu_vram_addr & 0x3E0)
+                    {
+                        case 928:
+                            ppu_vram_addr ^= 2976;
+                            break;
+                        case 992:
+                            ppu_vram_addr ^= 992;
+                            break;
+                        default:
+                            ppu_vram_addr += 32;
+                            break;
+                    }
+                }
+            }
+            else if ((ppu_vram_addr & 0x1F) == 31)
+            {
+                ppu_vram_addr ^= 1055;
+            }
+            else
+            {
+                ppu_vram_addr++;
+            }
+            for (ppu_bkg_render_i = 0; ppu_bkg_render_i < 8; ppu_bkg_render_i++)
+            {
+                ppu_bkg_render_tmp_val = ((ppu_bkgfetch_at_data << 2) & 0xC) | ((ppu_bkgfetch_lb_data >> 7) & 1) | ((ppu_bkgfetch_hb_data >> 6) & 2);
+                ppu_bkg_pixels[ppu_bkg_render_i + ppu_bkg_render_pos] = ppu_bkg_render_tmp_val;
+                ppu_bkgfetch_lb_data <<= 1;
+                ppu_bkgfetch_hb_data <<= 1;
+            }
+        }
+
+        private static void PPUSPRFetch0()
+        {
+            ppu_sprfetch_slot = (ppu_clock_h - 1 >> 3) & 7;
+            ppu_sprfetch_slot = 7 - ppu_sprfetch_slot;
+            ppu_sprfetch_y_data = ppu_oam_bank_secondary[ppu_sprfetch_slot * 4];
+            ppu_sprfetch_t_data = ppu_oam_bank_secondary[ppu_sprfetch_slot * 4 + 1];
+            ppu_sprfetch_at_data = ppu_oam_bank_secondary[ppu_sprfetch_slot * 4 + 2];
+            ppu_sprfetch_x_data = ppu_oam_bank_secondary[ppu_sprfetch_slot * 4 + 3];
+            ppu_temp_comparator = (ppu_clock_v - ppu_sprfetch_y_data) ^ (((ppu_sprfetch_at_data & 0x80u) != 0) ? 15 : 0);
+            if (ppu_reg_2000_Sprite_size == 16)
+            {
+                ppu_sprfetch_lb_addr = (ushort)(((uint)(ppu_sprfetch_t_data << 12) & 0x1000u) | ((uint)(ppu_sprfetch_t_data << 4) & 0xFE0u) | ((uint)(ppu_temp_comparator << 1) & 0x10u) | ((uint)ppu_temp_comparator & 7u));
+            }
+            else
+            {
+                ppu_sprfetch_lb_addr = (ushort)((uint)(ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites | (ppu_sprfetch_t_data << 4)) | ((uint)ppu_temp_comparator & 7u));
+            }
+            mem_board.OnPPUAddressUpdate(ref ppu_sprfetch_lb_addr);
+        }
+
+        private static void PPUSPRFetch1()
+        {
+            ppu_is_sprfetch = true;
+            mem_board.ReadCHR(ref ppu_sprfetch_lb_addr, out ppu_sprfetch_lb_data);
+            ppu_is_sprfetch = false;
+            if ((ppu_sprfetch_at_data & 0x40u) != 0)
+            {
+                ppu_sprfetch_lb_data = reverseLookup[ppu_sprfetch_lb_data];
+            }
+        }
+
+        private static void PPUSPRFetch2()
+        {
+            ppu_sprfetch_hb_addr = (ushort)(ppu_sprfetch_lb_addr | 8u);
+            mem_board.OnPPUAddressUpdate(ref ppu_sprfetch_hb_addr);
+        }
+
+        private static void PPUSPRFetch3()
+        {
+            ppu_is_sprfetch = true;
+            mem_board.ReadCHR(ref ppu_sprfetch_hb_addr, out ppu_sprfetch_hb_data);
+            ppu_is_sprfetch = false;
+            if ((ppu_sprfetch_at_data & 0x40u) != 0)
+            {
+                ppu_sprfetch_hb_data = reverseLookup[ppu_sprfetch_hb_data];
+            }
+            if (ppu_sprfetch_x_data == byte.MaxValue)
+            {
+                return;
+            }
+            for (ppu_bkg_render_i = 0; ppu_bkg_render_i < 8; ppu_bkg_render_i++)
+            {
+                if (ppu_sprfetch_x_data < byte.MaxValue)
+                {
+                    ppu_bkg_render_tmp_val = ((ppu_sprfetch_at_data << 2) & 0xC) | ((ppu_sprfetch_lb_data >> 7) & 1) | ((ppu_sprfetch_hb_data >> 6) & 2);
+                    if (((uint)ppu_bkg_render_tmp_val & 3u) != 0)
+                    {
+                        ppu_spr_pixels[ppu_sprfetch_x_data] = ppu_bkg_render_tmp_val;
+                        if (ppu_sprfetch_slot == 0 && ppu_sprite0_should_hit)
+                        {
+                            ppu_spr_pixels[ppu_sprfetch_x_data] |= 16384;
+                        }
+                        if ((ppu_sprfetch_at_data & 0x20) == 0)
+                        {
+                            ppu_spr_pixels[ppu_sprfetch_x_data] |= 32768;
+                        }
+                    }
+                    ppu_sprfetch_lb_data <<= 1;
+                    ppu_sprfetch_hb_data <<= 1;
+                    ppu_sprfetch_x_data++;
+                }
+            }
+        }
+
+        private static void PPUOamReset()
+        {
+            ppu_oamev_n = 0;
+            ppu_oamev_m = 0;
+            ppu_oamev_slot = 0;
+            ppu_phase_index = 0;
+            ppu_sprite0_should_hit = false;
+        }
+
+        private static void PPUOamClear()
+        {
+            for (int i = 0; i < ppu_spr_pixels.Length; i++)
+            {
+                ppu_spr_pixels[i] = 0;
+            }
+        }
+
+        private static void PPUOamEvFetch()
+        {
+            ppu_fetch_data = ppu_oam_bank[ppu_oamev_n * 4 + ppu_oamev_m];
+        }
+
+        private static void PPUOamPhase0()
+        {
+            ppu_oamev_compare = ppu_clock_v >= ppu_fetch_data && ppu_clock_v < ppu_fetch_data + ppu_reg_2000_Sprite_size;
+            if (ppu_oamev_compare)
+            {
+                ppu_oam_bank_secondary[ppu_oamev_slot * 4] = ppu_fetch_data;
+                ppu_oamev_m = 1;
+                ppu_phase_index++;
+                if (ppu_oamev_n == 0)
+                {
+                    ppu_sprite0_should_hit = true;
+                }
+            }
+            else
+            {
+                ppu_oamev_m = 0;
+                ppu_oamev_n++;
+                if (ppu_oamev_n == 64)
+                {
+                    ppu_oamev_n = 0;
+                    ppu_phase_index = 8;
+                }
+            }
+        }
+
+        private static void PPUOamPhase1()
+        {
+            ppu_oam_bank_secondary[ppu_oamev_slot * 4 + ppu_oamev_m] = ppu_fetch_data;
+            ppu_oamev_m = 2;
+            ppu_phase_index++;
+        }
+
+        private static void PPUOamPhase2()
+        {
+            ppu_oam_bank_secondary[ppu_oamev_slot * 4 + ppu_oamev_m] = ppu_fetch_data;
+            ppu_oamev_m = 3;
+            ppu_phase_index++;
+        }
+
+        private static void PPUOamPhase3()
+        {
+            ppu_oam_bank_secondary[ppu_oamev_slot * 4 + ppu_oamev_m] = ppu_fetch_data;
+            ppu_oamev_m = 0;
+            ppu_oamev_n++;
+            ppu_oamev_slot++;
+            if (ppu_oamev_n == 64)
+            {
+                ppu_oamev_n = 0;
+                ppu_phase_index = 8;
+            }
+            else if (ppu_oamev_slot < 8)
+            {
+                ppu_phase_index = 0;
+            }
+            else if (ppu_oamev_slot == 8)
+            {
+                ppu_phase_index = 4;
+            }
+        }
+
+        private static void PPUOamPhase4()
+        {
+            ppu_oamev_compare = ppu_clock_v >= ppu_fetch_data && ppu_clock_v < ppu_fetch_data + ppu_reg_2000_Sprite_size;
+            if (ppu_oamev_compare)
+            {
+                ppu_oamev_m = 1;
+                ppu_phase_index++;
+                ppu_reg_2002_SpriteOverflow = true;
+                return;
+            }
+            ppu_oamev_m++;
+            if (ppu_oamev_m == 4)
+            {
+                ppu_oamev_m = 0;
+            }
+            ppu_oamev_n++;
+            if (ppu_oamev_n == 64)
+            {
+                ppu_oamev_n = 0;
+                ppu_phase_index = 8;
+            }
+            else
+            {
+                ppu_phase_index = 4;
+            }
+        }
+
+        private static void PPUOamPhase5()
+        {
+            ppu_oamev_m = 2;
+            ppu_phase_index++;
+        }
+
+        private static void PPUOamPhase6()
+        {
+            ppu_oamev_m = 3;
+            ppu_phase_index++;
+        }
+
+        private static void PPUOamPhase7()
+        {
+            ppu_oamev_m = 0;
+            ppu_oamev_n++;
+            if (ppu_oamev_n == 64)
+            {
+                ppu_oamev_n = 0;
+            }
+            ppu_phase_index = 8;
+        }
+
+        private static void PPUOamPhase8()
+        {
+            ppu_oamev_n++;
+            if (ppu_oamev_n >= 64)
+            {
+                ppu_oamev_n = 0;
+            }
+        }
+
+        private static void RenderPixel()
+        {
+            if (ppu_clock_v == ppu_clock_vblank_end)
+            {
+                return;
+            }
+            ppu_render_x = ppu_clock_h - 1;
+            ppu_render_y = ppu_clock_v * 256;
+            if (ppu_render_x < 8)
+            {
+                if (ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen)
+                {
+                    ppu_bkg_current_pixel = 0x3F00 | ppu_bkg_pixels[ppu_render_x + ppu_vram_finex];
+                }
+                else
+                {
+                    ppu_bkg_current_pixel = 16128;
+                }
+                if (ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen)
+                {
+                    ppu_spr_current_pixel = 0x3F10 | ppu_spr_pixels[ppu_render_x];
+                }
+                else
+                {
+                    ppu_spr_current_pixel = 16144;
+                }
+            }
+            else
+            {
+                if (!ppu_reg_2001_show_background)
+                {
+                    ppu_bkg_current_pixel = 16128;
+                }
+                else
+                {
+                    ppu_bkg_current_pixel = 0x3F00 | ppu_bkg_pixels[ppu_render_x + ppu_vram_finex];
+                }
+                if (!ppu_reg_2001_show_sprites || ppu_clock_v == 0)
+                {
+                    ppu_spr_current_pixel = 16144;
+                }
+                else
+                {
+                    ppu_spr_current_pixel = 0x3F10 | ppu_spr_pixels[ppu_render_x];
+                }
+            }
+            ppu_current_pixel = 0;
+            if (((uint)ppu_spr_current_pixel & 0x8000u) != 0)
+            {
+                ppu_current_pixel = ppu_spr_current_pixel;
+            }
+            else
+            {
+                ppu_current_pixel = ppu_bkg_current_pixel;
+            }
+            if ((ppu_bkg_current_pixel & 3) == 0)
+            {
+                ppu_current_pixel = ppu_spr_current_pixel;
+            }
+            else if ((ppu_spr_current_pixel & 3) == 0)
+            {
+                ppu_current_pixel = ppu_bkg_current_pixel;
+            }
+            else if (((uint)ppu_spr_pixels[ppu_render_x] & 0x4000u) != 0)
+            {
+                ppu_reg_2002_Sprite0Hit = true;
+            }
+            if ((ppu_current_pixel & 3) == 0)
+            {
+                ppu_screen_pixels[ppu_render_x + ppu_render_y] = ppu_palette[(ppu_palette_bank[ppu_current_pixel & 0xC] & ppu_reg_2001_grayscale) | ppu_reg_2001_emphasis];
+            }
+            else
+            {
+                ppu_screen_pixels[ppu_render_x + ppu_render_y] = ppu_palette[(ppu_palette_bank[ppu_current_pixel & 0x1F] & ppu_reg_2001_grayscale) | ppu_reg_2001_emphasis];
+            }
+        }
+
+        private static void PPUIORead(ref ushort addr, out byte value)
+        {
+            ppu_reg_io_addr = (byte)(addr & 7u);
+            ppu_reg_access_happened = true;
+            ppu_reg_access_w = false;
+            ppu_reg_read_func[ppu_reg_io_addr]();
+            value = ppu_reg_io_db;
+        }
+
+        private static void PPUIOWrite(ref ushort addr, ref byte value)
+        {
+            ppu_reg_io_addr = (byte)(addr & 7u);
+            ppu_reg_io_db = value;
+            ppu_reg_access_w = true;
+            ppu_reg_access_happened = true;
+        }
+
+        private static void PPUOnRegister2000()
+        {
+            if (ppu_reg_access_w)
+            {
+                ppu_vram_addr_temp = (ushort)((ppu_vram_addr_temp & 0x73FFu) | (uint)((ppu_reg_io_db & 3) << 10));
+                if ((ppu_reg_io_db & 4u) != 0)
+                {
+                    ppu_reg_2000_vram_address_increament = 32;
+                }
+                else
+                {
+                    ppu_reg_2000_vram_address_increament = 1;
+                }
+                if ((ppu_reg_io_db & 8u) != 0)
+                {
+                    ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites = 4096;
+                }
+                else
+                {
+                    ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites = 0;
+                }
+                if ((ppu_reg_io_db & 0x10u) != 0)
+                {
+                    ppu_reg_2000_background_pattern_table_address = 4096;
+                }
+                else
+                {
+                    ppu_reg_2000_background_pattern_table_address = 0;
+                }
+                if ((ppu_reg_io_db & 0x20u) != 0)
+                {
+                    ppu_reg_2000_Sprite_size = 16;
+                }
+                else
+                {
+                    ppu_reg_2000_Sprite_size = 8;
+                }
+                if (!ppu_reg_2000_VBI && (ppu_reg_io_db & 0x80u) != 0 && ppu_reg_2002_VblankStartedFlag)
+                {
+                    PPU_NMI_Current = true;
+                }
+                ppu_reg_2000_VBI = (ppu_reg_io_db & 0x80) != 0;
+                if (!ppu_reg_2000_VBI && ppu_is_nmi_time)
+                {
+                    PPU_NMI_Current = false;
+                }
+            }
+        }
+
+        private static void PPUOnRegister2001()
+        {
+            if (ppu_reg_access_w)
+            {
+                ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen = (ppu_reg_io_db & 2) != 0;
+                ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen = (ppu_reg_io_db & 4) != 0;
+                ppu_reg_2001_show_background = (ppu_reg_io_db & 8) != 0;
+                ppu_reg_2001_show_sprites = (ppu_reg_io_db & 0x10) != 0;
+                ppu_reg_2001_grayscale = ((((uint)ppu_reg_io_db & (true ? 1u : 0u)) != 0) ? 48 : 63);
+                ppu_reg_2001_emphasis = (ppu_reg_io_db & 0xE0) << 1;
+            }
+        }
+
+        private static void PPUOnRegister2002()
+        {
+            if (!ppu_reg_access_w)
+            {
+                ppu_vram_flip_flop = false;
+                ppu_reg_2002_VblankStartedFlag = false;
+                if (ppu_clock_v == ppu_clock_vblank_start)
+                {
+                    PPU_NMI_Current = ppu_reg_2002_VblankStartedFlag & ppu_reg_2000_VBI;
+                }
+            }
+        }
+
+        private static void PPUOnRegister2003()
+        {
+            if (ppu_reg_access_w)
+            {
+                ppu_reg_2003_oam_addr = ppu_reg_io_db;
+            }
+        }
+
+        private static void PPUOnRegister2004()
+        {
+            if (ppu_reg_access_w)
+            {
+                if (ppu_clock_v < 240 && IsRenderingOn())
+                {
+                    ppu_reg_io_db = byte.MaxValue;
+                }
+                if ((ppu_reg_2003_oam_addr & 3) == 2)
+                {
+                    ppu_reg_io_db &= 227;
+                }
+                ppu_oam_bank[ppu_reg_2003_oam_addr] = ppu_reg_io_db;
+                ppu_reg_2003_oam_addr = (byte)((uint)(ppu_reg_2003_oam_addr + 1) & 0xFFu);
+            }
+        }
+
+        private static void PPUOnRegister2005()
+        {
+            if (ppu_reg_access_w)
+            {
+                if (!ppu_vram_flip_flop)
+                {
+                    ppu_vram_addr_temp = (ushort)((ppu_vram_addr_temp & 0x7FE0u) | (uint)((ppu_reg_io_db & 0xF8) >> 3));
+                    ppu_vram_finex = (byte)(ppu_reg_io_db & 7u);
+                }
+                else
+                {
+                    ppu_vram_addr_temp = (ushort)((ppu_vram_addr_temp & 0xC1Fu) | (uint)((ppu_reg_io_db & 7) << 12) | (uint)((ppu_reg_io_db & 0xF8) << 2));
+                }
+                ppu_vram_flip_flop = !ppu_vram_flip_flop;
+            }
+        }
+
+        private static void PPUOnRegister2006()
+        {
+            if (ppu_reg_access_w)
+            {
+                if (!ppu_vram_flip_flop)
+                {
+                    ppu_vram_addr_temp = (ushort)((ppu_vram_addr_temp & 0xFFu) | (uint)((ppu_reg_io_db & 0x3F) << 8));
+                }
+                else
+                {
+                    ppu_vram_addr_temp = (ushort)((ppu_vram_addr_temp & 0x7F00u) | ppu_reg_io_db);
+                    ppu_vram_addr = ppu_vram_addr_temp;
+                    mem_board.OnPPUAddressUpdate(ref ppu_vram_addr);
+                }
+                ppu_vram_flip_flop = !ppu_vram_flip_flop;
+            }
+        }
+
+        private static void PPUOnRegister2007()
+        {
+            if (ppu_reg_access_w)
+            {
+                ppu_vram_addr_access_temp = (ushort)(ppu_vram_addr & 0x3FFFu);
+                if (ppu_vram_addr_access_temp < 8192)
+                {
+                    mem_board.WriteCHR(ref ppu_vram_addr_access_temp, ref ppu_reg_io_db);
+                }
+                else if (ppu_vram_addr_access_temp < 16128)
+                {
+                    mem_board.WriteNMT(ref ppu_vram_addr_access_temp, ref ppu_reg_io_db);
+                }
+                else if ((ppu_vram_addr_access_temp & 3u) != 0)
+                {
+                    ppu_palette_bank[ppu_vram_addr_access_temp & 0x1F] = ppu_reg_io_db;
+                }
+                else
+                {
+                    ppu_palette_bank[ppu_vram_addr_access_temp & 0xC] = ppu_reg_io_db;
+                }
+            }
+            else
+            {
+                if ((ppu_vram_addr & 0x3F00) == 16128)
+                {
+                    ppu_vram_addr_access_temp = (ushort)(ppu_vram_addr & 0x2FFFu);
+                }
+                else
+                {
+                    ppu_vram_addr_access_temp = (ushort)(ppu_vram_addr & 0x3FFFu);
+                }
+                if (ppu_vram_addr_access_temp < 8192)
+                {
+                    mem_board.ReadCHR(ref ppu_vram_addr_access_temp, out ppu_vram_data);
+                }
+                else if (ppu_vram_addr_access_temp < 16128)
+                {
+                    mem_board.ReadNMT(ref ppu_vram_addr_access_temp, out ppu_vram_data);
+                }
+            }
+            ppu_vram_addr = (ushort)((uint)(ppu_vram_addr + ppu_reg_2000_vram_address_increament) & 0x7FFFu);
+            mem_board.OnPPUAddressUpdate(ref ppu_vram_addr);
+        }
+
+        private static void PPURead2000()
+        {
+        }
+
+        private static void PPURead2001()
+        {
+        }
+
+        private static void PPURead2002()
+        {
+            ppu_reg_io_db = (byte)((ppu_reg_io_db & 0xDFu) | (ppu_reg_2002_SpriteOverflow ? 32u : 0u));
+            ppu_reg_io_db = (byte)((ppu_reg_io_db & 0xBFu) | (ppu_reg_2002_Sprite0Hit ? 64u : 0u));
+            ppu_reg_io_db = (byte)((ppu_reg_io_db & 0x7Fu) | (ppu_reg_2002_VblankStartedFlag ? 128u : 0u));
+        }
+
+        private static void PPURead2003()
+        {
+        }
+
+        private static void PPURead2004()
+        {
+            ppu_reg_io_db = ppu_oam_bank[ppu_reg_2003_oam_addr];
+            if (ppu_clock_v < 240 && IsRenderingOn())
+            {
+                if (ppu_clock_h < 64)
+                {
+                    ppu_reg_io_db = byte.MaxValue;
+                }
+                else if (ppu_clock_h < 192)
+                {
+                    ppu_reg_io_db = ppu_oam_bank[(ppu_clock_h - 64 << 1) & 0xFC];
+                }
+                else if (ppu_clock_h < 256)
+                {
+                    ppu_reg_io_db = (((ppu_clock_h & 1) == 1) ? ppu_oam_bank[252] : ppu_oam_bank[(ppu_clock_h - 192 << 1) & 0xFC]);
+                }
+                else if (ppu_clock_h < 320)
+                {
+                    ppu_reg_io_db = byte.MaxValue;
+                }
+                else
+                {
+                    ppu_reg_io_db = ppu_oam_bank[0];
+                }
+            }
+        }
+
+        private static void PPURead2005()
+        {
+        }
+
+        private static void PPURead2006()
+        {
+        }
+
+        private static void PPURead2007()
+        {
+            ppu_vram_addr_access_temp = (ushort)(ppu_vram_addr & 0x3FFFu);
+            if (ppu_vram_addr_access_temp < 16128)
+            {
+                ppu_reg_io_db = ppu_vram_data;
+            }
+            else if ((ppu_vram_addr_access_temp & 3u) != 0)
+            {
+                ppu_reg_io_db = ppu_palette_bank[ppu_vram_addr_access_temp & 0x1F];
+            }
+            else
+            {
+                ppu_reg_io_db = ppu_palette_bank[ppu_vram_addr_access_temp & 0xC];
+            }
+        }
+
+        internal static bool IsRenderingOn()
+        {
+            if (!ppu_reg_2001_show_background)
+            {
+                return ppu_reg_2001_show_sprites;
+            }
+            return true;
+        }
+
+        internal static bool IsInRender()
+        {
+            if (ppu_clock_v >= 240)
+            {
+                return ppu_clock_v == ppu_clock_vblank_end;
+            }
+            return true;
+        }
+
+        private static void PPUWriteState(ref BinaryWriter bin)
+        {
+            bin.Write(ppu_clock_h);
+            bin.Write(ppu_clock_v);
+            bin.Write(ppu_clock_vblank_start);
+            bin.Write(ppu_clock_vblank_end);
+            bin.Write(ppu_use_odd_cycle);
+            bin.Write(ppu_use_odd_swap);
+            bin.Write(ppu_is_nmi_time);
+            bin.Write(ppu_frame_finished);
+            bin.Write(ppu_oam_bank);
+            bin.Write(ppu_oam_bank_secondary);
+            bin.Write(ppu_palette_bank);
+            bin.Write(ppu_reg_io_db);
+            bin.Write(ppu_reg_io_addr);
+            bin.Write(ppu_reg_access_happened);
+            bin.Write(ppu_reg_access_w);
+            bin.Write(ppu_reg_2000_vram_address_increament);
+            bin.Write(ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites);
+            bin.Write(ppu_reg_2000_background_pattern_table_address);
+            bin.Write(ppu_reg_2000_Sprite_size);
+            bin.Write(ppu_reg_2000_VBI);
+            bin.Write(ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen);
+            bin.Write(ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen);
+            bin.Write(ppu_reg_2001_show_background);
+            bin.Write(ppu_reg_2001_show_sprites);
+            bin.Write(ppu_reg_2001_grayscale);
+            bin.Write(ppu_reg_2001_emphasis);
+            bin.Write(ppu_reg_2002_SpriteOverflow);
+            bin.Write(ppu_reg_2002_Sprite0Hit);
+            bin.Write(ppu_reg_2002_VblankStartedFlag);
+            bin.Write(ppu_reg_2003_oam_addr);
+            bin.Write(ppu_vram_addr);
+            bin.Write(ppu_vram_data);
+            bin.Write(ppu_vram_addr_temp);
+            bin.Write(ppu_vram_addr_access_temp);
+            bin.Write(ppu_vram_flip_flop);
+            bin.Write(ppu_vram_finex);
+            bin.Write(ppu_bkgfetch_nt_addr);
+            bin.Write(ppu_bkgfetch_nt_data);
+            bin.Write(ppu_bkgfetch_at_addr);
+            bin.Write(ppu_bkgfetch_at_data);
+            bin.Write(ppu_bkgfetch_lb_addr);
+            bin.Write(ppu_bkgfetch_lb_data);
+            bin.Write(ppu_bkgfetch_hb_addr);
+            bin.Write(ppu_bkgfetch_hb_data);
+            bin.Write(ppu_sprfetch_slot);
+            bin.Write(ppu_sprfetch_y_data);
+            bin.Write(ppu_sprfetch_t_data);
+            bin.Write(ppu_sprfetch_at_data);
+            bin.Write(ppu_sprfetch_x_data);
+            bin.Write(ppu_sprfetch_lb_addr);
+            bin.Write(ppu_sprfetch_lb_data);
+            bin.Write(ppu_sprfetch_hb_addr);
+            bin.Write(ppu_sprfetch_hb_data);
+            bin.Write(ppu_bkg_render_i);
+            bin.Write(ppu_bkg_render_pos);
+            bin.Write(ppu_bkg_render_tmp_val);
+            bin.Write(ppu_bkg_current_pixel);
+            bin.Write(ppu_spr_current_pixel);
+            bin.Write(ppu_current_pixel);
+            bin.Write(ppu_render_x);
+            bin.Write(0);
+            bin.Write(ppu_oamev_n);
+            bin.Write(ppu_oamev_m);
+            bin.Write(ppu_oamev_compare);
+            bin.Write(ppu_oamev_slot);
+            bin.Write(ppu_fetch_data);
+            bin.Write(ppu_phase_index);
+            bin.Write(ppu_sprite0_should_hit);
+        }
+
+        private static void PPUReadState(ref BinaryReader bin)
+        {
+            ppu_clock_h = bin.ReadInt32();
+            ppu_clock_v = bin.ReadUInt16();
+            ppu_clock_vblank_start = bin.ReadUInt16();
+            ppu_clock_vblank_end = bin.ReadUInt16();
+            ppu_use_odd_cycle = bin.ReadBoolean();
+            ppu_use_odd_swap = bin.ReadBoolean();
+            ppu_is_nmi_time = bin.ReadBoolean();
+            ppu_frame_finished = bin.ReadBoolean();
+            bin.Read(ppu_oam_bank, 0, ppu_oam_bank.Length);
+            bin.Read(ppu_oam_bank_secondary, 0, ppu_oam_bank_secondary.Length);
+            bin.Read(ppu_palette_bank, 0, ppu_palette_bank.Length);
+            ppu_reg_io_db = bin.ReadByte();
+            ppu_reg_io_addr = bin.ReadByte();
+            ppu_reg_access_happened = bin.ReadBoolean();
+            ppu_reg_access_w = bin.ReadBoolean();
+            ppu_reg_2000_vram_address_increament = bin.ReadByte();
+            ppu_reg_2000_sprite_pattern_table_address_for_8x8_sprites = bin.ReadUInt16();
+            ppu_reg_2000_background_pattern_table_address = bin.ReadUInt16();
+            ppu_reg_2000_Sprite_size = bin.ReadByte();
+            ppu_reg_2000_VBI = bin.ReadBoolean();
+            ppu_reg_2001_show_background_in_leftmost_8_pixels_of_screen = bin.ReadBoolean();
+            ppu_reg_2001_show_sprites_in_leftmost_8_pixels_of_screen = bin.ReadBoolean();
+            ppu_reg_2001_show_background = bin.ReadBoolean();
+            ppu_reg_2001_show_sprites = bin.ReadBoolean();
+            ppu_reg_2001_grayscale = bin.ReadInt32();
+            ppu_reg_2001_emphasis = bin.ReadInt32();
+            ppu_reg_2002_SpriteOverflow = bin.ReadBoolean();
+            ppu_reg_2002_Sprite0Hit = bin.ReadBoolean();
+            ppu_reg_2002_VblankStartedFlag = bin.ReadBoolean();
+            ppu_reg_2003_oam_addr = bin.ReadByte();
+            ppu_vram_addr = bin.ReadUInt16();
+            ppu_vram_data = bin.ReadByte();
+            ppu_vram_addr_temp = bin.ReadUInt16();
+            ppu_vram_addr_access_temp = bin.ReadUInt16();
+            ppu_vram_flip_flop = bin.ReadBoolean();
+            ppu_vram_finex = bin.ReadByte();
+            ppu_bkgfetch_nt_addr = bin.ReadUInt16();
+            ppu_bkgfetch_nt_data = bin.ReadByte();
+            ppu_bkgfetch_at_addr = bin.ReadUInt16();
+            ppu_bkgfetch_at_data = bin.ReadByte();
+            ppu_bkgfetch_lb_addr = bin.ReadUInt16();
+            ppu_bkgfetch_lb_data = bin.ReadByte();
+            ppu_bkgfetch_hb_addr = bin.ReadUInt16();
+            ppu_bkgfetch_hb_data = bin.ReadByte();
+            ppu_sprfetch_slot = bin.ReadInt32();
+            ppu_sprfetch_y_data = bin.ReadByte();
+            ppu_sprfetch_t_data = bin.ReadByte();
+            ppu_sprfetch_at_data = bin.ReadByte();
+            ppu_sprfetch_x_data = bin.ReadByte();
+            ppu_sprfetch_lb_addr = bin.ReadUInt16();
+            ppu_sprfetch_lb_data = bin.ReadByte();
+            ppu_sprfetch_hb_addr = bin.ReadUInt16();
+            ppu_sprfetch_hb_data = bin.ReadByte();
+            ppu_bkg_render_i = bin.ReadInt32();
+            ppu_bkg_render_pos = bin.ReadInt32();
+            ppu_bkg_render_tmp_val = bin.ReadInt32();
+            ppu_bkg_current_pixel = bin.ReadInt32();
+            ppu_spr_current_pixel = bin.ReadInt32();
+            ppu_current_pixel = bin.ReadInt32();
+            ppu_render_x = bin.ReadInt32();
+            bin.ReadInt32();
+            ppu_oamev_n = bin.ReadByte();
+            ppu_oamev_m = bin.ReadByte();
+            ppu_oamev_compare = bin.ReadBoolean();
+            ppu_oamev_slot = bin.ReadByte();
+            ppu_fetch_data = bin.ReadByte();
+            ppu_phase_index = bin.ReadByte();
+            ppu_sprite0_should_hit = bin.ReadBoolean();
+        }
+
+        internal static void CheckGame(string fileName, out bool valid)
+        {
+            string text = Path.GetExtension(fileName).ToLower();
+            if (text != null && text == ".nes")
+            {
+                Tracer.WriteLine("Checking INES header ...");
+                INes nes = new INes();
+                nes.Load(fileName, loadDumps: false);
+                valid = nes.IsValid;
+                Tracer.WriteLine("INES header is valid.");
+            }
+            else
+            {
+                Tracer.WriteWarning("File format is not supported. Format: " + Path.GetExtension(fileName));
+                valid = false;
+            }
+        }
+
+        internal static void Initialize()
+        {
+            Tracer.WriteLine("Loading database file ...");
+            NesCartDatabase.LoadDatabase(out bool success);
+
+            if (success)
+            {
+                Tracer.WriteInformation("Nes Cart database file loaded successfully.");
+            }
+            else
+            {
+                Tracer.WriteError("Error loading Nes Cart database file.");
+            }
+
+            FrameLimiterEnabled = true;
+            CPUInitialize();
+            PPUInitialize();
+            APUInitialize();
+            PORTSInitialize();
+        }
+
+        internal static void SetupRenderingMethods(RenderVideoFrame renderVideo, RenderAudioSamples renderAudio, TogglePause renderTogglePause, GetIsPlaying renderGetIsPlaying)
+        {
+            render_initialized = false;
+            render_video = renderVideo;
+            render_audio = renderAudio;
+            render_audio_toggle_pause = renderTogglePause;
+            render_audio_get_is_playing = renderGetIsPlaying;
+            render_initialized = render_video != null && render_audio != null && render_audio_toggle_pause != null && render_audio_get_is_playing != null;
+            if (render_initialized)
+            {
+                Tracer.WriteInformation("Renderer methods initialized successfully.");
+                return;
+            }
+            Tracer.WriteError("ERROR RENDERER INITIALIZING !!");
+            Tracer.WriteError("Faild to initialize the renderers methods. Please use the method 'SetupRenderingMethods' to initialize the renderers methods before you can run the emulation.");
+        }
+
+        public static void LoadGame(string fileName, out bool success, bool useThread)
+        {
+            if (!render_initialized)
+            {
+                Tracer.WriteError("NO RENDERER INITIALIZED !! EMU CANNOT BE INTIALIZED WITHOUT A RENDERER !!");
+                Tracer.WriteError("Please use the method 'SetupRenderingMethods' to initialize the renderers methods before you can run the emulation.");
+                success = false;
+                return;
+            }
+            Tracer.WriteLine("Checking INES header ...");
+            INes nes = new INes();
+            nes.Load(fileName, loadDumps: true);
+            if (nes.IsValid)
+            {
+                emu_request_mode = RequestMode.None;
+                CurrentFilePath = fileName;
+                if (ON)
+                {
+                    ShutDown();
+                }
+                Tracer.WriteLine("INES header is valid, loading game ...");
+                ApplyRegionSetting();
+                MEMInitialize(nes);
+                ApplyAudioSettings();
+                ApplyFrameSkipSettings();
+                ApplyPaletteSetting();
+                PORTSInitialize();
+                hardReset();
+                Tracer.WriteLine("EMU is ready.");
+                success = true;
+                ON = true;
+                PAUSED = false;
+                if (useThread)
+                {
+                    Tracer.WriteLine("Running in a thread ... using custom frame limiter.");
+                    FrameLimiterEnabled = true;
+                    currentFrame = 0;
+                    mainThread = new Thread(EmuClock);
+                    mainThread.Start();
+                }
+                MyNesMain.VideoProvider.SignalToggle(started: true);
+                MyNesMain.AudioProvider.SignalToggle(started: true);
+            }
+            else
+            {
+                success = false;
+            }
+        }
+
+        public static void HardReset()
+        {
+            PAUSED = true;
+            emu_request_mode = RequestMode.HardReset;
+        }
+
+        private static void hardReset()
+        {
+            if (MyNesMain.WaveRecorder.IsRecording)
+            {
+                MyNesMain.WaveRecorder.Stop();
+            }
+            render_audio_toggle_pause(paused: true);
+            switch (Region)
+            {
+                case EmuRegion.NTSC:
+                    emu_time_target_fps = 60.0988;
+                    break;
+                case EmuRegion.PALB:
+                case EmuRegion.DENDY:
+                    emu_time_target_fps = 50.0;
+                    break;
+            }
+            fps_time_period = 1.0 / emu_time_target_fps;
+            MEMHardReset();
+            CPUHardReset();
+            PPUHardReset();
+            APUHardReset();
+            DMAHardReset();
+            render_audio_toggle_pause(paused: false);
+            MyNesMain.VideoProvider.WriteWarningNotification(MNInterfaceLanguage.Message_HardReset, instant: false);
+        }
+
+        public static void SoftReset()
+        {
+            PAUSED = true;
+            emu_request_mode = RequestMode.SoftReset;
+        }
+
+        private static void softReset()
+        {
+            CPUSoftReset();
+            APUSoftReset();
+            MyNesMain.VideoProvider.WriteWarningNotification(MNInterfaceLanguage.Message_SoftReset, instant: false);
+        }
+
+        public static void SaveState()
+        {
+            PAUSED = true;
+            emu_request_mode = RequestMode.SaveState;
+        }
+
+        public static void LoadState()
+        {
+            PAUSED = true;
+            emu_request_mode = RequestMode.LoadState;
+        }
+
+        internal static void TakeSnapshot()
+        {
+            PAUSED = true;
+            emu_request_mode = RequestMode.TakeSnapshot;
+        }
+
+        public static void ShutDown()
+        {
+            MyNesMain.VideoProvider.SignalToggle(started: false);
+            MyNesMain.AudioProvider.SignalToggle(started: false);
+            if (MyNesMain.WaveRecorder.IsRecording)
+            {
+                MyNesMain.WaveRecorder.Stop();
+            }
+            render_audio_get_is_playing(out render_audio_is_playing);
+            if (render_audio_is_playing)
+            {
+                render_audio_toggle_pause(paused: true);
+            }
+            Tracer.WriteLine("Shutting down the emulation core...");
+            ON = false;
+            if (mainThread != null)
+            {
+                Tracer.WriteLine("Aborting thread ..");
+                mainThread.Abort();
+                mainThread = null;
+            }
+            SaveSRAM();
+            Tracer.WriteInformation("Emulation core shutdown successfully.");
+            NesEmu.EmuShutdown?.Invoke(null, new EventArgs());
+        }
+
+        private static Stopwatch sw = new Stopwatch();
+        private static double fixTime;
+        public static ulong currentFrame;
+        private static void EmuClock()
+        {
+            while (ON)
+            {
+                if (!PAUSED)
+                {
+                    var waitTime = GetTime() + fps_time_period + fixTime;
+
+                    while (!ppu_frame_finished)
+                        CPUClock();
+
+                    FrameFinished();
+
+                    fixTime = waitTime - GetTime();
+                    while (fixTime > 0)
+                    {
+                        fixTime = waitTime - GetTime();
+                    };
+
+                    currentFrame++;
+
+                    continue;
+                }
+                render_audio_get_is_playing(out render_audio_is_playing);
+                if (render_audio_is_playing)
+                {
+                    render_audio_toggle_pause(paused: true);
+                }
+                Thread.Sleep(100);
+                switch (emu_request_mode)
+                {
+                    case RequestMode.HardReset:
+                        hardReset();
+                        PAUSED = false;
+                        emu_request_mode = RequestMode.None;
+                        break;
+                    case RequestMode.SoftReset:
+                        softReset();
+                        PAUSED = false;
+                        emu_request_mode = RequestMode.None;
+                        break;
+                    case RequestMode.SaveState:
+                        StateHandler.SaveState();
+                        PAUSED = false;
+                        emu_request_mode = RequestMode.None;
+                        break;
+                    case RequestMode.LoadState:
+                        StateHandler.LoadState();
+                        PAUSED = false;
+                        emu_request_mode = RequestMode.None;
+                        break;
+                    case RequestMode.TakeSnapshot:
+                        MyNesMain.VideoProvider.TakeSnapshot();
+                        PAUSED = false;
+                        emu_request_mode = RequestMode.None;
+                        break;
+                }
+                isPaused = true;
+            }
+        }
+
+        internal static void EmuClockComponents()
+        {
+            PPUClock();
+            PollInterruptStatus();
+            PPUClock();
+            PPUClock();
+            APUClock();
+            DMAClock();
+            mem_board.OnCPUClock();
+        }
+
+        internal static void ApplyFrameSkipSettings()
+        {
+            FrameSkipEnabled = MyNesMain.RendererSettings.FrameSkipEnabled;
+            FrameSkipInterval = MyNesMain.RendererSettings.FrameSkipInterval;
+        }
+
+        private static void FrameFinished()
+        {
+            if (!FrameSkipEnabled)
+            {
+                render_video(ref ppu_screen_pixels);
+            }
+            else
+            {
+                FrameSkipCounter++;
+                if (FrameSkipCounter >= FrameSkipInterval)
+                {
+                    render_video(ref ppu_screen_pixels);
+                    FrameSkipCounter = 0;
+                }
+            }
+            isPaused = false;
+            ppu_frame_finished = false;
+            joypad1.Update();
+            joypad2.Update();
+            if (IsFourPlayers)
+            {
+                joypad3.Update();
+                joypad4.Update();
+            }
+            if (SoundEnabled)
+            {
+                render_audio_get_is_playing(out render_audio_is_playing);
+                if (!render_audio_is_playing)
+                {
+                    render_audio_toggle_pause(paused: false);
+                }
+                render_audio(ref audio_samples, ref audio_samples_added);
+                audio_w_pos = 0;
+                audio_samples_added = 0;
+                audio_timer = 0.0;
+            }
+        }
+
+        private static double GetTime()
+        {
+            return (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
+        }
+
+
+        public static void SetFramePeriod(ref double period)
+        {
+            fps_time_period = period;
+        }
+
+        public static void RevertFramePeriod()
+        {
+            fps_time_period = 1 / emu_time_target_fps;
+        }
+
+        public static void ApplyRegionSetting()
+        {
+            switch ((RegionSetting)MyNesMain.EmuSettings.RegionSetting)
+            {
+                case RegionSetting.AUTO:
+                    Tracer.WriteLine("REGION = AUTO");
+                    Region = EmuRegion.NTSC;
+                    if (CurrentFilePath.Contains("(E)"))
+                    {
+                        Region = EmuRegion.PALB;
+                    }
+                    Tracer.WriteLine("REGION SELECTED: " + Region);
+                    break;
+                case RegionSetting.ForceNTSC:
+                    Tracer.WriteLine("REGION: FORCE NTSC");
+                    Region = EmuRegion.NTSC;
+                    break;
+                case RegionSetting.ForcePALB:
+                    Tracer.WriteLine("REGION: FORCE PALB");
+                    Region = EmuRegion.PALB;
+                    break;
+                case RegionSetting.ForceDENDY:
+                    Tracer.WriteLine("REGION: FORCE DENDY");
+                    Region = EmuRegion.DENDY;
+                    break;
+            }
+            SystemIndex = (int)Region;
+        }
+
+        public static void ApplyPaletteSetting()
+        {
+            Tracer.WriteLine("Loading palette generators values from settings...");
+            NTSCPaletteGenerator.brightness = MyNesMain.RendererSettings.Palette_NTSC_brightness;
+            NTSCPaletteGenerator.contrast = MyNesMain.RendererSettings.Palette_NTSC_contrast;
+            NTSCPaletteGenerator.gamma = MyNesMain.RendererSettings.Palette_NTSC_gamma;
+            NTSCPaletteGenerator.hue_tweak = MyNesMain.RendererSettings.Palette_NTSC_hue_tweak;
+            NTSCPaletteGenerator.saturation = MyNesMain.RendererSettings.Palette_NTSC_saturation;
+            PALBPaletteGenerator.brightness = MyNesMain.RendererSettings.Palette_PALB_brightness;
+            PALBPaletteGenerator.contrast = MyNesMain.RendererSettings.Palette_PALB_contrast;
+            PALBPaletteGenerator.gamma = MyNesMain.RendererSettings.Palette_PALB_gamma;
+            PALBPaletteGenerator.hue_tweak = MyNesMain.RendererSettings.Palette_PALB_hue_tweak;
+            PALBPaletteGenerator.saturation = MyNesMain.RendererSettings.Palette_PALB_saturation;
+            Tracer.WriteLine("Setting up palette ....");
+            switch ((PaletteSelectSetting)MyNesMain.RendererSettings.Palette_PaletteSetting)
+            {
+                case PaletteSelectSetting.AUTO:
+                    Tracer.WriteLine("Palette set to auto detect depending on region.");
+                    switch (Region)
+                    {
+                        case EmuRegion.NTSC:
+                            SetupPalette(NTSCPaletteGenerator.GeneratePalette());
+                            Tracer.WriteLine("Region is NTSC, Palette set from NTSC generator.");
+                            break;
+                        case EmuRegion.PALB:
+                        case EmuRegion.DENDY:
+                            SetupPalette(PALBPaletteGenerator.GeneratePalette());
+                            Tracer.WriteLine("Region is PALB/DENDY, Palette set from PALB generator.");
+                            break;
+                    }
+                    break;
+                case PaletteSelectSetting.ForceNTSC:
+                    Tracer.WriteLine("Palette set to always use NTSC palette generator.");
+                    SetupPalette(NTSCPaletteGenerator.GeneratePalette());
+                    Tracer.WriteLine("Palette set from NTSC generator.");
+                    break;
+                case PaletteSelectSetting.ForcePALB:
+                    Tracer.WriteLine("Palette set to always use PALB palette generator.");
+                    SetupPalette(NTSCPaletteGenerator.GeneratePalette());
+                    Tracer.WriteLine("Palette set from PALB generator.");
+                    break;
+                case PaletteSelectSetting.File:
+                    {
+                        Tracer.WriteLine("Palette set to load from file.");
+
+                        var paletteFileStream = MyNesMain.Supporter.OpenPaletteFile();
+                        if (paletteFileStream != null)
+                        {
+                            PaletteFileWrapper.LoadFile(paletteFileStream, out var palette);
+                            SetupPalette(palette);
+                            Tracer.WriteLine("Palette set from file");
+                            break;
+                        }
+                        Tracer.WriteError("Palette from file is not exist is not exist. Setting up palette from generators.");
+                        switch (Region)
+                        {
+                            case EmuRegion.NTSC:
+                                SetupPalette(NTSCPaletteGenerator.GeneratePalette());
+                                Tracer.WriteLine("Region is NTSC, Palette set from NTSC generator.");
+                                break;
+                            case EmuRegion.PALB:
+                            case EmuRegion.DENDY:
+                                SetupPalette(PALBPaletteGenerator.GeneratePalette());
+                                Tracer.WriteLine("Region is PALB/DENDY, Palette set from PALB generator.");
+                                break;
+                        }
+                        break;
+                    }
+            }
+        }
+
+        internal static void WriteStateData(ref BinaryWriter bin)
+        {
+            APUWriteState(ref bin);
+            CPUWriteState(ref bin);
+            DMAWriteState(ref bin);
+            InterruptsWriteState(ref bin);
+            MEMWriteState(ref bin);
+            PORTWriteState(ref bin);
+            PPUWriteState(ref bin);
+        }
+
+        internal static void ReadStateData(ref BinaryReader bin)
+        {
+            APUReadState(ref bin);
+            CPUReadState(ref bin);
+            DMAReadState(ref bin);
+            InterruptsReadState(ref bin);
+            MEMReadState(ref bin);
+            PORTReadState(ref bin);
+            PPUReadState(ref bin);
+        }
+
+        private static void SQ2HardReset()
+        {
+            sq2_duty_cycle = 0;
+            sq2_length_halt = false;
+            sq2_constant_volume_envelope = false;
+            sq2_volume_devider_period = 0;
+            sq2_sweep_enable = false;
+            sq2_sweep_devider_period = 0;
+            sq2_sweep_negate = false;
+            sq2_sweep_shift_count = 0;
+            sq2_timer = 0;
+            sq2_period_devider = 0;
+            sq2_seqencer = 0;
+            sq2_length_enabled = false;
+            sq2_length_counter = 0;
+            sq2_envelope_start_flag = false;
+            sq2_envelope_devider = 0;
+            sq2_envelope_decay_level_counter = 0;
+            sq2_envelope = 0;
+            sq2_sweep_counter = 0;
+            sq2_sweep_reload = false;
+            sq2_sweep_change = 0;
+            sq2_valid_freq = false;
+            sq2_output = 0;
+            sq2_ignore_reload = false;
+        }
+
+        private static void SQ2SoftReset()
+        {
+            SQ2HardReset();
+        }
+
+        private static void SQ2Clock()
+        {
+            sq2_period_devider--;
+            if (sq2_period_devider > 0)
+            {
+                return;
+            }
+            sq2_period_devider = sq2_timer + 1;
+            sq2_seqencer = (byte)((uint)(sq2_seqencer + 1) & 7u);
+            if (sq2_length_counter > 0 && sq2_valid_freq)
+            {
+                if (audio_sq2_outputable)
+                {
+                    sq2_output = sq_duty_cycle_sequences[sq2_duty_cycle][sq2_seqencer] * sq2_envelope;
+                }
+            }
+            else
+            {
+                sq2_output = 0;
+            }
+            audio_signal_outputed = true;
+        }
+
+        private static void SQ2ClockLength()
+        {
+            if (sq2_length_counter > 0 && !sq2_length_halt)
+            {
+                sq2_length_counter--;
+                if (apu_reg_access_happened && apu_reg_io_addr == 7 && apu_reg_access_w)
+                {
+                    sq2_ignore_reload = true;
+                }
+            }
+            sq2_sweep_counter--;
+            if (sq2_sweep_counter == 0)
+            {
+                sq2_sweep_counter = sq2_sweep_devider_period + 1;
+                if (sq2_sweep_enable && sq2_sweep_shift_count > 0 && sq2_valid_freq)
+                {
+                    sq2_sweep_change = sq2_timer >> (int)sq2_sweep_shift_count;
+                    sq2_timer += (sq2_sweep_negate ? (-sq2_sweep_change) : sq2_sweep_change);
+                    SQ2CalculateValidFreq();
+                }
+            }
+            else if (sq2_sweep_reload)
+            {
+                sq2_sweep_counter = sq2_sweep_devider_period + 1;
+                sq2_sweep_reload = false;
+            }
+        }
+
+        private static void SQ2ClockEnvelope()
+        {
+            if (sq2_envelope_start_flag)
+            {
+                sq2_envelope_start_flag = false;
+                sq2_envelope_decay_level_counter = 15;
+                sq2_envelope_devider = (byte)(sq2_volume_devider_period + 1);
+            }
+            else if (sq2_envelope_devider > 0)
+            {
+                sq2_envelope_devider--;
+            }
+            else
+            {
+                sq2_envelope_devider = (byte)(sq2_volume_devider_period + 1);
+                if (sq2_envelope_decay_level_counter > 0)
+                {
+                    sq2_envelope_decay_level_counter--;
+                }
+                else if (sq2_length_halt)
+                {
+                    sq2_envelope_decay_level_counter = 15;
+                }
+            }
+            sq2_envelope = (sq2_constant_volume_envelope ? sq2_volume_devider_period : sq2_envelope_decay_level_counter);
+        }
+
+        private static void APUOnRegister4004()
+        {
+            if (apu_reg_access_w)
+            {
+                sq2_duty_cycle = (byte)((apu_reg_io_db & 0xC0) >> 6);
+                sq2_volume_devider_period = (byte)(apu_reg_io_db & 0xFu);
+                sq2_length_halt = (apu_reg_io_db & 0x20) != 0;
+                sq2_constant_volume_envelope = (apu_reg_io_db & 0x10) != 0;
+                sq2_envelope = (sq2_constant_volume_envelope ? sq2_volume_devider_period : sq2_envelope_decay_level_counter);
+            }
+        }
+
+        private static void APUOnRegister4005()
+        {
+            if (apu_reg_access_w)
+            {
+                sq2_sweep_enable = (apu_reg_io_db & 0x80) == 128;
+                sq2_sweep_devider_period = (byte)((uint)(apu_reg_io_db >> 4) & 7u);
+                sq2_sweep_negate = (apu_reg_io_db & 8) == 8;
+                sq2_sweep_shift_count = (byte)(apu_reg_io_db & 7u);
+                sq2_sweep_reload = true;
+                SQ2CalculateValidFreq();
+            }
+        }
+
+        private static void APUOnRegister4006()
+        {
+            if (apu_reg_access_w)
+            {
+                sq2_timer = (sq2_timer & 0xFF00) | apu_reg_io_db;
+                SQ2CalculateValidFreq();
+            }
+        }
+
+        private static void APUOnRegister4007()
+        {
+            if (apu_reg_access_w)
+            {
+                sq2_timer = (sq2_timer & 0xFF) | ((apu_reg_io_db & 7) << 8);
+                if (sq2_length_enabled && !sq2_ignore_reload)
+                {
+                    sq2_length_counter = sq_duration_table[apu_reg_io_db >> 3];
+                }
+                if (sq2_ignore_reload)
+                {
+                    sq2_ignore_reload = false;
+                }
+                sq2_seqencer = 0;
+                sq2_envelope_start_flag = true;
+                SQ2CalculateValidFreq();
+            }
+        }
+
+        private static void SQ2On4015()
+        {
+            sq2_length_enabled = (apu_reg_io_db & 2) != 0;
+            if (!sq2_length_enabled)
+            {
+                sq2_length_counter = 0;
+            }
+        }
+
+        private static void SQ2Read4015()
+        {
+            if (sq2_length_counter > 0)
+            {
+                apu_reg_io_db = (byte)((apu_reg_io_db & 0xFDu) | 2u);
+            }
+        }
+
+        private static void SQ2CalculateValidFreq()
+        {
+            sq2_valid_freq = sq2_timer >= 8 && (sq2_sweep_negate || ((sq2_timer + (sq2_timer >> (int)sq2_sweep_shift_count)) & 0x800) == 0);
+        }
+
+        private static void SQ2WriteState(ref BinaryWriter bin)
+        {
+            bin.Write(sq2_duty_cycle);
+            bin.Write(sq2_length_halt);
+            bin.Write(sq2_constant_volume_envelope);
+            bin.Write(sq2_volume_devider_period);
+            bin.Write(sq2_sweep_enable);
+            bin.Write(sq2_sweep_devider_period);
+            bin.Write(sq2_sweep_negate);
+            bin.Write(sq2_sweep_shift_count);
+            bin.Write(sq2_timer);
+            bin.Write(sq2_period_devider);
+            bin.Write(sq2_seqencer);
+            bin.Write(sq2_length_enabled);
+            bin.Write(sq2_length_counter);
+            bin.Write(sq2_envelope_start_flag);
+            bin.Write(sq2_envelope_devider);
+            bin.Write(sq2_envelope_decay_level_counter);
+            bin.Write(sq2_envelope);
+            bin.Write(sq2_sweep_counter);
+            bin.Write(sq2_sweep_reload);
+            bin.Write(sq2_sweep_change);
+            bin.Write(sq2_valid_freq);
+            bin.Write(sq2_output);
+            bin.Write(sq2_ignore_reload);
+        }
+
+        private static void SQ2ReadState(ref BinaryReader bin)
+        {
+            sq2_duty_cycle = bin.ReadByte();
+            sq2_length_halt = bin.ReadBoolean();
+            sq2_constant_volume_envelope = bin.ReadBoolean();
+            sq2_volume_devider_period = bin.ReadByte();
+            sq2_sweep_enable = bin.ReadBoolean();
+            sq2_sweep_devider_period = bin.ReadByte();
+            sq2_sweep_negate = bin.ReadBoolean();
+            sq2_sweep_shift_count = bin.ReadByte();
+            sq2_timer = bin.ReadInt32();
+            sq2_period_devider = bin.ReadInt32();
+            sq2_seqencer = bin.ReadByte();
+            sq2_length_enabled = bin.ReadBoolean();
+            sq2_length_counter = bin.ReadInt32();
+            sq2_envelope_start_flag = bin.ReadBoolean();
+            sq2_envelope_devider = bin.ReadByte();
+            sq2_envelope_decay_level_counter = bin.ReadByte();
+            sq2_envelope = bin.ReadByte();
+            sq2_sweep_counter = bin.ReadInt32();
+            sq2_sweep_reload = bin.ReadBoolean();
+            sq2_sweep_change = bin.ReadInt32();
+            sq2_valid_freq = bin.ReadBoolean();
+            sq2_output = bin.ReadInt32();
+            sq2_ignore_reload = bin.ReadBoolean();
+        }
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/PALBPaletteGenerator.cs b/OtherCore/MyNes.Standard2/MyNes.Core/PALBPaletteGenerator.cs
new file mode 100644
index 00000000..266f1751
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/PALBPaletteGenerator.cs
@@ -0,0 +1,109 @@
+using System;
+
+namespace MyNes.Core
+{
+    public class PALBPaletteGenerator
+    {
+    	public const float default_saturation = 1.496f;
+
+    	public const float default_hue_tweak = 0f;
+
+    	public const float default_contrast = 1.016f;
+
+    	public const float default_brightness = 1.075f;
+
+    	public const float default_gamma = 1.975f;
+
+    	private const float black = 0.518f;
+
+    	private const float white = 1.962f;
+
+    	private const float attenuation = 0.746f;
+
+    	public static float saturation = 2f;
+
+    	public static float hue_tweak = 0f;
+
+    	public static float contrast = 1.4f;
+
+    	public static float brightness = 1.07f;
+
+    	public static float gamma = 2f;
+
+    	private static float[] levels = new float[8] { 0.35f, 0.518f, 0.962f, 1.55f, 1.094f, 1.506f, 1.962f, 1.962f };
+
+    	private static int wave(int p, int color)
+    	{
+    		if ((color + p + 8) % 12 >= 6)
+    		{
+    			return 0;
+    		}
+    		return 1;
+    	}
+
+    	private static float gammafix(float f, float gamma)
+    	{
+    		return (float)((f < 0f) ? 0.0 : Math.Pow(f, 2.2f / gamma));
+    	}
+
+    	private static int clamp(float v)
+    	{
+    		return (int)((v < 0f) ? 0f : ((v > 255f) ? 255f : v));
+    	}
+
+    	public static int MakeRGBcolor(int pixel)
+    	{
+    		int num = pixel & 0xF;
+    		int num2 = ((num >= 14) ? 1 : ((pixel >> 4) & 3));
+    		float[] array = new float[2]
+    		{
+    			levels[num2 + ((num == 0) ? 4 : 0)],
+    			levels[num2 + ((num <= 12) ? 4 : 0)]
+    		};
+    		float num3 = 0f;
+    		float num4 = 0f;
+    		float num5 = 0f;
+    		for (int i = 0; i < 12; i++)
+    		{
+    			float num6 = array[wave(i, num)];
+    			if ((((uint)pixel & 0x40u) != 0 && wave(i, 12) == 1) || (((uint)pixel & 0x80u) != 0 && wave(i, 4) == 1) || (((uint)pixel & 0x100u) != 0 && wave(i, 8) == 1))
+    			{
+    				num6 *= 0.746f;
+    			}
+    			float num7 = (num6 - 0.518f) / 1.444f;
+    			num7 = (num7 - 0.5f) * contrast + 0.5f;
+    			num7 *= brightness / 12f;
+    			num3 += num7;
+    			num4 += (float)((double)num7 * Math.Cos(Math.PI / 6.0 * (double)((float)i + 0.5f + hue_tweak)));
+    			num5 += (float)((double)num7 * Math.Sin(Math.PI / 6.0 * (double)((float)i + 0.5f + hue_tweak)));
+    		}
+    		num4 *= saturation;
+    		num5 *= saturation;
+    		return 65536 * clamp(255f * gammafix(num3 + 0.946882f * num4 + 0.623557f * num5, gamma)) + 256 * clamp(255f * gammafix(num3 - 245f / (328f * (float)Math.E) * num4 - 0.635691f * num5, gamma)) + clamp(255f * gammafix(num3 - 1.108545f * num4 + 1.709007f * num5, gamma));
+    	}
+
+    	public static int[] GeneratePalette()
+    	{
+    		int[] array = new int[512];
+    		for (int i = 0; i < 512; i++)
+    		{
+    			array[i] = MakeRGBcolor(i) | -16777216;
+    		}
+    		return array;
+    	}
+
+    	public static int[] GeneratePaletteGBR()
+    	{
+    		int[] array = new int[512];
+    		for (int i = 0; i < 512; i++)
+    		{
+    			int num = MakeRGBcolor(i);
+    			byte b = (byte)((num & 0xFF0000) >> 16);
+    			byte b2 = (byte)((num & 0xFF00) >> 8);
+    			byte b3 = (byte)((uint)num & 0xFFu);
+    			array[i] = -16777216 | (b3 << 16) | (b2 << 8) | b;
+    		}
+    		return array;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/PRGArea.cs b/OtherCore/MyNes.Standard2/MyNes.Core/PRGArea.cs
new file mode 100644
index 00000000..a9e1a501
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/PRGArea.cs
@@ -0,0 +1,18 @@
+namespace MyNes.Core
+{
+    internal enum PRGArea : byte
+    {
+    	Area4000 = 4,
+    	Area5000,
+    	Area6000,
+    	Area7000,
+    	Area8000,
+    	Area9000,
+    	AreaA000,
+    	AreaB000,
+    	AreaC000,
+    	AreaD000,
+    	AreaE000,
+    	AreaF000
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/PaletteFileWrapper.cs b/OtherCore/MyNes.Standard2/MyNes.Core/PaletteFileWrapper.cs
new file mode 100644
index 00000000..3f657bab
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/PaletteFileWrapper.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace MyNes.Core
+{
+    public class PaletteFileWrapper
+    {
+    	public static bool LoadFile(Stream fileStream, out int[] palette)
+    	{
+            Stream stream = fileStream;
+    		if (stream.Length == 192 || stream.Length == 1536)
+    		{
+    			int[] array = new int[512];
+    			byte[] array2 = new byte[stream.Length];
+    			stream.Read(array2, 0, array2.Length);
+    			int num = 0;
+    			for (int i = 0; i < 512; i++)
+    			{
+    				byte b = array2[num];
+    				num++;
+    				if (num == array2.Length)
+    				{
+    					num = 0;
+    				}
+    				byte b2 = array2[num];
+    				num++;
+    				if (num == array2.Length)
+    				{
+    					num = 0;
+    				}
+    				byte b3 = array2[num];
+    				num++;
+    				if (num == array2.Length)
+    				{
+    					num = 0;
+    				}
+    				array[i] = -16777216 | (b << 16) | (b2 << 8) | b3;
+    			}
+    			stream.Close();
+    			palette = array;
+    			return true;
+    		}
+    		palette = null;
+    		return false;
+    	}
+
+    	public static void SaveFile(string file, int[] palette)
+    	{
+    		Stream stream = new FileStream(file, FileMode.Create, FileAccess.Write);
+    		List<byte> list = new List<byte>();
+    		foreach (int num in palette)
+    		{
+    			list.Add((byte)((uint)(num >> 16) & 0xFFu));
+    			list.Add((byte)((uint)(num >> 8) & 0xFFu));
+    			list.Add((byte)((uint)num & 0xFFu));
+    		}
+    		stream.Write(list.ToArray(), 0, list.Count);
+    		stream.Close();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/PaletteSelectSetting.cs b/OtherCore/MyNes.Standard2/MyNes.Core/PaletteSelectSetting.cs
new file mode 100644
index 00000000..72607fba
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/PaletteSelectSetting.cs
@@ -0,0 +1,10 @@
+namespace MyNes.Core
+{
+    public enum PaletteSelectSetting
+    {
+    	AUTO,
+    	ForceNTSC,
+    	ForcePALB,
+    	File
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/RegionSetting.cs b/OtherCore/MyNes.Standard2/MyNes.Core/RegionSetting.cs
new file mode 100644
index 00000000..ce6c6756
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/RegionSetting.cs
@@ -0,0 +1,10 @@
+namespace MyNes.Core
+{
+    public enum RegionSetting
+    {
+    	AUTO,
+    	ForceNTSC,
+    	ForcePALB,
+    	ForceDENDY
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/RenderAudioSamples.cs b/OtherCore/MyNes.Standard2/MyNes.Core/RenderAudioSamples.cs
new file mode 100644
index 00000000..61b3f64d
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/RenderAudioSamples.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void RenderAudioSamples(ref short[] buffer, ref int samples_added);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/RenderVideoFrame.cs b/OtherCore/MyNes.Standard2/MyNes.Core/RenderVideoFrame.cs
new file mode 100644
index 00000000..12fed8c8
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/RenderVideoFrame.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void RenderVideoFrame(ref int[] buffer);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/RendererSettings.cs b/OtherCore/MyNes.Standard2/MyNes.Core/RendererSettings.cs
new file mode 100644
index 00000000..c9952097
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/RendererSettings.cs
@@ -0,0 +1,124 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    public class RendererSettings : ISettings
+    {
+    	public string Video_ProviderID = "";
+
+    	public bool Vid_AutoStretch = true;
+
+    	public int Vid_StretchMultiply = 3;
+
+    	public bool Vid_KeepAspectRatio;
+
+    	public bool Vid_ShowFPS;
+
+    	public bool Vid_HideLines = true;
+
+    	public bool Vid_Fullscreen;
+
+    	public bool Vid_HardwareVertexProcessing;
+
+    	public bool Vid_VSync;
+
+    	public bool Vid_ShowNotifications = true;
+
+    	public int Vid_Filter = 1;
+
+    	public bool FrameSkipEnabled;
+
+    	public int FrameSkipInterval = 2;
+
+    	public string Audio_ProviderID = "";
+
+    	public bool Audio_EnableFilters = true;
+
+    	public int Audio_Volume = 100;
+
+    	public bool Audio_SoundEnabled = true;
+
+    	public int Audio_Frequency = 48000;
+
+    	public int Audio_InternalSamplesCount = 1024;
+
+    	public int Audio_InternalPeekLimit = 124;
+
+    	public int Audio_PlaybackAmplitude = 200;
+
+    	public int Audio_PlaybackBufferSizeInKB = 16;
+
+    	public bool Audio_UseDefaultMixer;
+
+    	public bool Audio_ChannelEnabled_SQ1 = true;
+
+    	public bool Audio_ChannelEnabled_SQ2 = true;
+
+    	public bool Audio_ChannelEnabled_NOZ = true;
+
+    	public bool Audio_ChannelEnabled_TRL = true;
+
+    	public bool Audio_ChannelEnabled_DMC = true;
+
+    	public bool Audio_ChannelEnabled_MMC5_SQ1 = true;
+
+    	public bool Audio_ChannelEnabled_MMC5_SQ2 = true;
+
+    	public bool Audio_ChannelEnabled_MMC5_PCM = true;
+
+    	public bool Audio_ChannelEnabled_VRC6_SQ1 = true;
+
+    	public bool Audio_ChannelEnabled_VRC6_SQ2 = true;
+
+    	public bool Audio_ChannelEnabled_VRC6_SAW = true;
+
+    	public bool Audio_ChannelEnabled_SUN1 = true;
+
+    	public bool Audio_ChannelEnabled_SUN2 = true;
+
+    	public bool Audio_ChannelEnabled_SUN3 = true;
+
+    	public bool Audio_ChannelEnabled_NMT1 = true;
+
+    	public bool Audio_ChannelEnabled_NMT2 = true;
+
+    	public bool Audio_ChannelEnabled_NMT3 = true;
+
+    	public bool Audio_ChannelEnabled_NMT4 = true;
+
+    	public bool Audio_ChannelEnabled_NMT5 = true;
+
+    	public bool Audio_ChannelEnabled_NMT6 = true;
+
+    	public bool Audio_ChannelEnabled_NMT7 = true;
+
+    	public bool Audio_ChannelEnabled_NMT8 = true;
+
+    	public int Palette_PaletteSetting;
+
+    	public float Palette_NTSC_brightness = 1.075f;
+
+    	public float Palette_NTSC_contrast = 1.016f;
+
+    	public float Palette_NTSC_gamma = 1.975f;
+
+    	public float Palette_NTSC_hue_tweak;
+
+    	public float Palette_NTSC_saturation = 1.496f;
+
+    	public float Palette_PALB_brightness = 1.075f;
+
+    	public float Palette_PALB_contrast = 1.016f;
+
+    	public float Palette_PALB_gamma = 1.975f;
+
+    	public float Palette_PALB_hue_tweak;
+
+    	public float Palette_PALB_saturation = 1.496f;
+
+    	public RendererSettings(string path)
+    		: base(path)
+    	{
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/SRAMBankInfo.cs b/OtherCore/MyNes.Standard2/MyNes.Core/SRAMBankInfo.cs
new file mode 100644
index 00000000..4978583f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/SRAMBankInfo.cs
@@ -0,0 +1,22 @@
+namespace MyNes.Core
+{
+    public struct SRAMBankInfo
+    {
+    	public int id;
+
+    	public string SIZE;
+
+    	public bool BATTERY;
+
+    	public SRAMBankInfo(int id, string SIZE, bool BATTERY)
+    	{
+    		this.SIZE = SIZE;
+    		if (SIZE == "0kb")
+    		{
+    			SIZE = "8kb";
+    		}
+    		this.BATTERY = BATTERY;
+    		this.id = id;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/SoundDCBlockerFilter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/SoundDCBlockerFilter.cs
new file mode 100644
index 00000000..36b88bd0
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/SoundDCBlockerFilter.cs
@@ -0,0 +1,33 @@
+namespace MyNes.Core
+{
+    internal class SoundDCBlockerFilter
+    {
+    	private double R;
+
+    	private double y;
+
+    	private double y_1;
+
+    	private double x;
+
+    	private double x_1;
+
+    	public SoundDCBlockerFilter(double R)
+    	{
+    		this.R = R;
+    	}
+
+    	public void Reset()
+    	{
+    		y = (y_1 = (x = (x_1 = 0.0)));
+    	}
+
+    	public void DoFiltering(double sample, out double filtered)
+    	{
+    		x = sample;
+    		filtered = (y = x - x_1 + R * y_1);
+    		x_1 = x;
+    		y_1 = y;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/SoundHighPassFilter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/SoundHighPassFilter.cs
new file mode 100644
index 00000000..3c88fcdc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/SoundHighPassFilter.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace MyNes.Core
+{
+    internal class SoundHighPassFilter
+    {
+    	private double K;
+
+    	private double y_1;
+
+    	private double x_1;
+
+    	public SoundHighPassFilter(double k)
+    	{
+    		K = k;
+    	}
+
+    	public void Reset()
+    	{
+    		y_1 = (x_1 = 0.0);
+    	}
+
+    	public void DoFiltering(double sample, out double filtered)
+    	{
+    		filtered = K * y_1 + K * (sample - x_1);
+    		x_1 = sample;
+    		y_1 = filtered;
+    	}
+
+    	public static double GetK(double dt, double fc)
+    	{
+    		double num = Math.PI * 2.0 * dt * fc;
+    		return num / (num + 1.0);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/SoundLowPassFilter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/SoundLowPassFilter.cs
new file mode 100644
index 00000000..4008600b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/SoundLowPassFilter.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace MyNes.Core
+{
+    internal class SoundLowPassFilter
+    {
+    	private double K;
+
+    	private double K_1;
+
+    	private double y;
+
+    	private double y_1;
+
+    	private double x;
+
+    	private double x_1;
+
+    	public SoundLowPassFilter(double k)
+    	{
+    		K = k;
+    		K_1 = 1.0 - k;
+    	}
+
+    	public void Reset(double k)
+    	{
+    		y = (y_1 = (x = (x_1 = 0.0)));
+    		K = k;
+    		K_1 = 1.0 - k;
+    	}
+
+    	public void DoFiltering(double sample, out double filtered)
+    	{
+    		filtered = K * sample + K_1 * y_1;
+    		x_1 = sample;
+    		y_1 = filtered;
+    	}
+
+    	public static double GetK(double dt, double fc)
+    	{
+    		double num = Math.PI * 2.0 * dt * fc;
+    		return num / (num + 1.0);
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/StateHandler.cs b/OtherCore/MyNes.Standard2/MyNes.Core/StateHandler.cs
new file mode 100644
index 00000000..1e770a8b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/StateHandler.cs
@@ -0,0 +1,194 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace MyNes.Core
+{
+    public class StateHandler
+    {
+    	public static int Slot = 0;
+
+    	internal static string StateFolder = "States";
+
+    	private const byte state_version = 7;
+
+    	private static bool IsSavingState = false;
+
+    	private static bool IsLoadingState = false;
+
+    	public static void SaveState(string fileName, bool saveImage)
+    	{
+    		if (!NesEmu.ON)
+    		{
+    			Tracer.WriteError("Can't save state, emu is off.");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error1, instant: false);
+    			return;
+    		}
+    		if (!File.Exists(NesEmu.CurrentFilePath))
+    		{
+    			Tracer.WriteError("Can't save state, no rom file is loaded.");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error2, instant: false);
+    			return;
+    		}
+    		if (IsLoadingState)
+    		{
+    			Tracer.WriteError("Can't save state while loading a state !");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error3, instant: false);
+    			return;
+    		}
+    		if (IsSavingState)
+    		{
+    			Tracer.WriteError("Already saving state !!");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error4, instant: false);
+    			return;
+    		}
+    		IsSavingState = true;
+    		BinaryWriter bin = new BinaryWriter(new MemoryStream());
+    		bin.Write(Encoding.ASCII.GetBytes("MNS"));
+    		bin.Write((byte)7);
+    		for (int i = 0; i < NesEmu.SHA1.Length; i += 2)
+    		{
+    			string value = NesEmu.SHA1.Substring(i, 2).ToUpper();
+    			bin.Write(Convert.ToByte(value, 16));
+    		}
+    		NesEmu.WriteStateData(ref bin);
+    		byte[] outData = new byte[0];
+    		ZlipWrapper.CompressData(((MemoryStream)bin.BaseStream).GetBuffer(), out outData);
+    		FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
+    		fileStream.Write(outData, 0, outData.Length);
+    		MyNesMain.VideoProvider.TakeSnapshotAs(fileName.Replace(".mns", ".jpg"), ".jpg");
+    		bin.Flush();
+    		bin.Close();
+    		fileStream.Flush();
+    		fileStream.Close();
+    		IsSavingState = false;
+    		Tracer.WriteInformation("State saved at slot " + Slot);
+    		MyNesMain.VideoProvider.WriteInfoNotification(MNInterfaceLanguage.Message_Info1 + " " + Slot, instant: false);
+    	}
+
+    	public static void SaveState(int Slot)
+    	{
+    		if (StateFolder == "States")
+    		{
+    			StateFolder = Path.Combine(MyNesMain.WorkingFolder, "States");
+    		}
+    		Directory.CreateDirectory(StateFolder);
+    		SaveState(Path.Combine(StateFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath)) + "_" + Slot + ".mns", saveImage: false);
+    	}
+
+    	public static void SaveState()
+    	{
+    		SaveState(Slot);
+    	}
+
+    	public static void LoadState()
+    	{
+    		LoadState(Slot);
+    	}
+
+    	public static void LoadState(string fileName)
+    	{
+    		if (!NesEmu.ON)
+    		{
+    			Tracer.WriteError("Can't load state, emu is off.");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error5, instant: false);
+    			return;
+    		}
+    		if (!File.Exists(NesEmu.CurrentFilePath))
+    		{
+    			Tracer.WriteError("Can't load state, no rom file is loaded.");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error6, instant: false);
+    			return;
+    		}
+    		if (IsSavingState)
+    		{
+    			Tracer.WriteError("Can't load state while saving a state !");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error7, instant: false);
+    			return;
+    		}
+    		if (IsLoadingState)
+    		{
+    			Tracer.WriteError("Already loading state !!");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error8, instant: false);
+    			return;
+    		}
+    		if (!File.Exists(fileName))
+    		{
+    			Tracer.WriteError("No state found in slot " + Slot);
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error9 + " " + Slot, instant: false);
+    			return;
+    		}
+    		IsLoadingState = true;
+    		FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
+    		byte[] array = new byte[fileStream.Length];
+    		byte[] outData = new byte[0];
+    		fileStream.Read(array, 0, array.Length);
+    		fileStream.Close();
+    		ZlipWrapper.DecompressData(array, out outData);
+    		BinaryReader bin = new BinaryReader(new MemoryStream(outData));
+    		byte[] array2 = new byte[3];
+    		bin.Read(array2, 0, array2.Length);
+    		if (Encoding.ASCII.GetString(array2) != "MNS")
+    		{
+    			Tracer.WriteError("Unable load state at slot " + Slot + "; Not My Nes State File !");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error10 + " " + Slot + "; " + MNInterfaceLanguage.Message_Error11, instant: false);
+    			IsLoadingState = false;
+    			return;
+    		}
+    		if (bin.ReadByte() != 7)
+    		{
+    			Tracer.WriteError("Unable load state at slot " + Slot + "; Not compatible state file version !");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error10 + " " + Slot + "; " + MNInterfaceLanguage.Message_Error12, instant: false);
+    			IsLoadingState = false;
+    			return;
+    		}
+    		string text = "";
+    		for (int i = 0; i < NesEmu.SHA1.Length; i += 2)
+    		{
+    			text += bin.ReadByte().ToString("X2");
+    		}
+    		if (text.ToLower() != NesEmu.SHA1.ToLower())
+    		{
+    			Tracer.WriteError("Unable load state at slot " + Slot + "; This state file is not for this game; not same SHA1 !");
+    			MyNesMain.VideoProvider.WriteErrorNotification(MNInterfaceLanguage.Message_Error10 + " " + Slot + "; " + MNInterfaceLanguage.Message_Error13, instant: false);
+    			IsLoadingState = false;
+    		}
+    		else
+    		{
+    			NesEmu.ReadStateData(ref bin);
+    			bin.Close();
+    			IsLoadingState = false;
+    			Tracer.WriteInformation("State loaded from slot " + Slot);
+    			MyNesMain.VideoProvider.WriteInfoNotification(MNInterfaceLanguage.Message_Info2 + " " + Slot, instant: false);
+    		}
+    	}
+
+    	public static void LoadState(int Slot)
+    	{
+    		if (StateFolder == "States")
+    		{
+    			StateFolder = Path.Combine(MyNesMain.WorkingFolder, "States");
+    		}
+    		Directory.CreateDirectory(StateFolder);
+    		LoadState(Path.Combine(StateFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath)) + "_" + Slot + ".mns");
+    	}
+
+    	public static string GetStateFile(int slot)
+    	{
+    		if (File.Exists(NesEmu.CurrentFilePath))
+    		{
+    			return Path.Combine(StateFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath)) + "_" + slot + ".mns";
+    		}
+    		return "";
+    	}
+
+    	public static string GetStateImageFile(int slot)
+    	{
+    		if (File.Exists(NesEmu.CurrentFilePath))
+    		{
+    			return Path.Combine(StateFolder, Path.GetFileNameWithoutExtension(NesEmu.CurrentFilePath)) + "_" + slot + ".jpg";
+    		}
+    		return "";
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Sunsoft5BChnl.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Sunsoft5BChnl.cs
new file mode 100644
index 00000000..8f479879
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Sunsoft5BChnl.cs
@@ -0,0 +1,95 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class Sunsoft5BChnl
+    {
+    	internal bool Enabled;
+
+    	internal byte Volume;
+
+    	private int dutyStep;
+
+    	private int freqTimer;
+
+    	private int frequency;
+
+    	private int cycles;
+
+    	internal int output;
+
+    	internal bool Outputable;
+
+    	internal void HardReset()
+    	{
+    	}
+
+    	internal void SoftReset()
+    	{
+    	}
+
+    	internal void Write0(ref byte data)
+    	{
+    		frequency = (frequency & 0xF00) | data;
+    		freqTimer = (frequency + 1) * 2;
+    	}
+
+    	internal void Write1(ref byte data)
+    	{
+    		frequency = (frequency & 0xFF) | ((data & 0xF) << 8);
+    		freqTimer = (frequency + 1) * 2;
+    	}
+
+    	internal void ClockSingle()
+    	{
+    		if (--cycles > 0)
+    		{
+    			return;
+    		}
+    		cycles = freqTimer;
+    		dutyStep = (dutyStep + 1) & 0x1F;
+    		if (dutyStep <= 15)
+    		{
+    			if (Enabled)
+    			{
+    				if (Outputable)
+    				{
+    					output = Volume;
+    				}
+    				else
+    				{
+    					output = 0;
+    				}
+    			}
+    			else
+    			{
+    				output = 0;
+    			}
+    		}
+    		else
+    		{
+    			output = 0;
+    		}
+    	}
+
+    	internal void SaveState(ref BinaryWriter stream)
+    	{
+    		stream.Write(Enabled);
+    		stream.Write(Volume);
+    		stream.Write(dutyStep);
+    		stream.Write(freqTimer);
+    		stream.Write(frequency);
+    		stream.Write(cycles);
+    	}
+
+    	internal void LoadState(ref BinaryReader stream)
+    	{
+    		Enabled = stream.ReadBoolean();
+    		Volume = stream.ReadByte();
+    		dutyStep = stream.ReadInt32();
+    		freqTimer = stream.ReadInt32();
+    		frequency = stream.ReadInt32();
+    		cycles = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumJoyIndex.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumJoyIndex.cs
new file mode 100644
index 00000000..69c2a938
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumJoyIndex.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    public enum EnumJoyIndex : byte
+    {
+        P1, P2, P3, P4
+    }
+}
\ No newline at end of file
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumKeyKind.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumKeyKind.cs
new file mode 100644
index 00000000..77d08754
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Support/EnumKeyKind.cs
@@ -0,0 +1,7 @@
+namespace MyNes.Core
+{
+    public enum EnumKeyKind
+    {
+        Up, Down, Left, Right, Select, Start, B, A, TurboB, TurboA
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Support/IExternalSuppoter.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Support/IExternalSuppoter.cs
new file mode 100644
index 00000000..ef23d594
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Support/IExternalSuppoter.cs
@@ -0,0 +1,13 @@
+using System.IO;
+namespace MyNes.Core
+{
+
+    public interface IExternalSupporter
+    {
+        string GetWorkingFolderPath();
+        Stream OpenDatabaseFile();
+        Stream OpenPaletteFile();
+        Stream OpenRomFile(string path);
+        bool IsKeyPressing(EnumJoyIndex index,EnumKeyKind key);
+    }
+}
\ No newline at end of file
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/TogglePause.cs b/OtherCore/MyNes.Standard2/MyNes.Core/TogglePause.cs
new file mode 100644
index 00000000..71167bdc
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/TogglePause.cs
@@ -0,0 +1,4 @@
+namespace MyNes.Core
+{
+    internal delegate void TogglePause(bool paused);
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/Tracer.cs b/OtherCore/MyNes.Standard2/MyNes.Core/Tracer.cs
new file mode 100644
index 00000000..ea5ea040
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/Tracer.cs
@@ -0,0 +1,75 @@
+#define TRACE
+using System;
+
+namespace MyNes.Core
+{
+    public sealed class Tracer
+    {
+        public static event EventHandler<TracerEventArgs> EventRaised;
+
+        public static void WriteLine(string message)
+        {
+            Tracer.EventRaised?.Invoke(null, new TracerEventArgs(message, TracerStatus.Normal));
+            //Debug.Log(message);
+        }
+
+        public static void WriteLine(string message, string category)
+        {
+            Tracer.EventRaised?.Invoke(null, new TracerEventArgs($"{category}: {message}", TracerStatus.Normal));
+            //Debug.Log(message);
+        }
+
+        public static void WriteLine(string message, TracerStatus status)
+        {
+            Tracer.EventRaised?.Invoke(null, new TracerEventArgs(message, status));
+            switch (status)
+            {
+                case TracerStatus.Error: WriteLine(message); break;
+                case TracerStatus.Infromation:
+                case TracerStatus.Normal:
+                    WriteLine(message);
+                    break;
+                case TracerStatus.Warning:
+                    WriteLine(message);
+                    break;
+            }
+
+        }
+
+        public static void WriteLine(string message, string category, TracerStatus status)
+        {
+            Tracer.EventRaised?.Invoke(null, new TracerEventArgs($"{category}: {message}", status));
+            WriteLine($"{category}:{message}", status);
+        }
+
+        public static void WriteError(string message)
+        {
+            WriteLine(message, TracerStatus.Error);
+        }
+
+        public static void WriteError(string message, string category)
+        {
+            WriteLine(message, category, TracerStatus.Error);
+        }
+
+        public static void WriteWarning(string message)
+        {
+            WriteLine(message, TracerStatus.Warning);
+        }
+
+        public static void WriteWarning(string message, string category)
+        {
+            WriteLine(message, category, TracerStatus.Warning);
+        }
+
+        public static void WriteInformation(string message)
+        {
+            WriteLine(message, TracerStatus.Infromation);
+        }
+
+        public static void WriteInformation(string message, string category)
+        {
+            WriteLine(message, category, TracerStatus.Infromation);
+        }
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/TracerEventArgs.cs b/OtherCore/MyNes.Standard2/MyNes.Core/TracerEventArgs.cs
new file mode 100644
index 00000000..4f066653
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/TracerEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace MyNes.Core
+{
+    public class TracerEventArgs : EventArgs
+    {
+    	public string Message { get; private set; }
+
+    	public TracerStatus Status { get; private set; }
+
+    	public TracerEventArgs(string message, TracerStatus status)
+    	{
+    		Message = message;
+    		Status = status;
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/TracerStatus.cs b/OtherCore/MyNes.Standard2/MyNes.Core/TracerStatus.cs
new file mode 100644
index 00000000..77b53f5b
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/TracerStatus.cs
@@ -0,0 +1,10 @@
+namespace MyNes.Core
+{
+    public enum TracerStatus
+    {
+    	Normal,
+    	Error,
+    	Warning,
+    	Infromation
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Pulse.cs b/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Pulse.cs
new file mode 100644
index 00000000..4ecd20b2
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Pulse.cs
@@ -0,0 +1,116 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class VRC6Pulse
+    {
+    	private int dutyForm;
+
+    	private int dutyStep;
+
+    	private bool enabled = true;
+
+    	internal bool Outputable;
+
+    	private bool mode;
+
+    	private byte volume;
+
+    	private int freqTimer;
+
+    	private int frequency;
+
+    	private int cycles;
+
+    	internal int output;
+
+    	internal void HardReset()
+    	{
+    		dutyForm = 0;
+    		dutyStep = 15;
+    		enabled = true;
+    		mode = false;
+    		output = 0;
+    	}
+
+    	internal void Write0(ref byte data)
+    	{
+    		mode = (data & 0x80) == 128;
+    		dutyForm = (data & 0x70) >> 4;
+    		volume = (byte)(data & 0xFu);
+    	}
+
+    	internal void Write1(ref byte data)
+    	{
+    		frequency = (frequency & 0xF00) | data;
+    	}
+
+    	internal void Write2(ref byte data)
+    	{
+    		frequency = (frequency & 0xFF) | ((data & 0xF) << 8);
+    		enabled = (data & 0x80) == 128;
+    	}
+
+    	internal void ClockSingle()
+    	{
+    		if (--cycles > 0)
+    		{
+    			return;
+    		}
+    		cycles = (frequency << 1) + 2;
+    		if (!enabled)
+    		{
+    			return;
+    		}
+    		if (mode)
+    		{
+    			output = volume;
+    			return;
+    		}
+    		dutyStep--;
+    		if (dutyStep < 0)
+    		{
+    			dutyStep = 15;
+    		}
+    		if (dutyStep <= dutyForm)
+    		{
+    			if (Outputable)
+    			{
+    				output = volume;
+    			}
+    			else
+    			{
+    				output = 0;
+    			}
+    		}
+    		else
+    		{
+    			output = 0;
+    		}
+    	}
+
+    	internal void SaveState(ref BinaryWriter stream)
+    	{
+    		stream.Write(dutyForm);
+    		stream.Write(dutyStep);
+    		stream.Write(enabled);
+    		stream.Write(mode);
+    		stream.Write(volume);
+    		stream.Write(freqTimer);
+    		stream.Write(frequency);
+    		stream.Write(cycles);
+    	}
+
+    	internal void LoadState(ref BinaryReader stream)
+    	{
+    		dutyForm = stream.ReadInt32();
+    		dutyStep = stream.ReadInt32();
+    		enabled = stream.ReadBoolean();
+    		mode = stream.ReadBoolean();
+    		volume = stream.ReadByte();
+    		freqTimer = stream.ReadInt32();
+    		frequency = stream.ReadInt32();
+    		cycles = stream.ReadInt32();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Sawtooth.cs b/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Sawtooth.cs
new file mode 100644
index 00000000..1a50eb55
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/VRC6Sawtooth.cs
@@ -0,0 +1,114 @@
+using System.IO;
+
+namespace MyNes.Core
+{
+    internal class VRC6Sawtooth
+    {
+    	private byte AccumRate;
+
+    	private int accumClock;
+
+    	private byte accumulationRegister;
+
+    	private int frequency;
+
+    	private int freqTimer;
+
+    	private int cycles;
+
+    	private bool enabled;
+
+    	internal int output;
+
+    	internal bool Outputable;
+
+    	internal void HardReset()
+    	{
+    	}
+
+    	private void UpdateFrequency()
+    	{
+    		freqTimer = (frequency + 1) * 2;
+    	}
+
+    	internal void Write0(ref byte data)
+    	{
+    		AccumRate = (byte)(data & 0x3Fu);
+    	}
+
+    	internal void Write1(ref byte data)
+    	{
+    		frequency = (frequency & 0xF00) | data;
+    		UpdateFrequency();
+    	}
+
+    	internal void Write2(ref byte data)
+    	{
+    		frequency = (frequency & 0xFF) | ((data & 0xF) << 8);
+    		enabled = (data & 0x80) == 128;
+    		UpdateFrequency();
+    	}
+
+    	internal void ClockSingle()
+    	{
+    		if (--cycles > 0)
+    		{
+    			return;
+    		}
+    		cycles = freqTimer;
+    		if (enabled)
+    		{
+    			accumClock++;
+    			switch (++accumClock)
+    			{
+    			case 2:
+    			case 4:
+    			case 6:
+    			case 8:
+    			case 10:
+    			case 12:
+    				accumulationRegister += AccumRate;
+    				break;
+    			case 14:
+    				accumulationRegister = 0;
+    				accumClock = 0;
+    				break;
+    			}
+    			if (Outputable)
+    			{
+    				output = (accumulationRegister >> 3) & 0x1F;
+    			}
+    			else
+    			{
+    				output = 0;
+    			}
+    		}
+    		else
+    		{
+    			output = 0;
+    		}
+    	}
+
+    	internal void SaveState(ref BinaryWriter stream)
+    	{
+    		stream.Write(AccumRate);
+    		stream.Write(accumClock);
+    		stream.Write(accumulationRegister);
+    		stream.Write(frequency);
+    		stream.Write(freqTimer);
+    		stream.Write(cycles);
+    		stream.Write(enabled);
+    	}
+
+    	internal void LoadState(ref BinaryReader stream)
+    	{
+    		AccumRate = stream.ReadByte();
+    		accumClock = stream.ReadInt32();
+    		accumulationRegister = stream.ReadByte();
+    		frequency = stream.ReadInt32();
+    		freqTimer = stream.ReadInt32();
+    		cycles = stream.ReadInt32();
+    		enabled = stream.ReadBoolean();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/WaveRecorder.cs b/OtherCore/MyNes.Standard2/MyNes.Core/WaveRecorder.cs
new file mode 100644
index 00000000..5e8afcdf
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/WaveRecorder.cs
@@ -0,0 +1,302 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace MyNes.Core
+{
+    public class WaveRecorder
+    {
+    	private string _fileName;
+
+    	private Stream STR;
+
+    	private bool _IsRecording;
+
+    	private int SIZE;
+
+    	private int NoOfSamples;
+
+    	private int _Time;
+
+    	private int TimeSamples;
+
+    	private short channels;
+
+    	private short bitsPerSample;
+
+    	private int Frequency;
+
+    	public int Time => _Time;
+
+    	public bool IsRecording => _IsRecording;
+
+    	public void Record(string FilePath, short channels, short bitsPerSample, int Frequency)
+    	{
+    		_fileName = FilePath;
+    		this.channels = channels;
+    		this.bitsPerSample = bitsPerSample;
+    		this.Frequency = Frequency;
+    		_Time = 0;
+    		STR = new FileStream(FilePath, FileMode.Create);
+    		ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
+    		STR.Write(aSCIIEncoding.GetBytes("RIFF"), 0, 4);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.Write(aSCIIEncoding.GetBytes("WAVE"), 0, 4);
+    		STR.Write(aSCIIEncoding.GetBytes("fmt "), 0, 4);
+    		STR.WriteByte(16);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(1);
+    		STR.WriteByte(0);
+    		STR.WriteByte((byte)((uint)channels & 0xFFu));
+    		STR.WriteByte((byte)((channels & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Frequency & 0xFFu));
+    		STR.WriteByte((byte)((Frequency & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((Frequency & 0xFF0000) >> 16));
+    		STR.WriteByte((byte)((Frequency & 0xFF000000u) >> 24));
+    		int num = Frequency * channels * (bitsPerSample / 8);
+    		STR.WriteByte((byte)((uint)num & 0xFFu));
+    		STR.WriteByte((byte)((num & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((num & 0xFF0000) >> 16));
+    		STR.WriteByte((byte)((num & 0xFF000000u) >> 24));
+    		short num2 = (short)(channels * (bitsPerSample / 8));
+    		STR.WriteByte((byte)((uint)num2 & 0xFFu));
+    		STR.WriteByte((byte)((num2 & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)bitsPerSample & 0xFFu));
+    		STR.WriteByte((byte)((bitsPerSample & 0xFF00) >> 8));
+    		STR.Write(aSCIIEncoding.GetBytes("data"), 0, 4);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		STR.WriteByte(0);
+    		_IsRecording = true;
+    	}
+
+    	public void AddBuffer(ref byte[] buffer)
+    	{
+    		for (int i = 0; i < buffer.Length; i++)
+    		{
+    			switch (channels)
+    			{
+    			case 1:
+    				switch (bitsPerSample)
+    				{
+    				case 8:
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				case 16:
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				case 32:
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				}
+    				break;
+    			case 2:
+    				switch (bitsPerSample)
+    				{
+    				case 8:
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				case 16:
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				case 32:
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					STR.WriteByte(buffer[i]);
+    					i++;
+    					STR.WriteByte(buffer[i]);
+    					NoOfSamples++;
+    					TimeSamples++;
+    					if (TimeSamples >= Frequency)
+    					{
+    						_Time++;
+    						TimeSamples = 0;
+    					}
+    					break;
+    				}
+    				break;
+    			}
+    		}
+    	}
+
+    	public void AddSample(int Sample)
+    	{
+    		if (!_IsRecording)
+    		{
+    			return;
+    		}
+    		switch (channels)
+    		{
+    		case 1:
+    			switch (bitsPerSample)
+    			{
+    			case 8:
+    				AddSample_mono_08(Sample);
+    				break;
+    			case 16:
+    				AddSample_mono_16(Sample);
+    				break;
+    			case 32:
+    				AddSample_mono_32(Sample);
+    				break;
+    			}
+    			break;
+    		case 2:
+    			switch (bitsPerSample)
+    			{
+    			case 8:
+    				AddSample_stereo_08(Sample);
+    				break;
+    			case 16:
+    				AddSample_stereo_16(Sample);
+    				break;
+    			case 32:
+    				AddSample_stereo_32(Sample);
+    				break;
+    			}
+    			break;
+    		}
+    		NoOfSamples++;
+    		TimeSamples++;
+    		if (TimeSamples >= Frequency)
+    		{
+    			_Time++;
+    			TimeSamples = 0;
+    		}
+    	}
+
+    	private void AddSample_mono_08(int Sample)
+    	{
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	private void AddSample_mono_16(int Sample)
+    	{
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	private void AddSample_mono_32(int Sample)
+    	{
+    		STR.WriteByte((byte)((Sample & 0xFF000000u) >> 24));
+    		STR.WriteByte((byte)((Sample & 0xFF0000) >> 16));
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	private void AddSample_stereo_08(int Sample)
+    	{
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	private void AddSample_stereo_16(int Sample)
+    	{
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	private void AddSample_stereo_32(int Sample)
+    	{
+    		STR.WriteByte((byte)((Sample & 0xFF000000u) >> 24));
+    		STR.WriteByte((byte)((Sample & 0xFF0000) >> 16));
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    		STR.WriteByte((byte)((Sample & 0xFF000000u) >> 24));
+    		STR.WriteByte((byte)((Sample & 0xFF0000) >> 16));
+    		STR.WriteByte((byte)((Sample & 0xFF00) >> 8));
+    		STR.WriteByte((byte)((uint)Sample & 0xFFu));
+    	}
+
+    	public void Stop()
+    	{
+    		if (_IsRecording & (STR != null))
+    		{
+    			NoOfSamples *= channels * (bitsPerSample / 8);
+    			SIZE = NoOfSamples + 36;
+    			byte[] array = new byte[4];
+    			byte[] array2 = new byte[4];
+    			array = BitConverter.GetBytes(SIZE);
+    			if (!BitConverter.IsLittleEndian)
+    			{
+    				Array.Reverse(array);
+    			}
+    			array2 = BitConverter.GetBytes(NoOfSamples);
+    			if (!BitConverter.IsLittleEndian)
+    			{
+    				Array.Reverse(array2);
+    			}
+    			_IsRecording = false;
+    			STR.Position = 4L;
+    			STR.Write(array, 0, 4);
+    			STR.Position = 40L;
+    			STR.Write(array2, 0, 4);
+    			STR.Close();
+    			MyNesMain.VideoProvider.WriteInfoNotification("Sound file saved at " + Path.GetFileName(_fileName), instant: false);
+    		}
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/WithExternalSoundAttribute.cs b/OtherCore/MyNes.Standard2/MyNes.Core/WithExternalSoundAttribute.cs
new file mode 100644
index 00000000..9ac2ff8f
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/WithExternalSoundAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace MyNes.Core
+{
+    internal class WithExternalSoundAttribute : Attribute
+    {
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Core/ZlipWrapper.cs b/OtherCore/MyNes.Standard2/MyNes.Core/ZlipWrapper.cs
new file mode 100644
index 00000000..eb469170
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Core/ZlipWrapper.cs
@@ -0,0 +1,43 @@
+using System.IO;
+using ComponentAce.Compression.Libs.zlib;
+
+namespace MyNes.Core
+{
+    internal class ZlipWrapper
+    {
+    	internal static void CompressData(byte[] inData, out byte[] outData)
+    	{
+            using (MemoryStream memoryStream = new MemoryStream())
+            using (ZOutputStream zOutputStream = new ZOutputStream(memoryStream, -1))
+            using (Stream input = new MemoryStream(inData))
+            { 
+                CopyStream(input, zOutputStream);
+    		    zOutputStream.finish();
+    		    outData = memoryStream.ToArray();
+            }
+    	}
+
+    	internal static void DecompressData(byte[] inData, out byte[] outData)
+    	{
+            using (MemoryStream memoryStream = new MemoryStream())
+            using (ZOutputStream zOutputStream = new ZOutputStream(memoryStream))
+            using (Stream input = new MemoryStream(inData))
+            { 
+                CopyStream(input, zOutputStream);
+    		    zOutputStream.finish();
+    		    outData = memoryStream.ToArray();
+            }
+    	}
+
+    	internal static void CopyStream(Stream input, Stream output)
+    	{
+    		byte[] buffer = new byte[2000];
+    		int count;
+    		while ((count = input.Read(buffer, 0, 2000)) > 0)
+    		{
+    			output.Write(buffer, 0, count);
+    		}
+    		output.Flush();
+    	}
+    }
+}
diff --git a/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj b/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj
new file mode 100644
index 00000000..dbdcea46
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+</Project>
diff --git a/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj.user b/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj.user
new file mode 100644
index 00000000..075a3a06
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/MyNes.Standard2.csproj.user
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_LastSelectedProfileId>G:\Sin365\AxibugEmuOnline\MyNes.Standard2\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml b/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 00000000..2e73e295
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\netstandard2.0\publish\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user b/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 00000000..99855393
--- /dev/null
+++ b/OtherCore/MyNes.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <History>True|2024-07-19T08:13:43.4065117Z;True|2024-07-19T16:04:53.5646935+08:00;True|2024-07-19T16:04:45.2930639+08:00;True|2024-07-19T15:38:36.8500841+08:00;True|2024-07-19T13:03:44.4745338+08:00;</History>
+    <LastFailureDetails />
+  </PropertyGroup>
+</Project>
\ No newline at end of file