FK23C: Reimplemented from scratch based on NewRisingSun's research
+Removed duplicate implementations as other mappers
This commit is contained in:
parent
f6bef8b116
commit
bdd4d826dc
8 changed files with 389 additions and 289 deletions
|
@ -649,7 +649,7 @@
|
|||
<ClInclude Include="DebugBreakHelper.h" />
|
||||
<ClInclude Include="DebuggerTypes.h" />
|
||||
<ClInclude Include="Eh8813A.h" />
|
||||
<ClInclude Include="MMC3_Fk23C.h" />
|
||||
<ClInclude Include="Fk23C.h" />
|
||||
<ClInclude Include="LabelManager.h" />
|
||||
<ClInclude Include="MagicKidGooGoo.h" />
|
||||
<ClInclude Include="MemoryAccessCounter.h" />
|
||||
|
@ -895,7 +895,6 @@
|
|||
<ClInclude Include="Sunsoft89.h" />
|
||||
<ClInclude Include="Sunsoft93.h" />
|
||||
<ClInclude Include="SunsoftFme7.h" />
|
||||
<ClInclude Include="MMC3_Super24in1Sc03.h" />
|
||||
<ClInclude Include="Super40in1Ws.h" />
|
||||
<ClInclude Include="Supervision.h" />
|
||||
<ClInclude Include="T262.h" />
|
||||
|
@ -948,7 +947,6 @@
|
|||
<ClInclude Include="VsZapper.h" />
|
||||
<ClInclude Include="Waixing162.h" />
|
||||
<ClInclude Include="Waixing164.h" />
|
||||
<ClInclude Include="Waixing176.h" />
|
||||
<ClInclude Include="Waixing178.h" />
|
||||
<ClInclude Include="Waixing252.h" />
|
||||
<ClInclude Include="WaveRecorder.h" />
|
||||
|
|
|
@ -718,9 +718,6 @@
|
|||
<ClInclude Include="Waixing252.h">
|
||||
<Filter>Nes\Mappers\Waixing</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Waixing176.h">
|
||||
<Filter>Nes\Mappers\Waixing</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Waixing164.h">
|
||||
<Filter>Nes\Mappers\Waixing</Filter>
|
||||
</ClInclude>
|
||||
|
@ -997,9 +994,6 @@
|
|||
<ClInclude Include="Ax5705.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MMC3_Super24in1Sc03.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Super40in1Ws.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1117,9 +1111,6 @@
|
|||
<ClInclude Include="UnlPuzzle.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MMC3_Fk23C.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Unl255in1.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1471,6 +1462,9 @@
|
|||
<ClInclude Include="HistoryViewer.h">
|
||||
<Filter>Rewinder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Fk23C.h">
|
||||
<Filter>Nes\Mappers\Unif</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StereoCombFilter.h">
|
||||
<Filter>Nes\APU\Filters</Filter>
|
||||
</ClInclude>
|
||||
|
|
380
Core/Fk23C.h
Normal file
380
Core/Fk23C.h
Normal file
|
@ -0,0 +1,380 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "BaseMapper.h"
|
||||
|
||||
class Fk23C : public BaseMapper
|
||||
{
|
||||
private:
|
||||
uint8_t _prgBankingMode;
|
||||
uint8_t _outerChrBankSize;
|
||||
bool _selectChrRam;
|
||||
bool _mmc3ChrMode;
|
||||
bool _cnromChrMode;
|
||||
uint16_t _prgBaseBits;
|
||||
uint8_t _chrBaseBits;
|
||||
bool _extendedMmc3Mode;
|
||||
uint8_t _wramBankSelect;
|
||||
bool _ramInFirstChrBank;
|
||||
bool _allowSingleScreenMirroring;
|
||||
bool _fk23RegistersEnabled;
|
||||
bool _wramConfigEnabled;
|
||||
|
||||
bool _wramEnabled;
|
||||
bool _wramWriteProtected;
|
||||
|
||||
bool _invertPrgA14;
|
||||
bool _invertChrA12;
|
||||
|
||||
uint8_t _currentRegister;
|
||||
|
||||
uint8_t _irqReloadValue;
|
||||
uint8_t _irqCounter;
|
||||
bool _irqReload;
|
||||
bool _irqEnabled;
|
||||
|
||||
uint8_t _mirroringReg;
|
||||
|
||||
uint8_t _cnromChrReg;
|
||||
uint8_t _mmc3Registers[12];
|
||||
|
||||
uint8_t _irqDelay;
|
||||
A12Watcher _a12Watcher;
|
||||
|
||||
protected:
|
||||
uint16_t GetPRGPageSize() override { return 0x2000; }
|
||||
uint16_t GetCHRPageSize() override { return 0x0400; }
|
||||
|
||||
uint32_t GetChrRamSize() override { return 0x20000; } //only used for iNES 1.0 files w/ no DB entry
|
||||
uint16_t GetChrRamPageSize() override { return 0x400; }
|
||||
|
||||
uint32_t GetWorkRamSize() override { return 0x8000; } //only used for iNES 1.0 files w/ no DB entry
|
||||
uint32_t GetWorkRamPageSize() override { return 0x2000; }
|
||||
|
||||
void InitMapper() override
|
||||
{
|
||||
//$5000
|
||||
_prgBankingMode = 0;
|
||||
_outerChrBankSize = 0;
|
||||
_selectChrRam = false;
|
||||
_mmc3ChrMode = true;
|
||||
|
||||
//$5001 (mostly)
|
||||
//Subtype 1, 1024 KiB PRG-ROM, 1024 KiB CHR-ROM: boot in second 512 KiB of PRG-ROM.
|
||||
_prgBaseBits = (_prgSize == 1024*1024 && _prgSize == _chrRomSize) ? 0x20 : 0;
|
||||
|
||||
//$5002
|
||||
_chrBaseBits = 0;
|
||||
|
||||
//$5003
|
||||
_extendedMmc3Mode = false;
|
||||
_cnromChrMode = false;
|
||||
|
||||
//$A001
|
||||
_wramBankSelect = 0;
|
||||
_ramInFirstChrBank = false;
|
||||
_allowSingleScreenMirroring = false;
|
||||
_wramConfigEnabled = false;
|
||||
_fk23RegistersEnabled = false;
|
||||
_wramEnabled = false;
|
||||
_wramWriteProtected = false;
|
||||
|
||||
_currentRegister = 0;
|
||||
|
||||
_cnromChrReg = 0;
|
||||
|
||||
constexpr uint8_t initValues[12] = { 0,2,4,5,6,7,0,1,0xFE, 0xFF, 0xFF, 0xFF };
|
||||
for(int i = 0; i < 12; i++) {
|
||||
_mmc3Registers[i] = initValues[i];
|
||||
}
|
||||
|
||||
_invertPrgA14 = false;
|
||||
_invertChrA12 = false;
|
||||
|
||||
_mirroringReg = 0;
|
||||
|
||||
_irqCounter = 0;
|
||||
_irqEnabled = false;
|
||||
_irqReload = false;
|
||||
_irqReloadValue = 0;
|
||||
_irqDelay = 0;
|
||||
|
||||
AddRegisterRange(0x5000, 0x5FFF, MemoryOperation::Write);
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
void Reset(bool softReset) override
|
||||
{
|
||||
if(softReset) {
|
||||
if(_wramConfigEnabled && _selectChrRam && HasBattery()) {
|
||||
_prgBaseBits = 0;
|
||||
UpdateState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
SnapshotInfo a12Watcher { &_a12Watcher };
|
||||
ArrayInfo<uint8_t> regs { _mmc3Registers, 12 };
|
||||
|
||||
Stream(
|
||||
_prgBankingMode, _outerChrBankSize, _selectChrRam, _mmc3ChrMode, _cnromChrMode, _prgBaseBits, _chrBaseBits, _extendedMmc3Mode,
|
||||
_wramBankSelect, _ramInFirstChrBank, _allowSingleScreenMirroring, _fk23RegistersEnabled, _wramConfigEnabled, _wramEnabled, _wramWriteProtected,
|
||||
_invertPrgA14, _invertChrA12, _currentRegister, _irqReloadValue,_irqCounter, _irqReload, _irqEnabled, _mirroringReg, _cnromChrReg,
|
||||
_irqDelay, regs, a12Watcher
|
||||
);
|
||||
|
||||
if(!saving) {
|
||||
UpdateState();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default)
|
||||
{
|
||||
bool useChrRam = !HasChrRom() || (_selectChrRam && _chrRamSize > 0) || (_wramConfigEnabled && _ramInFirstChrBank && page <= 7);
|
||||
BaseMapper::SelectCHRPage(slot, page, useChrRam ? ChrMemoryType::ChrRam : ChrMemoryType::ChrRom);
|
||||
}
|
||||
|
||||
void UpdatePrg()
|
||||
{
|
||||
switch(_prgBankingMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
if(_extendedMmc3Mode) {
|
||||
uint8_t swap = _invertPrgA14 ? 2 : 0;
|
||||
uint16_t outer = (_prgBaseBits << 1);
|
||||
SelectPRGPage(0 ^ swap, _mmc3Registers[6] | outer);
|
||||
SelectPRGPage(1, _mmc3Registers[7] | outer);
|
||||
SelectPRGPage(2 ^ swap, _mmc3Registers[8] | outer);
|
||||
SelectPRGPage(3, _mmc3Registers[9] | outer);
|
||||
} else {
|
||||
uint8_t swap = _invertPrgA14 ? 2 : 0;
|
||||
uint8_t innerMask = 0x3F >> _prgBankingMode;
|
||||
uint16_t outer = (_prgBaseBits << 1) & ~innerMask;
|
||||
SelectPRGPage(0 ^ swap, (_mmc3Registers[6] & innerMask) | outer);
|
||||
SelectPRGPage(1, (_mmc3Registers[7] & innerMask) | outer);
|
||||
SelectPRGPage(2 ^ swap, (0xFE & innerMask) | outer);
|
||||
SelectPRGPage(3, (0xFF & innerMask) | outer);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
SelectPrgPage2x(0, _prgBaseBits << 1);
|
||||
SelectPrgPage2x(1, _prgBaseBits << 1);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
SelectPrgPage4x(0, (_prgBaseBits & 0xFFE) << 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateChr()
|
||||
{
|
||||
if(!_mmc3ChrMode) {
|
||||
uint16_t innerMask = _cnromChrMode ? (_outerChrBankSize ? 1 : 3) : 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
SelectCHRPage(i, (((_cnromChrReg & innerMask) | _chrBaseBits) << 3) + i);
|
||||
}
|
||||
} else {
|
||||
uint8_t swap = _invertChrA12 ? 0x04 : 0;
|
||||
if(_extendedMmc3Mode) {
|
||||
uint16_t outer = (_chrBaseBits << 3);
|
||||
SelectCHRPage(0 ^ swap, _mmc3Registers[0] | outer);
|
||||
SelectCHRPage(1 ^ swap, _mmc3Registers[10] | outer);
|
||||
SelectCHRPage(2 ^ swap, _mmc3Registers[1] | outer);
|
||||
SelectCHRPage(3 ^ swap, _mmc3Registers[11] | outer);
|
||||
SelectCHRPage(4 ^ swap, _mmc3Registers[2] | outer);
|
||||
SelectCHRPage(5 ^ swap, _mmc3Registers[3] | outer);
|
||||
SelectCHRPage(6 ^ swap, _mmc3Registers[4] | outer);
|
||||
SelectCHRPage(7 ^ swap, _mmc3Registers[5] | outer);
|
||||
} else {
|
||||
uint8_t innerMask = (_outerChrBankSize ? 0x7F : 0xFF);
|
||||
uint16_t outer = (_chrBaseBits << 3) & ~innerMask;
|
||||
|
||||
SelectCHRPage(0 ^ swap, ((_mmc3Registers[0] & 0xFE) & innerMask) | outer);
|
||||
SelectCHRPage(1 ^ swap, ((_mmc3Registers[0] | 0x01) & innerMask) | outer);
|
||||
SelectCHRPage(2 ^ swap, ((_mmc3Registers[1] & 0xFE) & innerMask) | outer);
|
||||
SelectCHRPage(3 ^ swap, ((_mmc3Registers[1] | 0x01) & innerMask) | outer);
|
||||
SelectCHRPage(4 ^ swap, (_mmc3Registers[2] & innerMask) | outer);
|
||||
SelectCHRPage(5 ^ swap, (_mmc3Registers[3] & innerMask) | outer);
|
||||
SelectCHRPage(6 ^ swap, (_mmc3Registers[4] & innerMask) | outer);
|
||||
SelectCHRPage(7 ^ swap, (_mmc3Registers[5] & innerMask) | outer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateState()
|
||||
{
|
||||
switch(_mirroringReg & (_allowSingleScreenMirroring ? 0x03 : 0x01)) {
|
||||
case 0: SetMirroringType(MirroringType::Vertical); break;
|
||||
case 1: SetMirroringType(MirroringType::Horizontal); break;
|
||||
case 2: SetMirroringType(MirroringType::ScreenAOnly); break;
|
||||
case 3: SetMirroringType(MirroringType::ScreenBOnly); break;
|
||||
}
|
||||
|
||||
UpdatePrg();
|
||||
UpdateChr();
|
||||
|
||||
if(_wramConfigEnabled) {
|
||||
uint8_t nextBank = (_wramBankSelect + 1) & 0x03;
|
||||
SetCpuMemoryMapping(0x4000, 0x5FFF, (nextBank & 0x02) >> 1, (nextBank & 0x01) ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, MemoryAccessType::ReadWrite);
|
||||
SetCpuMemoryMapping(0x6000, 0x7FFF, (_wramBankSelect & 0x02) >> 1, (_wramBankSelect & 0x01) ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam, MemoryAccessType::ReadWrite);
|
||||
} else {
|
||||
if(_wramEnabled) {
|
||||
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, PrgMemoryType::WorkRam, _wramWriteProtected ? MemoryAccessType::Read : MemoryAccessType::ReadWrite);
|
||||
} else {
|
||||
RemoveCpuMemoryMapping(0x6000, 0x7FFF);
|
||||
}
|
||||
RemoveCpuMemoryMapping(0x4000, 0x5FFF);
|
||||
};
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value) override
|
||||
{
|
||||
if(addr < 0x8000) {
|
||||
if(_fk23RegistersEnabled || !_wramConfigEnabled) {
|
||||
uint16_t mask = 0x5010;
|
||||
if((addr & mask) != mask) {
|
||||
//not a register
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr & 0x03) {
|
||||
case 0:
|
||||
_prgBankingMode = value & 0x07;
|
||||
_outerChrBankSize = (value & 0x10) >> 4;
|
||||
_selectChrRam = (value & 0x20) != 0;
|
||||
_mmc3ChrMode = (value & 0x40) == 0;
|
||||
_prgBaseBits = (_prgBaseBits & ~0x180) | ((value & 0x80) << 1) | ((value & 0x08) << 4);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_prgBaseBits = (_prgBaseBits & ~0x7F) | (value & 0x7F);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_prgBaseBits = (_prgBaseBits & ~0x200) | ((value & 0x40) << 3);
|
||||
_chrBaseBits = value;
|
||||
_cnromChrReg = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_extendedMmc3Mode = (value & 0x02) != 0;
|
||||
_cnromChrMode = (value & 0x44) != 0;
|
||||
break;
|
||||
}
|
||||
UpdateState();
|
||||
} else {
|
||||
//FK23C Registers disabled, $5000-$5FFF maps to the second 4 KiB of the 8 KiB WRAM bank 2
|
||||
WritePrgRam(addr, value);
|
||||
}
|
||||
} else {
|
||||
if(_cnromChrMode && (addr <= 0x9FFF || addr >= 0xC000)) {
|
||||
_cnromChrReg = value & 0x03;
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
switch(addr & 0xE001) {
|
||||
case 0x8000:
|
||||
if(_prgSize == 16384*1024 && (value == 0x46 || value == 0x47)) {
|
||||
//Subtype 2, 16384 KiB PRG-ROM, no CHR-ROM: Like Subtype 0, but MMC3 registers $46 and $47 swapped.
|
||||
value ^= 1;
|
||||
}
|
||||
|
||||
_invertPrgA14 = (value & 0x40) != 0;
|
||||
_invertChrA12 = (value & 0x80) != 0;
|
||||
_currentRegister = value & 0x0F;
|
||||
UpdateState();
|
||||
break;
|
||||
|
||||
case 0x8001: {
|
||||
uint8_t reg = _currentRegister & (_extendedMmc3Mode ? 0x0F : 0x07);
|
||||
if(reg < 12) {
|
||||
_mmc3Registers[_currentRegister & (_extendedMmc3Mode ? 0x0F : 0x07)] = value;
|
||||
UpdateState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA000:
|
||||
_mirroringReg = value & 0x03;
|
||||
UpdateState();
|
||||
break;
|
||||
|
||||
case 0xA001:
|
||||
if((value & 0x20) == 0) {
|
||||
//Ignore extra bits if bit 5 is not set
|
||||
value &= 0xC0;
|
||||
}
|
||||
|
||||
_wramBankSelect = (value & 0x03);
|
||||
_ramInFirstChrBank = (value & 0x04) != 0;
|
||||
_allowSingleScreenMirroring = (value & 0x08) != 0;
|
||||
_wramConfigEnabled = (value & 0x20) != 0;
|
||||
_fk23RegistersEnabled = (value & 0x40) != 0;
|
||||
|
||||
_wramWriteProtected = (value & 0x40) != 0;
|
||||
_wramEnabled = (value & 0x80) != 0;
|
||||
|
||||
UpdateState();
|
||||
break;
|
||||
|
||||
case 0xC000:
|
||||
_irqReloadValue = value;
|
||||
break;
|
||||
|
||||
case 0xC001:
|
||||
_irqCounter = 0;
|
||||
_irqReload = true;
|
||||
break;
|
||||
|
||||
case 0xE000:
|
||||
_irqEnabled = false;
|
||||
_console->GetCpu()->ClearIrqSource(IRQSource::External);
|
||||
break;
|
||||
|
||||
case 0xE001:
|
||||
_irqEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void ProcessCpuClock() override
|
||||
{
|
||||
if(_irqDelay > 0) {
|
||||
_irqDelay--;
|
||||
if(_irqDelay == 0) {
|
||||
_console->GetCpu()->SetIrqSource(IRQSource::External);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyVRAMAddressChange(uint16_t addr) override
|
||||
{
|
||||
switch(_a12Watcher.UpdateVramAddress(addr, _console->GetPpu()->GetFrameCycle())) {
|
||||
case A12StateChange::None:
|
||||
case A12StateChange::Fall:
|
||||
break;
|
||||
|
||||
case A12StateChange::Rise:
|
||||
if(_irqCounter == 0 || _irqReload) {
|
||||
_irqCounter = _irqReloadValue;
|
||||
} else {
|
||||
_irqCounter--;
|
||||
}
|
||||
|
||||
if(_irqCounter == 0 && _irqEnabled) {
|
||||
_irqDelay = 2;
|
||||
}
|
||||
_irqReload = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,141 +0,0 @@
|
|||
#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<uint8_t> 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;
|
||||
}
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "MMC3.h"
|
||||
|
||||
class MMC3_Super24in1Sc03 : public MMC3
|
||||
{
|
||||
private:
|
||||
const int _prgMask[8] = { 0x3F, 0x1F, 0x0F, 0x01, 0x03, 0, 0, 0 };
|
||||
uint8_t _exRegs[3];
|
||||
|
||||
protected:
|
||||
uint32_t GetChrRamSize() override { return 0x2000; }
|
||||
uint16_t GetChrRamPageSize() override { return 0x400; }
|
||||
|
||||
void InitMapper() override
|
||||
{
|
||||
MMC3::InitMapper();
|
||||
AddRegisterRange(0x5FF0, 0x5FF2, MemoryOperation::Write);
|
||||
}
|
||||
|
||||
void Reset(bool softReset) override
|
||||
{
|
||||
MMC3::ResetMmc3();
|
||||
|
||||
_exRegs[0] = 0x24;
|
||||
_exRegs[1] = 0x9F;
|
||||
_exRegs[2] = 0;
|
||||
|
||||
_registers[6] = 0;
|
||||
_registers[7] = 1;
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
MMC3::StreamState(saving);
|
||||
Stream(_exRegs[0], _exRegs[1], _exRegs[2]);
|
||||
|
||||
if(!saving) {
|
||||
UpdateState();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memoryType = ChrMemoryType::Default) override
|
||||
{
|
||||
MMC3::SelectCHRPage(slot, ((_exRegs[2] << 3) & 0xF00) | page, _exRegs[0] & 0x20 ? ChrMemoryType::ChrRam : ChrMemoryType::ChrRom);
|
||||
}
|
||||
|
||||
void SelectPRGPage(uint16_t slot, uint16_t page, PrgMemoryType memoryType = PrgMemoryType::PrgRom) override
|
||||
{
|
||||
MMC3::SelectPRGPage(slot, ((_exRegs[1] << 1) | (page & _prgMask[_exRegs[0] & 0x07])) & 0xFF);
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value) override
|
||||
{
|
||||
if(addr < 0x8000) {
|
||||
_exRegs[addr & 0x03] = value;
|
||||
UpdateState();
|
||||
} else {
|
||||
MMC3::WriteRegister(addr, value);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -59,6 +59,7 @@
|
|||
#include "FaridSlrom.h"
|
||||
#include "FaridUnrom.h"
|
||||
#include "FDS.h"
|
||||
#include "Fk23C.h"
|
||||
#include "FrontFareast.h"
|
||||
#include "Ghostbusters63in1.h"
|
||||
#include "Gkcx1.h"
|
||||
|
@ -186,11 +187,9 @@
|
|||
#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"
|
||||
#include "MMC3_Super24in1Sc03.h"
|
||||
#include "MMC4.h"
|
||||
#include "MMC5.h"
|
||||
#include "Namco108.h"
|
||||
|
@ -267,7 +266,6 @@
|
|||
#include "VsSystem.h"
|
||||
#include "Waixing162.h"
|
||||
#include "Waixing164.h"
|
||||
#include "Waixing176.h"
|
||||
#include "Waixing178.h"
|
||||
#include "Waixing252.h"
|
||||
#include "Yoko.h"
|
||||
|
@ -466,7 +464,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
case 173: return new Txc22211C();
|
||||
case 174: return new Mapper174();
|
||||
case 175: return new Kaiser7022();
|
||||
case 176: return new Waixing176();
|
||||
case 176: return new Fk23C();
|
||||
case 177: return new Henggedianzi177();
|
||||
case 178: return new Waixing178();
|
||||
case 179: return new Henggedianzi179();
|
||||
|
@ -640,13 +638,10 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
case UnifBoards::Ac08: return new Ac08(); //mapper 42?
|
||||
case UnifBoards::BmcGn45: return new BmcGn45();
|
||||
case UnifBoards::Cc21: return new Cc21();
|
||||
case UnifBoards::Fk23C: return new MMC3_Fk23C(false); //mapper 176?
|
||||
case UnifBoards::Fk23Ca: return new MMC3_Fk23C(true); //mapper 176?
|
||||
case UnifBoards::Ghostbusters63in1: return new Ghostbusters63in1(); //mapper 226?
|
||||
case UnifBoards::Gs2013: return new Gs2013();
|
||||
case UnifBoards::Malee: return new Malee(); //mapper 42?
|
||||
case UnifBoards::SssNrom256: return new FamicomBox();
|
||||
case UnifBoards::Super24in1Sc03: return new MMC3_Super24in1Sc03(); //mapper 176?
|
||||
case UnifBoards::Unl255in1: return new Unl255in1();
|
||||
case UnifBoards::Unl8237A: return new Unl8237A(); //mapper 215.1
|
||||
case UnifBoards::UnlPuzzle: return new UnlPuzzle();
|
||||
|
|
|
@ -45,8 +45,8 @@ std::unordered_map<string, int> UnifLoader::_boardMappings = std::unordered_map<
|
|||
{ "EWROM", 5 },
|
||||
{ "FARID_SLROM_8-IN-1", 323 },
|
||||
{ "FARID_UNROM_8-IN-1", 324 },
|
||||
{ "FK23C", UnifBoards::Fk23C },
|
||||
{ "FK23CA", UnifBoards::Fk23Ca },
|
||||
{ "FK23C", 176 },
|
||||
{ "FK23CA", 176 },
|
||||
{ "FS304", 162 },
|
||||
{ "G-146", 349 },
|
||||
{ "GK-192", 58 },
|
||||
|
@ -122,7 +122,7 @@ std::unordered_map<string, int> UnifLoader::_boardMappings = std::unordered_map<
|
|||
{ "Sachen-8259B", 138 },
|
||||
{ "Sachen-8259C", 139 },
|
||||
{ "Sachen-8259D", 137 },
|
||||
{ "Super24in1SC03", UnifBoards::Super24in1Sc03 },
|
||||
{ "Super24in1SC03", 176 },
|
||||
{ "SuperHIK8in1", 45 },
|
||||
{ "Supervision16in1", 53 },
|
||||
{ "T-227-1", UnifBoards::UnknownBoard },
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
#pragma once
|
||||
#include "BaseMapper.h"
|
||||
|
||||
class Waixing176 : public BaseMapper
|
||||
{
|
||||
private:
|
||||
bool _registersEnabled;
|
||||
|
||||
protected:
|
||||
uint16_t GetPRGPageSize() override { return 0x2000; }
|
||||
uint16_t GetCHRPageSize() override { return 0x2000; }
|
||||
uint16_t RegisterStartAddress() override { return 0x5000; }
|
||||
uint16_t RegisterEndAddress() override { return 0x5FFF; }
|
||||
|
||||
void InitMapper() override
|
||||
{
|
||||
_registersEnabled = false;
|
||||
|
||||
SelectPRGPage(0, 0);
|
||||
SelectPRGPage(1, 1);
|
||||
SelectPRGPage(2, (GetPRGPageCount() - 2) & 0x3F);
|
||||
SelectPRGPage(3, (GetPRGPageCount() - 1) & 0x3F);
|
||||
}
|
||||
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
BaseMapper::StreamState(saving);
|
||||
Stream(_registersEnabled);
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value) override
|
||||
{
|
||||
switch(addr) {
|
||||
case 0x5001:
|
||||
if(_registersEnabled) {
|
||||
SelectPrgPage4x(0, value*4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5010:
|
||||
if(value == 0x24) {
|
||||
_registersEnabled = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5011:
|
||||
if(_registersEnabled) {
|
||||
SelectPrgPage4x(0, (value >> 1) * 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x5FF1:
|
||||
SelectPrgPage4x(0, (value >> 1) * 4);
|
||||
break;
|
||||
|
||||
case 0x5FF2:
|
||||
if(!HasChrRam()) {
|
||||
SelectCHRPage(0, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue