Files

235 lines
4.9 KiB
C++
Raw Permalink Normal View History

2018-12-16 22:19:06 +01:00
#include "memory.h"
// Qt includes
#include <QDataStream>
// dbcorelib includes
#include "utils/datastreamutils.h"
// local includes
#include "nesemulator.h"
#include "rom.h"
#include "mappers/mapper000.h"
#include "mappers/mapper001.h"
#include "mappers/mapper002.h"
#include "mappers/mapper003.h"
#include "mappers/mapper004.h"
Memory::Memory(NesEmulator &emu) :
m_emu(emu)
{
}
std::unique_ptr<Board> Memory::getBoard(const Rom &rom)
{
switch(rom.mapperNumber)
{
case 0: return std::make_unique<Mapper000>(m_emu, rom);
case 1: return std::make_unique<Mapper001>(m_emu, rom);
case 2: return std::make_unique<Mapper002>(m_emu, rom);
case 3: return std::make_unique<Mapper003>(m_emu, rom);
case 4: return std::make_unique<Mapper004>(m_emu, rom);
}
throw std::runtime_error(QString("unknown mapper %0").arg(rom.mapperNumber).toStdString());
}
void Memory::initialize(const Rom &rom)
{
m_board = getBoard(rom);
m_board->mapper();
}
void Memory::hardReset()
{
m_wram.fill(0);
m_wram[0x08] = 0xF7;
m_wram[0x09] = 0xEF;
m_wram[0x0A] = 0xDF;
m_wram[0x0F] = 0xBF;
loadSram();
reloadGameGenieCodes();
m_board->hardReset();
}
void Memory::loadSram()
{
//TODO
}
void Memory::reloadGameGenieCodes()
{
//TODO
}
quint8 Memory::_readWRam(const quint16 address)
{
return m_wram[wramAddressToIndex(address & 0x7FF)];
}
quint8 Memory::readWRam(const quint16 address)
{
auto result = _readWRam(address);
return result;
}
void Memory::writeWRam(const quint16 address, const quint8 value)
{
m_wram[address & 0x7FF] = value;
}
quint8 Memory::_read(quint16 address)
{
m_busRw = true;
m_busAddress = address;
m_emu.emuClockComponents();
const auto roundAddress = [](quint16 address) { return (address & 0xF000) >> 12; };
switch(roundAddress(address))
{
case roundAddress(0x0000):
case roundAddress(0x1000):
return readWRam(address);
case roundAddress(0x2000):
case roundAddress(0x3000):
return m_emu.ppu().ioRead(address);
case roundAddress(0x4000):
return m_emu.apu().ioRead(address);
case roundAddress(0x5000):
return readEx(address);
case roundAddress(0x6000):
case roundAddress(0x7000):
return readSrm(address);
case roundAddress(0x8000):
case roundAddress(0x9000):
case roundAddress(0xA000):
case roundAddress(0xB000):
case roundAddress(0xC000):
case roundAddress(0xD000):
case roundAddress(0xE000):
case roundAddress(0xF000):
return readPrg(address);
}
qFatal("undefined read");
return 0;
}
quint8 Memory::read(quint16 address)
{
auto result = _read(address);
return result;
}
void Memory::write(quint16 address, quint8 value)
{
m_busRw = false;
m_busAddress = address;
m_emu.emuClockComponents();
const auto roundAddress = [](quint16 address) { return (address & 0xF000) >> 12; };
switch(roundAddress(address))
{
case roundAddress(0x0000):
case roundAddress(0x1000):
writeWRam(address, value);
break;
case roundAddress(0x2000):
case roundAddress(0x3000):
m_emu.ppu().ioWrite(address, value);
break;
case roundAddress(0x4000):
m_emu.apu().ioWrite(address, value);
break;
case roundAddress(0x5000):
writeEx(address, value);
break;
case roundAddress(0x6000):
case roundAddress(0x7000):
writeSrm(address, value);
break;
case roundAddress(0x8000):
case roundAddress(0x9000):
case roundAddress(0xA000):
case roundAddress(0xB000):
case roundAddress(0xC000):
case roundAddress(0xD000):
case roundAddress(0xE000):
case roundAddress(0xF000):
writePrg(address, value);
break;
default:
qFatal("undefined write");
}
}
quint8 Memory::readEx(const quint16 address)
{
return m_board->readEx(address);
}
void Memory::writeEx(const quint16 address, const quint8 value)
{
m_board->writeEx(address, value);
}
quint8 Memory::readSrm(const quint16 address)
{
return m_board->readSrm(address);
}
void Memory::writeSrm(const quint16 address, const quint8 value)
{
m_board->writeSrm(address, value);
}
quint8 Memory::readPrg(const quint16 address)
{
return m_board->readPrg(address);
}
void Memory::writePrg(const quint16 address, const quint8 value)
{
m_board->writePrg(address, value);
}
void Memory::readState(QDataStream &dataStream)
{
dataStream >> m_wram >> m_busRw >> m_busAddress;
m_board->readState(dataStream);
}
void Memory::writeState(QDataStream &dataStream) const
{
dataStream << m_wram << m_busRw << m_busAddress;
m_board->writeState(dataStream);
}
Board *Memory::board()
{
return m_board.get();
}
const Board *Memory::board() const
{
return m_board.get();
}
bool Memory::busRw() const
{
return m_busRw;
}
quint16 Memory::busAddress() const
{
return m_busAddress;
}
const std::array<quint8, 0x0800> &Memory::wram() const
{
return m_wram;
}