diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index c3ca3cbd47..67ece7e883 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -128,6 +128,7 @@ Code + Code diff --git a/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt b/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt index 9c213d91ac..2016736a02 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt +++ b/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt @@ -82,7 +82,7 @@ Open bus and bus conflict emulation is not considered complete or thorough in an 095 MMC3Variant Complete 096 Misc (J) Nothing 097 Misc (J) Complete -105 NES-EVENT ~NEEDED~ +105 NES-EVENT Minimal (not entirely tested, no timer/IRQ, no dip switches) 107 Unlicensed Complete 112 Misc (CN) Nothing 113 =USELESS= Junk diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NES-EVENT.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NES-EVENT.cs new file mode 100644 index 0000000000..cfcc51fc33 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NES-EVENT.cs @@ -0,0 +1,195 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //AKA mapper 105 + public class NES_EVENT : NES.NESBoardBase + { + //configuration + int prg_bank_mask_16k; + + //regenerable state + IntBuffer prg_banks_16k = new IntBuffer(2); + + //state + MMC1.MMC1_SerialController scnt; + bool slot_mode, prg_mode; + bool irq_control; + int prg_a,prg_b; + int init_sequence; + bool chip_select; + bool wram_disable; + + public override void Dispose() + { + base.Dispose(); + prg_banks_16k.Dispose(); + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + + scnt.SyncState(ser); + ser.Sync("slot_mode", ref slot_mode); + ser.Sync("prg_mode", ref prg_mode); + ser.Sync("irq_control", ref irq_control); + ser.Sync("prg_a", ref prg_a); + ser.Sync("prg_b", ref prg_b); + ser.Sync("init_sequence", ref init_sequence); + ser.Sync("chip_select", ref chip_select); + ser.Sync("wram_disable", ref wram_disable); + + if (ser.IsReader) Sync(); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "NES-EVENT": + AssertPrg(256); AssertChr(0); AssertVram(8); AssertWram(8); + break; + default: + return false; + } + + prg_bank_mask_16k = Cart.prg_size / 16 - 1; + + SetMirrorType(EMirrorType.Vertical); + + scnt = new MMC1.MMC1_SerialController(); + scnt.WriteRegister = SerialWriteRegister; + scnt.Reset = SerialReset; + + Sync(); + + return true; + } + + void SerialReset() + { + prg_mode = true; + slot_mode = true; + } + + void Sync() + { + if (init_sequence != 2) + { + //"use first 128k" + prg_banks_16k[0] = 0; + prg_banks_16k[1] = 1; + } + else + { + if (chip_select == false) + { + //"use first 128k" + prg_banks_16k[0] = prg_a*2; + prg_banks_16k[1] = prg_a*2 + 1; + } + else + { + if (prg_mode == false) + { + //"use second 128k" + prg_banks_16k[0] = (prg_b>>1) + 8; + prg_banks_16k[1] = (prg_b>>1) + 8; + } + else + { + //((these arent tested, i think...)) + if (slot_mode == false) + { + //"use second 128k" + prg_banks_16k[0] = 8; + prg_banks_16k[1] = prg_b + 8; + } + else + { + //"use second 128k" + prg_banks_16k[0] = prg_b + 8; + prg_banks_16k[1] = 8 + 7; + } + } + } + } + + prg_banks_16k[0] &= prg_bank_mask_16k; + prg_banks_16k[1] &= prg_bank_mask_16k; + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + int zzz = 9; + //Console.WriteLine("{0:X4} = {1:X2}", addr, value); + } + base.WritePPU(addr, value); + } + + void SerialWriteRegister(int addr, int value) + { + switch (addr) + { + case 0: //8000-9FFF + switch (value & 3) + { + case 0: SetMirrorType(EMirrorType.OneScreenA); break; + case 1: SetMirrorType(EMirrorType.OneScreenB); break; + case 2: SetMirrorType(EMirrorType.Vertical); break; + case 3: SetMirrorType(EMirrorType.Horizontal); break; + } + slot_mode = value.Bit(2); + prg_mode = value.Bit(3); + Sync(); + break; + case 1: //A000-BFFF + { + bool last_irq_control = irq_control; + irq_control = value.Bit(4); + if (init_sequence == 0) + if (irq_control == false) init_sequence = 1; else { } + else if (init_sequence == 1) + if (irq_control == true) init_sequence = 2; + chip_select = value.Bit(3); + prg_a = (value >> 1) & 3; + Sync(); + break; + } + case 2: //C000-DFFF + //unused + break; + case 3: //E000-FFFF + prg_b = value & 0xF; + wram_disable = value.Bit(4); + Sync(); + break; + } + //board.NES.LogLine("mapping.. chr_mode={0}, chr={1},{2}", chr_mode, chr_0, chr_1); + //board.NES.LogLine("mapping.. prg_mode={0}, prg_slot{1}, prg={2}", prg_mode, prg_slot, prg); + } + + public override void WritePRG(int addr, byte value) + { + scnt.Write(addr, value); + } + + + public override byte ReadPRG(int addr) + { + int bank_16k = addr >> 14; + int ofs = addr & ((1 << 14) - 1); + bank_16k = prg_banks_16k[bank_16k]; + addr = (bank_16k << 14) | ofs; + return ROM[addr]; + } + + + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs index 2190bc15ba..3143eb7edd 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs @@ -27,9 +27,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo public class MMC1 { NES.NESBoardBase board; + MMC1_SerialController scnt = new MMC1_SerialController(); + public MMC1(NES.NESBoardBase board) { this.board = board; + scnt.WriteRegister = SerialWriteRegister; + scnt.Reset = SerialReset; //collect data about whether this is required here: //kid icarus requires it @@ -40,8 +44,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo public void SyncState(Serializer ser) { - ser.Sync("shift_count", ref shift_count); - ser.Sync("shift_val", ref shift_val); + scnt.SyncState(ser); ser.Sync("chr_mode", ref chr_mode); ser.Sync("prg_mode", ref prg_mode); ser.Sync("prg_slot", ref prg_slot); @@ -57,8 +60,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo A, B1, B2, B3 } - //shift register - int shift_count, shift_val; //register 0: public int chr_mode; @@ -74,6 +75,52 @@ namespace BizHawk.Emulation.Consoles.Nintendo int wram_disable; int prg; + public class MMC1_SerialController + { + //state + int shift_count, shift_val; + + public void SyncState(Serializer ser) + { + ser.Sync("shift_count", ref shift_count); + ser.Sync("shift_val", ref shift_val); + } + + public Action Reset; + public Action WriteRegister; + + public void Write(int addr, byte value) + { + int data = value & 1; + int reset = (value >> 7) & 1; + if (reset == 1) + { + shift_count = 0; + shift_val = 0; + if (Reset != null) + Reset(); + } + else + { + shift_val >>= 1; + shift_val |= (data << 4); + shift_count++; + if (shift_count == 5) + { + WriteRegister(addr >> 13, shift_val); + shift_count = 0; + shift_val = 0; + } + } + } + } + + void SerialReset() + { + prg_mode = 1; + prg_slot = 1; + } + void StandardReset() { prg_mode = 1; @@ -84,30 +131,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo public void Write(int addr, byte value) { - int data = value & 1; - int reset = (value >> 7) & 1; - if (reset == 1) - { - shift_count = 0; - shift_val = 0; - prg_mode = 1; - prg_slot = 1; - } - else - { - shift_val >>= 1; - shift_val |= (data<<4); - shift_count++; - if (shift_count == 5) - { - WriteRegister(addr >> 13, shift_val); - shift_count = 0; - shift_val = 0; - } - } + scnt.Write(addr, value); } - void WriteRegister(int addr, int value) + void SerialWriteRegister(int addr, int value) { switch (addr) {