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