From 20bc25acd22f96748927227fc56de2bb38ff4fde Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 1 Oct 2016 16:49:51 -0400 Subject: [PATCH] Fix UNIF FK23C Works except for Dipswitches --- .../Nintendo/NES/Boards/UNIF/UNIF_BMCFK23C.cs | 307 ++++++++++++++---- 1 file changed, 252 insertions(+), 55 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMCFK23C.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMCFK23C.cs index ce8fe0c9be..9d2af23156 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMCFK23C.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMCFK23C.cs @@ -1,55 +1,252 @@ -using BizHawk.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.NES -{ - public sealed class UNIF_BMC_FK23C : MMC3Board_Base - { - private ByteBuffer exRegs = new ByteBuffer(8); - - public override bool Configure(NES.EDetectionOrigin origin) - { - switch (Cart.board_type) - { - case "UNIF_BMC-FK23C": - break; - default: - return false; - } - - exRegs[4] = 0xFF; - exRegs[5] = 0xFF; - exRegs[6] = 0xFF; - exRegs[7] = 0xFF; - exRegs[8] = 0xFF; - - BaseSetup(); - return true; - } - - public override void SyncState(Serializer ser) - { - base.SyncState(ser); - ser.Sync("exRegs", ref exRegs); - } - - public override void WriteEXP(int addr, byte value) - { - base.WriteEXP(addr, value); - } - - public override void WritePRG(int addr, byte value) - { - base.WritePRG(addr, value); - } - - protected override int Get_PRGBank_8K(int addr) - { - return base.Get_PRGBank_8K(addr); - } - - protected override int Get_CHRBank_1K(int addr) - { - return base.Get_CHRBank_1K(addr); - } - } -} +using BizHawk.Common; +using System; + +namespace BizHawk.Emulation.Cores.Nintendo.NES +{ + public sealed class UNIF_BMC_FK23C : MMC3Board_Base + { + private ByteBuffer exRegs = new ByteBuffer(8); + private IntBuffer chr_regs_1k = new IntBuffer(8); + public IntBuffer prg_regs_8k = new IntBuffer(4); + + private bool dip_switch; + private byte dip_switch_setting; + private int unromChr; + + private int prg_mask_8k, chr_mask_1k; + + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "UNIF_BMC-FK23C": + break; + default: + return false; + } + + exRegs[0] = 0;//xFF; + exRegs[1] = 0;// xFF; + exRegs[2] = 0;// xFF; + exRegs[3] = 0;// x FF; + exRegs[4] = 0xFF; + exRegs[5] = 0xFF; + exRegs[6] = 0xFF; + exRegs[7] = 0xFF; + + BaseSetup(); + + 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); + + byte r0_0 = (byte)(mmc3.regs[0] & ~1); + byte r0_1 = (byte)(mmc3.regs[0] | 1); + byte r1_0 = (byte)(mmc3.regs[1] & ~1); + byte r1_1 = (byte)(mmc3.regs[1] | 1); + + chr_regs_1k[0] = r0_0; + chr_regs_1k[1] = r0_1; + chr_regs_1k[2] = r1_0; + chr_regs_1k[3] = r1_1; + chr_regs_1k[4] = mmc3.regs[2]; + chr_regs_1k[5] = mmc3.regs[3]; + chr_regs_1k[6] = mmc3.regs[4]; + chr_regs_1k[7] = mmc3.regs[5]; + + UpdateChr_2(); + UpdatePrg_2(); + + return true; + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("exRegs", ref exRegs); + ser.Sync("prg_regs_8k", ref prg_regs_8k); + ser.Sync("prg_mask", ref prg_mask_8k); + ser.Sync("chr_mask", ref chr_mask_1k); + } + + void UpdateChr() + { + for (int i = 0; i < 8; i++) + { + int bank = mmc3.chr_regs_1k[i]; + if (((exRegs[0] & 0x40) == 0) && (((exRegs[3] & 0x2) == 0) || (i != 1 && i != 3))) + chr_regs_1k[i] = ((exRegs[2] & 0x7F) << 3 | bank ); + } + } + + void UpdateChr_2() + { + if ((exRegs[0] & 0x40) > 0) + { + int bank = (exRegs[2] | unromChr); + chr_regs_1k[0] = bank; + chr_regs_1k[1] = bank;//(bank + 1); + chr_regs_1k[2] = bank;//(bank + 2); + chr_regs_1k[3] = bank;//(bank + 3); + chr_regs_1k[4] = bank;//(bank + 4); + chr_regs_1k[5] = bank;//(bank + 5); + chr_regs_1k[6] = bank;//(bank + 6); + chr_regs_1k[7] = bank;//(bank + 7); + } + else + { + if ((exRegs[3] & 0x2) > 0) + { + int bank = (exRegs[2] & 0x7F) << 3; + chr_regs_1k[1] = (bank | exRegs[6]); + chr_regs_1k[3] = (bank | exRegs[7]); + } + UpdateChr(); + } + } + + void UpdatePrg() + { + for (int i = 0; i < 4; i++) + { + int bank = mmc3.prg_regs_8k[i]; + + uint check = (uint)(exRegs[0] & 0x7) - 3; + + if ((check > 1) && (((exRegs[3] & 0x2) == 0) || (i < 2))) + { + if ((exRegs[0] & 0x3) > 0) + bank = (bank & (0x3F >> (exRegs[0] & 0x3))) | (exRegs[1] << 1); + + prg_regs_8k[i] = (byte)(bank & prg_mask_8k); + } + } + } + + void UpdatePrg_2() + { + if ((exRegs[0] & 0x7) == 4) + { + int bank = exRegs[1]>>1; + bank *= 4; + bank &= prg_mask_8k; + + prg_regs_8k[0] = (byte)bank; + prg_regs_8k[1] = (byte)(bank + 1); + prg_regs_8k[2] = (byte)(bank + 2); + prg_regs_8k[3] = (byte)(bank + 3); + } + else if ((exRegs[0] & 0x7) == 3) + { + int bank = exRegs[1]; + 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 + { + if ((exRegs[3] & 0x2)>0) + { + prg_regs_8k[2] = (byte)(exRegs[4]); + prg_regs_8k[3] = (byte)(exRegs[5]); + } + UpdatePrg(); + } + } + + public override void WriteEXP(int addr, byte value) + { + if (addr>0x1000) + { + addr += 0x4000; + if ((addr & (1 << ((dip_switch ? dip_switch_setting : 0) + 4)))>0) + { + exRegs[addr & 0x3] = value; + UpdateChr_2(); + UpdatePrg_2(); + } + } + else + base.WriteEXP(addr, value); + } + + public override void WritePRG(int addr, byte value) + { + if ((exRegs[0] & 0x40)>0) + { + unromChr = ((exRegs[0] & 0x30)>0) ? 0x0 : (value & 0x3); + UpdateChr_2(); + } + else switch ((addr+0x8000) & 0xE001) + { + case 0x8000: base.WritePRG(addr,value); UpdatePrg(); UpdateChr(); break; + case 0x8001: + + if (((exRegs[3] << 2) & (mmc3.cmd & 0x8))>0) + { + exRegs[4 | mmc3.cmd & 0x3] = value; + + UpdatePrg_2(); + UpdateChr_2(); + } + else + { + base.WritePRG(addr, value); + UpdatePrg(); + UpdateChr(); + } + break; + + case 0xA000: + if (value == 0) + { + SetMirrorType(EMirrorType.Vertical); + } + else + { + SetMirrorType(EMirrorType.Horizontal); + } + break; + case 0xA001: base.WritePRG(addr, value); break; + case 0xC000: base.WritePRG(addr, value); break; + case 0xC001: base.WritePRG(addr, value); break; + case 0xE000: base.WritePRG(addr, value); break; + case 0xE001: base.WritePRG(addr, value); break; + + } + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + int bank_1k = addr >> 10; + bank_1k = chr_regs_1k[bank_1k]; + + if ((exRegs[0] & 0x40) > 0) + addr = (bank_1k << 13) | (addr & 0x1FFF); + else + 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)]; + } + } +}