From db2ba34c01ac5f52d277e5d4240702df84eae484 Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 13 Jun 2011 08:38:10 +0000 Subject: [PATCH] [NES] work on some mappers, make a mapper compatibility list --- BizHawk.Emulation/BizHawk.Emulation.csproj | 8 +- .../Consoles/Nintendo/Docs/compatibility.txt | 127 +++++++++ .../Consoles/Nintendo/NES/BoardSystem.cs | 2 +- .../Consoles/Nintendo/NES/Boards/AVE-NINA.cs | 200 ++++++++++--- .../Consoles/Nintendo/NES/Boards/BxROM.cs | 55 ++++ .../NES/Boards/{CxROM.cs => CNROM.cs} | 4 +- .../Consoles/Nintendo/NES/Boards/Camerica.cs | 170 +++++++++++ .../Consoles/Nintendo/NES/Boards/IC_74x377.cs | 4 +- .../Nintendo/NES/Boards/Jaleco-JF_11_14.cs | 2 +- .../Consoles/Nintendo/NES/Boards/Mapper069.cs | 269 ++++++++++++++++++ .../Consoles/Nintendo/NES/Boards/Mapper242.cs | 2 +- .../Consoles/Nintendo/NES/Boards/Sunsoft1.cs | 2 +- .../Consoles/Nintendo/NES/NES.cs | 27 +- .../Consoles/Nintendo/NES/iNES.cs | 7 + BizHawk.MultiClient/output/gamedb.txt | 1 + 15 files changed, 821 insertions(+), 59 deletions(-) create mode 100644 BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt create mode 100644 BizHawk.Emulation/Consoles/Nintendo/NES/Boards/BxROM.cs rename BizHawk.Emulation/Consoles/Nintendo/NES/Boards/{CxROM.cs => CNROM.cs} (88%) create mode 100644 BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Camerica.cs create mode 100644 BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper069.cs diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 3b32531857..e7f0f806d3 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -64,12 +64,12 @@ Code + + + Code - - Code - Code @@ -80,6 +80,7 @@ + @@ -230,6 +231,7 @@ + diff --git a/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt b/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt new file mode 100644 index 0000000000..2045c3cad3 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/Docs/compatibility.txt @@ -0,0 +1,127 @@ +mappers: +key: + +Complete - what it sounds like +Good - thought to be complete +Decent - mostly compatible, but many significant edge cases not tested +Minimal - Important games are playable, but emulation is known not to be complete +~NEEDED~ - Needed for neshawk 1.0 +Needed - Someone should do this +Nothing - Not implemented +Junk - Who cares about this. Not enough games, or unlicensed junk or no interesting games + +Mapper compatibility does not warrant game compatibility, which may be contingent on other aspects of emulation. +It is just a rough guide for future work. +Open bus and bus conflict emulation is not considered complete or thorough in any event. + +000 NROM Complete +001 SxROM=MMC1 Decent +002 UxROM Good +003 CNROM Good +004 MMC3 Decent +005 ExRom=MMC5 Minimal +007 AxROM Good +009 PxROM=MMC2 ~NEEDED~ +010 MMC4 Needed (easy once 009 is done) +011 Misc Complete +013 CPROM Complete +015 Multicart Junk +016 Bandai Nothing (+159) +018 Jaleco* Nothing +019 Namcot106 Needed (+210) +021 VRC4 Needed +022 VRC2 Nothing +023 VRC*? Nothing +024 VRC6 Needed +025 VRC4? Nothing +026 VRC6? Nothing +032 Irem_G101 Complete +033 Taito Complete +034 Misc Complete +044 Multicart Junk +045 Multicart Junk +046 Multicart Junk +047 MMC3Multi Needed (1st party) +048 MMC3Variant Needed (similar to mmc3, should inherit) +049 Multicart Junk +050 Pirate Junk +052 Multicart Junk +057 Multicart Junk +058 Multicart Junk +060 Multicart Junk +061 Multicart Junk +062 Multicart Junk +064 Tengen Needed +065 Misc (J) Nothing +066 GxROM Complete +067 Misc (J) Nothing +068 Sunsoft4 Complete +069 FME7 Minimal +070 Misc Nothing +071 Camerica Complete +072 Misc (J) Nothing +073 VRC3 Nothing +074 Pirate (CN) Junk +075 VRC1 Nothing +076 Misc (J) Nothing +077 Misc (J) Nothing +078 Misc Nothing +079 NINA-06 Complete +080 Misc (J) Nothing +082 Misc (J) Nothing +085 VRC7 Needed (lagrange point) +086 Misc (J) Nothing +087 Misc (J) Nothing (easy) +088 Misc (J) Nothing +089 Misc (J) Nothing (easy) +090 Garbage Junk (+209) +091 Pirate Junk +092 Misc (J) Nothing (similar to 072) +093 Misc (J) Nothing (easy) +094 Misc (J) Nothing (easy) +095 MMC3Variant Complete +096 Misc (J) Nothing +097 Misc (J) Nothing (easy) +105 NES-EVENT ~NEEDED~ +107 Misc Nothing (easy) +112 Misc (CN) Nothing +113 =USELESS= Junk +115 MMC3Variant Nothing +118 TLSROM Complete +119 TQROM Complete +140 Misc (J) Complete +152 Misc (J) Nothing +154 Misc (J) Nothing +159 Bandai {{See 016}} +164 Pirate Junk +165 Pirate Junk +180 Misc (J) Nothing +182 MMC3Variant Nothing +184 Sunsoft-1 Complete +185 Misc (J) Nothing +189 MMC3Variant Nothing +191 Pirate Junk +192 Pirate Junk +193 Unlicensed Junk +194 Pirate Junk +200 Multicart Junk +201 Multicart Junk +203 Multicart Junk +205 Multicart Junk +207 Misc (J) Nothing +209 Garbage {{See 090}} +210 Namcot106 {{See 019}} +225 Multicart Junk +226 Multicart Junk +227 Multicart Junk +228 Unlicensed Nothing +230 Multicart Junk +231 Multicart Junk +232 Camerica Complete +233 Multicart Junk +234 Misc Nothing +240 Misc (CN) Nothing +242 Misc (CN) Complete +243 Misc Nothing +245 Pirate Junk +246 Misc (CN) Nothing \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs index 283039fc4e..bc8ca1923d 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardSystem.cs @@ -304,7 +304,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo if (dict.ContainsKey("PAD_H")) cart.pad_h = byte.Parse(dict["PAD_H"]); if (dict.ContainsKey("PAD_V")) - cart.pad_h = byte.Parse(dict["PAD_V"]); + cart.pad_v = byte.Parse(dict["PAD_V"]); if (dict.ContainsKey("bad")) cart.bad = true; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AVE-NINA.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AVE-NINA.cs index edc59186fa..ea52e6bde7 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AVE-NINA.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/AVE-NINA.cs @@ -4,63 +4,171 @@ using System.Diagnostics; namespace BizHawk.Emulation.Consoles.Nintendo { - /* - - */ + //AKA half of mapper 034 (the other half is BxROM which is entirely different..) + class AVE_NINA_001 : NES.NESBoardBase + { + //configuration + int prg_bank_mask_32k, chr_bank_mask_4k; - class AVI_NINA_001 : NES.NESBoardBase - { - public override bool Configure(NES.EDetectionOrigin origin) - { - //configure + //state + IntBuffer chr_banks_4k = new IntBuffer(2); + int prg_bank_32k; + + public override void Dispose() + { + base.Dispose(); + chr_banks_4k.Dispose(); + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("chr_banks_4k", ref chr_banks_4k); + ser.Sync("prg_bank_32k", ref prg_bank_32k); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { switch (Cart.board_type) { - case "AVI_NINA_001": + case "AVE-NINA-01": //Impossible Mission 2 (U) + AssertPrg(64); AssertChr(64); AssertWram(8); AssertVram(0); break; + default: return false; } - SetMirrorType(Cart.pad_h, Cart.pad_v); - return true; - } - public override byte ReadPPU(int addr) - { - return base.ReadPPU(addr); - } + prg_bank_mask_32k = Cart.prg_size / 32 - 1; + chr_bank_mask_4k = Cart.chr_size / 4 - 1; + + SetMirrorType(Cart.pad_h, Cart.pad_v); + + return true; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + int bank_4k = addr >> 12; + int ofs = addr & ((1 << 12) - 1); + bank_4k = chr_banks_4k[bank_4k]; + addr = (bank_4k << 12) | ofs; + return VROM[addr]; + } + else return base.ReadPPU(addr); + } + + public override byte ReadPRG(int addr) + { + addr |= (prg_bank_32k << 15); + return ROM[addr]; + } + + public override void WriteWRAM(int addr, byte value) + { + switch (addr) + { + case 0x1FFD: //$7FFD: Select 32k PRG @ $8000 + prg_bank_32k = value; + prg_bank_32k &= prg_bank_mask_32k; + break; + case 0x1FFE: + chr_banks_4k[0] = value; + chr_banks_4k[0] &= chr_bank_mask_4k; + break; + case 0x1FFF: + chr_banks_4k[1] = value; + chr_banks_4k[1] &= chr_bank_mask_4k; + break; + default: + //apparently these regs are patched in over the WRAM.. + base.WriteWRAM(addr,value); + break; + } + } + + } + + //AKA mapper 079 + //historically, mapper 113 is confused with this, but I can't find any need for mapper 113. bootgod's db has nothing for mapper 113 + class AVE_NINA_006 : NES.NESBoardBase + { + //configuration + int prg_bank_mask_32k, chr_bank_mask_8k; + bool mirror_control_enabled; + + //state + int chr_bank_8k, prg_bank_32k; public override void SyncState(Serializer ser) - { + { base.SyncState(ser); - } - } - - /* - */ - class AVI_Misc : NES.NESBoardBase - { - public override bool Configure(NES.EDetectionOrigin origin) - { - //configure - switch (Cart.board_type) - { - case "AVI_Misc": - break; - default: - return false; - } - SetMirrorType(Cart.pad_h, Cart.pad_v); - return true; - } + ser.Sync("chr_bank_8k", ref chr_bank_8k); + ser.Sync("prg_bank_32k", ref prg_bank_32k); + } - public override byte ReadPPU(int addr) - { - return base.ReadPPU(addr); - } + public override bool Configure(NES.EDetectionOrigin origin) + { + //configure + switch (Cart.board_type) + { + case "AVE-NINA-06": //Blackjack (U) + case "AVE-NINA-03": //F-15 City War (U) + case "AVE-MB-91": //Deathbots (U) + AssertPrg(32, 64); AssertChr(32, 64); AssertWram(0); AssertVram(0); + break; + + default: + return false; + } + + prg_bank_mask_32k = Cart.prg_size / 32 - 1; + chr_bank_mask_8k = Cart.chr_size / 8 - 1; + + SetMirrorType(Cart.pad_h, Cart.pad_v); + + prg_bank_32k = 0; + + return true; + } + + //FCEUX responds to this for PRG writes as well.. ? + public override void WriteEXP(int addr, byte value) + { + addr &= 0x4100; + switch (addr) + { + case 0x0100: //$4100: [.CPP PCCC] + chr_bank_8k = (value & 7) | ((value >> 3) & 0x8); + chr_bank_8k = ((value >> 3) & 7); + prg_bank_32k &= prg_bank_mask_32k; + prg_bank_32k &= chr_bank_mask_8k; + if (mirror_control_enabled) + SetMirrorType(value.Bit(7) ? EMirrorType.Vertical : EMirrorType.Horizontal); + //NES.LogLine("chr={0:X2}, prg={1:X2}, with val={2:X2}", chr_reg, prg_reg, value); + break; + } + } + + public override byte ReadPRG(int addr) + { + addr |= (prg_bank_32k << 15); + return ROM[addr]; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + { + addr |= (chr_bank_8k << 13); + return VROM[addr]; + } + else return base.ReadPPU(addr); + } + + + } - public override void SyncState(Serializer ser) - { - base.SyncState(ser); - } - } } diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/BxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/BxROM.cs new file mode 100644 index 0000000000..ad9474ad0e --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/BxROM.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //AKA half of mapper 034 (the other half is AVE_NINA_001 which is entirely different..) + class BxROM : NES.NESBoardBase + { + //configuration + int prg_bank_mask_32k; + + //state + int prg_bank_32k; + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("prg_bank_32k", ref prg_bank_32k); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + switch (Cart.board_type) + { + case "IREM-BNROM": //Mashou (J).nes + case "NES-BNROM": //Deadly Towers (U) + AssertPrg(128); AssertChr(0); AssertWram(0); AssertVram(8); + break; + + default: + return false; + } + + prg_bank_mask_32k = Cart.prg_size / 32 - 1; + + SetMirrorType(Cart.pad_h, Cart.pad_v); + + return true; + } + + public override byte ReadPRG(int addr) + { + addr |= (prg_bank_32k << 15); + return ROM[addr]; + } + + public override void WritePRG(int addr, byte value) + { + value = HandleNormalPRGConflict(addr, value); + prg_bank_32k = value & prg_bank_mask_32k; + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CNROM.cs similarity index 88% rename from BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs rename to BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CNROM.cs index e2c883d593..7cf5bf2dfa 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CxROM.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/CNROM.cs @@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo //Bump 'n' Jump //Cybernoid - public class CxROM : NES.NESBoardBase + public class CNROM : NES.NESBoardBase { //configuration int prg_mask,chr_mask; @@ -28,7 +28,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo { case "NES-CNROM": //adventure island case "HVC-CNROM": - AssertPrg(16, 32); AssertChr(16,32); + AssertPrg(16, 32); AssertChr(8,16,32); break; default: diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Camerica.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Camerica.cs new file mode 100644 index 0000000000..fe4e369d5c --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Camerica.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //AKA mapper 071 + //TODO - apparently this mapper contains good nes timing test cases + class Camerica_Mapper071 : NES.NESBoardBase + { + //configuration + int prg_bank_mask_16k; + bool mirror_control_enabled; + + //state + IntBuffer prg_banks_16k = new IntBuffer(2); + + public override void Dispose() + { + base.Dispose(); + prg_banks_16k.Dispose(); + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("prg_banks_16k", ref prg_banks_16k); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + //configure + switch (Cart.board_type) + { + case "CAMERICA-ALGQ": //Linus Spacehead's Cosmic Crusade (U) + AssertPrg(128,256); AssertChr(0); AssertWram(0); AssertVram(8); + break; + case "CAMERICA-BF9093": //Big Nose Freaks Out (U) + AssertPrg(64,128,256); AssertChr(0); AssertWram(0); AssertVram(8); + break; + case "CAMERICA-BF9097": //Fire Hawk + AssertPrg(128); AssertChr(0); AssertWram(0); AssertVram(8); + mirror_control_enabled = true; + break; + default: + return false; + } + + prg_bank_mask_16k = Cart.prg_size / 16 - 1; + + prg_banks_16k[0] = 0x00; + prg_banks_16k[1] = 0xFF & prg_bank_mask_16k; + + SetMirrorType(Cart.pad_h, Cart.pad_v); + + return true; + } + + public override void WritePRG(int addr, byte value) + { + addr &= 0x7000; + switch (addr) + { + //$8000-9FFF: [...M ....] Mirroring (for Fire Hawk only!) + case 0x0000: + case 0x1000: + if(mirror_control_enabled) + SetMirrorType(value.Bit(4) ? EMirrorType.OneScreenB : EMirrorType.OneScreenA); + break; + + //$C000-FFFF: PRG Select (16k @ $8000) + case 0x4000: case 0x5000: + case 0x6000: case 0x7000: + prg_banks_16k[0] = value & prg_bank_mask_16k; + break; + } + } + + + public override byte ReadPRG(int addr) + { + int bank_16k = addr >> 14; + int ofs = addr & ((1 << 14) - 1); + bank_16k = prg_banks_16k[bank_16k]; + addr = (bank_16k << 14) | ofs; + return ROM[addr]; + } + } + + //AKA mapper 232 + class Camerica_Mapper232 : NES.NESBoardBase + { + //configuration + int prg_bank_mask_16k; + + //state + IntBuffer prg_banks_16k = new IntBuffer(2); + int prg_block, prg_page; + + public override void Dispose() + { + base.Dispose(); + prg_banks_16k.Dispose(); + } + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("prg_banks_16k", ref prg_banks_16k); + ser.Sync("prg_block", ref prg_block); + ser.Sync("prg_page", ref prg_page); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + //configure + switch (Cart.board_type) + { + case "CAMERICA-ALGQ": //Quattro Adventure (U) + case "CAMERICA-9096": //Quattro Arcade (U) + AssertPrg(256); AssertChr(0); AssertWram(0); AssertVram(8); + break; + default: + return false; + } + + prg_bank_mask_16k = Cart.prg_size / 16 - 1; + + SetMirrorType(Cart.pad_h, Cart.pad_v); + SyncPRG(); + + + return true; + } + + public override void WritePRG(int addr, byte value) + { + addr &= 0x4000; + switch (addr) + { + case 0x0000: + prg_block = (value>>3)&3; + SyncPRG(); + break; + case 0x4000: + prg_page = value & 3; + SyncPRG(); + break; + } + } + + void SyncPRG() + { + prg_banks_16k[0] = (prg_block << 2) | prg_page; + prg_banks_16k[1] = (prg_block << 2) | 3; + prg_banks_16k[0] &= prg_bank_mask_16k; + prg_banks_16k[1] &= prg_bank_mask_16k; + } + + public override byte ReadPRG(int addr) + { + int bank_16k = addr >> 14; + int ofs = addr & ((1 << 14) - 1); + bank_16k = prg_banks_16k[bank_16k]; + addr = (bank_16k<<14) | ofs; + return ROM[addr]; + } + } + +} \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs index bb60db9989..e9dd9d8f86 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/IC_74x377.cs @@ -4,7 +4,7 @@ using System.Diagnostics; namespace BizHawk.Emulation.Consoles.Nintendo { - //mapper 11 + //mapper 011 //Crystal Mines //Metal Fighter @@ -22,6 +22,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo { switch (Cart.board_type) { + case "Discrete_74x377-FLEX": + break; case "COLORDREAMS-74*377": AssertPrg(32,64,128); AssertChr(16,32,64,128); AssertVram(0); AssertWram(0); break; diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Jaleco-JF_11_14.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Jaleco-JF_11_14.cs index 46666f9ed4..a4a0e87f7f 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Jaleco-JF_11_14.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Jaleco-JF_11_14.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo * Life Span: October 1986 - April 1987 PCB Class: Jaleco-JF-11 Jaleco-JF-14 -iNES Mapper #140 +iNES Mapper 140 JF-11 PRG-ROM: 128kb diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper069.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper069.cs new file mode 100644 index 0000000000..c35de4edc3 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper069.cs @@ -0,0 +1,269 @@ +using System; +using System.IO; +using System.Diagnostics; + +namespace BizHawk.Emulation.Consoles.Nintendo +{ + //Mapper 069 is FME7 + //or, Sunsoft-5, which is FME7 with additional sound hardware + + class Sunsoft_5 : Sunsoft_FME7 + { + public override bool Configure(NES.EDetectionOrigin origin) + { + //configure + switch (Cart.board_type) + { + case "SUNSOFT-5A": //Batman (J) + AssertPrg(128); AssertChr(128); AssertWram(0); AssertVram(0); AssertBattery(false); + break; + case "SUNSOFT-5B": //Gimmick! (J) + AssertPrg(256); AssertChr(128); AssertWram(0); AssertVram(0); AssertBattery(false); + break; + default: + return false; + } + + BaseConfigure(); + + return true; + } + + public override void WritePRG(int addr, byte value) + { + //TODO - sound + base.WritePRG(addr, value); + } + } + + class Sunsoft_FME7 : NES.NESBoardBase + { + //configuration + int prg_bank_mask_8k, chr_bank_mask_1k, wram_bank_mask_8k; + + //state + int addr_reg; + ByteBuffer regs = new ByteBuffer(12); + ByteBuffer prg_banks_8k = new ByteBuffer(4); + int wram_bank; + bool wram_ram_selected, wram_ram_enabled; + ushort irq_counter; + bool irq_countdown, irq_enabled, irq_asserted; + int clock_counter; + + + public override void SyncState(Serializer ser) + { + base.SyncState(ser); + ser.Sync("addr_reg", ref addr_reg); + ser.Sync("regs", ref regs); + ser.Sync("prg_banks_8k", ref prg_banks_8k); + ser.Sync("wram_bank", ref wram_bank); + ser.Sync("wram_ram_selected", ref wram_ram_selected); + ser.Sync("wram_ram_enabled", ref wram_ram_enabled); + ser.Sync("irq_counter", ref irq_counter); + ser.Sync("irq_countdown", ref irq_countdown); + ser.Sync("irq_enabled", ref irq_enabled); + ser.Sync("irq_asserted", ref irq_asserted); + ser.Sync("clock_counter", ref clock_counter); + } + + public override void Dispose() + { + base.Dispose(); + regs.Dispose(); + prg_banks_8k.Dispose(); + } + + public override bool Configure(NES.EDetectionOrigin origin) + { + //configure + switch (Cart.board_type) + { + case "MAPPER069-FLEX": + break; + case "SUNSOFT-FME-7": //Barcode World (J) + AssertPrg(128,256); AssertChr(256); AssertWram(0,8); AssertVram(0); + break; + case "NES-BTR": //Batman - Return of the Joker (U) + AssertPrg(128); AssertChr(256); AssertWram(8); AssertVram(0); AssertBattery(false); + break; + default: + return false; + } + + BaseConfigure(); + + return true; + } + + protected void BaseConfigure() + { + prg_bank_mask_8k = (Cart.prg_size / 8) - 1; + wram_bank_mask_8k = (Cart.wram_size / 8) - 1; + chr_bank_mask_1k = Cart.chr_size - 1; + prg_banks_8k[3] = 0xFF; + SetMirrorType(EMirrorType.Vertical); + } + + void SyncPRG() + { + wram_ram_enabled = (regs[8] & 0x80) != 0; + wram_ram_selected = (regs[8]&0x40)!=0; + wram_bank = (byte)(regs[8] & 0x7F); + for(int i=0;i<3;i++) + { + prg_banks_8k[i] = regs[8 + i + 1]; + } + } + + public override void WritePRG(int addr, byte value) + { + addr &= 0xE000; + switch (addr) + { + case 0x0000: //$8000: [.... AAAA] Address for use with $A000 + addr_reg = value & 0xF; + break; + case 0x2000: //$A000: [DDDD DDDD] Data port + switch(addr_reg) + { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + regs[addr_reg] = value; + //NES.LogLine("cr set to {0},{1},{2},{3},{4},{5},{6},{7}", regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]); + break; + case 8: case 9: case 0xA: case 0xB: + regs[addr_reg] = value; + //NES.LogLine("pr/wr set to {0},{1},{2},{3},~0xFF~", regs[8], regs[9], regs[10], regs[11]); + SyncPRG(); + break; + case 0xC: + switch (value & 3) + { + case 0: SetMirrorType(EMirrorType.Vertical); break; + case 1: SetMirrorType(EMirrorType.Horizontal); break; + case 2: SetMirrorType(EMirrorType.OneScreenA); break; + case 3: SetMirrorType(EMirrorType.OneScreenB); break; + } + break; + case 0xD: + irq_countdown = value.Bit(7); + irq_enabled = value.Bit(0); + //if (value != 0) NES.LogLine("irq set to {0},{1} with value {2:x2}", irq_countdown, irq_enabled, value); + if (!irq_enabled) irq_asserted = false; + SyncIrq(); + break; + case 0xE: + irq_counter &= 0xFF00; + irq_counter |= value; + //NES.LogLine("irq_counter set to {0:x4}", irq_counter); + break; + case 0xF: + irq_counter &= 0x00FF; + irq_counter |= (ushort)(value << 8); + //NES.LogLine("irq_counter set to {0:x4}", irq_counter); + break; + } + break; + } + } + + void SyncIrq() + { + NES.irq_cart = irq_asserted; + } + + void ClockCPU() + { + if (!irq_countdown) return; + irq_counter--; + if (irq_counter == 0xFFFF) + { + irq_asserted = true; + SyncIrq(); + } + } + + public override void ClockPPU() + { + clock_counter++; + if (clock_counter == 3) + { + ClockCPU(); + clock_counter = 0; + } + } + + public override byte ReadPRG(int addr) + { + int bank_8k = addr >> 13; + int ofs = addr & ((1<<13)-1); + bank_8k = prg_banks_8k[bank_8k]; + bank_8k &= prg_bank_mask_8k; + addr = (bank_8k << 13) | ofs; + return ROM[addr]; + } + + int CalcWRAMAddress(int addr, int bank_mask_8k) + { + int ofs = addr & ((1 << 13) - 1); + int bank_8k = wram_bank; + bank_8k &= bank_mask_8k; + addr = (bank_8k << 13) | ofs; + return addr; + } + + int CalcPPUAddress(int addr) + { + int bank_1k = addr >> 10; + int ofs = addr & ((1 << 10) - 1); + bank_1k = regs[bank_1k]; + bank_1k &= chr_bank_mask_1k; + return (bank_1k<<10) | ofs; + } + + public override byte ReadPPU(int addr) + { + if (addr < 0x2000) + return VROM[CalcPPUAddress(addr)]; + else return base.ReadPPU(addr); + } + + public override void WritePPU(int addr, byte value) + { + if (addr < 0x2000) + { } + else base.WritePPU(addr, value); + } + + public override byte ReadWRAM(int addr) + { + if (!wram_ram_selected) + { + addr = CalcWRAMAddress(addr, prg_bank_mask_8k); + return ROM[addr]; + } + else if (!wram_ram_enabled) + return 0xFF; //empty bus + else + { + addr = CalcWRAMAddress(addr, wram_bank_mask_8k); + return WRAM[addr]; + } + } + + public override void WriteWRAM(int addr, byte value) + { + if (!wram_ram_selected) return; + else if (!wram_ram_enabled) + return; //empty bus + else + { + addr = CalcWRAMAddress(addr, wram_bank_mask_8k); + WRAM[addr] = value; + } + } + + } +} diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper242.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper242.cs index 6a008661db..77d28176d2 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper242.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Mapper242.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo /* PCB Class: Unknown -iNES Mapper #242 +iNES Mapper 242 PRG-ROM: 32KB PRG-RAM: None CHR-ROM: 16KB diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft1.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft1.cs index 438e8b3b61..6bcb7d3500 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft1.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/Sunsoft1.cs @@ -7,7 +7,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo /* * Life Span: April 1986 - July 1986 PCB Class: SUNSOFT-1 -iNES Mapper #184 +iNES Mapper 184 PRG-ROM: 32KB PRG-RAM: None CHR-ROM: 16KB diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs index f6d7429282..ea5c20fb2a 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs @@ -16,8 +16,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo static readonly bool USE_DATABASE = true; //Game issues: - //Dragon warrior 3/4 certainly need some additional work done to the mapper wiring to get to the super big PRG (probably SXROM too) //Tecmo superbowl - wobbly "NFL" logo at the end of a game (even skipped game) [zeromus cant test this; how do you skip game?] + //Bigfoot (U) seems not to work + //Bill and ted's excellent video game adventure (U) doesnt work until more detailed emulation exists (check 001.txt) //--- //Game issues for tester to check off. @@ -381,6 +382,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo Console.WriteLine("headerless rom hash: {0}", hash_sha1); Console.WriteLine("headerless rom hash: {0}", hash_md5); + Type boardType = null; CartInfo choice = null; if(USE_DATABASE) choice = IdentifyFromBootGodDB(hash_sha1); @@ -403,8 +405,28 @@ namespace BizHawk.Emulation.Consoles.Nintendo string iNES_board = iNESBoardDetector.Detect(choice); if (iNES_board == null) throw new Exception("couldnt identify NES rom"); - Console.WriteLine("Chose board from iNES heuristics: " + iNES_board); choice.board_type = iNES_board; + + //try spinning up a board with 8K wram and with 0K wram to see if one answers + try + { + boardType = FindBoard(choice, origin); + } + catch { } + if (boardType == null) + { + if (choice.wram_size == 8) choice.wram_size = 0; + else if (choice.wram_size == 0) choice.wram_size = 8; + try + { + boardType = FindBoard(choice, origin); + } + catch { } + if (boardType != null) + Console.WriteLine("Ambiguous iNES wram size resolved as {0}k", choice.wram_size); + } + + Console.WriteLine("Chose board from iNES heuristics: " + iNES_board); choice.game.name = game.Name; origin = EDetectionOrigin.INES; } @@ -425,7 +447,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo game_name = choice.game.name; //find a INESBoard to handle this - Type boardType = null; boardType = FindBoard(choice, origin); if (boardType == null) throw new Exception("No class implements the necessary board type: " + choice.board_type); diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs index 2cfcc54f81..c9e444ef27 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/NES/iNES.cs @@ -91,13 +91,20 @@ static string ClassifyTable = @" 4 512 128 8 0 NES-TKROM; Pool of radiance (J) 7 128 0 8 0 NES-ANROM; marble madness 7 256 0 8 8 NES-AOROM; battletoads +11 -1 -1 -1 -1 Discrete_74x377-FLEX; Bible Adventures (U) ? 13 32 0 8 16 NES-CPROM; videomation 65 -1 -1 -1 -1 IREM-H3001-FLEX; //Ai Sensei No Oshiete - Watashi No Hoshi (J).nes 66 64 16 8 0 NES-MHROM; super mario bros / duck hunt 66 128 32 8 0 NES-GNROM; gumshoe 68 128 256 8 0 SUNSOFT-4; After Burner 2 (J) +69 -1 -1 -1 -1 MAPPER069-FLEX; Gimmick! (J) +71 -1 -1 -1 -1 CAMERICA-BF9093; Micro Machines (U) +79 -1 -1 -1 -1 AVE-NINA-06; Blackjack (U) +113 -1 -1 -1 -1 AVE-NINA-06; ??? +232 -1 -1 -1 -1 CAMERICA-ALGQ; Quattro Adventure "; } +//;232 -1 -1 -1 -1 Camerica_BF9096-FLEX; Quattro Adventure unsafe struct iNES_HEADER { diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt index 0840c6c7fb..b60c244add 100644 --- a/BizHawk.MultiClient/output/gamedb.txt +++ b/BizHawk.MultiClient/output/gamedb.txt @@ -2284,6 +2284,7 @@ sha1:192C543866F1037276D2778046ABEDCA84868E26 Bio Senshi Dan - Increaser To No sha1:E80FF0B707B0D675FDBEF474E3FDB1A83E2B7C44 Mississippi Satsujin Jiken (J) NES board=JALECO-JF-11;PRG=128;CHR=32;PAD_H=1 sha1:8A5FD1061ADACDEABF422A2D2E555FF70749AE7C Mississippi Satsujin Jiken (Alt) (J) NES board=GXROM_HACKY;PRG=128;CHR=32;PAD_H=1 sha1:8C7D33753649A2BAF2EAAF8D5FFC2AE8E9316A13 Akira (J) NES board=TAITO-TC0190FMC;PRG=128;CHR=256;WRAM=0 +sha1:0AE47BD83202A5A2235B0BC16278F56D66038AB5 Deathbots (U) NES board=AVE-NINA-06;PRG=64;CHR=64;PAD_H=1;PAD_V=0 ;these roms are in goodNES but theyre junk sha1:4D6117577CE301BB987C5C32FEEF7B132A21B046 Afro Man (Mega Man 3 Hack) (UNL) NES board=TXROM-HOMEBREW;PRG=256;CHR=128;WRAM=8