diff --git a/Core/Bmc235.h b/Core/Bmc235.h index 9a97675ab..b34a611d1 100644 --- a/Core/Bmc235.h +++ b/Core/Bmc235.h @@ -4,12 +4,12 @@ class Bmc235 : public BaseMapper { -private: - bool _openBus = false; protected: virtual uint16_t GetPRGPageSize() override { return 0x4000; } virtual uint16_t GetCHRPageSize() override { return 0x2000; } + uint8_t _unrom; + void InitMapper() override { SelectPrgPage2x(0, 0); @@ -19,45 +19,34 @@ class Bmc235 : public BaseMapper void Reset(bool softReset) override { SelectPrgPage2x(0, 0); - _openBus = false; - } - - void StreamState(bool saving) override - { - BaseMapper::StreamState(saving); - Stream(_openBus); - if(!saving && _openBus) { - RemoveCpuMemoryMapping(0x8000, 0xFFFF); + if(_prgSize & 0x20000) { + if(softReset) { + _unrom = !_unrom; + } else { + _unrom = false; + } } } void WriteRegister(uint16_t addr, uint8_t value) override { - SetMirroringType((addr & 0x0400) ? MirroringType::ScreenAOnly : (addr & 0x2000) ? MirroringType::Horizontal : MirroringType::Vertical); + uint8_t bank = (addr >> 3) & 0x60 | (addr & 0x1F); - const uint8_t config[4][4][2] = { - { { 0x00, 0 }, { 0x00, 1 }, { 0x00, 1 }, { 0x00, 1 } }, - { { 0x00, 0 }, { 0x00, 1 }, { 0x20, 0 }, { 0x00, 1 } }, - { { 0x00, 0 }, { 0x00, 1 }, { 0x20, 0 }, { 0x40, 0 } }, - { { 0x00, 0 }, { 0x20, 0 }, { 0x40, 0 }, { 0x60, 0 } } - }; + if(_unrom) { + SetMirroringType(MirroringType::Vertical); + SelectPRGPage(0, GetPRGPageCount() & 0xC0 | value & 0x07); + SelectPRGPage(1, GetPRGPageCount() & 0xC0 | 0x07); + return; + } - uint8_t mode; - switch(GetPRGPageCount()) { - case 64: mode = 0; break; - case 128: mode = 1; break; - case 256: mode = 2; break; - default: mode = 3; break; - }; + if(bank >= (GetPRGPageCount() >> 1)) { + RemoveCpuMemoryMapping(0x8000, 0xFFFF); + return; + } - uint8_t bank = config[mode][addr >> 8 & 0x03][0] | (addr & 0x1F); + SetMirroringType((addr & 0x0400) ? MirroringType::ScreenAOnly : (addr & 0x2000) ? MirroringType::Horizontal : MirroringType::Vertical); - _openBus = false; - if(config[mode][addr >> 8 & 0x03][1]) { - //Open bus - _openBus = true; - RemoveCpuMemoryMapping(0x8000, 0xFFFF); - } else if(addr & 0x800) { + if(addr & 0x800) { bank = (bank << 1) | (addr >> 12 & 0x01); SelectPRGPage(0, bank); SelectPRGPage(1, bank); diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index d01ebc69e..46d5abdf1 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -769,6 +769,7 @@ + @@ -784,6 +785,9 @@ + + + @@ -796,8 +800,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 06609825b..af281d922 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -436,6 +436,9 @@ Nes\Mappers\Unnamed + + Nes\Mappers\Unnamed + Nes\Mappers\Sunsoft @@ -1429,6 +1432,15 @@ Nes\Mappers\Unnamed + + Nes\Mappers\Unnamed + + + Nes\Mappers\Unnamed + + + Nes\Mappers\Unnamed + Nes\Mappers\MMC @@ -1459,6 +1471,69 @@ Nes\Mappers\MMC + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + + + Nes\Mappers\MMC + Nes\Mappers\Unif diff --git a/Core/MMC3_219.h b/Core/MMC3_219.h index d4496ec83..e49fa5f1d 100644 --- a/Core/MMC3_219.h +++ b/Core/MMC3_219.h @@ -10,59 +10,79 @@ class MMC3_219 : public MMC3 void InitMapper() override { MMC3::InitMapper(); - SelectPrgPage4x(0, -4); - SelectChrPage8x(0, 0); - _exRegs[0] = _exRegs[1] = _exRegs[2] = 0; + AddRegisterRange(0x5000, 0x5FFF); } - void UpdatePrgMapping() override + void Reset(bool softreset) override { + _exRegs[0] = _exRegs[2] = 0x00; + _exRegs[1] = 0x03; + MMC3::UpdateState(); } - void UpdateChrMapping() override + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override { + MMC3::SelectCHRPage(slot, (_exRegs[1] << 7) | (page & 0x7F)); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + MMC3::SelectPRGPage(slot, (_exRegs[1] << 4) | (page & 0x0F)); } void WriteRegister(uint16_t addr, uint8_t value) override { - if(addr < 0xA000) { + if(addr < 0x8000) { + switch(addr & 0x01) { + case 0: _exRegs[1] = (_exRegs[1] & ~0x01) | ((value >> 3) & 0x01); break; + case 1: _exRegs[1] = (_exRegs[1] & ~0x02) | ((value >> 4) & 0x02); break; + } + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else if(addr < 0xA000) { switch(addr & 0xE003) { - case 0x8000: - _exRegs[0] = 0; - _exRegs[1] = value; - break; + case 0x8000: + MMC3::WriteRegister(addr, value); + break; + + case 0x8002: + _exRegs[0] = value; + MMC3::WriteRegister(addr, value); + break; - case 0x8001: - if(_exRegs[0] >= 0x23 && _exRegs[0] <= 0x26) { + case 0x8001: + if(_exRegs[0] & 0x20) { // Extended Mode + uint8_t bankRegister = MMC3::GetState().Reg8000; + if((bankRegister >= 0x25) && (bankRegister <= 0x26)) { uint8_t prgBank = ((value & 0x20) >> 5) | ((value & 0x10) >> 3) | ((value & 0x08) >> 1) | ((value & 0x04) << 1); - SelectPRGPage(0x26 - _exRegs[0], prgBank); - } - - switch(_exRegs[1]) { - case 0x08: case 0x0A: case 0x0E: case 0x12: case 0x16: case 0x1A: case 0x1E: - _exRegs[2] = value << 4; - break; + MMC3::_registers[6 | (bankRegister & 0x01)] = prgBank; + MMC3::UpdatePrgMapping(); + } else if((bankRegister >= 0x08) && (bankRegister <= 0x1F)) { + switch(bankRegister) { + case 0x08: case 0x0A: case 0x0E: case 0x12: case 0x16: case 0x1A: case 0x1E: + _exRegs[2] = value << 4; + break; - case 0x09: SelectCHRPage(0, _exRegs[2] | (value >> 1 & 0x0E)); break; - case 0x0B: SelectCHRPage(1, _exRegs[2] | (value >> 1 | 0x1)); break; - case 0x0C: - case 0x0D: SelectCHRPage(2, _exRegs[2] | (value >> 1 & 0xE)); break; - case 0x0F: SelectCHRPage(3, _exRegs[2] | (value >> 1 | 0x1)); break; - case 0x10: - case 0x11: SelectCHRPage(4, _exRegs[2] | (value >> 1 & 0xF)); break; - case 0x14: - case 0x15: SelectCHRPage(5, _exRegs[2] | (value >> 1 & 0xF)); break; - case 0x18: - case 0x19: SelectCHRPage(6, _exRegs[2] | (value >> 1 & 0xF)); break; - case 0x1C: - case 0x1D: SelectCHRPage(7, _exRegs[2] | (value >> 1 & 0xF)); break; + case 0x09: MMC3::_registers[0] = _exRegs[2] | (value >> 1 & 0x0E); break; + case 0x0B: MMC3::_registers[0] = _exRegs[2] | (value >> 1 | 0x1); break; + case 0x0C: + case 0x0D: MMC3::_registers[1] = _exRegs[2] | (value >> 1 & 0xE); break; + case 0x0F: MMC3::_registers[1] = _exRegs[2] | (value >> 1 | 0x1); break; + case 0x10: + case 0x11: MMC3::_registers[2] = _exRegs[2] | (value >> 1 & 0xF); break; + case 0x14: + case 0x15: MMC3::_registers[3] = _exRegs[2] | (value >> 1 & 0xF); break; + case 0x18: + case 0x19: MMC3::_registers[4] = _exRegs[2] | (value >> 1 & 0xF); break; + case 0x1C: + case 0x1D: MMC3::_registers[5] = _exRegs[2] | (value >> 1 & 0xF); break; + } + MMC3::UpdateChrMapping(); } - break; - - case 0x8002: - _exRegs[0] = value; - _exRegs[1] = 0; - break; + } else { // Normal MMC3 + MMC3::WriteRegister(addr, value); + } + break; } } else { MMC3::WriteRegister(addr, value); diff --git a/Core/MMC3_267.h b/Core/MMC3_267.h new file mode 100644 index 000000000..694f91eeb --- /dev/null +++ b/Core/MMC3_267.h @@ -0,0 +1,52 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_267 : public MMC3 +{ +private: + uint8_t _outerBank = 0; + +protected: + virtual uint16_t RegisterStartAddress() override { return 0x6000; } + virtual uint16_t RegisterEndAddress() override { return 0xFFFF; } + + virtual void Reset(bool softreset) override + { + _outerBank = 0; + MMC3::UpdateState(); + } + + virtual void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_outerBank); + } + + virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + page &= 0x7F; + page |= (((_outerBank >> 2) & 0x08) | (_outerBank & 0x06)) << 6; + MMC3::SelectCHRPage(slot, page, memoryType); + } + + virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + page &= 0x1F; + page |= (((_outerBank >> 2) & 0x08) | (_outerBank & 0x06)) << 4; + MMC3::SelectPRGPage(slot, page, memoryType); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(!(_outerBank & 0x80)) { + _outerBank = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_334.h b/Core/MMC3_334.h new file mode 100644 index 000000000..5ab2cdc01 --- /dev/null +++ b/Core/MMC3_334.h @@ -0,0 +1,45 @@ +#pragma once +#include "MMC3.h" + +class MMC3_334 : public MMC3 +{ +protected: + uint32_t GetDipSwitchCount() override { return 1; } + bool AllowRegisterRead() override { return true; } + + void InitMapper() override + { + MMC3::InitMapper(); + SelectPrgPage4x(0, -4); + SelectChrPage8x(0, 0); + AddRegisterRange(0x6000, 0x7FFF, MemoryOperation::Any); + RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read); + } + + void UpdatePrgMapping() override + { + } + + uint8_t ReadRegister(uint16_t addr) override + { + uint8_t value = _console->GetMemoryManager()->GetOpenBus(); + + if(addr & 0x02) { + value &= ~0x01; + value |= GetDipSwitches() & 0x01; + } + + return value; + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(!(addr & 0x01)) { + SelectPrgPage4x(0, (value & 0xFE) << 1); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_353.h b/Core/MMC3_353.h new file mode 100644 index 000000000..898ddd27a --- /dev/null +++ b/Core/MMC3_353.h @@ -0,0 +1,94 @@ +#pragma once +#include "MMC3.h" + +class MMC3_353 : public MMC3 +{ +protected: + uint16_t GetChrRamPageSize() override { return 0x2000; } + uint32_t GetChrRamSize() override { return 0x2000; } + + uint8_t _exReg; + + void InitMapper() override + { + _exReg = 0; + MMC3::InitMapper(); + } + + void Reset(bool softreset) + { + _exReg = 0; + MMC3::UpdateState(); + } + + void UpdateMirroring() override + { + if(!(_exReg == 0)) { + MMC3::UpdateMirroring(); + } + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType) override + { + if((_exReg == 2) && (MMC3::_registers[0] & 0x80)) { + MMC3::SelectChrPage8x(0, 0, ChrMemoryType::ChrRam); + } else { + MMC3::SelectCHRPage(slot, (_exReg << 7) | (page & 0x7F), memoryType); + } + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if(_exReg == 2) { + page &= 0x0F; + page |= ((MMC3::_registers[0] >> 3) & 0x10); + page |= (_exReg << 5); + } else { + page &= 0x1F; + page |= (_exReg << 5); + } + + MMC3::SelectPRGPage(slot, page); + + if((_exReg == 3) && !(MMC3::_registers[0] & 0x80)) { + MMC3::SelectPRGPage(2, MMC3::_registers[6] | 0x70); + MMC3::SelectPRGPage(3, MMC3::_registers[7] | 0x70); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if((addr & 0x80) == 0x80) { + _exReg = (addr >> 13) & 0x03; + UpdatePrgMapping(); + UpdateChrMapping(); + } else { + if((_exReg == 0) && (addr & 0xE001) == 0x8001) { + uint8_t nametable = value >> 7; + + if(GetChrMode() == 0) { + switch(GetCurrentRegister()) { + case 0: + SetNametable(0, nametable); + SetNametable(1, nametable); + break; + + case 1: + SetNametable(2, nametable); + SetNametable(3, nametable); + break; + } + } else { + switch(GetCurrentRegister()) { + case 2: SetNametable(0, nametable); break; + case 3: SetNametable(1, nametable); break; + case 4: SetNametable(2, nametable); break; + case 5: SetNametable(3, nametable); break; + } + } + } + + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_364.h b/Core/MMC3_364.h new file mode 100644 index 000000000..69dac6e9b --- /dev/null +++ b/Core/MMC3_364.h @@ -0,0 +1,38 @@ +#pragma once +#include "MMC3.h" + +class MMC3_364 : public MMC3 +{ +protected: + uint8_t _exReg; + + void InitMapper() override + { + _exReg = 0; + MMC3::InitMapper(); + AddRegisterRange(0x7000, 0x7FFF, MemoryOperation::Write); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType) override + { + uint8_t mask = (_exReg & 0x20) ? 0x7F : 0xFF; + MMC3::SelectCHRPage(slot, ((_exReg << 4) & 0x100) | (page & mask)); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_exReg & 0x20) ? 0x0F : 0x1F; + MMC3::SelectPRGPage(slot, ((_exReg >> 1) & 0x20) | (page & mask)); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr <= 0x7FFF) { + _exReg = value; + UpdatePrgMapping(); + UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_370.h b/Core/MMC3_370.h new file mode 100644 index 000000000..f7ce05f62 --- /dev/null +++ b/Core/MMC3_370.h @@ -0,0 +1,90 @@ +#pragma once +#include "MMC3.h" + +class MMC3_370 : public MMC3 +{ +protected: + uint32_t GetDipSwitchCount() override { return 1; } + bool AllowRegisterRead() override { return true; } + + uint8_t _exReg; + + void InitMapper() override + { + _exReg = 0; + MMC3::InitMapper(); + AddRegisterRange(0x5000, 0x5FFF, MemoryOperation::Any); + RemoveRegisterRange(0x8000, 0xFFFF, MemoryOperation::Read); + } + + void Reset(bool softreset) + { + _exReg = 0; + MMC3::UpdateState(); + } + + void UpdateMirroring() override + { + if((_exReg & 0x07) != 0x01) { + MMC3::UpdateMirroring(); + } + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType) override + { + uint8_t mask = (_exReg & 0x04) ? 0xFF : 0x7F; + MMC3::SelectCHRPage(slot, ((_exReg << 7) & 0x380) | (page & mask)); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_exReg & 0x20) ? 0x0F : 0x1F; + MMC3::SelectPRGPage(slot, ((_exReg << 1) & 0x70) | (page & mask)); + } + + uint8_t ReadRegister(uint16_t addr) override + { + uint8_t value = _console->GetMemoryManager()->GetOpenBus(); + + value &= ~0x80; + value |= ((GetDipSwitches() << 7) & 0x80); + + return value; + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x5FFF) { + _exReg = addr & 0x3F; + UpdatePrgMapping(); + UpdateChrMapping(); + } else { + if(((_exReg & 0x07) == 0x01) && (addr & 0xE001) == 0x8001) { + uint8_t nametable = value >> 7; + + if(GetChrMode() == 0) { + switch(GetCurrentRegister()) { + case 0: + SetNametable(0, nametable); + SetNametable(1, nametable); + break; + + case 1: + SetNametable(2, nametable); + SetNametable(3, nametable); + break; + } + } else { + switch(GetCurrentRegister()) { + case 2: SetNametable(0, nametable); break; + case 3: SetNametable(1, nametable); break; + case 4: SetNametable(2, nametable); break; + case 5: SetNametable(3, nametable); break; + } + } + } + + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_372.h b/Core/MMC3_372.h new file mode 100644 index 000000000..61ee7929f --- /dev/null +++ b/Core/MMC3_372.h @@ -0,0 +1,18 @@ +#pragma once +#include "MMC3_45.h" + +class MMC3_372 : public MMC3_45 +{ +private: + uint16_t GetChrRamPageSize() override { return 0x400; } + uint32_t GetChrRamSize() override { return 0x2000; } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if(!(_reg[2] & 0x20)) { + page &= 0xFF >> (0x0F - (_reg[2] & 0x0F)); + page |= _reg[0] | ((_reg[2] & 0xF0) << 4); + } + MMC3::SelectCHRPage(slot, page, (_reg[2] & 0x20) ? ChrMemoryType::ChrRam : ChrMemoryType::ChrRom); + } +}; \ No newline at end of file diff --git a/Core/MMC3_376.h b/Core/MMC3_376.h new file mode 100644 index 000000000..5d8b43b24 --- /dev/null +++ b/Core/MMC3_376.h @@ -0,0 +1,58 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_376 : public MMC3 +{ +private: + uint8_t _exReg[2]; + +protected: + uint16_t RegisterStartAddress() override { return 0x7000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + _exReg[0] = _exReg[1] = 0; + MMC3::InitMapper(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exReg[0], _exReg[1]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + page &= 0x7F; + page |= ((_exReg[1] << 8) & 0x100) | ((_exReg[0] << 1) & 0x80); + MMC3::SelectCHRPage(slot, page, memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t outerBank = ((_exReg[1] << 4) & 0x10) | ((_exReg[0] >> 3) & 0x08) | (_exReg[0] & 0x07); + if(_exReg[0] & 0x80) { + if(_exReg[0] & 0x20) { + MMC3::SelectPrgPage4x(0, (outerBank & 0xFE) << 1); + } else { + MMC3::SelectPrgPage2x(0, outerBank << 1); + MMC3::SelectPrgPage2x(1, outerBank << 1); + } + } else { + MMC3::SelectPRGPage(slot, ((outerBank << 1) & ~0x0F) | (page & 0x0F), memoryType); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _exReg[addr & 0x01] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_377.h b/Core/MMC3_377.h new file mode 100644 index 000000000..95284c543 --- /dev/null +++ b/Core/MMC3_377.h @@ -0,0 +1,52 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_377 : public MMC3 +{ +private: + uint8_t _outerBank = 0; + +protected: + virtual uint16_t RegisterStartAddress() override { return 0x6000; } + virtual uint16_t RegisterEndAddress() override { return 0xFFFF; } + + virtual void Reset(bool softreset) override + { + _outerBank = 0; + MMC3::UpdateState(); + } + + virtual void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_outerBank); + } + + virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + page &= 0x7F; + page |= (((_outerBank >> 2) & 0x08) | (_outerBank & 0x06)) << 6; + MMC3::SelectCHRPage(slot, page, memoryType); + } + + virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + page &= 0x0F; + page |= (((_outerBank >> 2) & 0x08) | (_outerBank & 0x06)) << 3; + MMC3::SelectPRGPage(slot, page, memoryType); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(!(_outerBank & 0x80)) { + _outerBank = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_383.h b/Core/MMC3_383.h new file mode 100644 index 000000000..1db3487c2 --- /dev/null +++ b/Core/MMC3_383.h @@ -0,0 +1,79 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_383 : public MMC3 +{ +private: + uint8_t _A15; + uint8_t _A16; + uint8_t _A17A18; + +protected: + bool AllowRegisterRead() override { return true; } + + void InitMapper() override + { + MMC3::InitMapper(); + RemoveRegisterRange(0xC000, 0xFFFF, MemoryOperation::Read); + } + + void Reset(bool softreset) override + { + _A15 = 0; + _A16 = 0; + _A17A18 = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_A15, _A16, _A17A18); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + MMC3::SelectCHRPage(slot, (_A17A18 << 3) | (page & 0x7F), memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + switch(_A17A18) { + case 0x00: + page &= _A16 ? 0x07: 0x03; + MMC3::SelectPRGPage(slot, _A17A18 | _A16 | (_A16 ? 0x00 : _A15) | page); + break; + case 0x10: + case 0x20: + MMC3::SelectPRGPage(slot, _A17A18 | (page & 0x0F)); + break; + case 0x30: + MMC3::SelectPRGPage(slot ^ 0x02, _A17A18 | (page & 0x0F)); + if(slot == 3) { + SetCpuMemoryMapping(0x6000, 0x7FFF, _A17A18 | (page & 0x0B), PrgMemoryType::PrgRom); + } + break; + } + } + + uint8_t ReadRegister(uint16_t addr) override + { + if(_A17A18 == 0x00) { + _A16 = MMC3::_registers[6 | (addr >> 13) & 0x01] & 0x08; + MMC3::UpdatePrgMapping(); + } + return InternalReadRam(addr); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr & 0x100) { + _A15 = (addr >> 11) & 0x04; + _A17A18 = addr & 0x30; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + MMC3::WriteRegister(addr, value); + } +}; \ No newline at end of file diff --git a/Core/MMC3_391.h b/Core/MMC3_391.h new file mode 100644 index 000000000..d77492f38 --- /dev/null +++ b/Core/MMC3_391.h @@ -0,0 +1,72 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_391 : public MMC3 +{ +private: + uint8_t _reg[2]; + +protected: + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + MMC3::InitMapper(); + RemoveRegisterRange(0xC000, 0xFFFF, MemoryOperation::Read); + } + + void Reset(bool softreset) override + { + _reg[0] = _reg[1] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_reg[0], _reg[1]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_reg[0] & 0x40) ? 0x7F : 0xFF; + page &= mask; + page |= ((_reg[1] << 8) & 0x100 | ((_reg[0] << 3) & 0x80)) & ~mask; + MMC3::SelectCHRPage(slot, page, memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_reg[0] & 0x08) ? 0x0F: 0x1F; + uint8_t outerBank = (_reg[0] << 4) & 0x30; + if(_reg[0] &0x20) { + if(_reg[0] & 0x04) { + MMC3::SelectPRGPage(0, (outerBank & ~mask) | ((MMC3::_registers[6] & ~0x02) & mask)); + MMC3::SelectPRGPage(1, (outerBank & ~mask) | ((MMC3::_registers[7] & ~0x02) & mask)); + MMC3::SelectPRGPage(2, (outerBank & ~mask) | ((MMC3::_registers[6] | 0x02) & mask)); + MMC3::SelectPRGPage(3, (outerBank & ~mask) | ((MMC3::_registers[7] | 0x02) & mask)); + } else { + MMC3::SelectPRGPage(0, (outerBank & ~mask) | (MMC3::_registers[6] & mask)); + MMC3::SelectPRGPage(1, (outerBank & ~mask) | (MMC3::_registers[7] & mask)); + MMC3::SelectPRGPage(2, (outerBank & ~mask) | (MMC3::_registers[6] & mask)); + MMC3::SelectPRGPage(3, (outerBank & ~mask) | (MMC3::_registers[7] & mask)); + } + } else { + MMC3::SelectPRGPage(slot, (outerBank & ~mask) | (page & mask)); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _reg[0] = value; + _reg[1] = addr >> 8; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_393.h b/Core/MMC3_393.h new file mode 100644 index 000000000..bac970da3 --- /dev/null +++ b/Core/MMC3_393.h @@ -0,0 +1,72 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_393 : public MMC3 +{ +private: + uint8_t _exReg[2]; + +protected: + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + uint16_t GetChrRamPageSize() override { return 0x400; } + uint32_t GetChrRamSize() override { return 0x2000; } + + void InitMapper() override + { + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _exReg[0] = _exReg[1] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exReg[0], _exReg[1]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if(_exReg[0] & 0x08) { + MMC3::SelectChrPage8x(0, 0, ChrMemoryType::ChrRam); + } else { + MMC3::SelectCHRPage(slot, (_exReg[0] << 8) | page, memoryType); + } + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if(_exReg[0] & 0x20) { + if(_exReg[0] & 0x10) { + MMC3::SelectPrgPage2x(0, ((_exReg[0] << 3) | (_exReg[1] & 0x07)) << 1); + MMC3::SelectPrgPage2x(1, ((_exReg[0] << 3) | 0x07) << 1); + } else { + page = (MMC3::_registers[6] >> 2) & 3; + SelectPrgPage4x(0, ((_exReg[0] << 2) | page) << 2); + } + } else { + MMC3::SelectPRGPage(slot, (_exReg[0] << 4) | (page & 0x0F)); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _exReg[0] = (uint8_t)addr; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + if(_exReg[1] != value) { + _exReg[1] = value; + MMC3::UpdatePrgMapping(); + } + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_395.h b/Core/MMC3_395.h new file mode 100644 index 000000000..7f4fcbc1f --- /dev/null +++ b/Core/MMC3_395.h @@ -0,0 +1,53 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_395 : public MMC3 +{ +private: + uint8_t _exReg[2]; + +protected: + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void Reset(bool softreset) override + { + _exReg[0] = _exReg[1] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exReg[0], _exReg[1]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_exReg[1] & 0x40) ? 0x7F: 0xFF; + uint16_t outerBank = ((_exReg[1] << 5) & 0x400) | ((_exReg[0] << 4) & 0x300) | ((_exReg[1] << 3) & 0x80); + MMC3::SelectCHRPage(slot, outerBank | (page & mask)); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_exReg[1] & 0x08) ? 0x0F: 0x1F; + uint8_t outerBank = ((_exReg[0] << 4) & 0x80) | ((_exReg[0] << 1) & 0x60) | ((_exReg[1] << 4) &0x10); + MMC3::SelectPRGPage(slot, outerBank | (page & mask), memoryType); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + WritePrgRam(addr, value); + if(!(_exReg[1] & 0x80)) { + _exReg[(addr >> 4) & 0x01] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_401.h b/Core/MMC3_401.h new file mode 100644 index 000000000..766d524ce --- /dev/null +++ b/Core/MMC3_401.h @@ -0,0 +1,33 @@ +#pragma once +#include "MMC3_45.h" + +class MMC3_401 : public MMC3_45 +{ +private: + uint32_t GetDipSwitchCount() override { return 3; } + bool AllowRegisterRead() override { return true; } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + page &= 0x1F ^ (_reg[3] & 0x1F); // mask + page |= (_reg[2] & 0x80) | _reg[1] & 0x1F; // outerbank + page |= (GetDipSwitches() & 0x02) ? (_reg[2] & 0x20): ((_reg[1] >> 1) & 0x20); // A18 + page |= (GetDipSwitches() & 0x04) ? (_reg[2] & 0x40): ((_reg[1] << 1) & 0x40); // A19 + + if((GetDipSwitches() & 0x01) && (_reg[1] & 0x80)) { + // openbus + } else { + MMC3::SelectPRGPage(slot, page, memoryType); + } + } + + uint8_t ReadRegister(uint16_t addr) override + { + if((addr >= 0x8000) && (addr <= 0xFFFF)) { + if((GetDipSwitches() & 0x01) && (_reg[1] & 0x80)) { + return _console->GetMemoryManager()->GetOpenBus(); + } + } + return InternalReadRam(addr); + } +}; \ No newline at end of file diff --git a/Core/MMC3_410.h b/Core/MMC3_410.h new file mode 100644 index 000000000..aa57085e8 --- /dev/null +++ b/Core/MMC3_410.h @@ -0,0 +1,21 @@ +#pragma once +#include "MMC3_45.h" + +class MMC3_410 : public MMC3_45 +{ +private: + uint16_t GetChrRamPageSize() override { return 0x400; } + uint32_t GetChrRamSize() override { return 0x2000; } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = 0xFF >> (0x0F - (_reg[2] & 0x0F)); + if(_reg[2] & 0x40) { + MMC3::SelectChrPage8x(0, 0, ChrMemoryType::ChrRam); + } else { + page &= mask; + page |= _reg[0] | ((_reg[2] & 0xF0) << 4); + MMC3::SelectCHRPage(slot, page); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_411.h b/Core/MMC3_411.h new file mode 100644 index 000000000..9851de828 --- /dev/null +++ b/Core/MMC3_411.h @@ -0,0 +1,62 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_411 : public MMC3 +{ +private: + uint8_t _exRegs[2]; + +protected: + virtual void InitMapper() override + { + AddRegisterRange(0x5000, 0x5FFF); + MMC3::InitMapper(); + } + + virtual void Reset(bool softreset) override + { + _exRegs[0] = 0x80; + _exRegs[1] = 0x82; + MMC3::UpdateState(); + } + + virtual void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exRegs[0], _exRegs[1]); + } + + virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + page &= (_exRegs[1] & 2) ? 0xFF : 0x7F; + MMC3::SelectCHRPage(slot, ((_exRegs[1] << 5) & 0x80) | ((_exRegs[0] << 4) & 0x100) | page); + } + + virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if (_exRegs[0] & 0x40) { // NROM Mode + uint8_t bank = ((_exRegs[1] >> 2) & 0x10) | (_exRegs[1] & 0x08) | (_exRegs[0] & 0x04) | ((_exRegs[0] >> 2) & 0x02) | (_exRegs[0] & 0x01); + if (_exRegs[0] & 0x02) { // NROM-256 + SelectPrgPage4x(0, (bank & 0xFE) << 1); + } else { // NROM-128 + MMC3::SelectPrgPage2x(0, bank << 1); + MMC3::SelectPrgPage2x(1, bank << 1); + } + } else { // MMC3 Mode + page &= (_exRegs[1] & 2) ? 0x1F : 0x0F; + MMC3::SelectPRGPage(slot, ((_exRegs[1] >> 1) & 0x20) | ((_exRegs[1] << 1) & 0x10) | page); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr <= 0x5FFF) { + _exRegs[addr & 0x01] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_412.h b/Core/MMC3_412.h new file mode 100644 index 000000000..ceb9a610a --- /dev/null +++ b/Core/MMC3_412.h @@ -0,0 +1,72 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_412 : public MMC3 +{ +private: + uint8_t _exRegs[4]; + +protected: + virtual uint16_t RegisterStartAddress() override { return 0x6000; } + virtual uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _exRegs[0] = 0; + _exRegs[1] = 0; + _exRegs[2] = 0; + _exRegs[3] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exRegs[0], _exRegs[1], _exRegs[2], _exRegs[3]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if (_exRegs[2] & 0x02) { + MMC3::SelectChrPage8x(0, _exRegs[0] << 1); + } else { + page &= 0x7F; + MMC3::SelectCHRPage(slot, (_exRegs[1] & 0x80) | page); + } + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if (_exRegs[2] & 0x02) { // NROM Mode + uint8_t bank = (_exRegs[2] >> 3); + if (_exRegs[2] & 0x04) { // NROM-256 + SelectPrgPage4x(0, (bank & 0xFE) << 1); + } else { // NROM-128 + MMC3::SelectPrgPage2x(0, bank << 1); + MMC3::SelectPrgPage2x(1, bank << 1); + } + } else { // MMC3 Mode + uint8_t mask = 0x3F & ~((_exRegs[1] << 3) & 0x38); + page &= mask; + page |= ((_exRegs[1] >> 2) & 0x3E) & ~mask; + MMC3::SelectPRGPage(slot, page); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _exRegs[addr & 0x03] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_430.h b/Core/MMC3_430.h new file mode 100644 index 000000000..f81f48f1c --- /dev/null +++ b/Core/MMC3_430.h @@ -0,0 +1,64 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_430 : public MMC3 +{ +private: + uint8_t _reg; + +protected: + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _reg = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_reg); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + if(_reg & 0x04) { + MMC3::SelectCHRPage(slot, ((_reg << 6) & 0x180) | (page & 0x7F), memoryType); + } else { + MMC3::SelectCHRPage(slot, ((_reg << 6) & 0x100) | (page & 0xFF), memoryType); + } + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if(_reg & 0x08) { + MMC3::SelectPRGPage(0, (_reg << 4) | ((MMC3::_registers[6] & ~0x02) & 0x0F)); + MMC3::SelectPRGPage(1, (_reg << 4) | ((MMC3::_registers[7] & ~0x02) & 0x0F)); + MMC3::SelectPRGPage(2, (_reg << 4) | ((MMC3::_registers[6] | 0x02) & 0x0F)); + MMC3::SelectPRGPage(3, (_reg << 4) | ((MMC3::_registers[7] | 0x02) & 0x0F)); + } else { + MMC3::SelectPRGPage(slot, (_reg << 4) | (page & 0x0F)); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(MMC3::CanWriteToWorkRam()) { + _reg = (uint8_t)addr; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_432.h b/Core/MMC3_432.h new file mode 100644 index 000000000..e36abf659 --- /dev/null +++ b/Core/MMC3_432.h @@ -0,0 +1,77 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_432 : public MMC3 +{ +private: + uint8_t _exRegs[2]; + +protected: + uint32_t GetDipSwitchCount() override { return 2; } + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + bool AllowRegisterRead() override { return true; } + + void InitMapper() override + { + RemoveRegisterRange(0x6000, 0x7FFF, MemoryOperation::Read); + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _exRegs[0] = 0; + _exRegs[1] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exRegs[0], _exRegs[1]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_exRegs[1] & 0x04) ? 0x7F : 0xFF; + page &= mask; + page |= (((_exRegs[1] << 5) & 0x100) | ((_exRegs[1] << 7) & 0x80)) & ~mask; + MMC3::SelectCHRPage(slot, page, memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_exRegs[1] & 0x02) ? 0x0F : 0x1F; + uint8_t outerBank = ((_exRegs[1] << 1) & 0x20) | ((_exRegs[1] << 4) & 0x10); + if(_exRegs[1] & 0x40) { + MMC3::SelectPRGPage(0, (outerBank & ~mask) | (MMC3::_registers[6] & mask), memoryType); + MMC3::SelectPRGPage(1, (outerBank & ~mask) | (MMC3::_registers[7] & mask), memoryType); + MMC3::SelectPRGPage(2, (outerBank & ~mask) | (MMC3::_registers[6] & mask), memoryType); + MMC3::SelectPRGPage(3, (outerBank & ~mask) | (MMC3::_registers[7] & mask), memoryType); + } else { + MMC3::SelectPRGPage(slot, (outerBank & ~mask) | (page & mask), memoryType); + } + } + + uint8_t ReadRegister(uint16_t addr) override + { + if(_exRegs[0] & 0x01) { + return GetDipSwitches(); + } + return InternalReadRam(addr); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(MMC3::CanWriteToWorkRam()) { + _exRegs[addr & 0x01] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_441.h b/Core/MMC3_441.h new file mode 100644 index 000000000..954af8f96 --- /dev/null +++ b/Core/MMC3_441.h @@ -0,0 +1,67 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_441 : public MMC3 +{ +private: + uint8_t _reg; + +protected: + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _reg = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_reg); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_reg & 0x40) ? 0x7F : 0xFF; + page &= mask; + page |= ((_reg << 3) & 0x180) & ~mask; + MMC3::SelectCHRPage(slot, page, memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_reg & 0x08) ? 0x0F: 0x1F; + uint8_t outerBank = (_reg << 4) & 0x30; + if(_reg & 0x04) { + MMC3::SelectPRGPage(0, (outerBank & ~mask) | ((MMC3::_registers[6] & ~0x02) & mask)); + MMC3::SelectPRGPage(1, (outerBank & ~mask) | ((MMC3::_registers[7] & ~0x02) & mask)); + MMC3::SelectPRGPage(2, (outerBank & ~mask) | ((MMC3::_registers[6] | 0x02) & mask)); + MMC3::SelectPRGPage(3, (outerBank & ~mask) | ((MMC3::_registers[7] | 0x02) & mask)); + } else { + MMC3::SelectPRGPage(slot, (outerBank & ~mask) | (page & mask)); + } + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(MMC3::CanWriteToWorkRam()) { + if(!(_reg & 0x80)) { + _reg = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_444.h b/Core/MMC3_444.h new file mode 100644 index 000000000..6da5848ac --- /dev/null +++ b/Core/MMC3_444.h @@ -0,0 +1,82 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +// NES 2.0 Mapper 444 denotes the NC7000M multicart circuit board. +// Its UNIF board name is BMC-BS-110, which is the name of a different PCB whose name was mixed-up. + +class MMC3_444 : public MMC3 +{ +private: + uint8_t _exRegs; + +protected: + uint32_t GetDipSwitchCount() override { return 2; } + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + bool AllowRegisterRead() override { return true; } + + void InitMapper() override + { + RemoveRegisterRange(0x6000, 0x7FFF, MemoryOperation::Read); + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _exRegs = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_exRegs); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_romInfo.SubMapperID & 0x01) ? 0xFF : 0x7F; + uint16_t outerBank = (_exRegs << 7) & ((_romInfo.SubMapperID & 0x01) ? 0x00 : 0x80); // A17 + outerBank |= ((_exRegs << ((_romInfo.SubMapperID & 0x02) ? 4 : 7)) & 0x100); // A18 + MMC3::SelectCHRPage(slot, (outerBank & ~mask) | (page & mask), memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + if(_exRegs & 0x04) { + page = (_exRegs << 4) | (MMC3::_registers[6] & 0x0F); + if(_exRegs & 0x08) { + page &= 0xFE; + MMC3::SelectPrgPage2x(0, page, memoryType); + MMC3::SelectPrgPage2x(1, page, memoryType); + } else { + page &= 0xFC; + MMC3::SelectPrgPage4x(0, page, memoryType); + } + } else { + MMC3::SelectPRGPage(slot, (_exRegs << 4) | (page & 0x0F), memoryType); + } + } + + uint8_t ReadRegister(uint16_t addr) override + { + if((_exRegs & 0x0C) == 0x08) { + return GetDipSwitches(); + } + return InternalReadRam(addr); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + /*if(MMC3::CanWriteToWorkRam()) */{ + _exRegs = (uint8_t)addr; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_445.h b/Core/MMC3_445.h new file mode 100644 index 000000000..3dfbc196e --- /dev/null +++ b/Core/MMC3_445.h @@ -0,0 +1,56 @@ +#pragma once +#include "stdafx.h" +#include "MMC3.h" + +class MMC3_445 : public MMC3 +{ +private: + uint8_t _reg[4]; + +protected: + + void InitMapper() override + { + AddRegisterRange(0x5000, 0x5FFF); + MMC3::InitMapper(); + } + + void Reset(bool softreset) override + { + _reg[0] = _reg[1] = _reg[2] = _reg[3] = 0; + MMC3::UpdateState(); + } + + void StreamState(bool saving) override + { + MMC3::StreamState(saving); + Stream(_reg[0], _reg[1], _reg[2], _reg[3]); + } + + void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override + { + uint8_t mask = (_reg[2] & 0x08) ? 0x7F : 0xFF; + MMC3::SelectCHRPage(slot, ((_reg[1] << 3) & ~mask) | (page & mask), memoryType); + } + + void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override + { + uint8_t mask = (_reg[2] & 0x01) ? 0x0F: 0x1F; + MMC3::SelectPRGPage(slot, (_reg[0] & ~mask) | (page & mask), memoryType); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + if(MMC3::CanWriteToWorkRam()) { + if(!(_reg[3] & 0x20)) { + _reg[addr & 0x03] = value; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); + } + } + } else { + MMC3::WriteRegister(addr, value); + } + } +}; \ No newline at end of file diff --git a/Core/MMC3_45.h b/Core/MMC3_45.h index 5f64adbc0..197bac2d8 100644 --- a/Core/MMC3_45.h +++ b/Core/MMC3_45.h @@ -6,24 +6,16 @@ class MMC3_45 : public MMC3 { private: uint8_t _regIndex; - uint8_t _reg[4]; protected: - virtual uint16_t RegisterStartAddress() override { return 0x8000; } + uint8_t _reg[4]; + + virtual uint16_t RegisterStartAddress() override { return 0x6000; } virtual uint16_t RegisterEndAddress() override { return 0xFFFF; } virtual void InitMapper() override { MMC3::InitMapper(); - - //Needed by Famicom Yarou Vol 1 - Game apparently writes to CHR RAM before initializing the registers - _registers[0] = 0; - _registers[1] = 2; - _registers[2] = 4; - _registers[3] = 5; - _registers[4] = 6; - _registers[5] = 7; - UpdateChrMapping(); } virtual void StreamState(bool saving) override @@ -31,26 +23,24 @@ class MMC3_45 : public MMC3 MMC3::StreamState(saving); ArrayInfo reg = { _reg, 4 }; Stream(_regIndex, reg); - - if(_reg[3] & 0x40) { - RemoveRegisterRange(0x6000, 0x7FFF); - } } virtual void Reset(bool softReset) override { - AddRegisterRange(0x6000, 0x7FFF); _regIndex = 0; - memset(_reg, 0, sizeof(_reg)); + _reg[0] = 0x00; + _reg[1] = 0x00; _reg[2] = 0x0F; + _reg[3] = 0x00; UpdateState(); } virtual void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override { + uint8_t mask = 0xFF >> (0x0F - (_reg[2] & 0x0F)); if(!HasChrRam()) { - page &= 0xFF >> (0x0F - (_reg[2] & 0x0F)); - page |= _reg[0] | ((_reg[2] & 0xF0) << 4); + page &= mask; + page |= ((_reg[0] | ((_reg[2] & 0xF0) << 4)) & ~mask); } MMC3::SelectCHRPage(slot, page, memoryType); } @@ -58,22 +48,20 @@ class MMC3_45 : public MMC3 virtual void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override { page &= 0x3F ^ (_reg[3] & 0x3F); - page |= _reg[1]; + page |= ((_reg[2] << 2) & 0x300) | _reg[1]; MMC3::SelectPRGPage(slot, page, memoryType); } void WriteRegister(uint16_t addr, uint8_t value) override { if(addr < 0x8000) { + WritePrgRam(addr, value); if(!(_reg[3] & 0x40)) { _reg[_regIndex] = value; _regIndex = (_regIndex + 1) & 0x03; + MMC3::UpdatePrgMapping(); + MMC3::UpdateChrMapping(); } - - if(_reg[3] & 0x40) { - RemoveRegisterRange(0x6000, 0x7FFF); - } - UpdateState(); } else { MMC3::WriteRegister(addr, value); } diff --git a/Core/Mapper227.h b/Core/Mapper227.h index 748233f06..6ce2516a7 100644 --- a/Core/Mapper227.h +++ b/Core/Mapper227.h @@ -4,20 +4,44 @@ class Mapper227 : public BaseMapper { protected: + uint32_t GetDipSwitchCount() override { return 4; } uint16_t GetPRGPageSize() override { return 0x4000; } uint16_t GetCHRPageSize() override { return 0x2000; } + bool AllowRegisterRead() override { return true; } + + bool _mFlag; void InitMapper() override { WriteRegister(0x8000, 0); } + void Reset(bool softreset) override + { + WriteRegister(0x8000, 0); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_mFlag); + } + + uint8_t ReadRegister(uint16_t addr) override + { + if(_mFlag) { + addr |= GetDipSwitches(); + } + return InternalReadRam(addr); + } + void WriteRegister(uint16_t addr, uint8_t value) override { uint16_t prgBank = ((addr >> 2) & 0x1F) | ((addr & 0x100) >> 3); bool sFlag = (addr & 0x01) == 0x01; bool lFlag = ((addr >> 9) & 0x01) == 0x01; bool prgMode = ((addr >> 7) & 0x01) == 0x01; + _mFlag = ((addr >> 10) & 0x01) == 0x01; if(prgMode) { if(sFlag) { @@ -46,6 +70,9 @@ class Mapper227 : public BaseMapper } } + // protect CHR-RAM on nrom modes + SetPpuMemoryMapping(0, 0x1FFF, 0, ChrMemoryType::Default, (!HasBattery() && prgMode) ? MemoryAccessType::Read : MemoryAccessType::ReadWrite); + SetMirroringType((addr & 0x02) == 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); } }; \ No newline at end of file diff --git a/Core/Mapper242.h b/Core/Mapper242.h index de8279a49..af960f5fd 100644 --- a/Core/Mapper242.h +++ b/Core/Mapper242.h @@ -1,28 +1,69 @@ -#pragma once -#include "stdafx.h" +#pragma once #include "BaseMapper.h" class Mapper242 : public BaseMapper { protected: - virtual uint16_t GetPRGPageSize() override { return 0x8000; } - virtual uint16_t GetCHRPageSize() override { return 0x2000; } + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } void InitMapper() override { - Reset(false); - SelectCHRPage(0, 0); + WriteRegister(0x8000, 0); } - virtual void Reset(bool softReset) override + void Reset(bool softreset) override { - SelectPRGPage(0, 0); - SetMirroringType(MirroringType::Vertical); + WriteRegister(0x8000, 0); } void WriteRegister(uint16_t addr, uint8_t value) override { - SetMirroringType(addr & 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); - SelectPRGPage(0, (addr >> 3) & 0x0F); + uint16_t prgBank = (addr >> 2) & 0x1F; + bool sFlag = (addr & 0x01) == 0x01; + bool lFlag = ((addr >> 9) & 0x01) == 0x01; + bool prgMode = ((addr >> 7) & 0x01) == 0x01; + bool cFlag = ((addr >> 10) & 0x01) == 0x01; + bool twoChips = (_prgSize & 0x20000) && (_prgSize > 0x20000); + + if(twoChips) { + if(cFlag | lFlag) { + prgBank &= 0x1F; + } else { + prgBank = 0x20 + (prgBank & 0x07); + } + } + + if(prgMode) { + if(sFlag) { + SelectPrgPage2x(0, prgBank & 0xFE); + } else { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank); + } + } else { + if(sFlag){ + if(lFlag) { + SelectPRGPage(0, prgBank & 0x3E); + SelectPRGPage(1, prgBank | 0x07); + } else { + SelectPRGPage(0, prgBank & 0x3E); + SelectPRGPage(1, prgBank & 0x38); + } + } else { + if(lFlag) { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank | 0x07); + } else { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank & 0x38); + } + } + } + + // protect CHR-RAM on nrom modes + SetPpuMemoryMapping(0, 0x1FFF, 0, ChrMemoryType::Default, (!HasBattery() && prgMode && (_prgSize > 256 * 1024)) ? MemoryAccessType::Read : MemoryAccessType::ReadWrite); + + SetMirroringType((addr & 0x02) == 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); } }; \ No newline at end of file diff --git a/Core/Mapper319.h b/Core/Mapper319.h new file mode 100644 index 000000000..a39e8d3e7 --- /dev/null +++ b/Core/Mapper319.h @@ -0,0 +1,51 @@ +#pragma once +#include "stdafx.h" +#include "BaseMapper.h" + +class Mapper319 : public BaseMapper +{ +private: + uint8_t _regs[3]; + +protected: + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + uint16_t RegisterStartAddress() override { return 0x6000; } + uint16_t RegisterEndAddress() override { return 0xFFFF; } + + void InitMapper() override + { + _regs[0] = _regs[1] = _regs[2] = 0; + UpdateState(); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_regs[0], _regs[1], _regs[2]); + } + + void UpdateState() + { + if(_regs[1] & 0x40) { + SelectPrgPage2x(0, (_regs[1] >> 2) & 0xE); + } else { + uint8_t bank = (_regs[1] >> 2) & 0x06 | (_regs[1] >> 5) & 0x01; + SelectPRGPage(0, bank); + SelectPRGPage(1, bank); + } + SelectCHRPage(0, (_regs[0] >> 4) & ~((_regs[0] << 2) & 0x04) | (_regs[2] << 2) & ((_regs[0] << 2) & 0x04)); + SetMirroringType(_regs[1] & 0x80 ? MirroringType::Vertical : MirroringType::Horizontal); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(addr < 0x8000) { + _regs[(addr & 0x04) >> 2] = value; + UpdateState(); + } else { + _regs[2] = value; + UpdateState(); + } + } +}; \ No newline at end of file diff --git a/Core/Mapper375.h b/Core/Mapper375.h new file mode 100644 index 000000000..f15636f58 --- /dev/null +++ b/Core/Mapper375.h @@ -0,0 +1,78 @@ +#pragma once +#include "BaseMapper.h" + +class Mapper375 : public BaseMapper +{ +protected: + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + + uint16_t latchea; + uint8_t latched; + + void InitMapper() override + { + WriteRegister(0x8000, 0); + } + + virtual void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(latchea, latched); + } + + void UpdateState() + { + uint16_t prgBank = ((latchea >> 2) & 0x1F) | ((latchea >> 3) & 0x20) | ((latchea >> 4) & 0x40); + bool sFlag = (latchea & 0x01) == 0x01; + bool lFlag = ((latchea >> 9) & 0x01) == 0x01; + bool prgMode = ((latchea >> 7) & 0x01) == 0x01; + uint16_t p0 = prgBank; + + if((latchea & 0x800) == 0x800) + p0 = (prgBank & ~0x07) | (latched & 0x07); + + if (prgMode) { + if (sFlag) { + SelectPrgPage2x(0, prgBank & 0xFE); + } else { + SelectPRGPage(0, p0); + SelectPRGPage(1, prgBank); + } + } else { + if (sFlag) { + if (lFlag) { + SelectPRGPage(0, p0 & 0x7E); + SelectPRGPage(1, prgBank | 0x07); + } else { + SelectPRGPage(0, p0 & 0x7E); + SelectPRGPage(1, prgBank & 0x78); + } + } else { + if (lFlag) { + SelectPRGPage(0, p0); + SelectPRGPage(1, prgBank | 0x07); + } else { + SelectPRGPage(0, p0); + SelectPRGPage(1, prgBank & 0x78); + } + } + } + + // protect CHR-RAM on nrom modes + SetPpuMemoryMapping(0, 0x1FFF, 0, ChrMemoryType::Default, (latchea & 0x80) ? MemoryAccessType::Read : MemoryAccessType::ReadWrite); + + SetMirroringType((latchea & 0x02) == 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + if(latchea & 0x800) { + latched = value; + } else { + latchea = addr; + latched = value; + } + UpdateState(); + } +}; \ No newline at end of file diff --git a/Core/Mapper380.h b/Core/Mapper380.h new file mode 100644 index 000000000..c4337526a --- /dev/null +++ b/Core/Mapper380.h @@ -0,0 +1,63 @@ +#pragma once +#include "BaseMapper.h" + +class Mapper380 : public BaseMapper +{ +protected: + uint32_t GetDipSwitchCount() override { return 4; } + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + bool AllowRegisterRead() override { return true; } + + bool _mFlag; + + void InitMapper() override + { + WriteRegister(0x8000, 0); + } + + void Reset(bool softreset) override + { + WriteRegister(0x8000, 0); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_mFlag); + } + + uint8_t ReadRegister(uint16_t addr) override + { + if(_mFlag && _romInfo.SubMapperID == 0) { + addr |= GetDipSwitches(); + } + return InternalReadRam(addr); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + uint16_t prgBank = (addr >> 2) & 0x1F; + bool sFlag = (addr & 0x01) == 0x01; + bool prgMode = ((addr >> 9) & 0x01) == 0x01; + + _mFlag = ((addr >> 8) & 0x01) == 0x01; + + if (prgMode) { + if (sFlag) { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank); + } else { + SelectPrgPage2x(0, prgBank & 0xFE); + } + } else { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank | 0x07 | (((_romInfo.SubMapperID == 1) && (addr & 0x100)) ? 0x08: 0x00)); + } + + // protect CHR-RAM on nrom modes + SetPpuMemoryMapping(0, 0x1FFF, 0, ChrMemoryType::Default, (addr & 0x80) ? MemoryAccessType::Read : MemoryAccessType::ReadWrite); + + SetMirroringType((addr & 0x02) == 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); + } +}; \ No newline at end of file diff --git a/Core/Mapper449.h b/Core/Mapper449.h new file mode 100644 index 000000000..e7d5f724f --- /dev/null +++ b/Core/Mapper449.h @@ -0,0 +1,66 @@ +#pragma once +#include "BaseMapper.h" + +class Mapper449 : public BaseMapper +{ +protected: + uint32_t GetDipSwitchCount() override { return 4; } + uint16_t GetPRGPageSize() override { return 0x4000; } + uint16_t GetCHRPageSize() override { return 0x2000; } + bool AllowRegisterRead() override { return true; } + + bool _mFlag; + + void InitMapper() override + { + WriteRegister(0x8000, 0); + } + + void Reset(bool softreset) override + { + WriteRegister(0x8000, 0); + } + + void StreamState(bool saving) override + { + BaseMapper::StreamState(saving); + Stream(_mFlag); + } + + uint8_t ReadRegister(uint16_t addr) override + { + if(_mFlag) { + addr |= GetDipSwitches(); + } + return InternalReadRam(addr); + } + + void WriteRegister(uint16_t addr, uint8_t value) override + { + uint16_t prgBank = ((addr >> 2) & 0x1F) | ((addr >> 3) & 0x20); + bool sFlag = (addr & 0x01) == 0x01; + bool lFlag = ((addr >> 9) & 0x01) == 0x01; + bool prgMode = ((addr >> 7) & 0x01) == 0x01; + + _mFlag = ((addr >> 9) & 0x01) == 0x01; + + if(prgMode) { + if(sFlag) { + SelectPrgPage2x(0, prgBank & 0xFE); + } else { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank); + } + } else { + SelectPRGPage(0, prgBank); + SelectPRGPage(1, prgBank | 0x07); + } + + // protect CHR-RAM on nrom modes + SetPpuMemoryMapping(0, 0x1FFF, 0, ChrMemoryType::Default, (!HasBattery() && prgMode) ? MemoryAccessType::Read : MemoryAccessType::ReadWrite); + + SelectCHRPage(0, value); + + SetMirroringType((addr & 0x02) == 0x02 ? MirroringType::Horizontal : MirroringType::Vertical); + } +}; \ No newline at end of file diff --git a/Core/Mapper91.h b/Core/Mapper91.h index 0cffdbcb2..17932d405 100644 --- a/Core/Mapper91.h +++ b/Core/Mapper91.h @@ -6,39 +6,100 @@ class Mapper91 : public MMC3 { protected: virtual uint16_t RegisterStartAddress() override { return 0x6000; } - virtual uint16_t RegisterEndAddress() override { return 0x7FFF; } + virtual uint16_t RegisterEndAddress() override { return 0x9FFF; } virtual uint16_t GetPRGPageSize() override { return 0x2000; } virtual uint16_t GetCHRPageSize() override { return 0x800; } + uint8_t _prgBanks[2]; + uint8_t _chrBanks[4]; + uint8_t _outerBank; + + // for Submapper 1 + bool _verticalMirroring; + void InitMapper() override { - SelectPRGPage(2, -2); - SelectPRGPage(3, -1); + UpdateState(); } - void UpdateState() override + void UpdateState() { - //Do nothing, we are only using MMC3 code to emulate the IRQs + SelectPRGPage(0, ((_outerBank << 3) & 0x30) | (_prgBanks[0] & 0x0F)); + SelectPRGPage(1, ((_outerBank << 3) & 0x30) | (_prgBanks[1] & 0x0F)); + SelectPRGPage(2, ((_outerBank << 3) & 0x30) | 0xE); + SelectPRGPage(3, ((_outerBank << 3) & 0x30) | 0xF); + + SelectCHRPage(0, ((_outerBank << 8) & 0x100) | _chrBanks[0]); + SelectCHRPage(1, ((_outerBank << 8) & 0x100) | _chrBanks[1]); + SelectCHRPage(2, ((_outerBank << 8) & 0x100) | _chrBanks[2]); + SelectCHRPage(3, ((_outerBank << 8) & 0x100) | _chrBanks[3]); + + if(_romInfo.SubMapperID == 1) { + SetMirroringType(_verticalMirroring ? MirroringType::Vertical : MirroringType::Horizontal); + } } void WriteRegister(uint16_t addr, uint8_t value) override { - switch(addr & 0x7003) { - case 0x6000: SelectCHRPage(0, value); break; - case 0x6001: SelectCHRPage(1, value); break; - case 0x6002: SelectCHRPage(2, value); break; - case 0x6003: SelectCHRPage(3, value); break; - case 0x7000: SelectPRGPage(0, value & 0x0F); break; - case 0x7001: SelectPRGPage(1, value & 0x0F); break; - case 0x7002: - MMC3::WriteRegister(0xE000, value); - break; - case 0x7003: - MMC3::WriteRegister(0xC000, 0x07); - MMC3::WriteRegister(0xC001, value); - MMC3::WriteRegister(0xE001, value); - break; + if(addr <= 0x6FFF) { + if(_romInfo.SubMapperID == 1) { + switch(addr & 0x07) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + _chrBanks[addr & 0x03] = value; + UpdateState(); + return; + + case 0x04: + case 0x05: + _verticalMirroring = (addr & 0x01) == 0x01; + UpdateState(); + return; + + case 0x06: + return; + + case 0x07: + return; + + default: + return; + } + } else { + _chrBanks[addr & 0x03] = value; + UpdateState(); + return; + } } + + if(addr <= 0x7FFF) { + switch(addr & 0x03) { + case 0x00: + case 0x01: + _prgBanks[addr & 0x01] = value; + UpdateState(); + return; + + case 0x02: + MMC3::WriteRegister(0xE000, value); + return; + + case 0x03: + MMC3::WriteRegister(0xC000, 0x07); + MMC3::WriteRegister(0xC001, value); + MMC3::WriteRegister(0xE001, value); + return; + + default: + return; + + } + } + + _outerBank = (uint8_t)addr; + UpdateState(); } }; \ No newline at end of file diff --git a/Core/MapperFactory.cpp b/Core/MapperFactory.cpp index f46b49316..4391a4f20 100644 --- a/Core/MapperFactory.cpp +++ b/Core/MapperFactory.cpp @@ -157,6 +157,10 @@ #include "Mapper244.h" #include "Mapper246.h" #include "Mapper253.h" +#include "Mapper319.h" +#include "Mapper375.h" +#include "Mapper380.h" +#include "Mapper449.h" #include "McAcc.h" #include "MMC1.h" #include "MMC1_105.h" @@ -195,7 +199,28 @@ #include "MMC3_249.h" #include "MMC3_250.h" #include "MMC3_254.h" +#include "MMC3_267.h" +#include "MMC3_334.h" +#include "MMC3_353.h" +#include "MMC3_364.h" +#include "MMC3_370.h" +#include "MMC3_372.h" +#include "MMC3_376.h" +#include "MMC3_377.h" +#include "MMC3_383.h" +#include "MMC3_391.h" +#include "MMC3_393.h" +#include "MMC3_395.h" +#include "MMC3_401.h" +#include "MMC3_410.h" +#include "MMC3_411.h" +#include "MMC3_412.h" #include "MMC3_422.h" +#include "MMC3_430.h" +#include "MMC3_432.h" +#include "MMC3_441.h" +#include "MMC3_444.h" +#include "MMC3_445.h" #include "MMC3_534.h" #include "MMC3_Bmc411120C.h" #include "MMC3_BmcF15.h" @@ -387,6 +412,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 52: return new MMC3_52(); case 53: return new Supervision(); case 54: return new NovelDiamond(); + case 55: return new Malee(); case 56: return new Kaiser202(); case 57: return new Mapper57(); case 58: return new Mapper58(); @@ -577,7 +603,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 264: return new Yoko(); case 265: return new T262(); case 266: return new CityFighter(); - //267 + case 267: return new MMC3_267(); case 268: if(romData.Info.BoardName.compare("MINDKIDS") == 0) { romData.Info.SubMapperID = 1; @@ -619,7 +645,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 314: return new Bmc64in1NoRepeat(); case 315: return new Bmc830134C(); //316-318 - case 319: return new Hp898f(); + case 319: return new Mapper319(); case 320: return new Bmc830425C4391T(); //321 case 322: return new MMC3_BmcK3033(); @@ -633,7 +659,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 331: return new Bmc12in1(); case 332: return new Super40in1Ws(); case 333: return new Bmc8in1(); // + NEWSTAR-GRM070-8IN1 - //334 + case 334: return new MMC3_334(); case 335: return new BmcCtc09(); case 336: return new BmcK3046(); case 337: return new BmcCtc12in1(); @@ -651,11 +677,39 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case 349: return new BmcG146(); case 350: return new Bmc891227(); //352: + case 353: return new MMC3_353(); + case 364: return new MMC3_364(); case 366: return new BmcGn45(); + case 370: return new MMC3_370(); + case 372: return new MMC3_372(); + case 375: return new Mapper375(); + case 376: return new MMC3_376(); + case 377: return new MMC3_377(); + //378-379 + case 380: return new Mapper380(); + //381-382 + case 383: return new MMC3_383(); + //384-390 + case 391: return new MMC3_391(); + case 393: return new MMC3_393(); + //394 + case 395: return new MMC3_395(); + //396-400 + case 401: return new MMC3_401(); + case 410: return new MMC3_410(); + case 411: return new MMC3_411(); + case 412: return new MMC3_412(); case 422: return new MMC3_422(); + case 430: return new MMC3_430(); + case 432: return new MMC3_432(); case 434: return new BmcS2009(); + case 441: return new MMC3_441(); + case 444: return new MMC3_444(); + case 445: return new MMC3_445(); + case 449: return new Mapper449(); + case 513: return new Sachen9602(); //514-517 case 518: return new Dance2000(); @@ -676,13 +730,13 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData) case UnifBoards::Ac08: return new Ac08(); //mapper 42? case UnifBoards::Cc21: return new Cc21(); case UnifBoards::Ghostbusters63in1: return new Ghostbusters63in1(); //mapper 226? - case UnifBoards::Malee: return new Malee(); //mapper 42? case UnifBoards::SssNrom256: return new FamicomBox(); case UnifBoards::Unl255in1: return new Unl255in1(); case UnifBoards::Unl8237A: return new Unl8237A(); //mapper 215.1 case UnifBoards::UnlPuzzle: return new UnlPuzzle(); case UnifBoards::Ks106C: return new UnlKs106C(); //mapper 352, sub 1 case UnifBoards::ResetNromX1n1: return new BmcResetNromX1n1(); //352 + case UnifBoards::Hp898f: return new Hp898f(); // Mapper 319 with the differentt bank order, specific for UNIF dump of Prima Soft 9999999-in-1 case MapperFactory::StudyBoxMapperID: return new StudyBox(); case MapperFactory::NsfMapperID: return new NsfMapper(); diff --git a/Core/UnifBoards.h b/Core/UnifBoards.h index 2d1636db7..a750fe3c2 100644 --- a/Core/UnifBoards.h +++ b/Core/UnifBoards.h @@ -20,5 +20,6 @@ namespace UnifBoards { SssNrom256, Ks106C, ResetNromX1n1, + Hp898f, }; } \ No newline at end of file diff --git a/Core/UnifLoader.cpp b/Core/UnifLoader.cpp index f0f2ed6aa..787a02f8a 100644 --- a/Core/UnifLoader.cpp +++ b/Core/UnifLoader.cpp @@ -73,7 +73,7 @@ std::unordered_map UnifLoader::_boardMappings = std::unordered_map< { "LH51", 309 }, { "LH53", UnifBoards::UnknownBoard }, { "MALISB", 325 }, - { "MARIO1-MALEE2", UnifBoards::Malee }, + { "MARIO1-MALEE2", 55 }, { "MHROM", 66 }, { "N625092", 221 }, { "NROM", 0 }, @@ -154,7 +154,7 @@ std::unordered_map UnifLoader::_boardMappings = std::unordered_map< { "158B", 258 }, { "DRAGONFIGHTER", 292 }, { "EH8813A", 519 }, - { "HP898F", 319 }, + { "HP898F", UnifBoards::Hp898f }, { "F-15", 259 }, { "RT-01", 328 }, { "81-01-31-C", UnifBoards::UnknownBoard }, @@ -196,4 +196,5 @@ std::unordered_map UnifLoader::_boardMappings = std::unordered_map< { "BS-5652", 134 }, { "891227", 350 }, { "CTC-12IN1", 337 }, + { "BS-110", 444 }, }; \ No newline at end of file