#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(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>& prgHandlers = _console->GetCartridge()->GetPrgRomHandlers(); vector>& 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 psRam = { _psRam, _psRamSize }; ArrayInfo regs = { _regs, 0x10 }; ArrayInfo 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; }