diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index c6203628..a257f737 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -96,6 +96,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index a4d2e148..31762e00 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -123,6 +123,9 @@
Header Files\Mappers
+
+ Header Files\Mappers
+
diff --git a/Core/MMC2.h b/Core/MMC2.h
new file mode 100644
index 00000000..4e86ad7e
--- /dev/null
+++ b/Core/MMC2.h
@@ -0,0 +1,99 @@
+#include "stdafx.h"
+#include "BaseMapper.h"
+
+class MMC2 : public BaseMapper
+{
+ private:
+ enum class MMC2Registers
+ {
+ RegA000 = 0xA,
+ RegB000 = 0xB,
+ RegC000 = 0xC,
+ RegD000 = 0xD,
+ RegE000 = 0xE,
+ RegF000 = 0xF
+ };
+
+ uint8_t _leftLatch;
+ uint8_t _rightLatch;
+ uint8_t _leftChrPage[2];
+ uint8_t _rightChrPage[2];
+
+ protected:
+ virtual uint32_t GetPRGPageSize() { return 0x2000; }
+ virtual uint32_t GetCHRPageSize() { return 0x1000; }
+
+ void InitMapper()
+ {
+ _leftLatch = 1;
+ _rightLatch = 1;
+ _leftChrPage[0] = 0;
+ _leftChrPage[1] = 0;
+ _rightChrPage[0] = 0;
+ _rightChrPage[1] = 0;
+
+ SelectPRGPage(0, 0);
+ SelectPRGPage(1, -3);
+ SelectPRGPage(2, -2);
+ SelectPRGPage(3, -1);
+ SelectCHRPage(0, 0);
+ SelectCHRPage(0, 1);
+ }
+
+ void StreamState(bool saving)
+ {
+ Stream(_leftLatch);
+ Stream(_rightLatch);
+ StreamArray(_leftChrPage, 2);
+ StreamArray(_rightChrPage, 2);
+
+ BaseMapper::StreamState(saving);
+ }
+
+ public:
+ void WriteRAM(uint16_t addr, uint8_t value)
+ {
+ switch((MMC2Registers)(addr >> 12)) {
+ case MMC2Registers::RegA000:
+ SelectPRGPage(0, value);
+ break;
+
+ case MMC2Registers::RegB000:
+ _leftChrPage[0] = value;
+ SelectCHRPage(0, _leftChrPage[_leftLatch]);
+ break;
+
+ case MMC2Registers::RegC000:
+ _leftChrPage[1] = value;
+ SelectCHRPage(0, _leftChrPage[_leftLatch]);
+ break;
+
+ case MMC2Registers::RegD000:
+ _rightChrPage[0] = value;
+ SelectCHRPage(1, _rightChrPage[_rightLatch]);
+ break;
+
+ case MMC2Registers::RegE000:
+ _rightChrPage[1] = value;
+ SelectCHRPage(1, _rightChrPage[_rightLatch]);
+ break;
+
+ case MMC2Registers::RegF000:
+ _mirroringType = ((value & 0x01) == 0x01) ? MirroringType::Horizontal : MirroringType::Vertical;
+ break;
+ }
+ }
+
+ virtual void NotifyVRAMAddressChange(uint16_t addr)
+ {
+ SelectCHRPage(0, _leftChrPage[_leftLatch]);
+ SelectCHRPage(1, _rightChrPage[_rightLatch]);
+
+ switch(addr & 0xFFF8) {
+ case 0x0FD8: _leftLatch = 0; break;
+ case 0x0FE8: _leftLatch = 1; break;
+ case 0x1FD8: _rightLatch = 0; break;
+ case 0x1FE8: _rightLatch = 1; break;
+ }
+ }
+};
\ No newline at end of file
diff --git a/Core/MapperFactory.h b/Core/MapperFactory.h
index 20773766..d2c7afbd 100644
--- a/Core/MapperFactory.h
+++ b/Core/MapperFactory.h
@@ -3,6 +3,7 @@
#include "AXROM.h"
#include "CNROM.h"
#include "MMC1.h"
+#include "MMC2.h"
#include "MMC3.h"
#include "NROM.h"
#include "UNROM.h"
@@ -19,6 +20,8 @@ class MapperFactory
case 3: return new CNROM();
case 4: return new MMC3();
case 7: return new AXROM();
+ case 9: return new MMC2();
+ case 71: return new UNROM(); //TODO: "It's largely a clone of UNROM, and Camerica games were initially emulated under iNES Mapper 002 before 071 was assigned."
}
throw std::exception("Unsupported mapper");