From 916066c3f0c72aa130a902aea1a0a25c26dd74ba Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 15 Jun 2012 19:24:06 +0000 Subject: [PATCH] nes-mmc3/namcot108 differences have become more clear in the past few months. refactor those mappers (split them apart, theyre not as similar as once thought) to reflect new understandings. no functional improvement from this other than maybe some new bugs, but it will help on some other mappers later --- BizHawk.Emulation/BizHawk.Emulation.csproj | 9 +- .../MMC3_family/{MMC3_family.cs => MMC3.cs} | 275 ++++++++---------- .../NES/Boards/MMC3_family/Mapper044.cs | 2 +- .../NES/Boards/MMC3_family/Mapper049.cs | 2 +- .../NES/Boards/MMC3_family/Mapper115.cs | 2 +- .../NES/Boards/MMC3_family/Mapper191.cs | 6 +- .../Nintendo/NES/Boards/MMC3_family/TQROM.cs | 4 +- .../{MMC3_family => Namcot1xx}/DRROM.cs | 2 +- .../{MMC3_family => Namcot1xx}/Mapper095.cs | 17 +- .../{MMC3_family => Namcot1xx}/Mapper206.cs | 4 +- .../NES/Boards/Namcot1xx/Namcot1xx.cs | 187 ++++++++++++ 11 files changed, 335 insertions(+), 175 deletions(-) rename BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/{MMC3_family.cs => MMC3.cs} (65%) rename BizHawk.Emulation/Consoles/Nintendo/NES/Boards/{MMC3_family => Namcot1xx}/DRROM.cs (92%) rename BizHawk.Emulation/Consoles/Nintendo/NES/Boards/{MMC3_family => Namcot1xx}/Mapper095.cs (58%) rename BizHawk.Emulation/Consoles/Nintendo/NES/Boards/{MMC3_family => Namcot1xx}/Mapper206.cs (92%) create mode 100644 BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Namcot1xx/Namcot1xx.cs 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