diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 7653d89c..a6178fb8 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -447,6 +447,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index be92c7d9..85254acd 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -1126,6 +1126,9 @@ Nes\Mappers\Unif + + Nes\Mappers\Unif + diff --git a/Core/MMC3_Fk23C.h b/Core/MMC3_Fk23C.h new file mode 100644 index 00000000..170aa5a3 --- /dev/null +++ b/Core/MMC3_Fk23C.h @@ -0,0 +1,141 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_Fk23C : public MMC3 +{ +private: + bool _isFk23Ca; + uint8_t _exRegs[8]; + uint8_t _chrReg; + +protected: + uint32_t GetChrRamSize() override { return _isFk23Ca ? 0x2000 : 0; } + uint16_t GetChrRamPageSize() override { return 0x400; } + + void InitMapper() override + { + _exRegs[0] = _exRegs[1] = _exRegs[2] = _exRegs[3] = 0; + _exRegs[4] = _exRegs[5] = _exRegs[6] = _exRegs[7] = 0xFF; + _chrReg = 0; + + AddRegisterRange(0x5000, 0x5FFF, MemoryOperation::Write); + + MMC3::InitMapper(); + } + + void Reset(bool softReset) override + { + _exRegs[0] = _exRegs[1] = _exRegs[2] = _exRegs[3] = 0; + _exRegs[4] = _exRegs[5] = _exRegs[6] = _exRegs[7] = 0xFF; + _chrReg = 0; + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + ArrayInfo exRegs{ _exRegs,8 }; + Stream(_chrReg, exRegs); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if(_exRegs[0] & 0x20) { + MMC3::SelectCHRPage(slot, page, _isFk23Ca ? ChrMemoryType::ChrRam : ChrMemoryType::Default); + } else { + uint16_t base = (_exRegs[2] & 0x7F) << 3; + MMC3::SelectCHRPage(slot, page | base, memoryType); + } + } + + void UpdateChrMapping() override + { + if(_exRegs[0] & 0x40) { + SelectChrPage8x(0, (_exRegs[2] | _chrReg) << 3); + } else if(_exRegs[3] & 0x02) { + uint16_t base = (_exRegs[2] & 0x7F) << 3; + int slotBase = _chrMode ? 4 : 0; + MMC3::SelectCHRPage(0 ^ slotBase, _registers[0] | base); + MMC3::SelectCHRPage(1 ^ slotBase, _exRegs[6] | base); + MMC3::SelectCHRPage(2 ^ slotBase, _registers[1] | base); + MMC3::SelectCHRPage(3 ^ slotBase, _exRegs[7] | base); + MMC3::SelectCHRPage(4 ^ slotBase, _registers[2] | base); + MMC3::SelectCHRPage(5 ^ slotBase, _registers[3] | base); + MMC3::SelectCHRPage(6 ^ slotBase, _registers[4] | base); + MMC3::SelectCHRPage(7 ^ slotBase, _registers[5] | base); + } else { + MMC3::UpdateChrMapping(); + } + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if((_exRegs[0] & 0x07) == 0x04) { + SelectPrgPage4x(0, _exRegs[1] << 1); + } else if((_exRegs[0] & 0x07) == 0x03) { + SelectPrgPage2x(0, _exRegs[1] << 1); + SelectPrgPage2x(1, _exRegs[1] << 1); + } else { + if(_exRegs[0] & 0x03) { + uint32_t blocksize = 6 - (_exRegs[0] & 0x03); + uint32_t mask = (1 << blocksize) - 1; + MMC3::SelectPRGPage(slot, (page & mask) | (_exRegs[1] << 1)); + } else { + MMC3::SelectPRGPage(slot, page & (_isFk23Ca ? 0x3F : 0x7F)); + } + + if(_exRegs[3] & 0x02) { + MMC3::SelectPRGPage(2, _exRegs[4]); + MMC3::SelectPRGPage(3, _exRegs[5]); + } + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr >= 0x8000) { + if(_exRegs[0] & 0x40) { + if(_exRegs[0] & 0x30) { + _chrReg = 0; + } else { + _chrReg = value & 0x03; + UpdateChrMapping(); + } + } else { + if(addr == 0x8001 && (_exRegs[3] & 0x02) && (GetState().Reg8000 & 0x08)) { + _exRegs[0x04 | (GetState().Reg8000 & 0x03)] = value; + UpdateChrMapping(); + UpdatePrgMapping(); + } else { + if(addr < 0xC000) { + if(HasChrRam()) { + if((addr == 0x8000) && (value == 0x46)) { + value = 0x47; + } else if((addr == 0x8000) && (value == 0x47)) { + value = 0x46; + } + } + } + MMC3::WriteRegister(addr, value); + } + } + } else { + if(addr & 0x10) { + _exRegs[addr & 0x03] = value; + if(((_exRegs[0] & 0xF0) == 0x20) || (addr & 0x03) == 1 || (addr & 0x03) == 2) { + UpdateState(); + } + } + + if(_isFk23Ca && (_exRegs[3] & 0x02)) { + _exRegs[0] &= ~7; + } + } + } + +public: + MMC3_Fk23C(bool isFk23Ca) + { + _isFk23Ca = isFk23Ca; + } +}; \ No newline at end of file diff --git a/Core/MapperFactory.cpp b/Core/MapperFactory.cpp index 51623662..670f2887 100644 --- a/Core/MapperFactory.cpp +++ b/Core/MapperFactory.cpp @@ -160,6 +160,7 @@ #include "MMC3_BmcF15.h" #include "MMC3_ChrRam.h" #include "MMC3_Coolboy.h" +#include "MMC3_Fk23C.h" #include "MMC3_Kof97.h" #include "MMC3_MaliSB.h" #include "MMC3_StreetHeroes.h" @@ -511,6 +512,8 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case UnifBoards::DreamTech01: return new DreamTech01(); case UnifBoards::Edu2000: return new Edu2000(); case UnifBoards::Eh8813A: return new Eh8813A(); + case UnifBoards::Fk23C: return new MMC3_Fk23C(false); + case UnifBoards::Fk23Ca: return new MMC3_Fk23C(true); case UnifBoards::Ghostbusters63in1: return new Ghostbusters63in1(); case UnifBoards::Gs2004: return new Gs2004(); case UnifBoards::Gs2013: return new Gs2013(); diff --git a/Core/UnifBoards.h b/Core/UnifBoards.h index 658a160b..be50eede 100644 --- a/Core/UnifBoards.h +++ b/Core/UnifBoards.h @@ -49,5 +49,7 @@ namespace UnifBoards { Unl43272, Bmc411120C, UnlPuzzle, + Fk23C, + Fk23Ca, }; } \ No newline at end of file diff --git a/Core/UnifLoader.cpp b/Core/UnifLoader.cpp index 97710703..6bc7b7f2 100644 --- a/Core/UnifLoader.cpp +++ b/Core/UnifLoader.cpp @@ -41,8 +41,8 @@ std::unordered_map UnifLoader::_boardMappings = std::unordered_map< { "ELROM", 5 }, { "ETROM", 5 }, { "EWROM", 5 }, - { "FK23C", UnifBoards::UnknownBoard }, - { "FK23CA", UnifBoards::UnknownBoard }, + { "FK23C", UnifBoards::Fk23C }, + { "FK23CA", UnifBoards::Fk23Ca }, { "FS304", 162 }, { "G-146", UnifBoards::BmcG146 }, { "GK-192", 58 },