Imported existing sources
This commit is contained in:
1 parent
b848581174
commit
619ec483e7
69 files changed
+7961
-36
No files matched your search
@@ -0,0 +1,582 @@
|
||||
#include "board.h"
|
||||
|
||||
// system includes
|
||||
#include <algorithm>
|
||||
|
||||
// local includes
|
||||
#include "rom.h"
|
||||
|
||||
Board::Board(NesEmulator &emu, const Rom &rom) :
|
||||
m_emu(emu),
|
||||
m_rom(rom)
|
||||
{
|
||||
// PRG RAM
|
||||
m_sramSaveRequired = false;
|
||||
|
||||
/* foreach from db */
|
||||
{
|
||||
const int SIZE = prgRam8KbDefaultBlkCount() * 8;
|
||||
const bool BATTERY = true;
|
||||
|
||||
if (BATTERY)
|
||||
m_sramSaveRequired = true;
|
||||
|
||||
if (SIZE > 0)
|
||||
{
|
||||
int kb4_count = SIZE / 2;
|
||||
for (int i = 0; i < kb4_count; i++)
|
||||
m_prgRam.append({
|
||||
/* .ram = */ {},
|
||||
/* .enabled = */ true,
|
||||
/* .writeable = */ true,
|
||||
/* .battery = */ BATTERY
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TRAINER, it should be copied into the RAM blk at 0x7000. In this case, it should be copied into ram blk 3
|
||||
if (rom.hasTrainer)
|
||||
std::copy(std::begin(rom.trainer), std::end(rom.trainer), std::begin(m_prgRam[3].ram));
|
||||
|
||||
// CHR RAM
|
||||
// Map 8 Kb for now
|
||||
const int chr_ram_banks_1k = chrRom1KbDefaultBlkCount(); // from db
|
||||
m_chrRam.reserve(chr_ram_banks_1k);
|
||||
for (int i = 0; i < chr_ram_banks_1k; i++)
|
||||
m_chrRam.append({
|
||||
/* .ram = */ {},
|
||||
/* .enabled = */ true,
|
||||
/* .writeable = */ true,
|
||||
/* .battery = */ false
|
||||
});
|
||||
|
||||
// 6 Nametables
|
||||
}
|
||||
|
||||
Board::~Board()
|
||||
{
|
||||
}
|
||||
|
||||
QString Board::name() const
|
||||
{
|
||||
throw std::runtime_error("has not been implemented");
|
||||
}
|
||||
|
||||
quint8 Board::mapper() const
|
||||
{
|
||||
throw std::runtime_error("has not been implemented");
|
||||
}
|
||||
|
||||
void Board::hardReset()
|
||||
{
|
||||
// Use the configuration of mapper 0 (NRAM).
|
||||
// PRG Switching
|
||||
// Toggle ram/rom
|
||||
// Switch 16KB ram, from 0x4000 into 0x7000
|
||||
toggle16kPrgRam(true, PRGArea::Area4000);
|
||||
switch16kPrg(0, PRGArea::Area4000);
|
||||
// Switch 32KB rom, from 0x8000 into 0xF000
|
||||
toggle32kPrgRam(false, PRGArea::Area8000);
|
||||
switch32kPrg(0, PRGArea::Area8000);
|
||||
|
||||
// CHR Switching
|
||||
// Pattern tables
|
||||
toggle8kChrRam((chrRom1KbCount() == 0));
|
||||
switch8kChr(0);
|
||||
|
||||
// Nametables
|
||||
switch1kNmt(m_rom.mirroring);
|
||||
}
|
||||
|
||||
void Board::softReset()
|
||||
{
|
||||
}
|
||||
|
||||
quint8 Board::_readEx(quint16 address)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
return m_prgRam[prgTmpIndex].ram[address & 0xFFF];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRom4KbMask();
|
||||
return m_rom.prg[prgTmpIndex][address & 0xFFF];
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::readEx(quint16 address)
|
||||
{
|
||||
auto result = _readEx(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Board::writeEx(quint16 address, quint8 value)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
if (m_prgRam[prgTmpIndex].writeable)
|
||||
m_prgRam[prgTmpIndex].ram[address & 0xFFF] = value;
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::_readSrm(quint16 address)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
return m_prgRam[prgTmpIndex].ram[address & 0xFFF];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRom4KbMask();
|
||||
return m_rom.prg[prgTmpIndex][address & 0xFFF];
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::readSrm(quint16 address)
|
||||
{
|
||||
auto result = _readSrm(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Board::writeSrm(quint16 address, quint8 value)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
if (m_prgRam[prgTmpIndex].writeable)
|
||||
m_prgRam[prgTmpIndex].ram[address & 0xFFF] = value;
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::_readPrg(quint16 address)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
const int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
const int temp = address & 0xFFF;
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
return m_prgRam[prgTmpIndex].ram[temp];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRom4KbMask();
|
||||
const int temp = address & 0xFFF;
|
||||
return m_rom.prg[prgTmpIndex][temp];
|
||||
}
|
||||
|
||||
/*
|
||||
if (IsGameGenieActive)
|
||||
{
|
||||
foreach (GameGenieCode code in GameGenieCodes)
|
||||
{
|
||||
if (!code.Enabled)
|
||||
continue;
|
||||
|
||||
if (code.Address != addr)
|
||||
continue;
|
||||
|
||||
if (!code.IsCompare || code.Compare == return_value)
|
||||
return code.Value;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
quint8 Board::readPrg(quint16 address)
|
||||
{
|
||||
auto result = _readPrg(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Board::writePrg(quint16 address, quint8 value)
|
||||
{
|
||||
int prgTmpArea = address >> 12 & 0xF;
|
||||
if (m_prgAreaBlk[prgTmpArea].ram)
|
||||
{
|
||||
int prgTmpIndex = m_prgAreaBlk[prgTmpArea].index & prgRam4KbMask();
|
||||
|
||||
if (m_prgRam[prgTmpIndex].enabled)
|
||||
if (m_prgRam[prgTmpIndex].writeable)
|
||||
m_prgRam[prgTmpIndex].ram[address & 0xFFF] = value;
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::_readChr(quint16 address)
|
||||
{
|
||||
// 00-07 means patterntables
|
||||
// 08-11 means nametables, should not included
|
||||
// 12-15 nametables mirrors, should not included as well
|
||||
int chrTmpArea = (address >> 10) & 0x7;// 0x0000 - 0x1FFF, 0-7.
|
||||
int chrTmpIndex = m_chrAreaBlk[chrTmpArea].index;
|
||||
if (m_chrAreaBlk[chrTmpArea].ram)
|
||||
{
|
||||
chrTmpIndex &= chrRam1KbMask();
|
||||
if (m_chrRam[chrTmpIndex].enabled)
|
||||
return m_chrRam[chrTmpIndex].ram[address & 0x3FF];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chrTmpIndex &= chrRom1KbMask();
|
||||
return m_rom.chr[chrTmpIndex][address & 0x3FF];
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::readChr(quint16 address)
|
||||
{
|
||||
auto result = _readChr(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Board::writeChr(quint16 address, quint8 value)
|
||||
{
|
||||
// 00-07 means patterntables
|
||||
// 08-11 means nametables, should not included
|
||||
// 12-15 nametables mirrors, should not included as well
|
||||
int chrTmpArea = (address >> 10) & 0x7;// 0x0000 - 0x1FFF, 0-7.
|
||||
|
||||
if (m_chrAreaBlk[chrTmpArea].ram)
|
||||
{
|
||||
int chrTmpIndex = m_chrAreaBlk[chrTmpArea].index & chrRam1KbMask();
|
||||
if (m_chrRam[chrTmpIndex].enabled)
|
||||
if (m_chrRam[chrTmpIndex].writeable)
|
||||
m_chrRam[chrTmpIndex].ram[address & 0x3FF] = value;
|
||||
}
|
||||
}
|
||||
|
||||
quint8 Board::_readNmt(quint16 address)
|
||||
{
|
||||
int nmtTmpArea = (address >> 10) & 0x3;// 0x2000 - 0x2C00, 0-3.
|
||||
int nmtTmpIndex = m_nmtRam[nmtTmpArea].index;
|
||||
|
||||
return m_nmtRam[nmtTmpIndex].ram[address & 0x3FF];
|
||||
}
|
||||
|
||||
quint8 Board::readNmt(quint16 address)
|
||||
{
|
||||
auto result = _readNmt(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Board::writeNmt(quint16 address, quint8 value)
|
||||
{
|
||||
int nmtTmpArea = (address >> 10) & 0x3;// 0x2000 - 0x2C00, 0-3.
|
||||
int nmtTmpIndex = m_nmtRam[nmtTmpArea].index;
|
||||
|
||||
m_nmtRam[nmtTmpIndex].ram[address & 0x3FF] = value;
|
||||
}
|
||||
|
||||
void Board::onPpuAddressUpdate(quint16 address)
|
||||
{
|
||||
if (ppuA12ToggleTimerEnabled())
|
||||
{
|
||||
m_oldVramAddress = m_newVramAddress;
|
||||
m_newVramAddress = address & 0x1000;
|
||||
if (ppuA12TogglesOnRaisingEdge())
|
||||
{
|
||||
if (m_oldVramAddress < m_newVramAddress)
|
||||
{
|
||||
if (m_ppuCyclesTimer > 8)
|
||||
onPpuA12RaisingEdge();
|
||||
|
||||
m_ppuCyclesTimer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_oldVramAddress > m_newVramAddress)
|
||||
{
|
||||
if (m_ppuCyclesTimer > 8)
|
||||
onPpuA12RaisingEdge();
|
||||
|
||||
m_ppuCyclesTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Board::onCpuClock()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onPpuClock()
|
||||
{
|
||||
if (ppuA12ToggleTimerEnabled())
|
||||
m_ppuCyclesTimer++;
|
||||
}
|
||||
|
||||
void Board::onPpuA12RaisingEdge()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onPpuScanlineTick()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onApuClockDuration()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onApuClockEnvelope()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onApuClockSingle()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::onApuClock()
|
||||
{
|
||||
}
|
||||
|
||||
double Board::apuGetSample() const
|
||||
{
|
||||
return 0.;
|
||||
}
|
||||
|
||||
void Board::apuApplyChannelsSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void Board::readState(QDataStream &dataStream)
|
||||
{
|
||||
Q_UNUSED(dataStream)
|
||||
}
|
||||
|
||||
void Board::writeState(QDataStream &dataStream) const
|
||||
{
|
||||
Q_UNUSED(dataStream)
|
||||
}
|
||||
|
||||
int Board::prgRam8KbDefaultBlkCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Board::chrRom1KbDefaultBlkCount() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
bool Board::ppuA12ToggleTimerEnabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Board::ppuA12TogglesOnRaisingEdge() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Board::switch4kPrg(int index, PRGArea area)
|
||||
{
|
||||
m_prgAreaBlk[int(area)].index = index;
|
||||
}
|
||||
|
||||
void Board::switch8kPrg(int index, PRGArea area)
|
||||
{
|
||||
index *= 2;
|
||||
m_prgAreaBlk[int(area)].index = index;
|
||||
m_prgAreaBlk[int(area) + 1].index = index + 1;
|
||||
}
|
||||
|
||||
void Board::switch16kPrg(int index, PRGArea area)
|
||||
{
|
||||
index *= 4;
|
||||
m_prgAreaBlk[int(area)].index = index;
|
||||
m_prgAreaBlk[int(area) + 1].index = index + 1;
|
||||
m_prgAreaBlk[int(area) + 2].index = index + 2;
|
||||
m_prgAreaBlk[int(area) + 3].index = index + 3;
|
||||
}
|
||||
|
||||
void Board::switch32kPrg(int index, PRGArea area)
|
||||
{
|
||||
index *= 8;
|
||||
m_prgAreaBlk[int(area)].index = index;
|
||||
m_prgAreaBlk[int(area) + 1].index = index + 1;
|
||||
m_prgAreaBlk[int(area) + 2].index = index + 2;
|
||||
m_prgAreaBlk[int(area) + 3].index = index + 3;
|
||||
m_prgAreaBlk[int(area) + 4].index = index + 4;
|
||||
m_prgAreaBlk[int(area) + 5].index = index + 5;
|
||||
m_prgAreaBlk[int(area) + 6].index = index + 6;
|
||||
m_prgAreaBlk[int(area) + 7].index = index + 7;
|
||||
}
|
||||
|
||||
void Board::toggle4kPrgRam(bool ram, PRGArea area)
|
||||
{
|
||||
m_prgAreaBlk[int(area)].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle8kPrgRam(bool ram, PRGArea area)
|
||||
{
|
||||
m_prgAreaBlk[int(area)].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 1].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle16kPrgRam(bool ram, PRGArea area)
|
||||
{
|
||||
m_prgAreaBlk[int(area)].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 1].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 2].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 3].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle32kPrgRam(bool ram, PRGArea area)
|
||||
{
|
||||
m_prgAreaBlk[int(area)].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 1].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 2].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 3].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 4].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 5].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 6].ram = ram;
|
||||
m_prgAreaBlk[int(area) + 7].ram = ram;
|
||||
}
|
||||
|
||||
void Board::togglePrgRamEnable(bool enable)
|
||||
{
|
||||
for(auto &page : m_prgRam)
|
||||
page.enabled = enable;
|
||||
}
|
||||
|
||||
void Board::togglePrgRamWritableEnable(bool enable)
|
||||
{
|
||||
for(auto &page : m_prgRam)
|
||||
page.writeable = enable;
|
||||
}
|
||||
|
||||
void Board::toggle4kPrgRamEnabled(bool enable, int index)
|
||||
{
|
||||
m_prgRam[index].enabled = enable;
|
||||
}
|
||||
|
||||
void Board::toggle4kPrgRamWritable(bool enable, int index)
|
||||
{
|
||||
m_prgRam[index].writeable = enable;
|
||||
}
|
||||
|
||||
void Board::toggle4kPrgRamBattery(bool enable, int index)
|
||||
{
|
||||
m_prgRam[index].battery = enable;
|
||||
}
|
||||
|
||||
void Board::switch1kChr(int index, CHRArea area)
|
||||
{
|
||||
m_chrAreaBlk[int(area)].index = index;
|
||||
}
|
||||
|
||||
void Board::switch2kChr(int index, CHRArea area)
|
||||
{
|
||||
index *= 2;
|
||||
m_chrAreaBlk[int(area)].index = index;
|
||||
m_chrAreaBlk[int(area) + 1].index = index + 1;
|
||||
}
|
||||
|
||||
void Board::switch4kChr(int index, CHRArea area)
|
||||
{
|
||||
index *= 4;
|
||||
m_chrAreaBlk[int(area)].index = index;
|
||||
m_chrAreaBlk[int(area) + 1].index = index + 1;
|
||||
m_chrAreaBlk[int(area) + 2].index = index + 2;
|
||||
m_chrAreaBlk[int(area) + 3].index = index + 3;
|
||||
}
|
||||
|
||||
void Board::switch8kChr(int index)
|
||||
{
|
||||
index *= 8;
|
||||
for(int i = 0; i < 8; i++)
|
||||
m_chrAreaBlk[i].index = index + i;
|
||||
}
|
||||
|
||||
void Board::toggle1kChrRam(bool ram, CHRArea area)
|
||||
{
|
||||
m_chrAreaBlk[int(area)].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle2kChrRam(bool ram, CHRArea area)
|
||||
{
|
||||
m_chrAreaBlk[int(area)].ram = ram;
|
||||
m_chrAreaBlk[int(area) + 1].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle4kChrRam(bool ram, CHRArea area)
|
||||
{
|
||||
m_chrAreaBlk[int(area)].ram = ram;
|
||||
m_chrAreaBlk[int(area) + 1].ram = ram;
|
||||
m_chrAreaBlk[int(area) + 2].ram = ram;
|
||||
m_chrAreaBlk[int(area) + 3].ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle8kChrRam(bool ram)
|
||||
{
|
||||
for(auto &areaBlk : m_chrAreaBlk)
|
||||
areaBlk.ram = ram;
|
||||
}
|
||||
|
||||
void Board::toggle1kChrRamEnabled(bool enable, int index)
|
||||
{
|
||||
m_chrRam[index].enabled = enable;
|
||||
}
|
||||
|
||||
void Board::toggle1kChrRamWritable(bool enable, int index)
|
||||
{
|
||||
m_chrRam[index].writeable = enable;
|
||||
}
|
||||
|
||||
void Board::toggleChrRamWritableEnable(bool enable)
|
||||
{
|
||||
for (auto &ramPage : m_chrRam)
|
||||
ramPage.writeable = enable;
|
||||
}
|
||||
|
||||
void Board::toggle1kChrRamBattery(bool enable, int index)
|
||||
{
|
||||
m_chrRam[index].battery = enable;
|
||||
}
|
||||
|
||||
void Board::switch1kNmt(int index, quint8 area)
|
||||
{
|
||||
m_nmtRam[area].index = index;
|
||||
}
|
||||
|
||||
void Board::switch1kNmt(Mirroring mirroring)
|
||||
{
|
||||
// Mirroring value:
|
||||
// 0000 0000
|
||||
// ddcc bbaa
|
||||
// aa: index for area 0x2000
|
||||
// bb: index for area 0x2400
|
||||
// cc: index for area 0x2800
|
||||
// dd: index for area 0x2C00
|
||||
m_nmtRam[0].index = int(mirroring) & 0x3;
|
||||
m_nmtRam[1].index = (int(mirroring) >> 2) & 0x3;
|
||||
m_nmtRam[2].index = (int(mirroring) >> 4) & 0x3;
|
||||
m_nmtRam[3].index = (int(mirroring) >> 6) & 0x3;
|
||||
}
|
||||
|
||||
bool Board::enableExternalSound() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user