diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 13e58b398d..bc2ee55db0 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -79,6 +79,14 @@ + + + + + + + + Code @@ -86,7 +94,6 @@ Code - Code diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs index 7a4049f909..22a47268ad 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs @@ -82,7 +82,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo else SetMirrorType(EMirrorType.OneScreenB); } - protected void SetMirrorType(EMirrorType mirrorType) + public void SetMirrorType(EMirrorType mirrorType) { switch (mirrorType) { diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs new file mode 100644 index 0000000000..4fdf0a526d --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/DRROM.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +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 override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-DRROM": //gauntlet (U) + AssertPrg(128); AssertChr(64); AssertVram(2); AssertWram(0); + break; + default: + return false; + } + + BaseSetup(); + SetMirrorType(Cart.pad_h, Cart.pad_v); + + return true; + } + + //the addressing logic for nametables is a bit speculative here + //how it is wired back to the NES and locally mirrored is unknown, + //but it probably doesnt matter in practice. + //still, purists could validate it. + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + //read patterns from mapper controlled area + return base.ReadPPU(addr); + } + else if (addr < 0x2800) + { + return VRAM[addr - 0x2000]; + } + else return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + //nothing wired here + } + else if (addr < 0x2800) + { + VRAM[addr - 0x2000] = value; + } + else base.WritePPU(addr, value); + } + } + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs new file mode 100644 index 0000000000..76aaaec427 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/MMC3_family.cs @@ -0,0 +1,284 @@ +//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 + +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + public class Namcot109 : IDisposable + { + public Namcot109(int num_prg_banks) + { + bank_regs[8] = (byte)(num_prg_banks - 1); + bank_regs[9] = (byte)(num_prg_banks - 2); + } + + public void Dispose() + { + bank_regs.Dispose(); + prg_lookup.Dispose(); + } + + //state + public int chr_mode, prg_mode, reg_addr; + + //this contains the 8 programmable regs and 2 more at the end to represent PRG banks -2 and -1; and 4 more at the end to break down chr regs 0 and 1 + ByteBuffer bank_regs = new ByteBuffer(14); + ByteBuffer prg_lookup = new ByteBuffer(new byte[] { 6, 7, 9, 8, 9, 7, 6, 8 }); + ByteBuffer chr_lookup = new ByteBuffer(new byte[] { 10, 11, 12, 13, 2, 3, 4, 5 }); + + public virtual void WritePRG(int addr, byte value) + { + switch (addr & 0x6001) + { + case 0x0000: //$8000 + chr_mode = (value >> 7) & 1; + prg_mode = (value >> 6) & 1; + reg_addr = (value & 7); + break; + case 0x0001: //$8001 + bank_regs[reg_addr] = value; + //setup the 2K chr regs + bank_regs[10] = (byte)((bank_regs[0] & ~1) + 0); + bank_regs[11] = (byte)((bank_regs[0] & ~1) + 1); + bank_regs[12] = (byte)((bank_regs[1] & ~1) + 0); + bank_regs[13] = (byte)((bank_regs[1] & ~1) + 1); + break; + } + } + + public int Get_PRGBank_8K(int addr) + { + int bank_8k = addr >> 13; + bank_8k = bank_regs[prg_lookup[prg_mode * 4 + bank_8k]]; + return bank_8k; + } + + public int Get_CHRBank_1K(int addr) + { + int bank_1k = addr >> 10; + if (chr_mode == 1) + bank_1k ^= 4; + bank_1k = bank_regs[chr_lookup[bank_1k]]; + return bank_1k; + } + + + } + + public class MMC3 : Namcot109 + { + NES.NESBoardBase board; + public MMC3(NES.NESBoardBase board, int num_prg_banks) + : base(num_prg_banks) + { + this.board = board; + } + + //state + public NES.NESBoardBase.EMirrorType mirror; + int ppubus_state, ppubus_statecounter; + byte irq_reload, irq_counter; + bool irq_pending, irq_enable; + + void SyncIRQ() + { + board.NES.irq_cart = irq_pending; + } + + public override void WritePRG(int addr, byte value) + { + switch (addr & 0x6001) + { + case 0x0000: //$8000 + case 0x0001: //$8001 + base.WritePRG(addr, value); + break; + case 0x2000: //$A000 + //mirroring + if ((value & 1) == 0) mirror = NES.NESBoardBase.EMirrorType.Vertical; + else mirror = NES.NESBoardBase.EMirrorType.Horizontal; + board.SetMirrorType(mirror); + break; + case 0x2001: //$A001 + //wram enable/protect + break; + case 0x4000: //$C000 + irq_reload = value; + break; + case 0x4001: //$C001 + irq_counter = 0; + break; + case 0x6000: //$E000 + irq_enable = false; + irq_pending = false; + SyncIRQ(); + break; + case 0x6001: //$E001 + irq_enable = true; + SyncIRQ(); + break; + } + } + + void ClockIRQ() + { + if (irq_counter == 0) + irq_counter = irq_reload; + else + { + irq_counter--; + //Console.WriteLine(irq_counter); + if (irq_counter == 0) + { + if (irq_enable) + irq_pending = true; + SyncIRQ(); + } + } + } + + //TODO - this should be determined from NES timestamps to correctly emulate ppu writes interfering + public void Tick_PPU(int addr) + { + ppubus_statecounter++; + int state = (addr >> 12) & 1; + if (ppubus_state == 0 && ppubus_statecounter > 1 && state == 1) + { + ppubus_statecounter = 0; + ClockIRQ(); + } + if (ppubus_state != state) + { + ppubus_state = state; + } + } + + } + + public abstract class MMC3_Family_Board_Base : NES.NESBoardBase + { + //configuration + protected int prg_mask, chr_mask; + + public override void Dispose() + { + mapper.Dispose(); + } + + protected Namcot109 mapper; + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + int bank_1k = mapper.Get_CHRBank_1K(addr); + bank_1k &= chr_mask; + addr = (bank_1k << 10) | (addr & 0x3FF); + if (VROM != null) + return VROM[addr]; + else return VRAM[addr]; + } + else return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte 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 = mapper.Get_PRGBank_8K(addr); + bank_8k &= prg_mask; + addr = (bank_8k << 13) | (addr & 0x1FFF); + return ROM[addr]; + } + + 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; + } + + //used by a couple of boards for controlling nametable wiring with the mapper + protected int RewireNametable_Mapper095_and_TLSROM(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; + } + } + + public abstract class MMC3Board_Base : MMC3_Family_Board_Base + { + //configuration + protected int wram_mask; + + //state + protected MMC3 mmc3; + + public override byte ReadPPU(int addr) + { + mmc3.Tick_PPU(addr); + return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + mmc3.Tick_PPU(addr); + base.WritePPU(addr, value); + } + + public override void WritePRG(int addr, byte value) + { + base.WritePRG(addr, value); + } + + protected override void BaseSetup() + { + wram_mask = (Cart.wram_size * 1024) - 1; + + 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() + { + int num_prg_banks = Cart.prg_size / 8; + mapper = new Namcot109(num_prg_banks); + + base.BaseSetup(); + } + } + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs new file mode 100644 index 0000000000..021909f2f9 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper095.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using System.Diagnostics; + +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 override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NAMCOT-3425": //dragon buster (J) + AssertPrg(128); AssertChr(32); AssertVram(0); AssertWram(0); + break; + default: + return false; + } + + BaseSetup(); + SetMirrorType(EMirrorType.Vertical); + + return true; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) return base.ReadPPU(addr); + else return base.ReadPPU(RewireNametable_Mapper095_and_TLSROM(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); + } + } +} \ 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/MMC3_family/Mapper206.cs new file mode 100644 index 0000000000..008ad40b52 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper206.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //various japanese namcot 109 boards plus DEROM + public class Mapper206 : Namcot109Board_Base + { + public override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-DEROM": //R.B.I. baseball (U) + AssertPrg(64); AssertChr(32,64); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3401": //babel no tou (J) + AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3405": //side pocket (J) + AssertPrg(128); AssertChr(32); AssertVram(0); AssertWram(0); + throw new Exception("TODO - test please"); + break; + case "NAMCOT-3406": //karnov (J) + AssertPrg(128); AssertChr(64); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3407": //family jockey (J) + AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3413": //pro yakyuu family stadium (J) + AssertPrg(64); AssertChr(32); AssertVram(0); AssertWram(0); + throw new Exception("TODO - test please"); + break; + case "NAMCOT-3414": //family boxing (J) + AssertPrg(64); AssertChr(64); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3415": //mappy-land (J) + AssertPrg(128); AssertChr(32); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3416": //dragon slayer IV (J) (aka legacy of the wizard) + AssertPrg(128); AssertChr(64); AssertVram(0); AssertWram(0); + break; + case "NAMCOT-3417": //spy kid (J) + //apparently this shows up as namcot 108 as well but perhaps there is no difference + //(is this game older than the other namcot 109 games?) + AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); + throw new Exception("TODO - test please"); + break; + + default: + return false; + } + + BaseSetup(); + SetMirrorType(Cart.pad_h, Cart.pad_v); + + return true; + } + + } + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TLSROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TLSROM.cs new file mode 100644 index 0000000000..9334cb5663 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TLSROM.cs @@ -0,0 +1,50 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //aka mapper 118 + //wires the mapper outputs to control the nametables. check out the companion board Mapper095 + public class TLSROM : MMC3Board_Base + { + public override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-TLSROM": //pro sport hockey (U) + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + break; + case "HVC-TKSROM": //ys III: wanderers from ys (J) + AssertPrg(256); AssertChr(128); AssertVram(0); AssertWram(8); + AssertBattery(true); + break; + default: + return false; + } + + BaseSetup(); + SetMirrorType(EMirrorType.Vertical); + + return true; + } + + public override void WritePRG(int addr, byte value) + { + base.WritePRG(addr, value); + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) return base.ReadPPU(addr); + else return base.ReadPPU(RewireNametable_Mapper095_and_TLSROM(addr, 7)); + } + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) base.WritePPU(addr, value); + else base.WritePPU(RewireNametable_Mapper095_and_TLSROM(addr, 7), value); + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs new file mode 100644 index 0000000000..115e7613c2 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TQROM.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //aka mapper 119 + //just high speed and pinbot with an MMC3 and some custom logic to select between chr rom and chr ram + public class TQSROM : MMC3Board_Base + { + public override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-TQROM": //high speed and pinbot + AssertPrg(128); AssertChr(64); AssertVram(8); AssertWram(0); + break; + default: + return false; + } + + BaseSetup(); + + return true; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + int bank_1k = mapper.Get_CHRBank_1K(addr); + int use_ram = (bank_1k >> 6) & 1; + if (use_ram == 1) + { + mmc3.Tick_PPU(addr); + addr = ((bank_1k&0x3f) << 10) | (addr & 0x3FF); + addr &= 0x1FFF; + return VRAM[addr]; + } + else return base.ReadPPU(addr); + } + else + return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { + int bank_1k = mapper.Get_CHRBank_1K(addr); + int use_ram = (bank_1k >> 6) & 1; + if (use_ram == 1) + { + mmc3.Tick_PPU(addr); + addr = ((bank_1k & 0x3f) << 10) | (addr & 0x3FF); + addr &= 0x1FFF; + VRAM[addr] = value; + } + else base.WritePPU(addr, value); + } + else + base.WritePPU(addr, value); + } + + } + + +} diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TVROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TVROM.cs new file mode 100644 index 0000000000..584ecee7b7 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TVROM.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + public class TVROM : MMC3Board_Base + { + public override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-TVROM": //rad racer II (U) + AssertPrg(64); AssertChr(64); AssertVram(8); AssertWram(0); + AssertBattery(false); + break; + default: + return false; + } + + BaseSetup(); + + return true; + } + + //nesdev wiki says that the nes CIRAM doesnt get used at all. + //and that even though 8KB is really here, only 4KB gets used. + //still, purists could validate it. + + public override byte ReadPPU(int addr) + { + mmc3.Tick_PPU(addr); + if (addr < 0x2000) + { + //read patterns from mapper controlled area + return base.ReadPPU(addr); + } + else + { + return VRAM[addr & 0xFFF]; + } + } + + public override void WritePPU(int addr, byte value) + { + mmc3.Tick_PPU(addr); + if (addr < 0x2000) + { + //nothing wired here + } + else + { + VRAM[addr & 0xFFF] = value; + } + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs new file mode 100644 index 0000000000..be3ada4fd6 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/MMC3_family/TxROM.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; +using System.Diagnostics; + +//http://wiki.nesdev.com/w/index.php/TxROM +//read some background info on namco 108 and DxROM boards here + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + public class TxROM : MMC3Board_Base + { + public override void WritePRG(int addr, byte value) + { + base.WritePRG(addr, value); + SetMirrorType(mmc3.mirror); //often redundant, but gets the job done + } + + public override byte[] SaveRam + { + get + { + if (!Cart.wram_battery) return null; + return WRAM; + //some boards have a wram that is backed-up or not backed-up. need to handle that somehow + //(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture) + } + } + + public override byte ReadWRAM(int addr) + { + if (Cart.wram_size != 0) + return WRAM[addr & wram_mask]; + else return 0xFF; + } + + public override void WriteWRAM(int addr, byte value) + { + if (Cart.wram_size != 0) + WRAM[addr & wram_mask] = value; + } + + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + //analyze board type + switch (Cart.board_type) + { + case "NES-TBROM": //tecmo world cup soccer (DE) [untested] + AssertPrg(64); AssertChr(64); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TEROM": //Adv of lolo 2 + AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TFROM": //legacy of the wizard + AssertPrg(128); AssertChr(32, 64); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TGROM": //mega man 4 & 6 + AssertPrg(128, 256, 512); AssertChr(0); AssertVram(8); AssertWram(0); + AssertBattery(false); + break; + case "NES-TKROM": //kirby's adventure + AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(8); + break; + case "NES-TLROM": //mega man 3 + AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TL1ROM": //Double dragon 2 + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TL2ROM": //batman (U) ? + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + case "NES-TSROM": //super mario bros. 3 (U) + AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(8); + AssertBattery(false); + break; + case "NES-B4": //batman (U) + AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); + AssertBattery(false); + break; + default: + return false; + } + + BaseSetup(); + + return true; + } + + } + + +} diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs index 3cf70e1fed..a00ad17f88 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/SxROM.cs @@ -225,7 +225,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo { if (!Cart.wram_battery) return null; return WRAM; - //some boards have a pram that is backed-up or not backed-up. need to handle that somehow + //some boards have a wram that is backed-up or not backed-up. need to handle that somehow //(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture) } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/TxROM_DxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/TxROM_DxROM.cs deleted file mode 100644 index 9b9bdf2e6a..0000000000 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/TxROM_DxROM.cs +++ /dev/null @@ -1,322 +0,0 @@ -using System; -using System.IO; -using System.Diagnostics; - -//TODO - mapper 118 and 119 need to be gracefully worked in here. -//but we might want to break them down into a new board type and reuse class mmc3. be sure to try that to see how it goes - -namespace BizHawk.Emulation.Consoles.Nintendo -{ - public class TxROM_DxROM : NES.NESBoardBase - { - class MMC3 : IDisposable - { - NES.NESBoardBase board; - public MMC3(NES.NESBoardBase board, int num_prg_banks) - { - this.board = board; - bank_regs[8] = (byte)(num_prg_banks - 1); - bank_regs[9] = (byte)(num_prg_banks - 2); - } - - public void Dispose() - { - bank_regs.Dispose(); - prg_lookup.Dispose(); - } - - //state - int chr_mode, prg_mode, reg_addr; - public NES.NESBoardBase.EMirrorType mirror; - int ppubus_state, ppubus_statecounter; - - //this contains the 8 programmable regs and 2 more at the end to represent PRG banks -2 and -1; and 4 more at the end to break down chr regs 0 and 1 - ByteBuffer bank_regs = new ByteBuffer(14); - ByteBuffer prg_lookup = new ByteBuffer(new byte[] { 6, 7, 9, 8, 9, 7, 6, 8 }); - ByteBuffer chr_lookup = new ByteBuffer(new byte[] { 10, 11, 12, 13, 2, 3, 4, 5 }); - byte irq_reload, irq_counter; - bool irq_pending, irq_enable; - - void SyncIRQ() - { - board.NES.irq_cart = irq_pending; - } - - public void WritePRG(int addr, byte value) - { - switch (addr & 0x6001) - { - case 0x0000: //$8000 - chr_mode = (value >> 7) & 1; - prg_mode = (value >> 6) & 1; - reg_addr = (value & 7); - break; - case 0x0001: //$8001 - bank_regs[reg_addr] = value; - //setup the 2K chr regs - bank_regs[10] = (byte)((bank_regs[0] & ~1) + 0); - bank_regs[11] = (byte)((bank_regs[0] & ~1) + 1); - bank_regs[12] = (byte)((bank_regs[1] & ~1) + 0); - bank_regs[13] = (byte)((bank_regs[1] & ~1) + 1); - break; - case 0x2000: //$A000 - //mirroring - if ((value & 1) == 0) mirror = EMirrorType.Vertical; - else mirror = EMirrorType.Horizontal; - break; - case 0x2001: //$A001 - //wram enable/protect - break; - case 0x4000: //$C000 - irq_reload = value; - break; - case 0x4001: //$C001 - irq_counter = 0; - break; - case 0x6000: //$E000 - irq_enable = false; - irq_pending = false; - SyncIRQ(); - break; - case 0x6001: //$E001 - irq_enable = true; - SyncIRQ(); - break; - } - } - - public int Get_PRGBank_8K(int addr) - { - int bank_8k = addr >> 13; - bank_8k = bank_regs[prg_lookup[prg_mode * 4 + bank_8k]]; - return bank_8k; - } - - public int Get_CHRBank_1K(int addr) - { - int bank_1k = addr >> 10; - if (chr_mode == 1) - bank_1k ^= 4; - bank_1k = bank_regs[chr_lookup[bank_1k]]; - return bank_1k; - } - - void ClockIRQ() - { - if (irq_counter == 0) - irq_counter = irq_reload; - else - { - irq_counter--; - //Console.WriteLine(irq_counter); - if (irq_counter == 0) - { - if (irq_enable) - irq_pending = true; - SyncIRQ(); - } - } - } - - //TODO - this should be determined from NES timestamps to correctly emulate ppu writes interfering - public void Tick_PPU(int addr) - { - ppubus_statecounter++; - int state = (addr >> 12) & 1; - if (ppubus_state == 0 && ppubus_statecounter > 1 && state == 1) - { - ppubus_statecounter = 0; - ClockIRQ(); - } - if (ppubus_state != state) - { - ppubus_state = state; - } - } - - } - - //configuration - int prg_mask, chr_mask; - int wram_mask, vram_mask; - int vram_bytes; - bool fourscreen; - - //state - MMC3 mmc3; - - public override void Dispose() - { - mmc3.Dispose(); - } - - public override void WritePRG(int addr, byte value) - { - mmc3.WritePRG(addr, value); - SetMirrorType(mmc3.mirror); //often redundant, but gets the job done - } - - public override byte ReadPRG(int addr) - { - int bank_8k = mmc3.Get_PRGBank_8K(addr); - bank_8k &= prg_mask; - addr = (bank_8k << 13) | (addr & 0x1FFF); - return ROM[addr]; - } - - public override byte ReadPPU(int addr) - { - mmc3.Tick_PPU(addr); - if (addr < 0x2000) - { - int bank_1k = mmc3.Get_CHRBank_1K(addr); - bank_1k &= chr_mask; - addr = (bank_1k << 10) | (addr & 0x3FF); - if (VROM != null) - return VROM[addr]; - else return VRAM[addr]; - } - else if (fourscreen) - { - int myaddr = addr - 0x2000; - if (myaddr < vram_bytes) - return VRAM[myaddr]; - else - return base.ReadPPU(addr); - } - else return base.ReadPPU(addr); - } - - public override void WritePPU(int addr, byte value) - { - mmc3.Tick_PPU(addr); - if (fourscreen) - { - if (addr >= 0x2000) - { - int myaddr = addr - 0x2000; - if (myaddr < vram_bytes) - VRAM[myaddr] = value; - else - base.WritePPU(addr, value); - } - else base.WritePPU(addr, value); - } - else base.WritePPU(addr, value); - } - - public override byte ReadWRAM(int addr) - { - if (Cart.wram_size != 0) - return WRAM[addr & wram_mask]; - else return 0xFF; - } - - public override void WriteWRAM(int addr, byte value) - { - if (Cart.wram_size != 0) - WRAM[addr & wram_mask] = value; - } - - public override byte[] SaveRam - { - get - { - if (!Cart.wram_battery) return null; - return WRAM; - //some boards have a pram that is backed-up or not backed-up. need to handle that somehow - //(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture) - } - } - - public override void SyncState(Serializer ser) - { - base.SyncState(ser); - } - - public override bool Configure(NES.EDetectionOrigin origin) - { - //analyze board type - switch (Cart.board_type) - { - case "NES-TBROM": //tecmo world cup soccer (DE) [untested] - AssertPrg(64); AssertChr(64); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TEROM": //Adv of lolo 2 - AssertPrg(32); AssertChr(32); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TFROM": //legacy of the wizard - AssertPrg(128); AssertChr(32, 64); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TGROM": //mega man 4 & 6 - AssertPrg(128, 256, 512); AssertChr(0); AssertVram(8); AssertWram(0); - AssertBattery(false); - break; - case "NES-TKROM": //kirby's adventure - AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(8); - break; - case "NES-TLROM": //mega man 3 - AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TL1ROM": //Double dragon 2 - AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TL2ROM": //batman (U) ? - AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-TQROM": //{mapper 119} high speed - ALMOST POSITIVELTY NEEDS WORK - AssertPrg(128); AssertChr(64); AssertVram(8); AssertWram(0); - AssertBattery(false); - break; - case "NES-TR1ROM": //gauntlet (U) - someone please test this - AssertPrg(128); AssertChr(64); AssertVram(2); AssertWram(0); - fourscreen = true; - AssertBattery(false); - break; - case "NES-TSROM": //super mario bros. 3 (U) - AssertPrg(128, 256, 512); AssertChr(128, 256); AssertVram(0); AssertWram(8); - AssertBattery(false); - break; - case "NES-TVROM": //rad racer II (U) - AssertPrg(64); AssertChr(64); AssertVram(8); AssertWram(0); - fourscreen = true; - AssertBattery(false); - break; - case "NES-B4": //batman (U) - AssertPrg(128); AssertChr(128); AssertVram(0); AssertWram(0); - AssertBattery(false); - break; - case "NES-DRROM": //gauntlet (U) sometimes - AssertPrg(128); AssertChr(64); AssertVram(2); AssertWram(0); - fourscreen = true; - AssertBattery(false); - break; - default: - return false; - } - - //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; - - wram_mask = (Cart.wram_size * 1024) - 1; - vram_mask = (Cart.vram_size * 1024) - 1; - vram_bytes = Cart.vram_size * 1024; - - mmc3 = new MMC3(this, num_prg_banks); - SetMirrorType(EMirrorType.Vertical); - - return true; - } - - } -}