From 25b9878c9b1c1dafcf44a3998a7ef1ce5a4a9488 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Wed, 28 Sep 2016 12:55:43 -0400 Subject: [PATCH] Fix mapper 215 This one was tricky. Really, I don't see how this could be implemented in hardware as coded, but it works without errors so I'll leave it at that. --- .../NES/Boards/MMC3_family/Mapper215.cs | 414 ++++++++++++------ 1 file changed, 278 insertions(+), 136 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper215.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper215.cs index 6ee7e50519..29b7c88258 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper215.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper215.cs @@ -1,136 +1,278 @@ -using BizHawk.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.NES -{ - public class Mapper215 : MMC3Board_Base - { - private ByteBuffer exRegs = new ByteBuffer(4); - private byte cmd; - - private int prg_mask_32k; - - private readonly byte[,] regperm = new byte[,] - { - { 0, 1, 2, 3, 4, 5, 6, 7 }, - { 0, 2, 6, 1, 7, 3, 4, 5 }, - { 0, 5, 4, 1, 7, 2, 6, 3 }, // unused - { 0, 6, 3, 7, 5, 2, 4, 1 }, - { 0, 2, 5, 3, 6, 1, 7, 4 }, - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - }; - - private readonly byte[,] adrperm = new byte[,] - { - { 0, 1, 2, 3, 4, 5, 6, 7 }, - { 3, 2, 0, 4, 1, 5, 6, 7 }, - { 0, 1, 2, 3, 4, 5, 6, 7 }, // unused - { 5, 0, 1, 2, 3, 7, 6, 4 }, - { 3, 1, 0, 5, 2, 4, 6, 7 }, - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty - }; - - public override bool Configure(NES.EDetectionOrigin origin) - { - switch (Cart.board_type) - { - case "MAPPER215": - break; - default: - return false; - } - - BaseSetup(); - exRegs[1] = 3; - - prg_mask_32k = Cart.prg_size / 32 - 1; - return true; - } - - public override void SyncState(Serializer ser) - { - base.SyncState(ser); - ser.Sync("exRegs", ref exRegs); - ser.Sync("cmd", ref cmd); - } - - public override void WriteEXP(int addr, byte value) - { - if (addr == 0x1000) { exRegs[0] = value; } - if (addr == 0x1001) { exRegs[1] = value; } - if (addr == 0x1007) { exRegs[2] = value; } - - base.WriteEXP(addr, value); - } - - //public override void WritePRG(int addr, byte value) - //{ - // cmd = value; - // int addr2 = addr + 0x8000; - // byte dat = value; - - // var b = exRegs[2]; - - // byte adr = (byte)( adrperm[exRegs[2], ((addr2 >> 12) & 6) | (addr2 & 1)]); - // short addr3 = (short)((adr & 1) | ((adr & 6) << 12) | 0x8000); - // if (adr < 4) - // { - // if (adr == 0) - // { - // dat = (byte)((dat & 0xC0) | (regperm[exRegs[2], dat & 7])); - // } - - // } - - // base.WritePRG(addr, dat); - //} - - public override byte ReadPRG(int addr) - { - if ((exRegs[0] & 0x40) > 0) - { - byte sbank = (byte)(exRegs[1] & 0x10); - if ((exRegs[0] & 0x80) > 0) - { - byte bank =(byte)(((exRegs[1] & 3) << 4) | (exRegs[0] & 0x7) | (sbank >> 1)); - if ((exRegs[0] & 0x20) > 0) - { - return ROM[(bank << 15) + addr]; - } - else - { - return ROM[(bank << 14) + (addr & 0x3FFF)]; - } - } - else - { - return ROM[(((exRegs[1] & 3) << 5) | (cmd & 0x0F) | sbank) + addr]; - } - } - else - { - if ((exRegs[0] & 0x80) > 0) - { - byte bank = (byte)(((exRegs[1] & 3) << 4) | (exRegs[0] & 0xF)); - if ((exRegs[0] & 0x20) > 0) - { - return ROM[((bank >> 1) << 15) + addr]; - } - else - { - return ROM[(bank << 14) + (addr & 0x3FFF)]; - } - } - else - { - int bank32k = (((exRegs[1] & 3) << 5) | (cmd & 0x1F)); - bank32k &= prg_mask_32k; - return ROM[(bank32k << 15) + addr]; - } - } - } - } -} +using BizHawk.Common; +using System; + +namespace BizHawk.Emulation.Cores.Nintendo.NES +{ + public class Mapper215 : MMC3Board_Base + { + private ByteBuffer exRegs = new ByteBuffer(4); + + public ByteBuffer prg_regs_8k = new ByteBuffer(4); + + private bool is_mk3; + + private int prg_mask_8k, chr_mask_1k; + + private byte[] regs_sec = { 0, 2, 5, 3, 6, 1, 7, 4 }; + + /* + * I'm not sure where these matrices originated from, but they don't seem to be needed + * so let's leave them as commented out in case a need arises + private readonly byte[,] regperm = new byte[,] + { + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 0, 2, 6, 1, 7, 3, 4, 5 }, + { 0, 5, 4, 1, 7, 2, 6, 3 }, // unused + { 0, 6, 3, 7, 5, 2, 4, 1 }, + { 0, 2, 5, 3, 6, 1, 7, 4 }, // only one actually used? + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + }; + + private readonly byte[,] adrperm = new byte[,] + { + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 3, 2, 0, 4, 1, 5, 6, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unused + { 5, 0, 1, 2, 3, 7, 6, 4 }, + { 3, 1, 0, 5, 2, 4, 6, 7 }, // only one actully used? + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + }; + */ + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "MAPPER215": + break; + case "MK3E60": + is_mk3 = true; + break; + default: + return false; + } + + BaseSetup(); + exRegs[0] = 0; + exRegs[1] = 0xFF; + exRegs[2] = 4; + exRegs[3] = 0; + + prg_mask_8k = Cart.prg_size / 8 - 1; + chr_mask_1k = Cart.chr_size - 1; + + prg_regs_8k[0] = 0; + prg_regs_8k[1] = 1; + prg_regs_8k[2] = (byte)(0xFE & prg_mask_8k); + prg_regs_8k[3] = (byte)(0xFF & prg_mask_8k); + + + return true; + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("exRegs", ref exRegs); + ser.Sync("cmd", ref is_mk3); + ser.Sync("prg_mask", ref prg_mask_8k); + ser.Sync("chr_mask", ref chr_mask_1k); + } + + public void sync_prg(int i) + { + + if ((exRegs[0] & 0x80) == 0) + { + int temp = 0; + //for (int i=0;i<4;i++) + //{ + temp = mmc3.prg_regs_8k[i]; + + if ((exRegs[1] & 0x8) > 0) + temp = (temp & 0x1F) | 0x20; + else + temp = ((temp & 0x0F) | (exRegs[1] & 0x10)); + + prg_regs_8k[i] = (byte)(temp & prg_mask_8k); + //} + } + + + } + + public void sync_prg_2() + { + if ((exRegs[0] & 0x80) > 0) + { + int bank = (exRegs[0] & 0x0F) | (exRegs[1] & 0x10); + bank *= 2; + bank &= prg_mask_8k; + + prg_regs_8k[0] = (byte)bank; + prg_regs_8k[1] = (byte)(bank+1); + prg_regs_8k[2] = (byte)bank; + prg_regs_8k[3] = (byte)(bank+1); + + } + else + { + sync_prg(0); + sync_prg(1); + sync_prg(2); + sync_prg(3); + } + + } + + public override void WriteEXP(int addr, byte value) + { + if (addr == 0x1000) { exRegs[0] = value; sync_prg_2(); } + if (addr == 0x1001) { exRegs[1] = value; } + if (addr == 0x1007) { exRegs[2] = value; mmc3.reg_addr = 0; sync_prg_2(); } + + base.WriteEXP(addr, value); + } + + public override void WriteWRAM(int addr, byte value) + { + if (!is_mk3) + { + if (addr == 0x0000) { exRegs[0] = value; sync_prg_2(); } + if (addr == 0x0001) { exRegs[1] = value; } + if (addr == 0x0007) { exRegs[2] = value; mmc3.reg_addr = 0; sync_prg_2(); } + } + + base.WriteWRAM(addr, value); + } + + public override void WritePRG(int addr, byte value) + { + addr += 0x8000; + switch (addr &= 0xE001) + { + case 0x8000: + if (exRegs[2]==0) + { + base.WritePRG(0x0000, value); + sync_prg(0); + sync_prg(2); + } + break; + case 0x8001: + if (exRegs[2]>0) + { + if ((exRegs[3]>0) && ((exRegs[0] & 0x80) == 0 || (mmc3.reg_addr & 0x7) < 6)) + { + exRegs[3] = 0; + base.WritePRG(0x0001, value); + if (mmc3.reg_addr==7) + sync_prg(1); + else if ((mmc3.reg_addr==6) && mmc3.prg_mode) + sync_prg(2); + else if ((mmc3.reg_addr == 6) && !mmc3.prg_mode) + sync_prg(0); + } + } + else + { + base.WritePRG(0x0001, value); + if (mmc3.reg_addr == 7) + sync_prg(1); + else if ((mmc3.reg_addr == 6) && mmc3.prg_mode) + sync_prg(2); + else if ((mmc3.reg_addr == 6) && !mmc3.prg_mode) + sync_prg(0); + } + break; + case 0xA000: + if (exRegs[2]>0) + { + value = (byte)((value & 0xC0) | regs_sec[value & 0x07]); + exRegs[3] = 1; + + base.WritePRG(0x0000, value); + sync_prg(0); + sync_prg(2); + } + else + { + if (value==0) + { + SetMirrorType(EMirrorType.Vertical); + } + else + { + SetMirrorType(EMirrorType.Horizontal); + } + } + break; + case 0xA001: + base.WritePRG(0x4001, value); + break; + case 0xC000: + if (exRegs[2]>0) + if ((value >> 7 | value) == 0) + { + SetMirrorType(EMirrorType.Vertical); + } + else + { + SetMirrorType(EMirrorType.Horizontal); + } + else + base.WritePRG(0x4000, value); + break; + case 0xC001: + if (exRegs[2]>0) + base.WritePRG(0x6001, value); + else + base.WritePRG(0x4001, value); + break; + case 0xE000: + base.WritePRG(0x6000, value); + break; + case 0xE001: + if (exRegs[2]>0) + { + base.WritePRG(0x4000, value); + base.WritePRG(0x4001, value); + } + else + { + base.WritePRG(0x6001, value); + } + break; + } + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + int bank_1k = base.Get_CHRBank_1K(addr); + + if ((exRegs[1] & 0x4) > 0) + bank_1k = (bank_1k | 0x100); + else + bank_1k = (bank_1k & 0x7F) | (exRegs[1] << 3 & 0x80); + + bank_1k &= chr_mask_1k; + addr = (bank_1k << 10) | (addr & 0x3FF); + return VROM[addr]; + } + else return base.ReadPPU(addr); + } + + public override byte ReadPRG(int addr) + { + int bank = addr >> 13; + bank = prg_regs_8k[bank]; + return ROM[(bank << 13) + (addr & 0x1FFF)]; + } + } +}