diff --git a/Core/BmcDs07.h b/Core/BmcDs07.h new file mode 100644 index 000000000..503d9e5a7 --- /dev/null +++ b/Core/BmcDs07.h @@ -0,0 +1,51 @@ +#pragma once +#include "stdafx.h" +#include "BaseMapper.h" + +class BmcDs07 : public BaseMapper +{ +private: + uint8_t _regs[2]; + uint8_t _latch; + +protected: + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + uint16_t RegisterStartAddress() { return 0x6000; } + uint16_t RegisterEndAddress() { return 0xFFFF; } + + void InitMapper() override + { + _regs[0] = _regs[1] = -1; + _latch = 0; + UpdateState(); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_regs[0], _regs[1], _latch); + } + + void UpdateState() + { + uint8_t base = (_regs[0] & 0xF0) >> 1; + SelectPRGPage(0, base | (_latch & 0x07)); + SelectPRGPage(1, base | 0x07); + SetMirroringType((_latch & 0x80) ? MirroringType::Horizontal : MirroringType::Vertical); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _regs[addr & 0x01] = value; + } else { + if((_regs[0] & 0x80) == 0) { + _latch = (_latch & 0xF8) | (value & 0x07); + } else { + _latch = value; + } + } + UpdateState(); + } +}; \ No newline at end of file diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 42d607c7d..a4573a345 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -557,6 +557,7 @@ + @@ -851,6 +852,8 @@ + + @@ -859,6 +862,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index d8e31e638..d098187cf 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -802,6 +802,9 @@ Nes\Mappers + + Nes\Mappers + Nes\Mappers @@ -811,15 +814,24 @@ Nes\Mappers\MMC + + Nes\Mappers\MMC + Nes\Mappers\MMC + + Nes\Mappers\MMC + Nes\Mappers\MMC Nes\Mappers\MMC + + Nes\Mappers\MMC + Nes\Mappers\Waixing diff --git a/Core/MMC1_297.h b/Core/MMC1_297.h index e533fb191..54a34581a 100644 --- a/Core/MMC1_297.h +++ b/Core/MMC1_297.h @@ -24,7 +24,7 @@ class MMC1_297 : public MMC1 void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override { - BaseMapper::SelectPRGPage(slot, (_mode << 3) & 0x08 | (page & 0x07)); + BaseMapper::SelectPRGPage(slot, ((_mode << 3) & 0x08) | (page & 0x07)); } void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override diff --git a/Core/MMC3_269.h b/Core/MMC3_269.h index 629a47cd9..a255f5766 100644 --- a/Core/MMC3_269.h +++ b/Core/MMC3_269.h @@ -70,13 +70,13 @@ class MMC3_269 : public MMC3 case 2: _chrMask = 0xFF >> (~value & 0xF); - _outerChr = _outerChr & ~0x0F00 | ((value & 0xF0) << 4); + _outerChr = (_outerChr & ~0x0F00) | ((value & 0xF0) << 4); break; case 3: _prgMask = ~value & 0x3F; - _outerPrg = _outerPrg & ~0x0100 | ((value & 0x40) << 2); - _outerChr = _outerChr & ~0x1000 | ((value & 0x40) << 6); + _outerPrg = (_outerPrg & ~0x0100) | ((value & 0x40) << 2); + _outerChr = (_outerChr & ~0x1000) | ((value & 0x40) << 6); _locked = (value & 0x80) == 0x80; break; } diff --git a/Core/MMC3_369.h b/Core/MMC3_369.h index 43d6e9934..6a13d3062 100644 --- a/Core/MMC3_369.h +++ b/Core/MMC3_369.h @@ -43,7 +43,7 @@ class MMC3_369 : public MMC3 Stream(_outerBankReg, _smb2jBank, _m2Counter); } - void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override { switch (_outerBankReg) { case 0x00: @@ -68,7 +68,7 @@ class MMC3_369 : public MMC3 } } - void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override { switch (_outerBankReg) { case 0x00: diff --git a/Core/MMC3_420.h b/Core/MMC3_420.h new file mode 100644 index 000000000..707b8981a --- /dev/null +++ b/Core/MMC3_420.h @@ -0,0 +1,73 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_420 : public MMC3 +{ +private: + uint8_t _exRegs[4]; + +protected: + virtual void InitMapper() override + { + AddRegisterRange(0x6000, 0x7FFF, MemoryOperation::Write); + MMC3::InitMapper(); + } + + virtual void Reset(bool softReset) override + { + memset(_exRegs, 0, sizeof(_exRegs)); + + if(!softReset) { + MMC3::ResetMmc3(); + } + + MMC3::UpdateState(); + } + + virtual void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exRegs[0], _exRegs[1], _exRegs[2], _exRegs[3]); + + if (!saving) { + MMC3::UpdateState(); + } + } + + virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint16_t mask = 0xFF >> ((_exRegs[1] & 0x80) >> 7); + uint16_t base = ((_exRegs[1] << 1) & 0x100) | ((_exRegs[1] << 5) & 0x80); + + MMC3::SelectCHRPage(slot, base | (page & mask), memoryType); + } + + virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint16_t mask; + uint16_t base; + if(_exRegs[0] & 0x80) { + base = ((_exRegs[0] >> 1) & 0x07 | ((_exRegs[3] >> 2) & 0x08)) << 2; + page = slot; + mask = 0x03; + } else { + mask = 0x3F >> (((_exRegs[3] & 0x20) >> 5) | ((_exRegs[0] & 0x20) >> 4)); + base = ((_exRegs[3] << 3) & 0x20); + } + + MMC3::SelectPRGPage(slot, base | (page & mask), memoryType); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + WritePrgRam(addr, value); + _exRegs[addr & 3] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; diff --git a/Core/MMC3_512.h b/Core/MMC3_512.h new file mode 100644 index 000000000..b2a8eec1e --- /dev/null +++ b/Core/MMC3_512.h @@ -0,0 +1,74 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_512 : public MMC3 +{ +private: + uint8_t _reg = 0; + +protected: + virtual uint32_t GetChrRamSize() override { return 0x2000; } + virtual uint16_t GetChrRamPageSize() override { return 0x0400; } + + virtual uint32_t GetWorkRamSize() override { return 0x2000; } + virtual uint32_t GetWorkRamPageSize() override { return 0x2000; } + virtual bool ForceWorkRamSize() override { return true; } + + virtual void InitMapper() override + { + AddRegisterRange(0x4100, 0x4FFF, MemoryOperation::Write); + MMC3::InitMapper(); + } + + virtual void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_reg); + } + + virtual void UpdateMirroring() override + { + if(_reg == 0x01) { + SetPpuMemoryMapping(0x2000, 0x2FFF, 1 << 2, ChrMemoryType::ChrRam, MemoryAccessType::ReadWrite); + } else { + MMC3::UpdateMirroring(); + } + } + + virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if(_reg & 0x02) { + memoryType = ChrMemoryType::ChrRam; + page &= 0x03; + } + + MMC3::SelectCHRPage(slot, page, memoryType); + } + + virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + MMC3::SelectPRGPage(slot, page & 0x3F, memoryType); + } + + virtual void UpdateState() override + { + MMC3::UpdateState(); + + // Always enable WRAM + SetCpuMemoryMapping(0x6000, 0x7FFF, 0, HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, MemoryAccessType::ReadWrite); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000){ + if(addr & 0x100) { + _reg = value & 0x03; + UpdateChrMapping(); + UpdateMirroring(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; diff --git a/Core/Mapper400.h b/Core/Mapper400.h index 02349f551..c024d4e6e 100644 --- a/Core/Mapper400.h +++ b/Core/Mapper400.h @@ -18,7 +18,7 @@ class Mapper400 : public BaseMapper _regs[0] = 0x80; - AddRegisterRange(0x7800, 0x7FFFF, MemoryOperation::Write); + AddRegisterRange(0x7800, 0x7FFF, MemoryOperation::Write); WriteRegister(0xC000, 0); } diff --git a/Core/Mapper428.h b/Core/Mapper428.h new file mode 100644 index 000000000..fcf15f23d --- /dev/null +++ b/Core/Mapper428.h @@ -0,0 +1,74 @@ +#pragma once +#include "stdafx.h" +#include "BaseMapper.h" + +class Mapper428 : public BaseMapper +{ +private: + uint8_t _regs[4]; + uint8_t _chrLatch; + +protected: + uint32_t GetDipSwitchCount() override { return 2; } + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + + uint16_t RegisterStartAddress() { return 0x6000; } + uint16_t RegisterEndAddress() { return 0xFFFF; } + bool AllowRegisterRead() override { return true; } + + void InitMapper() override + { + RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read); + + _chrLatch = 0; + memset(_regs, 0, sizeof(_regs)); + UpdateState(); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_regs[0], _regs[1], _regs[2], _regs[3], _chrLatch); + + if(!saving) { + UpdateState(); + } + } + + void Reset(bool softReset) override + { + BaseMapper::Reset(softReset); + + _chrLatch = 0; + memset(_regs, 0, sizeof(_regs)); + UpdateState(); + } + + void UpdateState() + { + if (_regs[1] & 0x10) { + SelectPrgPage2x(0, (_regs[1] >> 5) & 0xFE); + } else { + SelectPRGPage(0, _regs[1] >> 5); + SelectPRGPage(1, _regs[1] >> 5); + } + SelectCHRPage(0, ((_regs[1] & 0x07) & ~(_regs[2] >> 6)) | (_chrLatch & (_regs[2] >> 6))); + SetMirroringType((_regs[1] & 0x08) ? MirroringType::Horizontal : MirroringType::Vertical); + } + + uint8_t ReadRegister(uint16_t addr) override + { + return (_console->GetMemoryManager()->GetOpenBus() & 0xFC) | (GetDipSwitches() & 0x03); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _regs[addr & 0x03] = value; + } else { + _chrLatch = value; + } + UpdateState(); + } +}; \ No newline at end of file diff --git a/Core/Mapper533.h b/Core/Mapper533.h index 4d9cedb80..a18d37bc4 100644 --- a/Core/Mapper533.h +++ b/Core/Mapper533.h @@ -11,7 +11,7 @@ class Mapper533 : public BaseMapper uint16_t GetPRGPageSize() override { return 0x8000; } uint16_t GetCHRPageSize() override { return 0x2000; } - bool AllowRegisterRead() { return true; } + bool AllowRegisterRead() override { return true; } void InitMapper() override { diff --git a/Core/Mapper556.h b/Core/Mapper556.h index 5c94ff130..66fbba8e4 100644 --- a/Core/Mapper556.h +++ b/Core/Mapper556.h @@ -271,14 +271,14 @@ class Mapper556 : public BaseMapper case 2: _chrMask = 0xFF >> (~value & 0xF); - _outerChr = _outerChr & ~0x0F00 | ((value & 0xF0) << 4); + _outerChr = (_outerChr & ~0x0F00) | ((value & 0xF0) << 4); _Vrc4Mode = (value & 0x80) == 0x80; break; case 3: _prgMask = ~value & 0x3F; - _outerPrg = _outerPrg & ~0x0100 | ((value & 0x40) << 2); - _outerChr = _outerChr & ~0x1000 | ((value & 0x40) << 6); + _outerPrg = (_outerPrg & ~0x0100) | ((value & 0x40) << 2); + _outerChr = (_outerChr & ~0x1000) | ((value & 0x40) << 6); _locked = (value & 0x80) == 0x80; break; } diff --git a/Core/MapperFactory.cpp b/Core/MapperFactory.cpp index 6329b1baf..baf231b20 100644 --- a/Core/MapperFactory.cpp +++ b/Core/MapperFactory.cpp @@ -38,6 +38,7 @@ #include "Bmc830425C4391T.h" #include "Bmc891227.h" #include "Bmc8in1.h" +#include "BmcDs07.h" #include "BmcK3036.h" #include "BmcG146.h" #include "BmcGn45.h" @@ -185,6 +186,7 @@ #include "Mapper541.h" #include "Mapper433.h" #include "Mapper431.h" +#include "Mapper428.h" #include "Mapper429.h" #include "Mapper417.h" #include "Mapper416.h" @@ -264,12 +266,14 @@ #include "MMC3_410.h" #include "MMC3_411.h" #include "MMC3_412.h" +#include "MMC3_420.h" #include "MMC3_422.h" #include "MMC3_430.h" #include "MMC3_432.h" #include "MMC3_441.h" #include "MMC3_444.h" #include "MMC3_445.h" +#include "MMC3_512.h" #include "MMC3_516.h" #include "MMC3_534.h" #include "MMC3_Bmc411120C.h" @@ -810,9 +814,11 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 416: return new Mapper416(); case 417: return new Mapper417(); case 418: return new Namco108_418(); + case 420: return new MMC3_420(); //419-21 case 422: return new MMC3_422(); //423-428 + case 428: return new Mapper428(); case 429: return new Mapper429(); case 430: return new MMC3_430(); case 431: return new Mapper431(); @@ -822,6 +828,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) //435-436 case 437: return new Mapper437(); case 438: return new Mapper438(); + case 439: return new BmcDs07(); //439-440 case 441: return new MMC3_441(); //442-443 @@ -836,6 +843,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 453: return new Mapper453(); //484-512 + case 512: return new MMC3_512(); case 513: return new Sachen9602(); //514-517 case 516: return new MMC3_516(); diff --git a/Core/UnifLoader.cpp b/Core/UnifLoader.cpp index 38591f411..92110d4e9 100644 --- a/Core/UnifLoader.cpp +++ b/Core/UnifLoader.cpp @@ -205,4 +205,6 @@ std::unordered_map UnifLoader::_boardMappings = std::unordered_map< { "K-3010", 438 }, { "K-3071", 438 }, { "AX-40G", 527 }, + { "DS-07", 439 }, + { "K86B", 439 }, }; \ No newline at end of file