#pragma once #include "BaseMapper.h" #include "CPU.h" class FrontFareast : public BaseMapper { private: uint16_t _irqCounter; bool _irqEnabled; bool _ffeAltMode; protected: uint16_t GetPRGPageSize() override { return 0x2000; } uint16_t GetCHRPageSize() override { return 0x400; } uint32_t GetChrRamSize() override { return 0x8000; } uint16_t RegisterStartAddress() override { return 0x42FE; } uint16_t RegisterEndAddress() override { return 0x4517; } void InitMapper() override { _irqCounter = 0; _irqEnabled = false; _ffeAltMode = true; switch(_mapperID) { case 6: AddRegisterRange(0x8000, 0xFFFF, MemoryOperation::Write); SelectPrgPage2x(0, 0); SelectPrgPage2x(1, 14); break; case 8: AddRegisterRange(0x8000, 0xFFFF, MemoryOperation::Write); SelectPrgPage4x(0, 0); break; case 17: SelectPrgPage4x(0, -4); break; } } void StreamState(bool saving) override { BaseMapper::StreamState(saving); Stream(_irqCounter, _irqEnabled, _ffeAltMode); } void ProcessCpuClock() override { if(_irqEnabled) { _irqCounter++; if(_irqCounter == 0) { CPU::SetIRQSource(IRQSource::External); _irqEnabled = false; } } } void WriteRegister(uint16_t addr, uint8_t value) override { switch(addr) { case 0x42FE: _ffeAltMode = (value & 0x80) == 0x00; switch((value >> 4) & 0x01) { case 0: SetMirroringType(MirroringType::ScreenAOnly); break; case 1: SetMirroringType(MirroringType::ScreenBOnly); break; } break; case 0x42FF: switch((value >> 4) & 0x01) { case 0: SetMirroringType(MirroringType::Vertical); break; case 1: SetMirroringType(MirroringType::Horizontal); break; } break; case 0x4501: _irqEnabled = false; CPU::ClearIRQSource(IRQSource::External); break; case 0x4502: _irqCounter = (_irqCounter & 0xFF00) | value; CPU::ClearIRQSource(IRQSource::External); break; case 0x4503: _irqCounter = (_irqCounter & 0x00FF) | (value << 8); _irqEnabled = true; CPU::ClearIRQSource(IRQSource::External); break; default: if(_mapperID == 6) { if(addr >= 0x8000) { if(HasChrRam() || _ffeAltMode) { SelectPrgPage2x(0, (value & 0xFC) >> 1); value &= 0x03; } SelectChrPage8x(0, value << 3); } } else if(_mapperID == 8) { if(addr >= 0x8000) { SelectPrgPage2x(0, (value & 0xF8) >> 2); SelectChrPage8x(0, (value & 0x07) << 3); } } else { switch(addr) { case 0x4504: case 0x4505: case 0x4506: case 0x4507: SelectPRGPage(addr - 0x4504, value); break; case 0x4510: case 0x4511: case 0x4512: case 0x4513: case 0x4514: case 0x4515: case 0x4516: case 0x4517: SelectCHRPage(addr - 0x4510, value); break; } } } } };