2014-06-14 15:27:55 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "MemoryManager.h"
|
2015-07-02 03:17:14 +00:00
|
|
|
#include "BaseMapper.h"
|
2015-06-24 23:26:19 +00:00
|
|
|
#include "Debugger.h"
|
2015-07-05 23:05:33 +00:00
|
|
|
#include "CheatManager.h"
|
2018-07-01 19:21:05 +00:00
|
|
|
#include "Console.h"
|
2014-06-19 23:58:15 +00:00
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
MemoryManager::MemoryManager(shared_ptr<Console> console)
|
2014-06-19 23:58:15 +00:00
|
|
|
{
|
2018-07-01 19:21:05 +00:00
|
|
|
_console = console;
|
2014-06-19 23:58:15 +00:00
|
|
|
_internalRAM = new uint8_t[InternalRAMSize];
|
2018-06-25 16:58:01 +00:00
|
|
|
_internalRamHandler.SetInternalRam(_internalRAM);
|
|
|
|
|
2015-07-30 02:10:34 +00:00
|
|
|
for(int i = 0; i < 2; i++) {
|
2014-07-02 02:56:06 +00:00
|
|
|
_nametableRAM[i] = new uint8_t[NameTableScreenSize];
|
2018-07-14 02:19:26 +00:00
|
|
|
_console->GetMapper()->InitializeRam(_nametableRAM[i], NameTableScreenSize);
|
2014-07-02 02:56:06 +00:00
|
|
|
}
|
2014-06-25 16:22:48 +00:00
|
|
|
|
|
|
|
_ramReadHandlers = new IMemoryHandler*[RAMSize];
|
|
|
|
_ramWriteHandlers = new IMemoryHandler*[RAMSize];
|
2016-08-24 21:32:22 +00:00
|
|
|
|
2018-06-25 16:58:01 +00:00
|
|
|
for(int i = 0; i < RAMSize; i++) {
|
|
|
|
_ramReadHandlers[i] = &_openBusHandler;
|
|
|
|
_ramWriteHandlers[i] = &_openBusHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterIODevice(&_internalRamHandler);
|
2014-06-19 23:58:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryManager::~MemoryManager()
|
|
|
|
{
|
|
|
|
delete[] _internalRAM;
|
2015-07-30 02:10:34 +00:00
|
|
|
for(int i = 0; i < 2; i++) {
|
2014-07-02 02:56:06 +00:00
|
|
|
delete[] _nametableRAM[i];
|
|
|
|
}
|
2014-06-25 16:22:48 +00:00
|
|
|
|
|
|
|
delete[] _ramReadHandlers;
|
|
|
|
delete[] _ramWriteHandlers;
|
2014-06-19 23:58:15 +00:00
|
|
|
}
|
2014-06-14 15:27:55 +00:00
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
void MemoryManager::SetMapper(shared_ptr<BaseMapper> mapper)
|
|
|
|
{
|
|
|
|
_mapper = mapper;
|
|
|
|
_mapper->SetDefaultNametables(_nametableRAM[0], _nametableRAM[1]);
|
|
|
|
}
|
|
|
|
|
2015-07-06 00:30:39 +00:00
|
|
|
void MemoryManager::Reset(bool softReset)
|
|
|
|
{
|
|
|
|
if(!softReset) {
|
2018-07-14 02:19:26 +00:00
|
|
|
_mapper->InitializeRam(_internalRAM, InternalRAMSize);
|
2015-07-06 00:30:39 +00:00
|
|
|
}
|
2016-01-19 02:46:53 +00:00
|
|
|
|
|
|
|
_mapper->Reset(softReset);
|
2015-07-06 00:30:39 +00:00
|
|
|
}
|
|
|
|
|
2016-06-26 00:46:54 +00:00
|
|
|
void MemoryManager::InitializeMemoryHandlers(IMemoryHandler** memoryHandlers, IMemoryHandler* handler, vector<uint16_t> *addresses, bool allowOverride)
|
2014-06-14 15:27:55 +00:00
|
|
|
{
|
2014-06-25 16:22:48 +00:00
|
|
|
for(uint16_t address : *addresses) {
|
2018-06-25 16:58:01 +00:00
|
|
|
if(!allowOverride && memoryHandlers[address] != &_openBusHandler && memoryHandlers[address] != handler) {
|
2015-07-11 12:27:22 +00:00
|
|
|
throw std::runtime_error("Not supported");
|
2014-06-16 01:45:36 +00:00
|
|
|
}
|
2014-06-25 16:22:48 +00:00
|
|
|
memoryHandlers[address] = handler;
|
2014-06-16 01:45:36 +00:00
|
|
|
}
|
2014-06-25 16:22:48 +00:00
|
|
|
}
|
2014-06-16 01:45:36 +00:00
|
|
|
|
2014-06-25 16:22:48 +00:00
|
|
|
void MemoryManager::RegisterIODevice(IMemoryHandler *handler)
|
|
|
|
{
|
|
|
|
MemoryRanges ranges;
|
|
|
|
handler->GetMemoryRanges(ranges);
|
|
|
|
|
2016-06-26 00:46:54 +00:00
|
|
|
InitializeMemoryHandlers(_ramReadHandlers, handler, ranges.GetRAMReadAddresses(), ranges.GetAllowOverride());
|
|
|
|
InitializeMemoryHandlers(_ramWriteHandlers, handler, ranges.GetRAMWriteAddresses(), ranges.GetAllowOverride());
|
2014-06-14 15:27:55 +00:00
|
|
|
}
|
|
|
|
|
2017-03-12 02:03:45 +00:00
|
|
|
void MemoryManager::UnregisterIODevice(IMemoryHandler *handler)
|
|
|
|
{
|
|
|
|
MemoryRanges ranges;
|
|
|
|
handler->GetMemoryRanges(ranges);
|
|
|
|
|
|
|
|
for(uint16_t address : *ranges.GetRAMReadAddresses()) {
|
2018-06-25 16:58:01 +00:00
|
|
|
_ramReadHandlers[address] = &_openBusHandler;
|
2017-03-12 02:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(uint16_t address : *ranges.GetRAMWriteAddresses()) {
|
2018-06-25 16:58:01 +00:00
|
|
|
_ramWriteHandlers[address] = &_openBusHandler;
|
2017-03-12 02:03:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
uint8_t* MemoryManager::GetInternalRAM()
|
|
|
|
{
|
|
|
|
return _internalRAM;
|
|
|
|
}
|
|
|
|
|
2017-08-30 22:31:27 +00:00
|
|
|
uint8_t MemoryManager::DebugRead(uint16_t addr, bool disableSideEffects)
|
2014-06-14 15:27:55 +00:00
|
|
|
{
|
2015-08-06 00:40:10 +00:00
|
|
|
uint8_t value = 0x00;
|
2015-06-24 23:26:19 +00:00
|
|
|
if(addr <= 0x1FFF) {
|
2018-06-25 16:58:01 +00:00
|
|
|
value = _ramReadHandlers[addr]->ReadRAM(addr);
|
2017-08-30 22:31:27 +00:00
|
|
|
} else {
|
|
|
|
IMemoryHandler* handler = _ramReadHandlers[addr];
|
|
|
|
if(handler) {
|
2017-09-02 22:33:51 +00:00
|
|
|
if(disableSideEffects) {
|
|
|
|
if(handler == _mapper.get()) {
|
|
|
|
//Only allow reads from prg/chr ram/rom (e.g not ppu, apu, mapper registers, etc.)
|
|
|
|
value = ((BaseMapper*)handler)->DebugReadRAM(addr);
|
|
|
|
}
|
2017-08-30 22:31:27 +00:00
|
|
|
} else {
|
|
|
|
value = handler->ReadRAM(addr);
|
|
|
|
}
|
|
|
|
} else {
|
2017-12-26 22:33:46 +00:00
|
|
|
//Fake open bus
|
|
|
|
value = addr >> 8;
|
2017-08-30 22:31:27 +00:00
|
|
|
}
|
2015-06-24 23:26:19 +00:00
|
|
|
}
|
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
_console->GetCheatManager()->ApplyRamCodes(addr, value);
|
2016-07-12 22:25:58 +00:00
|
|
|
|
2015-08-06 00:40:10 +00:00
|
|
|
return value;
|
2015-06-24 23:26:19 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 03:34:47 +00:00
|
|
|
uint16_t MemoryManager::DebugReadWord(uint16_t addr)
|
|
|
|
{
|
|
|
|
return DebugRead(addr) | (DebugRead(addr + 1) << 8);
|
|
|
|
}
|
|
|
|
|
2015-08-17 23:32:10 +00:00
|
|
|
uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType)
|
2015-06-24 23:26:19 +00:00
|
|
|
{
|
2018-06-25 16:58:01 +00:00
|
|
|
uint8_t value = _ramReadHandlers[addr]->ReadRAM(addr);
|
2018-07-01 19:21:05 +00:00
|
|
|
_console->GetCheatManager()->ApplyRamCodes(addr, value);
|
|
|
|
_console->DebugProcessRamOperation(operationType, addr, value);
|
2016-01-09 18:15:43 +00:00
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
_openBusHandler.SetOpenBus(value);
|
2016-07-12 22:25:58 +00:00
|
|
|
|
2014-06-27 16:18:07 +00:00
|
|
|
return value;
|
2014-06-14 15:27:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::Write(uint16_t addr, uint8_t value)
|
|
|
|
{
|
2018-07-01 19:21:05 +00:00
|
|
|
if(_console->DebugProcessRamOperation(MemoryOperationType::Write, addr, value)) {
|
2018-06-25 16:58:01 +00:00
|
|
|
_ramWriteHandlers[addr]->WriteRAM(addr, value);
|
2014-06-14 15:27:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-30 22:31:27 +00:00
|
|
|
void MemoryManager::DebugWrite(uint16_t addr, uint8_t value, bool disableSideEffects)
|
2016-09-05 13:05:34 +00:00
|
|
|
{
|
|
|
|
if(addr <= 0x1FFF) {
|
2018-06-25 16:58:01 +00:00
|
|
|
_ramWriteHandlers[addr]->WriteRAM(addr, value);
|
2016-09-05 13:05:34 +00:00
|
|
|
} else {
|
2017-08-30 22:31:27 +00:00
|
|
|
IMemoryHandler* handler = _ramReadHandlers[addr];
|
|
|
|
if(handler) {
|
2017-09-02 22:33:51 +00:00
|
|
|
if(disableSideEffects) {
|
|
|
|
if(handler == _mapper.get()) {
|
|
|
|
//Only allow writes to prg/chr ram/rom (e.g not ppu, apu, mapper registers, etc.)
|
|
|
|
((BaseMapper*)handler)->DebugWriteRAM(addr, value);
|
|
|
|
}
|
2017-08-30 22:31:27 +00:00
|
|
|
} else {
|
|
|
|
handler->WriteRAM(addr, value);
|
|
|
|
}
|
|
|
|
}
|
2016-09-05 13:05:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 03:34:47 +00:00
|
|
|
uint32_t MemoryManager::ToAbsolutePrgAddress(uint16_t ramAddr)
|
|
|
|
{
|
|
|
|
return _mapper->ToAbsoluteAddress(ramAddr);
|
|
|
|
}
|
|
|
|
|
2014-06-26 01:52:37 +00:00
|
|
|
void MemoryManager::StreamState(bool saving)
|
|
|
|
{
|
2016-06-03 03:56:11 +00:00
|
|
|
ArrayInfo<uint8_t> internalRam = { _internalRAM, MemoryManager::InternalRAMSize };
|
|
|
|
ArrayInfo<uint8_t> nameTable0Ram = { _nametableRAM[0], MemoryManager::NameTableScreenSize };
|
|
|
|
ArrayInfo<uint8_t> nameTable1Ram = { _nametableRAM[1], MemoryManager::NameTableScreenSize };
|
|
|
|
Stream(internalRam, nameTable0Ram, nameTable1Ram);
|
2016-07-12 22:25:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MemoryManager::GetOpenBus(uint8_t mask)
|
|
|
|
{
|
2018-07-01 19:21:05 +00:00
|
|
|
return _openBusHandler.GetOpenBus() & mask;
|
|
|
|
}
|