2016-05-01 00:08:53 +00:00
|
|
|
#pragma once
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "BaseMapper.h"
|
|
|
|
#include "VsControlManager.h"
|
|
|
|
|
|
|
|
class VsSystem : public BaseMapper
|
|
|
|
{
|
|
|
|
private:
|
2018-07-03 01:32:59 +00:00
|
|
|
uint8_t _prgChrSelectBit = 0;
|
2016-05-01 00:08:53 +00:00
|
|
|
|
|
|
|
protected:
|
2016-12-18 04:14:47 +00:00
|
|
|
virtual uint16_t GetPRGPageSize() override { return 0x2000; }
|
|
|
|
virtual uint16_t GetCHRPageSize() override { return 0x2000; }
|
2018-07-03 01:32:59 +00:00
|
|
|
virtual uint32_t GetWorkRamSize() override { return 0x800; }
|
2016-05-01 00:08:53 +00:00
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
virtual void InitMapper() override
|
2016-05-01 00:08:53 +00:00
|
|
|
{
|
2018-07-03 01:32:59 +00:00
|
|
|
//Force VS system if mapper 99 (since we assume VsControlManager exists below)
|
|
|
|
if(_prgSize >= 0x10000) {
|
|
|
|
//Assume DualSystem if PRG ROM is 64kb or larger
|
|
|
|
_gameSystem = GameSystem::VsDualSystem;
|
|
|
|
} else {
|
|
|
|
_gameSystem = GameSystem::VsUniSystem;
|
|
|
|
}
|
|
|
|
|
2016-07-10 13:05:41 +00:00
|
|
|
//"Note: unlike all other mappers, an undersize mapper 99 image implies open bus instead of mirroring."
|
|
|
|
//However, it doesn't look like any game actually rely on this behavior? So not implemented for now.
|
2018-07-03 01:32:59 +00:00
|
|
|
uint8_t prgOuter = _console->IsMaster() ? 0 : (GetPRGPageCount() / 2);
|
|
|
|
SelectPRGPage(0, 0 | prgOuter);
|
|
|
|
SelectPRGPage(1, 1 | prgOuter);
|
|
|
|
SelectPRGPage(2, 2 | prgOuter);
|
|
|
|
SelectPRGPage(3, 3 | prgOuter);
|
2016-05-01 00:08:53 +00:00
|
|
|
|
2018-07-03 01:32:59 +00:00
|
|
|
uint8_t chrOuter = _console->IsMaster() ? 0 : (GetCHRPageCount() / 2);
|
|
|
|
SelectCHRPage(0, 0 | chrOuter);
|
|
|
|
}
|
2016-07-10 13:05:41 +00:00
|
|
|
|
2018-07-03 01:32:59 +00:00
|
|
|
void Reset(bool softReset) override
|
|
|
|
{
|
|
|
|
BaseMapper::Reset(softReset);
|
|
|
|
UpdateMemoryAccess(0);
|
2016-05-01 00:08:53 +00:00
|
|
|
}
|
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
void StreamState(bool saving) override
|
2016-06-22 02:13:26 +00:00
|
|
|
{
|
|
|
|
BaseMapper::StreamState(saving);
|
|
|
|
Stream(_prgChrSelectBit);
|
|
|
|
}
|
|
|
|
|
2016-12-18 04:14:47 +00:00
|
|
|
void ProcessCpuClock() override
|
2016-05-01 00:08:53 +00:00
|
|
|
{
|
2018-07-01 19:21:05 +00:00
|
|
|
VsControlManager* controlManager = dynamic_cast<VsControlManager*>(_console->GetControlManager());
|
|
|
|
if(_prgChrSelectBit != controlManager->GetPrgChrSelectBit()) {
|
|
|
|
_prgChrSelectBit = controlManager->GetPrgChrSelectBit();
|
2016-07-10 13:05:41 +00:00
|
|
|
|
2018-07-03 01:32:59 +00:00
|
|
|
if(_prgSize > 0x8000 && _prgSize < 0x10000) {
|
2016-07-10 13:05:41 +00:00
|
|
|
//"Note: In case of games with 40KiB PRG - ROM(as found in VS Gumshoe), the above bit additionally changes 8KiB PRG - ROM at $8000 - $9FFF."
|
|
|
|
//"Only Vs. Gumshoe uses the 40KiB PRG variant; in the iNES encapsulation, the 8KiB banks are arranged as 0, 1, 2, 3, 0alternate, empty"
|
|
|
|
SelectPRGPage(0, _prgChrSelectBit << 2);
|
|
|
|
}
|
|
|
|
|
2018-07-03 01:32:59 +00:00
|
|
|
uint8_t chrOuter = _console->IsMaster() ? 0 : (GetCHRPageCount() / 2);
|
|
|
|
SelectCHRPage(0, _prgChrSelectBit | chrOuter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
void UpdateMemoryAccess(uint8_t slaveMasterBit)
|
|
|
|
{
|
|
|
|
shared_ptr<Console> dualConsole = _console->GetDualConsole();
|
|
|
|
if(_console->IsMaster() && dualConsole) {
|
|
|
|
VsSystem* otherMapper = dynamic_cast<VsSystem*>(dualConsole->GetMapper());
|
|
|
|
|
|
|
|
//Give memory access to master CPU or slave CPU, based on "slaveMasterBit"
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
|
|
SetCpuMemoryMapping(0x6000 + i * 0x800, 0x67FF + i * 0x800, _workRam, slaveMasterBit ? MemoryAccessType::ReadWrite : MemoryAccessType::NoAccess);
|
|
|
|
otherMapper->SetCpuMemoryMapping(0x6000 + i * 0x800, 0x67FF + i * 0x800, _workRam, slaveMasterBit ? MemoryAccessType::NoAccess : MemoryAccessType::ReadWrite);
|
|
|
|
}
|
2016-05-01 00:08:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|