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