1 #pragma once
2 #include "stdafx.h"
3 #include "MMC3.h"
4 
5 class MMC3_208 : public MMC3
6 {
7 private:
8 	const uint8_t _protectionLut[256] = {
9 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
10 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
11 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
12 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
13 		0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 		0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15 		0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16 		0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
18 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
19 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
20 		0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
21 		0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22 		0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 		0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 		0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 	};
26 
27 	uint8_t _exRegs[6];
28 
29 protected:
RegisterStartAddress()30 	uint16_t RegisterStartAddress() override { return 0x8000; }
RegisterEndAddress()31 	uint16_t RegisterEndAddress() override { return 0xFFFF; }
AllowRegisterRead()32 	bool AllowRegisterRead() override { return true; }
33 
InitMapper()34 	void InitMapper() override
35 	{
36 		_exRegs[5] = 3;
37 		MMC3::InitMapper();
38 		AddRegisterRange(0x4800, 0x4FFF, MemoryOperation::Write);
39 		AddRegisterRange(0x6800, 0x6FFF, MemoryOperation::Write);
40 		AddRegisterRange(0x5000, 0x5FFF, MemoryOperation::Write);
41 		AddRegisterRange(0x5800, 0x5FFF, MemoryOperation::Read);
42 		RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read);
43 	}
44 
StreamState(bool saving)45 	void StreamState(bool saving) override
46 	{
47 		MMC3::StreamState(saving);
48 		ArrayInfo<uint8_t> exRegs { _exRegs, 6 };
49 		Stream(exRegs);
50 	}
51 
UpdatePrgMapping()52 	void UpdatePrgMapping() override
53 	{
54 		SelectPrgPage4x(0, _exRegs[5] << 2);
55 	}
56 
ReadRegister(uint16_t addr)57 	uint8_t ReadRegister(uint16_t addr) override
58 	{
59 		return _exRegs[addr & 0x03];
60 	}
61 
WriteRegister(uint16_t addr,uint8_t value)62 	void WriteRegister(uint16_t addr, uint8_t value) override
63 	{
64 		if(addr >= 0x5000 && addr <= 0x5FFF) {
65 			if(addr <= 0x57FF) {
66 				_exRegs[4] = value;
67 			} else {
68 				_exRegs[addr & 0x03] = value ^ _protectionLut[_exRegs[4]];
69 			}
70 		} else if(addr < 0x8000) {
71 			_exRegs[5] = (value & 0x01) | ((value >> 3) & 0x02);
72 			UpdatePrgMapping();
73 		} else {
74 			MMC3::WriteRegister(addr, value);
75 		}
76 	}
77 };