1 #pragma once
2 #include "stdafx.h"
3 #include "BaseMapper.h"
4 
5 class Kaiser202 : public BaseMapper
6 {
7 	uint16_t _irqReloadValue;
8 	uint16_t _irqCounter;
9 	bool _irqEnabled;
10 	uint8_t _selectedReg;
11 	uint8_t _prgRegs[4];
12 
13 protected:
GetPRGPageSize()14 	virtual uint16_t GetPRGPageSize() override { return 0x2000; }
GetCHRPageSize()15 	virtual uint16_t GetCHRPageSize() override { return 0x0400; }
16 
InitMapper()17 	void InitMapper() override
18 	{
19 		_irqReloadValue = 0;
20 		_irqCounter = 0;
21 		_irqEnabled = 0;
22 		_selectedReg = 0;
23 		memset(_prgRegs, 0, sizeof(_prgRegs));
24 
25 		SelectPRGPage(3, -1);
26 	}
27 
StreamState(bool saving)28 	void StreamState(bool saving) override
29 	{
30 		BaseMapper::StreamState(saving);
31 		Stream(_irqReloadValue, _irqCounter, _irqEnabled, _selectedReg, _prgRegs[0], _prgRegs[1], _prgRegs[2], _prgRegs[3]);
32 
33 		if(!saving) {
34 			SetCpuMemoryMapping(0x6000, 0x7FFF, _prgRegs[3], PrgMemoryType::PrgRom, MemoryAccessType::ReadWrite);
35 		}
36 	}
37 
ProcessCpuClock()38 	void ProcessCpuClock() override
39 	{
40 		if(_irqEnabled) {
41 			_irqCounter++;
42 			if(_irqCounter == 0xFFFF) {
43 				_irqCounter = _irqReloadValue;
44 				_console->GetCpu()->SetIrqSource(IRQSource::External);
45 			}
46 		}
47 	}
48 
WriteRegister(uint16_t addr,uint8_t value)49 	void WriteRegister(uint16_t addr, uint8_t value) override
50 	{
51 		switch(addr & 0xF000) {
52 			case 0x8000: _irqReloadValue = (_irqReloadValue & 0xFFF0) | (value & 0x0F); break;
53 			case 0x9000: _irqReloadValue = (_irqReloadValue & 0xFF0F) | ((value & 0x0F) << 4); break;
54 			case 0xA000: _irqReloadValue = (_irqReloadValue & 0xF0FF) | ((value & 0x0F) << 8); break;
55 			case 0xB000: _irqReloadValue = (_irqReloadValue & 0x0FFF) | ((value & 0x0F) << 12); break;
56 
57 			case 0xC000:
58 				_irqEnabled = (value != 0);
59 				if(_irqEnabled) {
60 					_irqCounter = _irqReloadValue;
61 				}
62 				_console->GetCpu()->ClearIrqSource(IRQSource::External);
63 				break;
64 
65 			case 0xD000: _console->GetCpu()->ClearIrqSource(IRQSource::External); break;
66 			case 0xE000: _selectedReg = (value & 0x0F) - 1; break;
67 
68 			case 0xF000:
69 				if(_selectedReg < 3) {
70 					_prgRegs[_selectedReg] = ((_prgRegs[_selectedReg]) & 0x10) | (value & 0x0F);
71 				} else if(_selectedReg < 4) {
72 					//For Kaiser7032 (Mapper 142)
73 					_prgRegs[_selectedReg] = value;
74 					SetCpuMemoryMapping(0x6000, 0x7FFF, value, PrgMemoryType::PrgRom, MemoryAccessType::ReadWrite);
75 				}
76 
77 				switch(addr & 0xFC00) {
78 					case 0xF000: {
79 						uint8_t bank = addr & 0x03;
80 						if(bank < 3) {
81 							_prgRegs[bank] = (value & 0x10) | (_prgRegs[bank] & 0x0F);
82 						}
83 						break;
84 					}
85 
86 					case 0xF800:
87 						SetMirroringType(value & 0x01 ? MirroringType::Vertical : MirroringType::Horizontal);
88 						break;
89 
90 					case 0xFC00:
91 						SelectCHRPage(addr & 0x07, value);
92 						break;
93 				}
94 
95 				SelectPRGPage(0, _prgRegs[0]);
96 				SelectPRGPage(1, _prgRegs[1]);
97 				SelectPRGPage(2, _prgRegs[2]);
98 				break;
99 		}
100 	}
101 };