2019-02-26 22:27:09 -05:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "MemoryManager.h"
|
|
|
|
#include "Console.h"
|
|
|
|
#include "BaseCartridge.h"
|
|
|
|
#include "Cpu.h"
|
|
|
|
#include "Ppu.h"
|
2019-04-11 22:34:28 -04:00
|
|
|
#include "DmaController.h"
|
2019-02-26 22:27:09 -05:00
|
|
|
#include "RegisterHandlerA.h"
|
|
|
|
#include "RegisterHandlerB.h"
|
|
|
|
#include "RamHandler.h"
|
|
|
|
#include "MessageManager.h"
|
|
|
|
#include "DebugTypes.h"
|
2019-07-06 14:25:51 -04:00
|
|
|
#include "EmuSettings.h"
|
2019-07-30 22:34:52 -04:00
|
|
|
#include "Sa1.h"
|
|
|
|
#include "Gsu.h"
|
2019-08-03 23:43:51 -04:00
|
|
|
#include "Cx4.h"
|
2020-06-18 00:58:22 -04:00
|
|
|
#include "Gameboy.h"
|
2019-07-25 22:22:09 -04:00
|
|
|
#include "BaseCoprocessor.h"
|
2019-10-12 22:40:25 -04:00
|
|
|
#include "CheatManager.h"
|
2019-03-12 09:15:57 -04:00
|
|
|
#include "../Utilities/Serializer.h"
|
2019-02-26 22:27:09 -05:00
|
|
|
#include "../Utilities/HexUtilities.h"
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void MemoryManager::Initialize(Console *console)
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
|
|
|
_masterClock = 0;
|
2019-03-09 00:31:54 -05:00
|
|
|
_openBus = 0;
|
2019-04-20 09:30:51 -04:00
|
|
|
_cpuSpeed = 8;
|
2019-02-26 22:27:09 -05:00
|
|
|
_console = console;
|
|
|
|
_regs = console->GetInternalRegisters().get();
|
2019-07-12 23:34:19 -04:00
|
|
|
_cpu = console->GetCpu().get();
|
|
|
|
_ppu = console->GetPpu().get();
|
2019-07-25 22:22:09 -04:00
|
|
|
_cart = console->GetCartridge().get();
|
2019-10-12 22:40:25 -04:00
|
|
|
_cheatManager = console->GetCheatManager().get();
|
2019-02-26 22:27:09 -05:00
|
|
|
|
|
|
|
_workRam = new uint8_t[MemoryManager::WorkRamSize];
|
2019-07-06 14:25:51 -04:00
|
|
|
_console->GetSettings()->InitializeRam(_workRam, MemoryManager::WorkRamSize);
|
2019-02-26 22:27:09 -05:00
|
|
|
|
|
|
|
_registerHandlerA.reset(new RegisterHandlerA(
|
|
|
|
console->GetDmaController().get(),
|
|
|
|
console->GetInternalRegisters().get(),
|
|
|
|
console->GetControlManager().get()
|
|
|
|
));
|
2019-07-25 22:22:09 -04:00
|
|
|
|
2019-02-26 22:27:09 -05:00
|
|
|
_registerHandlerB.reset(new RegisterHandlerB(
|
2019-07-12 23:34:19 -04:00
|
|
|
_console,
|
|
|
|
_ppu,
|
2019-02-26 22:27:09 -05:00
|
|
|
console->GetSpc().get(),
|
|
|
|
_workRam
|
|
|
|
));
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
for(uint32_t i = 0; i < 128 * 1024; i += 0x1000) {
|
|
|
|
_workRamHandlers.push_back(unique_ptr<RamHandler>(new RamHandler(_workRam, i, MemoryManager::WorkRamSize, SnesMemoryType::WorkRam)));
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_mappings.RegisterHandler(0x7E, 0x7F, 0x0000, 0xFFFF, _workRamHandlers);
|
2019-02-26 22:27:09 -05:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_mappings.RegisterHandler(0x00, 0x3F, 0x2000, 0x2FFF, _registerHandlerB.get());
|
|
|
|
_mappings.RegisterHandler(0x80, 0xBF, 0x2000, 0x2FFF, _registerHandlerB.get());
|
2019-02-26 22:27:09 -05:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_mappings.RegisterHandler(0x00, 0x3F, 0x4000, 0x4FFF, _registerHandlerA.get());
|
|
|
|
_mappings.RegisterHandler(0x80, 0xBF, 0x4000, 0x4FFF, _registerHandlerA.get());
|
2019-02-26 22:27:09 -05:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_mappings.RegisterHandler(0x00, 0x3F, 0x0000, 0x0FFF, _workRamHandlers[0].get());
|
|
|
|
_mappings.RegisterHandler(0x80, 0xBF, 0x0000, 0x0FFF, _workRamHandlers[0].get());
|
|
|
|
_mappings.RegisterHandler(0x00, 0x3F, 0x1000, 0x1FFF, _workRamHandlers[1].get());
|
|
|
|
_mappings.RegisterHandler(0x80, 0xBF, 0x1000, 0x1FFF, _workRamHandlers[1].get());
|
2019-02-26 22:27:09 -05:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_cart->Init(_mappings);
|
2019-02-26 22:27:09 -05:00
|
|
|
|
|
|
|
GenerateMasterClockTable();
|
2020-06-24 18:43:49 -04:00
|
|
|
Reset();
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryManager::~MemoryManager()
|
|
|
|
{
|
|
|
|
delete[] _workRam;
|
|
|
|
}
|
|
|
|
|
2019-03-16 12:20:18 -04:00
|
|
|
void MemoryManager::Reset()
|
|
|
|
{
|
|
|
|
_masterClock = 0;
|
2019-04-20 09:30:51 -04:00
|
|
|
_hClock = 0;
|
2020-06-24 18:43:49 -04:00
|
|
|
_dramRefreshPosition = 538 - (_masterClock & 0x07);
|
|
|
|
_nextEventClock = _dramRefreshPosition;
|
|
|
|
_nextEvent = SnesEventType::DramRefresh;
|
2019-03-16 12:20:18 -04:00
|
|
|
}
|
|
|
|
|
2019-02-26 22:27:09 -05:00
|
|
|
void MemoryManager::GenerateMasterClockTable()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
for(int i = 0; i < 0x800; i++) {
|
2020-06-24 18:43:49 -04:00
|
|
|
uint8_t bank = (i & 0x300) >> 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(bank == 1) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Banks $40-$7F - Slow
|
|
|
|
_masterClockTable[i] = 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(bank == 3) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Banks $C0-$FF
|
|
|
|
//Slow or fast (depending on register)
|
|
|
|
_masterClockTable[i] = (i >= 0x400) ? 6 : 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Banks $00-$3F and $80-$BF
|
|
|
|
uint8_t page = (i & 0xFF);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(page <= 0x1F) {
|
2019-02-26 22:27:09 -05:00
|
|
|
//Slow
|
2020-06-24 18:43:49 -04:00
|
|
|
_masterClockTable[i] = 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(page >= 0x20 && page <= 0x3F) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Fast
|
|
|
|
_masterClockTable[i] = 6;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(page == 0x40 || page == 0x41) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Extra slow
|
|
|
|
_masterClockTable[i] = 12;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(page >= 0x42 && page <= 0x5F) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Fast
|
|
|
|
_masterClockTable[i] = 6;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(page >= 0x60 && page <= 0x7F) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Slow
|
|
|
|
_masterClockTable[i] = 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(bank == 0) {
|
2020-06-24 18:43:49 -04:00
|
|
|
//Slow
|
|
|
|
_masterClockTable[i] = 8;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2020-06-24 18:43:49 -04:00
|
|
|
//page >= $80
|
|
|
|
//Slow or fast (depending on register)
|
|
|
|
_masterClockTable[i] = (i >= 0x400) ? 6 : 8;
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-12 23:55:18 -04:00
|
|
|
void MemoryManager::IncMasterClock4()
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
2019-07-12 23:55:18 -04:00
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::IncMasterClock6()
|
|
|
|
{
|
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::IncMasterClock8()
|
|
|
|
{
|
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
Exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::IncMasterClock40()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
Exec(); Exec(); Exec(); Exec(); Exec();
|
|
|
|
Exec(); Exec(); Exec(); Exec(); Exec();
|
|
|
|
Exec(); Exec(); Exec(); Exec(); Exec();
|
|
|
|
Exec(); Exec(); Exec(); Exec(); Exec();
|
2019-07-12 23:55:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::IncMasterClockStartup()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
for(int i = 0; i < 182 / 2; i++) {
|
2019-07-12 23:55:18 -04:00
|
|
|
Exec();
|
|
|
|
}
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
2019-03-08 10:26:54 -05:00
|
|
|
void MemoryManager::IncrementMasterClockValue(uint16_t cyclesToRun)
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
switch(cyclesToRun) {
|
|
|
|
case 12: Exec();
|
|
|
|
case 10: Exec();
|
|
|
|
case 8: Exec();
|
|
|
|
case 6: Exec();
|
|
|
|
case 4: Exec();
|
|
|
|
case 2: Exec();
|
2019-03-08 10:26:54 -05:00
|
|
|
}
|
|
|
|
}
|
2019-03-04 17:49:14 -05:00
|
|
|
|
2020-06-24 18:43:49 -04:00
|
|
|
void MemoryManager::Exec()
|
2019-04-20 09:30:51 -04:00
|
|
|
{
|
2020-06-24 18:43:49 -04:00
|
|
|
_masterClock += 2;
|
|
|
|
_hClock += 2;
|
2019-04-20 11:46:51 -04:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_hClock == _nextEventClock) {
|
2020-06-24 18:43:49 -04:00
|
|
|
ProcessEvent();
|
2021-03-10 11:13:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if((_hClock & 0x03) == 0) {
|
2020-06-24 18:43:49 -04:00
|
|
|
_console->ProcessPpuCycle<CpuType::Cpu>();
|
|
|
|
_regs->ProcessIrqCounters();
|
2019-04-20 09:30:51 -04:00
|
|
|
}
|
2019-04-20 11:46:51 -04:00
|
|
|
|
2020-06-24 18:43:49 -04:00
|
|
|
_cart->SyncCoprocessors();
|
2019-04-20 09:30:51 -04:00
|
|
|
}
|
|
|
|
|
2020-06-24 18:43:49 -04:00
|
|
|
void MemoryManager::ProcessEvent()
|
2019-03-08 10:26:54 -05:00
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
switch(_nextEvent) {
|
|
|
|
case SnesEventType::HdmaInit:
|
|
|
|
_console->GetDmaController()->BeginHdmaInit();
|
|
|
|
_nextEvent = SnesEventType::DramRefresh;
|
|
|
|
_nextEventClock = _dramRefreshPosition;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SnesEventType::DramRefresh:
|
|
|
|
IncMasterClock40();
|
|
|
|
_cpu->IncreaseCycleCount<5>();
|
|
|
|
|
|
|
|
if(_ppu->GetScanline() < _ppu->GetVblankStart()) {
|
|
|
|
_nextEvent = SnesEventType::HdmaStart;
|
|
|
|
_nextEventClock = 276 * 4;
|
|
|
|
} else {
|
|
|
|
_nextEvent = SnesEventType::EndOfScanline;
|
|
|
|
_nextEventClock = 1360;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SnesEventType::HdmaStart:
|
|
|
|
_console->GetDmaController()->BeginHdmaTransfer();
|
2020-06-24 18:43:49 -04:00
|
|
|
_nextEvent = SnesEventType::EndOfScanline;
|
|
|
|
_nextEventClock = 1360;
|
2021-03-10 11:13:28 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SnesEventType::EndOfScanline:
|
|
|
|
if(_ppu->ProcessEndOfScanline(_hClock)) {
|
|
|
|
_hClock = 0;
|
|
|
|
|
|
|
|
if(_ppu->GetScanline() == 0) {
|
|
|
|
_nextEvent = SnesEventType::HdmaInit;
|
|
|
|
_nextEventClock = 12 + (_masterClock & 0x07);
|
|
|
|
} else {
|
|
|
|
_dramRefreshPosition = 538 - (_masterClock & 0x07);
|
|
|
|
_nextEvent = SnesEventType::DramRefresh;
|
|
|
|
_nextEventClock = _dramRefreshPosition;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_nextEventClock += 2;
|
2020-06-24 18:43:49 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
break;
|
2020-06-24 18:43:49 -04:00
|
|
|
}
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MemoryManager::Read(uint32_t addr, MemoryOperationType type)
|
|
|
|
{
|
2019-07-06 09:16:19 -04:00
|
|
|
IncrementMasterClockValue(_cpuSpeed - 4);
|
2019-02-26 22:27:09 -05:00
|
|
|
|
|
|
|
uint8_t value;
|
2021-03-10 11:13:28 -05:00
|
|
|
IMemoryHandler *handler = _mappings.GetHandler(addr);
|
|
|
|
if(handler) {
|
2019-07-25 22:22:09 -04:00
|
|
|
value = handler->Read(addr);
|
|
|
|
_memTypeBusA = handler->GetMemoryType();
|
2019-03-09 00:31:54 -05:00
|
|
|
_openBus = value;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-02-26 22:27:09 -05:00
|
|
|
//open bus
|
2019-03-09 00:31:54 -05:00
|
|
|
value = _openBus;
|
2019-07-25 22:22:09 -04:00
|
|
|
LogDebug("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
2019-10-12 22:40:25 -04:00
|
|
|
_cheatManager->ApplyCheat(addr, value);
|
2019-07-25 22:22:09 -04:00
|
|
|
_console->ProcessMemoryRead<CpuType::Cpu>(addr, value, type);
|
2019-07-06 09:16:19 -04:00
|
|
|
|
2019-07-12 23:55:18 -04:00
|
|
|
IncMasterClock4();
|
2019-02-26 22:27:09 -05:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2019-03-16 16:36:58 -04:00
|
|
|
uint8_t MemoryManager::ReadDma(uint32_t addr, bool forBusA)
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
2019-12-05 21:51:03 -05:00
|
|
|
_cpu->DetectNmiSignalEdge();
|
2019-07-12 23:55:18 -04:00
|
|
|
IncMasterClock4();
|
2019-04-20 09:30:51 -04:00
|
|
|
|
2019-02-26 22:27:09 -05:00
|
|
|
uint8_t value;
|
2019-07-25 22:22:09 -04:00
|
|
|
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(handler) {
|
|
|
|
if(forBusA && handler == _registerHandlerB.get() && (addr & 0xFF00) == 0x2100) {
|
2019-03-16 16:36:58 -04:00
|
|
|
//Trying to read from bus B using bus A returns open bus
|
|
|
|
value = _openBus;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(handler == _registerHandlerA.get()) {
|
2019-03-16 16:36:58 -04:00
|
|
|
uint16_t regAddr = addr & 0xFFFF;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(regAddr == 0x420B || regAddr == 0x420C || (regAddr >= 0x4300 && regAddr <= 0x437F)) {
|
2019-03-16 16:36:58 -04:00
|
|
|
//Trying to read the DMA controller with DMA returns open bus
|
|
|
|
value = _openBus;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
value = handler->Read(addr);
|
2019-03-16 16:36:58 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
value = handler->Read(addr);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(handler != _registerHandlerB.get()) {
|
2019-07-25 22:22:09 -04:00
|
|
|
_memTypeBusA = handler->GetMemoryType();
|
|
|
|
}
|
2019-03-16 16:36:58 -04:00
|
|
|
}
|
2019-03-09 00:31:54 -05:00
|
|
|
_openBus = value;
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-02-26 22:27:09 -05:00
|
|
|
//open bus
|
2019-03-09 00:31:54 -05:00
|
|
|
value = _openBus;
|
2019-07-25 22:22:09 -04:00
|
|
|
LogDebug("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
2019-10-12 22:40:25 -04:00
|
|
|
_cheatManager->ApplyCheat(addr, value);
|
2019-07-25 22:22:09 -04:00
|
|
|
_console->ProcessMemoryRead<CpuType::Cpu>(addr, value, MemoryOperationType::DmaRead);
|
2019-02-26 22:27:09 -05:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MemoryManager::Peek(uint32_t addr)
|
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
return _mappings.Peek(addr);
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
2019-02-28 16:53:04 -05:00
|
|
|
uint16_t MemoryManager::PeekWord(uint32_t addr)
|
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
return _mappings.PeekWord(addr);
|
2019-02-28 16:53:04 -05:00
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void MemoryManager::PeekBlock(uint32_t addr, uint8_t *dest)
|
2019-03-26 22:34:48 -04:00
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
_mappings.PeekBlock(addr, dest);
|
2019-03-26 22:34:48 -04:00
|
|
|
}
|
|
|
|
|
2019-02-26 22:27:09 -05:00
|
|
|
void MemoryManager::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
|
|
|
{
|
2019-07-12 23:55:18 -04:00
|
|
|
IncrementMasterClockValue(_cpuSpeed);
|
2019-02-26 22:27:09 -05:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
_console->ProcessMemoryWrite<CpuType::Cpu>(addr, value, type);
|
|
|
|
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(handler) {
|
2019-07-25 22:22:09 -04:00
|
|
|
handler->Write(addr, value);
|
|
|
|
_memTypeBusA = handler->GetMemoryType();
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 16:36:58 -04:00
|
|
|
void MemoryManager::WriteDma(uint32_t addr, uint8_t value, bool forBusA)
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
2019-12-05 21:51:03 -05:00
|
|
|
_cpu->DetectNmiSignalEdge();
|
2019-07-12 23:55:18 -04:00
|
|
|
IncMasterClock4();
|
2019-07-25 22:22:09 -04:00
|
|
|
_console->ProcessMemoryWrite<CpuType::Cpu>(addr, value, MemoryOperationType::DmaWrite);
|
2019-03-16 16:36:58 -04:00
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(handler) {
|
|
|
|
if(forBusA && handler == _registerHandlerB.get() && (addr & 0xFF00) == 0x2100) {
|
2019-03-16 16:36:58 -04:00
|
|
|
//Trying to write to bus B using bus A does nothing
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(handler == _registerHandlerA.get()) {
|
2019-03-16 16:36:58 -04:00
|
|
|
uint16_t regAddr = addr & 0xFFFF;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(regAddr == 0x420B || regAddr == 0x420C || (regAddr >= 0x4300 && regAddr <= 0x437F)) {
|
2019-03-16 16:36:58 -04:00
|
|
|
//Trying to write to the DMA controller with DMA does nothing
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
handler->Write(addr, value);
|
2019-03-16 16:36:58 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
handler->Write(addr, value);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(handler != _registerHandlerB.get()) {
|
2019-07-25 22:22:09 -04:00
|
|
|
_memTypeBusA = handler->GetMemoryType();
|
|
|
|
}
|
2019-03-16 16:36:58 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-07-25 22:22:09 -04:00
|
|
|
LogDebug("[Debug] Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-09 00:31:54 -05:00
|
|
|
uint8_t MemoryManager::GetOpenBus()
|
|
|
|
{
|
|
|
|
return _openBus;
|
|
|
|
}
|
|
|
|
|
2019-02-26 22:27:09 -05:00
|
|
|
uint64_t MemoryManager::GetMasterClock()
|
|
|
|
{
|
|
|
|
return _masterClock;
|
|
|
|
}
|
|
|
|
|
2019-04-20 11:46:51 -04:00
|
|
|
uint16_t MemoryManager::GetHClock()
|
|
|
|
{
|
|
|
|
return _hClock;
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
uint8_t * MemoryManager::DebugGetWorkRam()
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
|
|
|
return _workRam;
|
|
|
|
}
|
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
MemoryMappings* MemoryManager::GetMemoryMappings()
|
|
|
|
{
|
|
|
|
return &_mappings;
|
|
|
|
}
|
|
|
|
|
2019-04-20 09:30:51 -04:00
|
|
|
uint8_t MemoryManager::GetCpuSpeed(uint32_t addr)
|
|
|
|
{
|
2020-06-24 18:43:49 -04:00
|
|
|
return _masterClockTable[(_regs->IsFastRomEnabled() << 10) | ((addr & 0xC00000) >> 14) | ((addr & 0xFF00) >> 8)];
|
2019-04-20 09:30:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MemoryManager::GetCpuSpeed()
|
|
|
|
{
|
|
|
|
return _cpuSpeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::SetCpuSpeed(uint8_t speed)
|
|
|
|
{
|
|
|
|
_cpuSpeed = speed;
|
|
|
|
}
|
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
SnesMemoryType MemoryManager::GetMemoryTypeBusA()
|
2019-03-07 20:12:32 -05:00
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
return _memTypeBusA;
|
2019-03-07 20:12:32 -05:00
|
|
|
}
|
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
bool MemoryManager::IsRegister(uint32_t cpuAddress)
|
2019-03-09 14:27:32 -05:00
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
IMemoryHandler* handler = _mappings.GetHandler(cpuAddress);
|
|
|
|
return handler == _registerHandlerA.get() || handler == _registerHandlerB.get();
|
2019-03-09 14:27:32 -05:00
|
|
|
}
|
|
|
|
|
2019-07-25 22:22:09 -04:00
|
|
|
bool MemoryManager::IsWorkRam(uint32_t cpuAddress)
|
2019-02-26 22:27:09 -05:00
|
|
|
{
|
2019-07-25 22:22:09 -04:00
|
|
|
IMemoryHandler* handler = _mappings.GetHandler(cpuAddress);
|
|
|
|
return handler && handler->GetMemoryType() == SnesMemoryType::WorkRam;
|
2019-02-26 22:27:09 -05:00
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void MemoryManager::Serialize(Serializer &s)
|
2019-03-12 09:15:57 -04:00
|
|
|
{
|
2020-06-24 18:43:49 -04:00
|
|
|
s.Stream(_masterClock, _openBus, _cpuSpeed, _hClock, _dramRefreshPosition);
|
2019-03-12 09:15:57 -04:00
|
|
|
s.StreamArray(_workRam, MemoryManager::WorkRamSize);
|
2020-06-24 18:43:49 -04:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(s.GetVersion() < 8) {
|
2020-06-24 18:43:49 -04:00
|
|
|
bool unusedHasEvent[1369];
|
|
|
|
s.StreamArray(unusedHasEvent, sizeof(unusedHasEvent));
|
|
|
|
}
|
|
|
|
|
2019-10-14 17:10:56 -04:00
|
|
|
s.Stream(_registerHandlerB.get());
|
2019-03-12 09:15:57 -04:00
|
|
|
}
|