Mesen-S/Core/BsxCart.cpp
Sour 6539b92502 SA-1: Fixed timing regressions
Memory handlers did not have the _memoryType value set, which caused some memory accesses to be much faster than expected
2020-03-01 18:24:33 -05:00

222 lines
6.1 KiB
C++

#include "stdafx.h"
#include "BsxCart.h"
#include "Console.h"
#include "MemoryManager.h"
#include "MemoryMappings.h"
#include "BaseCartridge.h"
#include "BsxMemoryPack.h"
#include "BsxSatellaview.h"
#include "RamHandler.h"
#include "EmuSettings.h"
BsxCart::BsxCart(Console* console, BsxMemoryPack* memPack) : BaseCoprocessor(SnesMemoryType::Register)
{
_console = console;
_memoryManager = _console->GetMemoryManager().get();
_memPack = memPack;
MemoryMappings* mm = _console->GetMemoryManager()->GetMemoryMappings();
mm->RegisterHandler(0x00, 0x0F, 0x5000, 0x5FFF, this);
mm->RegisterHandler(0x10, 0x1F, 0x5000, 0x5FFF, _console->GetCartridge()->GetSaveRamHandlers());
//Override regular B-bus handler
_satellaview.reset(new BsxSatellaview(console, mm->GetHandler(0x2000)));
mm->RegisterHandler(0x00, 0x3F, 0x2000, 0x2FFF, _satellaview.get());
mm->RegisterHandler(0x80, 0xBF, 0x2000, 0x2FFF, _satellaview.get());
_psRamSize = 512 * 1024;
_psRam = new uint8_t[_psRamSize];
console->GetSettings()->InitializeRam(_psRam, _psRamSize);
for(uint32_t i = 0; i < _psRamSize / 0x1000; i++) {
_psRamHandlers.push_back(unique_ptr<IMemoryHandler>(new RamHandler(_psRam, i * 0x1000, _psRamSize, SnesMemoryType::BsxPsRam)));
}
Reset();
}
BsxCart::~BsxCart()
{
delete[] _psRam;
}
uint8_t BsxCart::Read(uint32_t addr)
{
uint8_t openBus = _memoryManager->GetOpenBus();
if((addr & 0xFFFF) != 0x5000) {
return openBus;
} else {
uint8_t reg = (addr >> 16) & 0x0F;
if(reg <= 0x0D) {
return (_regs[reg] << 7) | (openBus & 0x7F);
} else {
//E & F are write-only
return openBus & 0x7F;
}
}
}
void BsxCart::Write(uint32_t addr, uint8_t value)
{
if((addr & 0xFFFF) != 0x5000) {
return;
}
uint8_t reg = (addr >> 16) & 0x0F;
if(reg == 0x0E) {
if(_dirty) {
memcpy(_regs, _dirtyRegs, sizeof(_regs));
UpdateMemoryMappings();
_dirty = false;
}
} else {
uint8_t regValue = (value >> 7);
if(_regs[reg] != regValue) {
_dirtyRegs[reg] = regValue;
_dirty = true;
}
}
}
void BsxCart::UpdateMemoryMappings()
{
MemoryMappings* mm = _console->GetMemoryManager()->GetMemoryMappings();
vector<unique_ptr<IMemoryHandler>>& prgHandlers = _console->GetCartridge()->GetPrgRomHandlers();
vector<unique_ptr<IMemoryHandler>>& memPackHandlers = _memPack->GetMemoryHandlers();
uint8_t unmappedBank = (_regs[0x0B] << 5);
uint8_t psRamBank = (_regs[0x05] << 4) | (_regs[0x06] << 5);
if(!_regs[0x02]) {
//LoROM
//Memory pack mapping
mm->RegisterHandler(0x00, 0x7D, 0x8000, 0xFFFF, memPackHandlers);
mm->RegisterHandler(0x40, 0x7D, 0x0000, 0x7FFF, memPackHandlers);
mm->RegisterHandler(0x80, 0xFF, 0x8000, 0xFFFF, memPackHandlers);
mm->RegisterHandler(0xC0, 0xFF, 0x0000, 0x7FFF, memPackHandlers);
//Memory hole mapping
uint16_t unmappedAddr = _regs[0x0B] ? 0x0000 : 0x8000;
if(_regs[0x09]) {
mm->RegisterHandler(0x00 | (unmappedBank << 1), 0x1F | (unmappedBank << 1), unmappedAddr, 0xFFFF, nullptr);
}
if(_regs[0x0A]) {
mm->RegisterHandler(0x80 | (unmappedBank << 1), 0x9F | (unmappedBank << 1), unmappedAddr, 0xFFFF, nullptr);
}
//PSRAM mapping
uint16_t psRamAddr = (psRamBank & 0x20) ? 0x0000 : 0x8000;
if(_regs[0x03]) {
mm->RegisterHandler(0x00 | (psRamBank << 1), 0x0F | (psRamBank << 1), psRamAddr, 0xFFFF, _psRamHandlers);
mm->RegisterHandler(0x70, 0x7D, 0x0000, 0x7FFF, _psRamHandlers);
}
if(_regs[0x04]) {
mm->RegisterHandler(0x80 | (psRamBank << 1), 0x8F | (psRamBank << 1), psRamAddr, 0xFFFF, _psRamHandlers);
mm->RegisterHandler(0xF0, 0xFF, 0x0000, 0x7FFF, _psRamHandlers);
}
} else {
//HiROM
//Memory pack mapping
mm->RegisterHandler(0x00, 0x3F, 0x8000, 0xFFFF, memPackHandlers, 8);
mm->RegisterHandler(0x40, 0x7D, 0x0000, 0xFFFF, memPackHandlers, 0);
mm->RegisterHandler(0x80, 0xBF, 0x8000, 0xFFFF, memPackHandlers, 8);
mm->RegisterHandler(0xC0, 0xFF, 0x0000, 0xFFFF, memPackHandlers, 0);
//Memory hole mapping
if(_regs[0x09]) {
mm->RegisterHandler(0x00 | unmappedBank, 0x0F | unmappedBank, 0x8000, 0xFFFF, nullptr);
mm->RegisterHandler(0x40 | unmappedBank, 0x4F | unmappedBank, 0x0000, 0xFFFF, nullptr);
}
if(_regs[0x0A]) {
mm->RegisterHandler(0x80 | unmappedBank, 0x8F | unmappedBank, 0x8000, 0xFFFF, nullptr);
mm->RegisterHandler(0xC0 | unmappedBank, 0xCF | unmappedBank, 0x0000, 0xFFFF, nullptr);
}
//PSRAM mapping
if(_regs[0x03]) {
//Lower Banks (0x00-0x7D)
mm->RegisterHandler(0x00 | psRamBank, 0x07 | psRamBank, 0x8000, 0xFFFF, _psRamHandlers, 8);
mm->RegisterHandler(0x40 | psRamBank, 0x47 | psRamBank, 0x0000, 0xFFFF, _psRamHandlers);
mm->RegisterHandler(0x20, 0x3F, 0x6000, 0x7FFF, _psRamHandlers, 6);
}
if(_regs[0x04]) {
//Higher Banks (0x80-0xFF)
mm->RegisterHandler(0x80 | psRamBank, 0x87 | psRamBank, 0x8000, 0xFFFF, _psRamHandlers, 8);
mm->RegisterHandler(0xC0 | psRamBank, 0xC7 | psRamBank, 0x0000, 0xFFFF, _psRamHandlers);
mm->RegisterHandler(0xA0, 0xBF, 0x6000, 0x7FFF, _psRamHandlers, 6);
}
}
//BS-X BIOS mapping (can override other mappings above)
if(_regs[0x07]) {
mm->RegisterHandler(0x00, 0x3F, 0x8000, 0xFFFF, prgHandlers);
}
if(_regs[0x08]) {
mm->RegisterHandler(0x80, 0xBF, 0x8000, 0xFFFF, prgHandlers);
}
}
void BsxCart::Reset()
{
for(int i = 0; i < 0x10; i++) {
_regs[i] = true;
}
_regs[0x04] = false;
_regs[0x0A] = false;
_regs[0x0C] = false;
_regs[0x0D] = false;
_dirty = false;
memcpy(_dirtyRegs, _regs, sizeof(_regs));
_satellaview->Reset();
UpdateMemoryMappings();
}
void BsxCart::Serialize(Serializer& s)
{
ArrayInfo<uint8_t> psRam = { _psRam, _psRamSize };
ArrayInfo<uint8_t> regs = { _regs, 0x10 };
ArrayInfo<uint8_t> dirtyRegs = { _dirtyRegs, 0x10 };
s.Stream(psRam, regs, dirtyRegs, _dirty);
s.Stream(_satellaview.get());
if(!s.IsSaving()) {
UpdateMemoryMappings();
}
}
uint8_t BsxCart::Peek(uint32_t addr)
{
return 0;
}
void BsxCart::PeekBlock(uint32_t addr, uint8_t* output)
{
memset(output, 0, 0x1000);
}
AddressInfo BsxCart::GetAbsoluteAddress(uint32_t address)
{
return { -1, SnesMemoryType::Register };
}
uint8_t* BsxCart::DebugGetPsRam()
{
return _psRam;
}
uint32_t BsxCart::DebugGetPsRamSize()
{
return _psRamSize;
}