diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index 9a2ef861e0..e56b8b229e 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -98,10 +98,11 @@
-
+
+
@@ -118,7 +119,6 @@
-
Code
@@ -127,6 +127,7 @@
Code
+
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
index d1dfa5531a..e15ccb7fb8 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs
@@ -188,7 +188,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
protected void Assert_memtype(int value, string name, int[] valid)
{
foreach (int i in valid) if (value == i) return;
- Assert(false, "unhandled {0} size", name);
+ Assert(false, "unhandled {0} size of {1}", name,value);
}
protected void AssertBattery(bool has_bat) { Assert(Cart.wram_battery == has_bat); }
}
@@ -453,18 +453,3 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
}
}
-
- //STD_SAROM = MakeId< 1, 64, 64, 8, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SBROM = MakeId< 1, 64, 64, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SCROM = MakeId< 1, 64, 128, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SEROM = MakeId< 1, 32, 64, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SFROM = MakeId< 1, 256, 64, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SGROM = MakeId< 1, 256, 0, 0, 0, CRM_8, NMT_H, 0 >::ID,
- //STD_SHROM = MakeId< 1, 32, 128, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SJROM = MakeId< 1, 256, 64, 8, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SKROM = MakeId< 1, 256, 128, 8, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SLROM = MakeId< 1, 256, 128, 0, 0, CRM_0, NMT_H, 0 >::ID,
- //STD_SNROM = MakeId< 1, 256, 0, 8, 0, CRM_8, NMT_H, 0 >::ID,
- //STD_SOROM = MakeId< 1, 256, 0, 8, 8, CRM_8, NMT_H, 0 >::ID,
- //STD_SUROM = MakeId< 1, 512, 0, 8, 0, CRM_8, NMT_H, 0 >::ID,
- //STD_SXROM = MakeId< 1, 512, 0, 32, 0, CRM_8, NMT_H, 0 >::ID,
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft2.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper089.cs
similarity index 53%
rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft2.cs
rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper089.cs
index 9d0e233d94..641c33b085 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft2.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper089.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
+ //AKA Tenka no Goikenban: Mito Koumon
class MAPPER89 : NES.NESBoardBase
{
int chr;
@@ -15,11 +16,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
switch (Cart.board_type)
{
- case "MAPPER89":
+ case "SUNSOFT-2":
break;
default:
return false;
}
+
+ //yes, the board type SUNSOFT-2 has a pcb type of SUNSOFT-3
+ //(the pcb SUNSOFT-3R has a different revision of SUNSOFT-2 chip which works differently)
+ //and all these are different than the SUNSOFT-3 chip
+ if (Cart.pcb != "SUNSOFT-3") return false;
+
SetMirrorType(Cart.pad_h, Cart.pad_v);
prg_bank_mask_16k = (Cart.prg_size / 16) - 1;
prg_banks_16k[1] = 0xFF;
@@ -77,66 +84,4 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return base.ReadPPU(addr);
}
}
-
- class MAPPER93 : NES.NESBoardBase
- {
- int prg_bank_mask_16k;
- byte prg_bank_16k;
- ByteBuffer prg_banks_16k = new ByteBuffer(2);
-
- public override bool Configure(NES.EDetectionOrigin origin)
- {
- switch (Cart.board_type)
- {
- case "MAPPER93":
- break;
- default:
- return false;
- }
- SetMirrorType(Cart.pad_h, Cart.pad_v);
- prg_bank_mask_16k = (Cart.prg_size / 16) - 1;
- prg_banks_16k[1] = 0xFF;
- return true;
- }
-
- public override void Dispose()
- {
- prg_banks_16k.Dispose();
- base.Dispose();
- }
-
- public override void SyncState(Serializer ser)
- {
- base.SyncState(ser);
- ser.Sync("prg_bank_mask_16k", ref prg_bank_mask_16k);
- ser.Sync("prg_bank_16k", ref prg_bank_16k);
- ser.Sync("prg_banks_16k", ref prg_banks_16k);
- }
-
- void SyncPRG()
- {
- prg_banks_16k[0] = prg_bank_16k;
- }
-
- public override void WritePRG(int addr, byte value)
- {
- prg_bank_16k = (byte)((value >> 4) & 15);
- SyncPRG();
-
- if (value.Bit(0))
- SetMirrorType(EMirrorType.Horizontal);
- else
- SetMirrorType(EMirrorType.Vertical);
- }
-
- public override byte ReadPRG(int addr)
- {
- int bank_16k = addr >> 14;
- int ofs = addr & ((1 << 14) - 1);
- bank_16k = prg_banks_16k[bank_16k];
- bank_16k &= prg_bank_mask_16k;
- addr = (bank_16k << 14) | ofs;
- return ROM[addr];
- }
- }
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper093.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper093.cs
new file mode 100644
index 0000000000..4595ddaed2
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper093.cs
@@ -0,0 +1,76 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace BizHawk.Emulation.Consoles.Nintendo
+{
+ //AKA shanghai (although a lot of shanghais have been hacked to use a different mapper, so....
+ //TODO - this hasnt been tested yet and isnt even close to right
+ class MAPPER93 : NES.NESBoardBase
+ {
+ int prg_bank_mask_16k;
+ byte prg_bank_16k;
+ ByteBuffer prg_banks_16k = new ByteBuffer(2);
+
+ public override bool Configure(NES.EDetectionOrigin origin)
+ {
+ switch (Cart.board_type)
+ {
+ case "SUNSOFT-2":
+ break;
+ default:
+ return false;
+ }
+
+ //yes, the board type SUNSOFT-2 has a pcb type of SUNSOFT-3R
+ //(the pcb SUNSOFT-3 has a different revision of SUNSOFT-2 chip which works differently)
+ //and all these are different than the SUNSOFT-3 chip
+ if (Cart.pcb != "SUNSOFT-3R") return false;
+
+ SetMirrorType(Cart.pad_h, Cart.pad_v);
+ prg_bank_mask_16k = (Cart.prg_size / 16) - 1;
+ prg_banks_16k[1] = 0xFF;
+ return true;
+ }
+
+ public override void Dispose()
+ {
+ prg_banks_16k.Dispose();
+ base.Dispose();
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("prg_bank_mask_16k", ref prg_bank_mask_16k);
+ ser.Sync("prg_bank_16k", ref prg_bank_16k);
+ ser.Sync("prg_banks_16k", ref prg_banks_16k);
+ }
+
+ void SyncPRG()
+ {
+ prg_banks_16k[0] = prg_bank_16k;
+ }
+
+ public override void WritePRG(int addr, byte value)
+ {
+ prg_bank_16k = (byte)((value >> 4) & 15);
+ SyncPRG();
+
+ if (value.Bit(0))
+ SetMirrorType(EMirrorType.Horizontal);
+ else
+ SetMirrorType(EMirrorType.Vertical);
+ }
+
+ public override byte ReadPRG(int addr)
+ {
+ int bank_16k = addr >> 14;
+ int ofs = addr & ((1 << 14) - 1);
+ bank_16k = prg_banks_16k[bank_16k];
+ bank_16k &= prg_bank_mask_16k;
+ addr = (bank_16k << 14) | ofs;
+ return ROM[addr];
+ }
+ }
+}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/VRC6.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/VRC6.cs
new file mode 100644
index 0000000000..9bcc5d20db
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/VRC6.cs
@@ -0,0 +1,246 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace BizHawk.Emulation.Consoles.Nintendo
+{
+ //mapper 24 + 26
+ //If you change any of the IRQ logic here, be sure to change it in VRC4 as well.
+ public class VRC6 : NES.NESBoardBase
+ {
+ //configuration
+ int prg_bank_mask_8k, chr_bank_mask_1k;
+ bool newer_variant;
+
+ //state
+ int prg_bank_16k, prg_bank_8k;
+ ByteBuffer prg_banks_8k = new ByteBuffer(4);
+ ByteBuffer chr_banks_1k = new ByteBuffer(8);
+ bool irq_mode;
+ bool irq_enabled, irq_pending, irq_autoen;
+ byte irq_reload;
+ byte irq_counter;
+ int irq_prescaler;
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ prg_banks_8k.Dispose();
+ chr_banks_1k.Dispose();
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ ser.Sync("prg_bank_16k", ref prg_bank_16k);
+ ser.Sync("prg_bank_8k", ref prg_bank_8k);
+ ser.Sync("prg_banks_8k", ref prg_banks_8k);
+ ser.Sync("chr_banks_1k", ref chr_banks_1k);
+ ser.Sync("irq_mode", ref irq_mode);
+ ser.Sync("irq_enabled", ref irq_enabled);
+ ser.Sync("irq_pending", ref irq_pending);
+ ser.Sync("irq_autoen", ref irq_autoen);
+ ser.Sync("irq_reload", ref irq_reload);
+ ser.Sync("irq_counter", ref irq_counter);
+ ser.Sync("irq_prescaler", ref irq_prescaler);
+
+ if (ser.IsReader)
+ {
+ SyncPRG();
+ }
+ }
+
+ void SyncPRG()
+ {
+ prg_banks_8k[0] = (byte)(prg_bank_16k * 2);
+ prg_banks_8k[1] = (byte)(prg_bank_16k * 2 + 1);
+ prg_banks_8k[2] = (byte)(prg_bank_8k);
+ prg_banks_8k[3] = 0xFF;
+ }
+
+ void SyncIRQ()
+ {
+ NES.irq_cart = (irq_pending && irq_enabled);
+ }
+
+ public override bool Configure(NES.EDetectionOrigin origin)
+ {
+ switch (Cart.board_type)
+ {
+ case "KONAMI-VRC-6":
+ AssertPrg(256); AssertChr(128,256); AssertVram(0); AssertWram(0,8);
+ break;
+ default:
+ return false;
+ }
+
+ if (Cart.pcb == "351951")
+ newer_variant = false;
+ else if (Cart.pcb == "351949A")
+ newer_variant = true;
+ else throw new Exception("Unknown PCB type for VRC6");
+
+ prg_bank_mask_8k = Cart.prg_size / 8 - 1;
+ chr_bank_mask_1k = Cart.chr_size - 1;
+
+ prg_bank_16k = 0;
+ prg_bank_8k = 0;
+ SyncPRG();
+ SetMirrorType(EMirrorType.Vertical);
+
+ return true;
+ }
+ public override byte ReadPRG(int addr)
+ {
+ int bank_8k = addr >> 13;
+ int ofs = addr & ((1 << 13) - 1);
+ bank_8k = prg_banks_8k[bank_8k];
+ bank_8k &= prg_bank_mask_8k;
+ addr = (bank_8k << 13) | ofs;
+ return ROM[addr];
+ }
+
+ public override byte ReadPPU(int addr)
+ {
+ if (addr < 0x2000)
+ {
+ int bank_1k = addr >> 10;
+ int ofs = addr & ((1 << 10) - 1);
+ bank_1k = chr_banks_1k[bank_1k];
+ bank_1k &= chr_bank_mask_1k;
+ addr = (bank_1k << 10) | ofs;
+ return VROM[addr];
+ }
+ else return base.ReadPPU(addr);
+ }
+
+ public override void WritePRG(int addr, byte value)
+ {
+ if (newer_variant)
+ {
+ addr = (addr & 0xFFFC) | ((addr >> 1) & 1) | ((addr << 1) & 2);
+ }
+ switch (addr)
+ {
+ case 0x0000: //$8000
+ case 0x0001:
+ case 0x0002:
+ case 0x0003:
+ prg_bank_16k = value;
+ SyncPRG();
+ break;
+
+ case 0x1000: //$9000
+ case 0x1001: //$9001
+ case 0x1002: //$9002
+ //TODO pulse 1
+ break;
+
+ case 0x2000: //$A000
+ case 0x2001: //$A001
+ case 0x2002: //$A002
+ //TODO pulse 2
+ break;
+
+ case 0x3000: //$B000
+ case 0x3001: //$B001
+ case 0x3002: //$B002
+ //TODO sawtooth
+ break;
+
+ case 0x3003: //$B003
+ switch ((value>>2) & 3)
+ {
+ case 0: SetMirrorType(NES.NESBoardBase.EMirrorType.Vertical); break;
+ case 1: SetMirrorType(NES.NESBoardBase.EMirrorType.Horizontal); break;
+ case 2: SetMirrorType(NES.NESBoardBase.EMirrorType.OneScreenA); break;
+ case 3: SetMirrorType(NES.NESBoardBase.EMirrorType.OneScreenB); break;
+ }
+ break;
+
+ case 0x4000: //$C000
+ case 0x4001:
+ case 0x4002:
+ case 0x4003:
+ prg_bank_8k = value;
+ SyncPRG();
+ break;
+
+ case 0x5000: //$D000
+ case 0x5001: //$D001
+ case 0x5002: //$D002
+ case 0x5003: //$D003
+ chr_banks_1k[addr - 0x5000] = value;
+ break;
+
+ case 0x6000: //$E000
+ case 0x6001: //$E001
+ case 0x6002: //$E002
+ case 0x6003: //$E003
+ chr_banks_1k[4+ addr - 0x6000] = value;
+ break;
+
+ case 0x7000: //$F000 (reload)
+ irq_reload = value;
+ break;
+ case 0x7001: //$F001 (control)
+ irq_mode = value.Bit(2);
+ irq_autoen = value.Bit(0);
+
+ if (value.Bit(1))
+ {
+ //enabled
+ irq_enabled = true;
+ irq_counter = irq_reload;
+ irq_prescaler = 341;
+ }
+ else
+ {
+ //disabled
+ irq_enabled = false;
+ }
+ SyncIRQ();
+
+ break;
+
+ case 0x7002: //$F002 (ack)
+ irq_pending = false;
+ irq_enabled = irq_autoen;
+ SyncIRQ();
+ break;
+ }
+ }
+
+ void ClockIRQ()
+ {
+ if (irq_counter == 0xFF)
+ {
+ irq_pending = true;
+ irq_counter = irq_reload;
+ SyncIRQ();
+ }
+ else
+ irq_counter++;
+ }
+
+ public override void ClockPPU()
+ {
+ if (!irq_enabled) return;
+
+ if (irq_mode)
+ {
+ ClockIRQ();
+ }
+ else
+ {
+ irq_prescaler--;
+ if (irq_prescaler == 0)
+ {
+ irq_prescaler += 341;
+ ClockIRQ();
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
index dfe32bf5b0..ea250186d8 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Core.cs
@@ -59,8 +59,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
cpu.P = 0x34;
cpu.S = 0xFD;
-
- //cpu.debug = true;
}
bool resetSignal;