Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper035.cs
2 views
using BizHawk.Common;
using BizHawk.Common.NumberExtensions;

namespace BizHawk.Emulation.Cores.Nintendo.NES
{
	public sealed class Mapper035 : NES.NESBoardBase
	{
		private ByteBuffer reg = new ByteBuffer(8);
		private ByteBuffer chr = new ByteBuffer(8);

		private int prg_bank_mask_8k;
		private int chr_bank_mask_1k;

		private bool IRQa;
		private int IRQCount;

		public override bool Configure(NES.EDetectionOrigin origin)
		{
			switch (Cart.board_type)
			{
				case "MAPPER035":
					break;
				default:
					return false;
			}

			prg_bank_mask_8k = Cart.prg_size / 8 - 1;
			chr_bank_mask_1k = Cart.chr_size / 1 - 1;
			SetMirrorType(Cart.pad_h, Cart.pad_v);
			return true;
		}

		public override void Dispose()
		{
			reg.Dispose();
			chr.Dispose();
			base.Dispose();
		}

		public override void SyncState(Serializer ser)
		{
			ser.Sync("reg", ref reg);
			ser.Sync("chr", ref chr);
			ser.Sync("IRQa", ref IRQa);
			ser.Sync("IRQCount", ref IRQCount);
			base.SyncState(ser);
		}

		public override byte ReadEXP(int addr)
		{
			if (addr == 0x800)
			{
				return 0x20;
			}

			return base.ReadEXP(addr);
		}

		private void SetMirror()
		{
			SetMirrorType(reg[3].Bit(0) ? EMirrorType.Horizontal : EMirrorType.Vertical);
		}

		public override void WritePRG(int addr, byte value)
		{
			addr += 0x8000;
			switch (addr)
			{
				case 0x8000: reg[0] = value; break;
				case 0x8001: reg[1] = value; break;
				case 0x8002: reg[2] = value; break;
				case 0x9000: chr[0] = value; break;
				case 0x9001: chr[1] = value; break;
				case 0x9002: chr[2] = value; break;
				case 0x9003: chr[3] = value; break;
				case 0x9004: chr[4] = value; break;
				case 0x9005: chr[5] = value; break;
				case 0x9006: chr[6] = value; break;
				case 0x9007: chr[7] = value; break;

				case 0xC002: IRQa = false; IRQSignal = false; break;
				case 0xC005: IRQCount = value; break;
				case 0xC003: IRQa = true; break;

				case 0xD001: reg[3] = value;
					SetMirror(); break;
			}
		}

		public override byte ReadPRG(int addr)
		{
			int index = addr >> 13;

			int bank = reg[index];
			if (index == 3) { bank = 0xFF; }
			bank &= prg_bank_mask_8k;

			return ROM[(bank << 13) + (addr & 0x1FFF)];
		}

		public override byte ReadPPU(int addr)
		{
			if (addr < 0x2000)
			{
				int index = addr >> 10;
				int bank = chr[index];
				bank &= chr_bank_mask_1k;

				return VROM[(bank << 10) + (addr & 0x3FF)];
			}

			return base.ReadPPU(addr);
		}

		public override void ClockCPU()
		{
			IrqHook(1);
		}

		private void IrqHook(int a)
		{
			if (IRQa)
			{
				IRQCount += a;
				if (IRQCount > 0x10000)
				{
					IRQSignal = true;
					IRQa = false;
				}
			}
		}
	}
}