1 #pragma once
2 #include "BaseMapper.h"
3 #include "CPU.h"
4 
5 class FrontFareast : public BaseMapper
6 {
7 private:
8 	uint16_t _irqCounter;
9 	bool _irqEnabled;
10 	bool _ffeAltMode;
11 
12 protected:
GetPRGPageSize()13 	uint16_t GetPRGPageSize() override { return 0x2000; }
GetCHRPageSize()14 	uint16_t GetCHRPageSize() override { return 0x400; }
GetChrRamSize()15 	uint32_t GetChrRamSize() override { return 0x8000; }
RegisterStartAddress()16 	uint16_t RegisterStartAddress() override { return 0x42FE; }
RegisterEndAddress()17 	uint16_t RegisterEndAddress() override { return 0x4517; }
18 
InitMapper()19 	void InitMapper() override
20 	{
21 		_irqCounter = 0;
22 		_irqEnabled = false;
23 		_ffeAltMode = true;
24 
25 		switch(_romInfo.MapperID) {
26 			case 6:
27 				AddRegisterRange(0x8000, 0xFFFF, MemoryOperation::Write);
28 				SelectPrgPage2x(0, 0);
29 				SelectPrgPage2x(1, 14);
30 				break;
31 
32 			case 8:
33 				AddRegisterRange(0x8000, 0xFFFF, MemoryOperation::Write);
34 				SelectPrgPage4x(0, 0);
35 				break;
36 
37 			case 17:
38 				SelectPrgPage4x(0, -4);
39 				break;
40 		}
41 	}
42 
StreamState(bool saving)43 	void StreamState(bool saving) override
44 	{
45 		BaseMapper::StreamState(saving);
46 		Stream(_irqCounter, _irqEnabled, _ffeAltMode);
47 	}
48 
ProcessCpuClock()49 	void ProcessCpuClock() override
50 	{
51 		if(_irqEnabled) {
52 			_irqCounter++;
53 			if(_irqCounter == 0) {
54 				_console->GetCpu()->SetIrqSource(IRQSource::External);
55 				_irqEnabled = false;
56 			}
57 		}
58 	}
59 
WriteRegister(uint16_t addr,uint8_t value)60 	void WriteRegister(uint16_t addr, uint8_t value) override
61 	{
62 		switch(addr) {
63 			case 0x42FE:
64 				_ffeAltMode = (value & 0x80) == 0x00;
65 				switch((value >> 4) & 0x01) {
66 					case 0: SetMirroringType(MirroringType::ScreenAOnly); break;
67 					case 1: SetMirroringType(MirroringType::ScreenBOnly); break;
68 				}
69 				break;
70 
71 			case 0x42FF:
72 				switch((value >> 4) & 0x01) {
73 					case 0: SetMirroringType(MirroringType::Vertical); break;
74 					case 1: SetMirroringType(MirroringType::Horizontal); break;
75 				}
76 				break;
77 
78 			case 0x4501:
79 				_irqEnabled = false;
80 				_console->GetCpu()->ClearIrqSource(IRQSource::External);
81 				break;
82 
83 			case 0x4502:
84 				_irqCounter = (_irqCounter & 0xFF00) | value;
85 				_console->GetCpu()->ClearIrqSource(IRQSource::External);
86 				break;
87 
88 			case 0x4503:
89 				_irqCounter = (_irqCounter & 0x00FF) | (value << 8);
90 				_irqEnabled = true;
91 				_console->GetCpu()->ClearIrqSource(IRQSource::External);
92 				break;
93 
94 			default:
95 				if(_romInfo.MapperID == 6) {
96 					if(addr >= 0x8000) {
97 						if(HasChrRam() || _ffeAltMode) {
98 							SelectPrgPage2x(0, (value & 0xFC) >> 1);
99 							value &= 0x03;
100 						}
101 						SelectChrPage8x(0, value << 3);
102 					}
103 				} else if(_romInfo.MapperID == 8) {
104 					if(addr >= 0x8000) {
105 						SelectPrgPage2x(0, (value & 0xF8) >> 2);
106 						SelectChrPage8x(0, (value & 0x07) << 3);
107 					}
108 				} else {
109 					switch(addr) {
110 						case 0x4504: case 0x4505: case 0x4506: case 0x4507:
111 							SelectPRGPage(addr - 0x4504, value);
112 							break;
113 
114 						case 0x4510: case 0x4511: case 0x4512: case 0x4513: case 0x4514: case 0x4515: case 0x4516: case 0x4517:
115 							SelectCHRPage(addr - 0x4510, value);
116 							break;
117 					}
118 				}
119 		}
120 	}
121 };
122