From 53f1808f735ce02044d2922e2b52b6ff78738b30 Mon Sep 17 00:00:00 2001 From: Souryo Date: Thu, 2 Jun 2016 20:35:08 -0400 Subject: [PATCH] MMC3: Implemented submapper 3 (MM-ACC) - fixes Incredible Crash Dummies -Also fixed a bug in NES 2.0 mapper ID code --- Core/MMC3.h | 44 ++++++++++++++++++++++++++++++++++++++---- Core/MapperFactory.cpp | 2 +- Core/PPU.cpp | 8 ++++++-- Core/RomData.h | 2 +- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Core/MMC3.h b/Core/MMC3.h index 16add8ba..8c4b2945 100644 --- a/Core/MMC3.h +++ b/Core/MMC3.h @@ -21,6 +21,8 @@ class MMC3 : public BaseMapper RegE001 = 0xE001 }; + uint8_t _subMapperID; + uint8_t _currentRegister; uint8_t _chrMode; uint8_t _prgMode; @@ -36,6 +38,8 @@ class MMC3 : public BaseMapper bool _wramEnabled; bool _wramWriteProtected; + bool _needIrq; + struct { uint8_t Reg8000; uint8_t RegA000; @@ -61,6 +65,8 @@ class MMC3 : public BaseMapper _wramEnabled = false; _wramWriteProtected = false; + + _needIrq = false; } protected: @@ -145,7 +151,7 @@ class MMC3 : public BaseMapper BaseMapper::StreamState(saving); Stream(_state.Reg8000, _state.RegA000, _state.RegA001, _currentRegister, _chrMode, _prgMode, _irqReloadValue, _irqCounter, _irqReload, _irqEnabled, _lastCycle, _cyclesDown, - _wramEnabled, _wramWriteProtected, ArrayInfo{_registers, 8}); + _wramEnabled, _wramWriteProtected, ArrayInfo{_registers, 8}, _needIrq); } virtual uint16_t GetPRGPageSize() { return 0x2000; } @@ -208,12 +214,41 @@ class MMC3 : public BaseMapper } } + void TriggerIrq() + { + if(_subMapperID != 3) { + CPU::SetIRQSource(IRQSource::External); + } else { + //MM-ACC (Acclaim copy of the MMC3) + //IRQ will be triggered on the next falling edge of A12 instead of on the rising edge like normal MMC3 behavior + //This adds a 4 ppu cycle delay (until the PPU fetches the next garbage NT tile between sprites) + _needIrq = true; + } + } + + public: + MMC3(uint8_t subMapperID) + { + _subMapperID = subMapperID; + } + + MMC3() + { + _subMapperID = 0; + } + virtual void NotifyVRAMAddressChange(uint16_t addr) { uint32_t cycle = PPU::GetFrameCycle(); if((addr & 0x1000) == 0) { + if(_needIrq) { + //Used by MM-ACC (Acclaim copy of the MMC3), see TriggerIrq above + CPU::SetIRQSource(IRQSource::External); + _needIrq = false; + } + if(_cyclesDown == 0) { _cyclesDown = 1; } else { @@ -233,14 +268,15 @@ class MMC3 : public BaseMapper _irqCounter--; } - if(ForceMmc3RevAIrqs() || EmulationSettings::CheckFlag(EmulationFlags::Mmc3IrqAltBehavior)) { + //SubMapper 2 = MM-ACC (Acclaim MMC3 clone) + if(_subMapperID != 2 && (ForceMmc3RevAIrqs() || EmulationSettings::CheckFlag(EmulationFlags::Mmc3IrqAltBehavior))) { //MMC3 Revision A behavior if((count > 0 || _irqReload) && _irqCounter == 0 && _irqEnabled) { - CPU::SetIRQSource(IRQSource::External); + TriggerIrq(); } } else { if(_irqCounter == 0 && _irqEnabled) { - CPU::SetIRQSource(IRQSource::External); + TriggerIrq(); } } _irqReload = false; diff --git a/Core/MapperFactory.cpp b/Core/MapperFactory.cpp index b146a5ca..8a6a9805 100644 --- a/Core/MapperFactory.cpp +++ b/Core/MapperFactory.cpp @@ -104,7 +104,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 1: return new MMC1(); case 2: return new UNROM(); case 3: return new CNROM(false); - case 4: return new MMC3(); + case 4: return new MMC3(romData.SubMapperID); case 5: return new MMC5(); case 7: return new AXROM(); case 9: return new MMC2(); diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 73bffaab..75c43842 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -644,8 +644,12 @@ void PPU::ProcessPreVBlankScanline() if((_cycle - 260) % 8 == 0) { //Cycle 260, 268, etc. This is an approximation (each tile is actually loaded in 8 steps (e.g from 257 to 264)) LoadSpriteTileInfo(); - } else if(_cycle == 257) { - _spriteIndex = 0; + } else if((_cycle - 257) % 8 == 0) { + //Garbage NT sprite fetch (257, 265, 273, etc.) - Required for proper MC-ACC IRQs (MMC3 clone) + _memoryManager->ReadVRAM(GetNameTableAddr()); + if(_cycle == 257) { + _spriteIndex = 0; + } } } } else if(_cycle == 321 && IsRenderingEnabled()) { diff --git a/Core/RomData.h b/Core/RomData.h index f0232b30..c2a7ebc5 100644 --- a/Core/RomData.h +++ b/Core/RomData.h @@ -71,7 +71,7 @@ struct NESHeader { switch(GetRomHeaderVersion()) { case RomHeaderVersion::Nes2_0: - return (Byte8 & 0x0F << 4) | (Byte7 & 0xF0) | (Byte6 >> 4); + return ((Byte8 & 0x0F) << 4) | (Byte7 & 0xF0) | (Byte6 >> 4); default: case RomHeaderVersion::iNes: return (Byte7 & 0xF0) | (Byte6 >> 4);