2014-06-14 11:27:55 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "MemoryManager.h"
|
2015-07-01 23:17:14 -04:00
|
|
|
#include "BaseMapper.h"
|
2015-06-24 19:26:19 -04:00
|
|
|
#include "Debugger.h"
|
2015-07-05 19:05:33 -04:00
|
|
|
#include "CheatManager.h"
|
2014-06-19 19:58:15 -04:00
|
|
|
|
2016-07-12 18:25:58 -04:00
|
|
|
//Used for open bus
|
|
|
|
uint8_t MemoryManager::_lastReadValue = 0;
|
|
|
|
|
2014-06-24 02:47:32 -04:00
|
|
|
MemoryManager::MemoryManager(shared_ptr<BaseMapper> mapper)
|
2014-06-19 19:58:15 -04:00
|
|
|
{
|
2014-06-24 02:47:32 -04:00
|
|
|
_mapper = mapper;
|
2016-07-12 18:25:58 -04:00
|
|
|
_lastReadValue = 0;
|
2014-06-19 19:58:15 -04:00
|
|
|
|
|
|
|
_internalRAM = new uint8_t[InternalRAMSize];
|
2015-07-29 22:10:34 -04:00
|
|
|
for(int i = 0; i < 2; i++) {
|
2014-07-01 22:56:06 -04:00
|
|
|
_nametableRAM[i] = new uint8_t[NameTableScreenSize];
|
|
|
|
memset(_nametableRAM[i], 0, NameTableScreenSize);
|
|
|
|
}
|
2014-06-25 12:22:48 -04:00
|
|
|
|
2015-07-29 22:10:34 -04:00
|
|
|
_mapper->SetDefaultNametables(_nametableRAM[0], _nametableRAM[1]);
|
|
|
|
|
2014-06-25 12:22:48 -04:00
|
|
|
_ramReadHandlers = new IMemoryHandler*[RAMSize];
|
|
|
|
_ramWriteHandlers = new IMemoryHandler*[RAMSize];
|
|
|
|
|
2014-06-20 21:48:55 -04:00
|
|
|
memset(_internalRAM, 0, InternalRAMSize);
|
2014-06-25 12:22:48 -04:00
|
|
|
memset(_ramReadHandlers, 0, RAMSize * sizeof(IMemoryHandler*));
|
|
|
|
memset(_ramWriteHandlers, 0, RAMSize * sizeof(IMemoryHandler*));
|
2014-06-19 19:58:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryManager::~MemoryManager()
|
|
|
|
{
|
|
|
|
delete[] _internalRAM;
|
2015-07-29 22:10:34 -04:00
|
|
|
for(int i = 0; i < 2; i++) {
|
2014-07-01 22:56:06 -04:00
|
|
|
delete[] _nametableRAM[i];
|
|
|
|
}
|
2014-06-25 12:22:48 -04:00
|
|
|
|
|
|
|
delete[] _ramReadHandlers;
|
|
|
|
delete[] _ramWriteHandlers;
|
2014-06-19 19:58:15 -04:00
|
|
|
}
|
2014-06-14 11:27:55 -04:00
|
|
|
|
2015-07-05 20:30:39 -04:00
|
|
|
void MemoryManager::Reset(bool softReset)
|
|
|
|
{
|
|
|
|
if(!softReset) {
|
|
|
|
memset(_internalRAM, 0, InternalRAMSize);
|
|
|
|
}
|
2016-01-18 21:46:53 -05:00
|
|
|
|
|
|
|
_mapper->Reset(softReset);
|
2015-07-05 20:30:39 -04:00
|
|
|
}
|
|
|
|
|
2014-06-14 11:27:55 -04:00
|
|
|
uint8_t MemoryManager::ReadRegister(uint16_t addr)
|
|
|
|
{
|
2014-06-25 12:22:48 -04:00
|
|
|
if(_ramReadHandlers[addr]) {
|
|
|
|
return _ramReadHandlers[addr]->ReadRAM(addr);
|
2014-06-14 11:27:55 -04:00
|
|
|
} else {
|
2016-07-12 18:25:58 -04:00
|
|
|
return GetOpenBus();
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::WriteRegister(uint16_t addr, uint8_t value)
|
|
|
|
{
|
2014-06-25 12:22:48 -04:00
|
|
|
if(_ramWriteHandlers[addr]) {
|
|
|
|
_ramWriteHandlers[addr]->WriteRAM(addr, value);
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-25 20:46:54 -04:00
|
|
|
void MemoryManager::InitializeMemoryHandlers(IMemoryHandler** memoryHandlers, IMemoryHandler* handler, vector<uint16_t> *addresses, bool allowOverride)
|
2014-06-14 11:27:55 -04:00
|
|
|
{
|
2014-06-25 12:22:48 -04:00
|
|
|
for(uint16_t address : *addresses) {
|
2016-06-25 20:46:54 -04:00
|
|
|
if(!allowOverride && memoryHandlers[address] != nullptr) {
|
2015-07-11 08:27:22 -04:00
|
|
|
throw std::runtime_error("Not supported");
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|
2014-06-25 12:22:48 -04:00
|
|
|
memoryHandlers[address] = handler;
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|
2014-06-25 12:22:48 -04:00
|
|
|
}
|
2014-06-15 21:45:36 -04:00
|
|
|
|
2014-06-25 12:22:48 -04:00
|
|
|
void MemoryManager::RegisterIODevice(IMemoryHandler *handler)
|
|
|
|
{
|
|
|
|
MemoryRanges ranges;
|
|
|
|
handler->GetMemoryRanges(ranges);
|
|
|
|
|
2016-06-25 20:46:54 -04:00
|
|
|
InitializeMemoryHandlers(_ramReadHandlers, handler, ranges.GetRAMReadAddresses(), ranges.GetAllowOverride());
|
|
|
|
InitializeMemoryHandlers(_ramWriteHandlers, handler, ranges.GetRAMWriteAddresses(), ranges.GetAllowOverride());
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
|
2015-07-01 23:17:14 -04:00
|
|
|
uint8_t* MemoryManager::GetInternalRAM()
|
|
|
|
{
|
|
|
|
return _internalRAM;
|
|
|
|
}
|
|
|
|
|
2015-06-24 19:26:19 -04:00
|
|
|
uint8_t MemoryManager::DebugRead(uint16_t addr)
|
2014-06-14 11:27:55 -04:00
|
|
|
{
|
2015-08-05 20:40:10 -04:00
|
|
|
uint8_t value = 0x00;
|
2015-06-24 19:26:19 -04:00
|
|
|
if(addr <= 0x1FFF) {
|
2015-08-05 20:40:10 -04:00
|
|
|
value = _internalRAM[addr & 0x07FF];
|
2015-06-24 19:26:19 -04:00
|
|
|
} else if(addr > 0x4017) {
|
2015-08-05 20:40:10 -04:00
|
|
|
value = ReadRegister(addr);
|
2015-06-24 19:26:19 -04:00
|
|
|
}
|
|
|
|
|
2015-08-05 20:40:10 -04:00
|
|
|
CheatManager::ApplyRamCodes(addr, value);
|
2016-07-12 18:25:58 -04:00
|
|
|
|
2015-08-05 20:40:10 -04:00
|
|
|
return value;
|
2015-06-24 19:26:19 -04:00
|
|
|
}
|
|
|
|
|
2016-01-24 16:51:58 -05:00
|
|
|
void MemoryManager::ProcessCpuClock()
|
|
|
|
{
|
|
|
|
_mapper->ProcessCpuClock();
|
|
|
|
}
|
|
|
|
|
2015-08-17 19:32:10 -04:00
|
|
|
uint8_t MemoryManager::Read(uint16_t addr, MemoryOperationType operationType)
|
2015-06-24 19:26:19 -04:00
|
|
|
{
|
2014-06-27 12:18:07 -04:00
|
|
|
uint8_t value;
|
2014-06-14 11:27:55 -04:00
|
|
|
if(addr <= 0x1FFF) {
|
2014-06-27 12:18:07 -04:00
|
|
|
value = _internalRAM[addr & 0x07FF];
|
2014-06-14 11:27:55 -04:00
|
|
|
} else {
|
2014-06-27 12:18:07 -04:00
|
|
|
value = ReadRegister(addr);
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
2015-07-05 00:27:26 -04:00
|
|
|
|
2015-07-05 19:05:33 -04:00
|
|
|
CheatManager::ApplyRamCodes(addr, value);
|
2016-01-09 13:15:43 -05:00
|
|
|
|
|
|
|
Debugger::ProcessRamOperation(operationType, addr, value);
|
|
|
|
|
2016-07-12 18:25:58 -04:00
|
|
|
_lastReadValue = value;
|
|
|
|
|
2014-06-27 12:18:07 -04:00
|
|
|
return value;
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::Write(uint16_t addr, uint8_t value)
|
|
|
|
{
|
2016-01-09 13:15:43 -05:00
|
|
|
Debugger::ProcessRamOperation(MemoryOperationType::Write, addr, value);
|
2015-06-24 19:26:19 -04:00
|
|
|
|
2014-06-14 18:20:56 -04:00
|
|
|
if(addr <= 0x1FFF) {
|
2014-06-14 11:27:55 -04:00
|
|
|
_internalRAM[addr & 0x07FF] = value;
|
|
|
|
} else {
|
|
|
|
WriteRegister(addr, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-29 22:10:34 -04:00
|
|
|
void MemoryManager::ProcessVramAccess(uint16_t &addr)
|
|
|
|
{
|
2015-07-04 22:21:14 -04:00
|
|
|
addr &= 0x3FFF;
|
2015-07-29 22:10:34 -04:00
|
|
|
if(addr >= 0x3000) {
|
|
|
|
//Need to mirror 0x3000 writes to 0x2000, this appears to be how hardware behaves
|
|
|
|
//Required for proper MMC3 IRQ timing in Burai Fighter
|
|
|
|
addr -= 0x1000;
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|
2015-07-29 22:10:34 -04:00
|
|
|
_mapper->NotifyVRAMAddressChange(addr);
|
|
|
|
}
|
|
|
|
|
2015-08-05 20:40:10 -04:00
|
|
|
uint8_t MemoryManager::DebugReadVRAM(uint16_t addr)
|
|
|
|
{
|
|
|
|
addr &= 0x3FFF;
|
|
|
|
if(addr >= 0x3000) {
|
|
|
|
addr -= 0x1000;
|
|
|
|
}
|
2016-07-02 14:48:46 -04:00
|
|
|
return _mapper->ReadVRAM(addr, MemoryOperationType::Read);
|
2015-08-05 20:40:10 -04:00
|
|
|
}
|
|
|
|
|
2015-08-17 19:32:10 -04:00
|
|
|
uint8_t MemoryManager::ReadVRAM(uint16_t addr, MemoryOperationType operationType)
|
2015-07-29 22:10:34 -04:00
|
|
|
{
|
|
|
|
ProcessVramAccess(addr);
|
2016-07-02 14:48:46 -04:00
|
|
|
uint8_t value = _mapper->ReadVRAM(addr, operationType);
|
2016-01-09 13:15:43 -05:00
|
|
|
Debugger::ProcessVramOperation(operationType, addr, value);
|
|
|
|
return value;
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryManager::WriteVRAM(uint16_t addr, uint8_t value)
|
|
|
|
{
|
2016-01-09 13:15:43 -05:00
|
|
|
Debugger::ProcessVramOperation(MemoryOperationType::Write, addr, value);
|
2015-07-29 22:10:34 -04:00
|
|
|
ProcessVramAccess(addr);
|
|
|
|
_mapper->WriteVRAM(addr, value);
|
2014-06-25 21:52:37 -04:00
|
|
|
}
|
|
|
|
|
2015-08-14 21:50:14 -04:00
|
|
|
uint32_t MemoryManager::ToAbsoluteChrAddress(uint16_t vramAddr)
|
|
|
|
{
|
|
|
|
return _mapper->ToAbsoluteChrAddress(vramAddr);
|
|
|
|
}
|
|
|
|
|
2014-06-25 21:52:37 -04:00
|
|
|
void MemoryManager::StreamState(bool saving)
|
|
|
|
{
|
2016-06-02 23:56:11 -04: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 18:25:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MemoryManager::GetOpenBus(uint8_t mask)
|
|
|
|
{
|
|
|
|
return _lastReadValue & mask;
|
2014-06-15 21:45:36 -04:00
|
|
|
}
|