From 6a59bb52c98b82e6cb012fcb17ac6cbd6c89fe5a Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 17 Jun 2018 11:28:41 -0400 Subject: [PATCH] Fixed issues with Sunsoft-4 emulation (Mapper 68) - Nantettatte roms with external PRG now work properly --- Core/BaseMapper.cpp | 17 +++++++----- Core/BaseMapper.h | 2 ++ Core/Sunsoft4.h | 65 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index 959412b7..275380bb 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -400,6 +400,16 @@ void BaseMapper::InitializeChrRam(int32_t chrRamSize) } } +void BaseMapper::SetupDefaultWorkRam() +{ + //Setup a default work/save ram in 0x6000-0x7FFF space + if(HasBattery() && _saveRamSize > 0) { + SetCpuMemoryMapping(0x6000, 0x7FFF, 0, PrgMemoryType::SaveRam); + } else if(_workRamSize > 0) { + SetCpuMemoryMapping(0x6000, 0x7FFF, 0, PrgMemoryType::WorkRam); + } +} + bool BaseMapper::HasChrRam() { return _chrRamSize > 0; @@ -586,12 +596,7 @@ void BaseMapper::Initialize(RomData &romData) } } - //Setup a default work/save ram in 0x6000-0x7FFF space - if(HasBattery() && _saveRamSize > 0) { - SetCpuMemoryMapping(0x6000, 0x7FFF, 0, PrgMemoryType::SaveRam); - } else if(_workRamSize > 0) { - SetCpuMemoryMapping(0x6000, 0x7FFF, 0, PrgMemoryType::WorkRam); - } + SetupDefaultWorkRam(); InitMapper(); InitMapper(romData); diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index 9870bee2..a105823a 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -136,6 +136,8 @@ protected: uint8_t GetPowerOnByte(uint8_t defaultValue = 0); + void SetupDefaultWorkRam(); + void RestoreOriginalPrgRam(); void InitializeChrRam(int32_t chrRamSize = -1); diff --git a/Core/Sunsoft4.h b/Core/Sunsoft4.h index e15182f3..954afade 100644 --- a/Core/Sunsoft4.h +++ b/Core/Sunsoft4.h @@ -8,6 +8,10 @@ class Sunsoft4 : public BaseMapper private: uint8_t _ntRegs[2]; bool _useChrForNametables; + bool _prgRamEnabled; + uint32_t _licensingTimer; + bool _usingExternalRom; + uint8_t _externalPage = 0; void UpdateNametables() { @@ -35,24 +39,66 @@ protected: { _useChrForNametables = false; _ntRegs[0] = _ntRegs[1] = 0; + + _licensingTimer = 0; + _usingExternalRom = false; + _prgRamEnabled = false; //Bank 0's initial state is undefined, but some roms expect it to be the first page SelectPRGPage(0, 0); + SelectPRGPage(1, 7); - SelectPRGPage(1, -1); + UpdateState(); } void StreamState(bool saving) override { BaseMapper::StreamState(saving); - Stream(_ntRegs[0], _ntRegs[1], _useChrForNametables); + Stream(_ntRegs[0], _ntRegs[1], _useChrForNametables, _prgRamEnabled, _usingExternalRom, _externalPage); if(!saving) { UpdateNametables(); + UpdateState(); } } + void UpdateState() + { + if(!_prgRamEnabled) { + RemoveCpuMemoryMapping(0x6000, 0x7FFF); + } else { + SetupDefaultWorkRam(); + } + + if(_usingExternalRom) { + if(_licensingTimer == 0) { + RemoveCpuMemoryMapping(0x8000, 0xBFFF); + } else { + SelectPRGPage(0, _externalPage); + } + } + } + + void ProcessCpuClock() override + { + if(_licensingTimer) { + _licensingTimer--; + if(_licensingTimer == 0) { + UpdateState(); + } + } + } + + void WriteRAM(uint16_t addr, uint8_t value) override + { + if(addr >= 0x6000 && addr <= 0x7FFF) { + _licensingTimer = 1024 * 105; + UpdateState(); + } + BaseMapper::WriteRAM(addr, value); + } + void WriteRegister(uint16_t addr, uint8_t value) override { switch(addr & 0xF000) { @@ -79,8 +125,19 @@ protected: UpdateNametables(); break; case 0xF000: - SelectPRGPage(0, value & 0x0F); - //_prgRamEnabled = (value & 0x10) == 0x10; + bool externalPrg = (value & 0x08) == 0; + if(externalPrg && GetPRGPageCount() > 8) { + _usingExternalRom = true; + _externalPage = 0x08 | ((value & 0x07) % (GetPRGPageCount() - 0x08)); + SelectPRGPage(0, _externalPage); + } else { + _usingExternalRom = false; + SelectPRGPage(0, value & 0x07); + } + + _prgRamEnabled = (value & 0x10) == 0x10; + UpdateState(); + break; } }