diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index e53e3c6dbc..0e80f0116e 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -154,23 +154,24 @@
-
-
-
-
+
+
+
+
+
Code
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
similarity index 65%
rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs
rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
index f170ceb3a5..2924f0d01c 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3.cs
@@ -1,121 +1,23 @@
-//this file contains the MMC3 family of chips
-//which includes:
-//NAMCOT 109
-//MMC3 (which was apparently based on NAMCOT 109 and shares enough functionality to be derived from it in this codebase)
-
-//see http://nesdev.parodius.com/bbs/viewtopic.php?t=5426&sid=e7472c15a758ebf05c588c8330c2187f
-//and http://nesdev.parodius.com/bbs/viewtopic.php?t=311
-//for some info on NAMCOT 109
-
-//mappers handled by this:
-//004,095,118,119,206
+//this file contains the MMC3 family of boards
//fceux contains a comment in mmc3.cpp:
//Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118,119,165,205,214,215,245,249,250,254
-
using System;
using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
- // this is the base class for the MMC3 mapper
- public class Namcot109 : IDisposable
+ public class MMC3 : IDisposable
{
//state
- public int chr_mode, prg_mode, reg_addr;
+ int reg_addr;
+ bool chr_mode, prg_mode;
ByteBuffer chr_regs_1k = new ByteBuffer(8);
- ByteBuffer prg_regs_8k = new ByteBuffer(8);
+ ByteBuffer prg_regs_8k = new ByteBuffer(4);
+ ByteBuffer regs = new ByteBuffer(8);
- protected NES.NESBoardBase board;
- public Namcot109(NES.NESBoardBase board)
- {
- this.board = board;
-
- prg_regs_8k[0] = 0;
- prg_regs_8k[1] = 1;
- prg_regs_8k[2] = 0xFE; //constant
- prg_regs_8k[3] = 0xFF; //constant
- prg_regs_8k[4 + 0] = 0xFE; //constant
- prg_regs_8k[4 + 1] = 1;
- prg_regs_8k[4 + 2] = 0;
- prg_regs_8k[4 + 3] = 0xFF; //constant
-
- chr_regs_1k[0] = 0;
- chr_regs_1k[1] = 1;
- chr_regs_1k[2] = 2;
- chr_regs_1k[3] = 3;
- chr_regs_1k[4] = 4;
- chr_regs_1k[5] = 5;
- chr_regs_1k[6] = 6;
- chr_regs_1k[7] = 7;
- }
-
- public void Dispose()
- {
- chr_regs_1k.Dispose();
- prg_regs_8k.Dispose();
- }
-
- public virtual void SyncState(Serializer ser)
- {
- ser.Sync("chr_mode", ref chr_mode);
- ser.Sync("prg_mode", ref prg_mode);
- ser.Sync("reg_addr", ref reg_addr);
- ser.Sync("chr_regs_1k", ref chr_regs_1k);
- ser.Sync("prg_regs_8k", ref prg_regs_8k);
- }
-
- public virtual void WritePRG(int addr, byte value)
- {
- switch (addr & 0x6001)
- {
- case 0x0000: //$8000
- chr_mode = (value >> 7) & 1;
- chr_mode <<= 2;
- prg_mode = (value >> 6) & 1;
- prg_mode <<= 2;
- reg_addr = (value & 7);
- break;
- case 0x0001: //$8001
- switch (reg_addr)
- {
- case 0: chr_regs_1k[0] = (byte)(value & ~1); chr_regs_1k[1] = (byte)(value | 1); break;
- case 1: chr_regs_1k[2] = (byte)(value & ~1); chr_regs_1k[3] = (byte)(value | 1); break;
- case 2: chr_regs_1k[4] = value; break;
- case 3: chr_regs_1k[5] = value; break;
- case 4: chr_regs_1k[6] = value; break;
- case 5: chr_regs_1k[7] = value; break;
- case 6: prg_regs_8k[0] = value; prg_regs_8k[4 + 2] = value; break;
- case 7: prg_regs_8k[1] = value; prg_regs_8k[4 + 1] = value; break;
- }
- break;
- }
- }
-
- public int Get_PRGBank_8K(int addr)
- {
- int bank_8k = addr >> 13;
- bank_8k += prg_mode;
- bank_8k = prg_regs_8k[bank_8k];
- return bank_8k;
- }
-
- public int Get_CHRBank_1K(int addr)
- {
- int bank_1k = addr >> 10;
- bank_1k ^= chr_mode;
- bank_1k = chr_regs_1k[bank_1k];
- return bank_1k;
- }
-
-
- }
-
- public class MMC3 : Namcot109
- {
- //state
public byte mirror;
int a12_old;
byte irq_reload, irq_counter;
@@ -147,22 +49,80 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
bool oldIrqType;
+ public void Dispose()
+ {
+ chr_regs_1k.Dispose();
+ prg_regs_8k.Dispose();
+ regs.Dispose();
+ }
public NES.NESBoardBase.EMirrorType MirrorType { get { return mirror == 0 ? NES.NESBoardBase.EMirrorType.Vertical : NES.NESBoardBase.EMirrorType.Horizontal; } }
+ protected NES.NESBoardBase board;
public MMC3(NES.NESBoardBase board, int num_prg_banks)
- : base(board)
{
+ this.board = board;
if (board.Cart.chips.Contains("MMC3A")) MMC3Type = EMMC3Type.MMC3A;
else if (board.Cart.chips.Contains("MMC3B")) MMC3Type = EMMC3Type.MMC3BSharp;
else if (board.Cart.chips.Contains("MMC3BNONSHARP")) MMC3Type = EMMC3Type.MMC3BNonSharp;
else if (board.Cart.chips.Contains("MMC3C")) MMC3Type = EMMC3Type.MMC3C;
else MMC3Type = EMMC3Type.MMC3C; //arbitrary choice. is it the best choice?
+
+ Sync();
}
- public override void SyncState(Serializer ser)
+ void Sync()
{
- base.SyncState(ser);
+ if (prg_mode)
+ {
+ prg_regs_8k[0] = 0xFE;
+ prg_regs_8k[1] = regs[7];
+ prg_regs_8k[2] = regs[6];
+ prg_regs_8k[3] = 0xFF;
+ }
+ else
+ {
+ prg_regs_8k[0] = regs[6];
+ prg_regs_8k[1] = regs[7];
+ prg_regs_8k[2] = 0xFE;
+ prg_regs_8k[3] = 0xFF;
+ }
+
+ byte r0_0 = (byte)(regs[0] & ~1);
+ byte r0_1 = (byte)(regs[0] | 1);
+ byte r1_0 = (byte)(regs[1] & ~1);
+ byte r1_1 = (byte)(regs[1] | 1);
+
+ if (chr_mode)
+ {
+ chr_regs_1k[0] = regs[2];
+ chr_regs_1k[1] = regs[3];
+ chr_regs_1k[2] = regs[4];
+ chr_regs_1k[3] = regs[5];
+ chr_regs_1k[4] = r0_0;
+ chr_regs_1k[5] = r0_1;
+ chr_regs_1k[6] = r1_0;
+ chr_regs_1k[7] = r1_1;
+ }
+ else
+ {
+ 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] = regs[2];
+ chr_regs_1k[5] = regs[3];
+ chr_regs_1k[6] = regs[4];
+ chr_regs_1k[7] = regs[5];
+ }
+ }
+
+ public virtual void SyncState(Serializer ser)
+ {
+ ser.Sync("reg_addr", ref reg_addr);
+ ser.Sync("chr_mode", ref chr_mode);
+ ser.Sync("prg_mode", ref prg_mode);
+ ser.Sync("regs", ref regs);
ser.Sync("mirror", ref mirror);
ser.Sync("a12_old", ref a12_old);
ser.Sync("irq_reload", ref irq_reload);
@@ -174,6 +134,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ser.Sync("irq_reload_flag", ref irq_reload_flag);
ser.Sync("wram_enable", ref wram_enable);
ser.Sync("wram_write_protect", ref wram_write_protect);
+ Sync();
}
protected virtual void SyncIRQ()
@@ -181,13 +142,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo
board.NES.irq_cart = irq_pending;
}
- public override void WritePRG(int addr, byte value)
+ public void WritePRG(int addr, byte value)
{
switch (addr & 0x6001)
{
case 0x0000: //$8000
+ chr_mode = value.Bit(7);
+ prg_mode = value.Bit(6);
+ reg_addr = (value & 7);
+ Sync();
+ break;
case 0x0001: //$8001
- base.WritePRG(addr, value);
+ regs[reg_addr] = value;
+ Sync();
break;
case 0x2000: //$A000
//mirroring
@@ -272,6 +239,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
}
+ public virtual int Get_PRGBank_8K(int addr)
+ {
+ int bank_8k = addr >> 13;
+ bank_8k = prg_regs_8k[bank_8k];
+ return bank_8k;
+ }
+
+ public virtual int Get_CHRBank_1K(int addr)
+ {
+ int bank_1k = addr >> 10;
+ bank_1k = chr_regs_1k[bank_1k];
+ return bank_1k;
+ }
+
public virtual void AddressPPU(int addr)
{
@@ -292,30 +273,45 @@ namespace BizHawk.Emulation.Consoles.Nintendo
a12_old = a12;
}
-
}
- public abstract class MMC3_Family_Board_Base : NES.NESBoardBase
+ public abstract class MMC3Board_Base : NES.NESBoardBase
{
- protected Namcot109 mapper;
+ //state
+ protected MMC3 mmc3;
+
+ public override void AddressPPU(int addr)
+ {
+ mmc3.AddressPPU(addr);
+ }
+
+ public override void ClockPPU()
+ {
+ mmc3.ClockPPU();
+ }
//configuration
protected int prg_mask, chr_mask;
public override void Dispose()
{
- mapper.Dispose();
+ mmc3.Dispose();
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
- mapper.SyncState(ser);
+ mmc3.SyncState(ser);
}
protected virtual int Get_CHRBank_1K(int addr)
{
- return mapper.Get_CHRBank_1K(addr);
+ return mmc3.Get_CHRBank_1K(addr);
+ }
+
+ protected virtual int Get_PRGBank_8K(int addr)
+ {
+ return mmc3.Get_PRGBank_8K(addr);
}
int MapCHR(int addr)
@@ -352,12 +348,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public override void WritePRG(int addr, byte value)
{
- mapper.WritePRG(addr, value);
- }
-
- protected virtual int Get_PRGBank_8K(int addr)
- {
- return mapper.Get_PRGBank_8K(addr);
+ mmc3.WritePRG(addr, value);
}
public override byte ReadPRG(int addr)
@@ -370,58 +361,28 @@ namespace BizHawk.Emulation.Consoles.Nintendo
protected virtual void BaseSetup()
{
- //remember to setup the PRG banks -1 and -2
int num_prg_banks = Cart.prg_size / 8;
prg_mask = num_prg_banks - 1;
int num_chr_banks = (Cart.chr_size);
chr_mask = num_chr_banks - 1;
+
+ mmc3 = new MMC3(this, num_prg_banks);
+ SetMirrorType(EMirrorType.Vertical);
}
//used by a couple of boards for controlling nametable wiring with the mapper
- protected int RewireNametable_Mapper095_and_TLSROM(int addr, int bitsel)
+ protected int RewireNametable_TLSROM(int addr, int bitsel)
{
- int bank_1k = mapper.Get_CHRBank_1K(addr & 0x1FFF);
+ int bank_1k = mmc3.Get_CHRBank_1K(addr & 0x1FFF);
int nt = (bank_1k >> bitsel) & 1;
int ofs = addr & 0x3FF;
addr = 0x2000 + (nt << 10);
addr |= (ofs);
return addr;
}
+
}
- public abstract class MMC3Board_Base : MMC3_Family_Board_Base
- {
- //state
- protected MMC3 mmc3;
-
- public override void AddressPPU(int addr)
- {
- mmc3.AddressPPU(addr);
- }
-
- public override void ClockPPU()
- {
- mmc3.ClockPPU();
- }
-
- protected override void BaseSetup()
- {
- int num_prg_banks = Cart.prg_size / 8;
- mapper = mmc3 = new MMC3(this, num_prg_banks);
-
- base.BaseSetup();
- SetMirrorType(EMirrorType.Vertical);
- }
- }
-
- public abstract class Namcot109Board_Base : MMC3_Family_Board_Base
- {
- protected override void BaseSetup()
- {
- mapper = new Namcot109(this);
- base.BaseSetup();
- }
- }
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper044.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper044.cs
index 96a3dccc16..3b6c58da9d 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper044.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper044.cs
@@ -50,7 +50,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
protected override int Get_PRGBank_8K(int addr)
{
- int bank_8k = mapper.Get_PRGBank_8K(addr);
+ int bank_8k = mmc3.Get_PRGBank_8K(addr);
return (bank_8k & PRG_AND[block_select]) | PRG_OR[block_select];
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper049.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper049.cs
index af6affc73d..88271ca942 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper049.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper049.cs
@@ -50,7 +50,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
protected override int Get_PRGBank_8K(int addr)
{
if (mode)
- return (mapper.Get_PRGBank_8K(addr)&0xF) + block * (128 / 8);
+ return (mmc3.Get_PRGBank_8K(addr)&0xF) + block * (128 / 8);
int block_offset = addr >> 13;
return prg * 4 + block_offset;
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs
index 199d7d61be..8df5f8bbf2 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs
@@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
protected override int Get_PRGBank_8K(int addr)
{
- int bank_8k = mapper.Get_PRGBank_8K(addr);
+ int bank_8k = mmc3.Get_PRGBank_8K(addr);
if (prg_mode == false) return bank_8k;
else if (addr < 0x4000)
{
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper191.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper191.cs
index fab366bc6d..5dd255fe69 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper191.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper191.cs
@@ -17,13 +17,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return false;
}
- throw new InvalidOperationException("THIS MAPPER ISNT TESTED! WHAT GAME USES IT? PLEASE REPORT!");
-
//this board has 2k of chr ram
Cart.vram_size = 2;
BaseSetup();
- return true;
+ throw new InvalidOperationException("THIS MAPPER ISNT TESTED! WHAT GAME USES IT? PLEASE REPORT!");
+
+ //return true;
}
public override byte ReadPPU(int addr)
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs
index a17fe275e5..010ba15dd2 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs
@@ -29,7 +29,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
if (addr < 0x2000)
{
- int bank_1k = mapper.Get_CHRBank_1K(addr);
+ int bank_1k = mmc3.Get_CHRBank_1K(addr);
int use_ram = (bank_1k >> 6) & 1;
if (use_ram == 1)
{
@@ -47,7 +47,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
if (addr < 0x2000)
{
- int bank_1k = mapper.Get_CHRBank_1K(addr);
+ int bank_1k = mmc3.Get_CHRBank_1K(addr);
int use_ram = (bank_1k >> 6) & 1;
if (use_ram == 1)
{
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/DRROM.cs
similarity index 92%
rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs
rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/DRROM.cs
index 11721289cf..9d80ebb4f6 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/DRROM.cs
@@ -5,7 +5,7 @@ using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
//this board contains a Namcot 109 and some extra ram for nametables
- public class DRROM : Namcot109Board_Base
+ public class DRROM : Namcot108Board_Base
{
public override bool Configure(NES.EDetectionOrigin origin)
{
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper095.cs
similarity index 58%
rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs
rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper095.cs
index 021909f2f9..819fde4e72 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper095.cs
@@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
//pretty much just one game.
//wires the mapper outputs to control the nametables. check out the companion board TLSROM
- public class Mapper095 : Namcot109Board_Base
+ public class Mapper095 : Namcot108Board_Base
{
public override bool Configure(NES.EDetectionOrigin origin)
{
@@ -26,15 +26,26 @@ namespace BizHawk.Emulation.Consoles.Nintendo
return true;
}
+ int RewireNametable(int addr, int bitsel)
+ {
+ int bank_1k = mapper.Get_CHRBank_1K(addr & 0x1FFF);
+ int nt = (bank_1k >> bitsel) & 1;
+ int ofs = addr & 0x3FF;
+ addr = 0x2000 + (nt << 10);
+ addr |= (ofs);
+ return addr;
+ }
+
+ //mapper 095's chief unique contribution is to add this nametable rewiring logic: CHR A15 directly controls CIRAM A10
public override byte ReadPPU(int addr)
{
if (addr < 0x2000) return base.ReadPPU(addr);
- else return base.ReadPPU(RewireNametable_Mapper095_and_TLSROM(addr, 5));
+ else return base.ReadPPU(RewireNametable(addr, 5));
}
public override void WritePPU(int addr, byte value)
{
if (addr < 0x2000) base.WritePPU(addr, value);
- else base.WritePPU(RewireNametable_Mapper095_and_TLSROM(addr, 5), value);
+ else base.WritePPU(RewireNametable(addr, 5), value);
}
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper206.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper206.cs
similarity index 92%
rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper206.cs
rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper206.cs
index 0f632e0d93..c0e0faba23 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper206.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper206.cs
@@ -4,8 +4,8 @@ using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
- //various japanese namcot 109 boards plus DEROM
- public class Mapper206 : Namcot109Board_Base
+ //various japanese Namcot108 boards plus DEROM
+ public class Mapper206 : Namcot108Board_Base
{
public override bool Configure(NES.EDetectionOrigin origin)
{
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Namcot1xx.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Namcot1xx.cs
new file mode 100644
index 0000000000..eafca2a922
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Namcot1xx.cs
@@ -0,0 +1,187 @@
+//see http://nesdev.parodius.com/bbs/viewtopic.php?t=5426&sid=e7472c15a758ebf05c588c8330c2187f
+//and http://nesdev.parodius.com/bbs/viewtopic.php?t=311
+//for some info on NAMCOT 108
+//but mostly http://wiki.nesdev.com/w/index.php/INES_Mapper_206
+
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace BizHawk.Emulation.Consoles.Nintendo
+{
+ //also, Namcot109, Namcot118, Namcot119 chips are this exact same thing
+ public class Namcot108Chip : IDisposable
+ {
+ //state
+ int reg_addr;
+ ByteBuffer chr_regs_1k = new ByteBuffer(8);
+ ByteBuffer prg_regs_8k = new ByteBuffer(4);
+
+ NES.NESBoardBase board;
+ public Namcot108Chip(NES.NESBoardBase board)
+ {
+ this.board = board;
+
+ prg_regs_8k[0] = 0;
+ prg_regs_8k[1] = 1;
+ prg_regs_8k[2] = 0xFE; //constant
+ prg_regs_8k[3] = 0xFF; //constant
+
+ chr_regs_1k[0] = 0;
+ chr_regs_1k[1] = 1;
+ chr_regs_1k[2] = 2;
+ chr_regs_1k[3] = 3;
+ chr_regs_1k[4] = 4;
+ chr_regs_1k[5] = 5;
+ chr_regs_1k[6] = 6;
+ chr_regs_1k[7] = 7;
+ }
+
+ public void Dispose()
+ {
+ chr_regs_1k.Dispose();
+ prg_regs_8k.Dispose();
+ }
+
+ public virtual void SyncState(Serializer ser)
+ {
+ ser.Sync("reg_addr", ref reg_addr);
+ ser.Sync("chr_regs_1k", ref chr_regs_1k);
+ ser.Sync("prg_regs_8k", ref prg_regs_8k);
+ }
+
+ public virtual void WritePRG(int addr, byte value)
+ {
+ switch (addr & 0x6001)
+ {
+ case 0x0000: //$8000
+ reg_addr = (value & 7);
+ break;
+ case 0x0001: //$8001
+ switch (reg_addr)
+ {
+ //bottom bits of these chr regs are ignored
+ case 0:
+ chr_regs_1k[0] = (byte)(value & ~1);
+ chr_regs_1k[1] = (byte)(value | 1);
+ break;
+ case 1:
+ chr_regs_1k[2] = (byte)(value & ~1);
+ chr_regs_1k[3] = (byte)(value | 1);
+ break;
+
+ case 2: chr_regs_1k[4] = value; break;
+ case 3: chr_regs_1k[5] = value; break;
+ case 4: chr_regs_1k[6] = value; break;
+ case 5: chr_regs_1k[7] = value; break;
+ case 6: prg_regs_8k[0] = value; break;
+ case 7: prg_regs_8k[1] = value; break;
+ }
+ break;
+ }
+ }
+
+ public int Get_PRGBank_8K(int addr)
+ {
+ int bank_8k = addr >> 13;
+ bank_8k = prg_regs_8k[bank_8k];
+ return bank_8k;
+ }
+
+ public int Get_CHRBank_1K(int addr)
+ {
+ int bank_1k = addr >> 10;
+ bank_1k = chr_regs_1k[bank_1k];
+ return bank_1k;
+ }
+ }
+
+
+ public abstract class Namcot108Board_Base : NES.NESBoardBase
+ {
+ //state
+ protected Namcot108Chip mapper;
+
+ //configuration
+ protected int prg_mask, chr_mask;
+
+ public override void Dispose()
+ {
+ mapper.Dispose();
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ base.SyncState(ser);
+ mapper.SyncState(ser);
+ }
+
+ public int Get_CHRBank_1K(int addr)
+ {
+ return mapper.Get_CHRBank_1K(addr);
+ }
+
+ public int Get_PRGBank_8K(int addr)
+ {
+ return mapper.Get_PRGBank_8K(addr);
+ }
+
+ int MapCHR(int addr)
+ {
+ int bank_1k = Get_CHRBank_1K(addr);
+ bank_1k &= chr_mask;
+ addr = (bank_1k << 10) | (addr & 0x3FF);
+ return addr;
+ }
+
+ public override byte ReadPPU(int addr)
+ {
+ if (addr < 0x2000)
+ {
+ addr = MapCHR(addr);
+ if (VROM != null)
+ return VROM[addr];
+ else return VRAM[addr];
+ }
+ else return base.ReadPPU(addr);
+ }
+
+ public override void WritePPU(int addr, byte value)
+ {
+ if (addr < 0x2000)
+ {
+ if (VRAM == null) return;
+ addr = MapCHR(addr);
+ VRAM[addr] = value;
+ }
+ base.WritePPU(addr, value);
+ }
+
+
+ public override void WritePRG(int addr, byte value)
+ {
+ mapper.WritePRG(addr, value);
+ }
+
+ public override byte ReadPRG(int addr)
+ {
+ int bank_8k = Get_PRGBank_8K(addr);
+ bank_8k &= prg_mask;
+ addr = (bank_8k << 13) | (addr & 0x1FFF);
+ return ROM[addr];
+ }
+
+ protected virtual void BaseSetup()
+ {
+ int num_prg_banks = Cart.prg_size / 8;
+ prg_mask = num_prg_banks - 1;
+
+ int num_chr_banks = (Cart.chr_size);
+ chr_mask = num_chr_banks - 1;
+
+ mapper = new Namcot108Chip(this);
+ SetMirrorType(EMirrorType.Vertical);
+ }
+
+ }
+}
\ No newline at end of file