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)
{