add mappercontrolled mirroring, fix irq callback

This commit is contained in:
grimoire 2022-07-18 22:07:26 +08:00
parent 3334273032
commit 9a73b46afe
8 changed files with 38 additions and 42 deletions

View file

@ -1,5 +1,6 @@
#ifndef CPU_H
#define CPU_H
#include "CPUOpcodes.h"
#include "MainBus.h"
namespace sn
@ -8,12 +9,6 @@ namespace sn
class CPU
{
public:
enum InterruptType
{
IRQ,
NMI,
BRK_
};
CPU(MainBus &mem);

View file

@ -120,8 +120,15 @@ namespace sn
TSX = 0xba,
};
enum InterruptType
{
IRQ,
NMI,
BRK_
};
//0 implies unused opcode
int OperationCycles[0x100] = {
static const int OperationCycles[0x100] = {
7, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0,
2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0,

View file

@ -1,5 +1,6 @@
#ifndef MAPPER_H
#define MAPPER_H
#include "CPUOpcodes.h"
#include "Cartridge.h"
#include <memory>
#include <functional>
@ -13,6 +14,7 @@ namespace sn
FourScreen = 8,
OneScreenLower,
OneScreenHigher,
MapperControlled,
};
@ -54,7 +56,7 @@ namespace sn
virtual void scanlineIRQ(){}
static std::unique_ptr<Mapper> createMapper (Type mapper_t, Cartridge& cart, std::function<void(int)> interrupt_cb, std::function<void(void)> mirroring_cb);
static std::unique_ptr<Mapper> createMapper (Type mapper_t, Cartridge& cart, std::function<void(InterruptType)> interrupt_cb, std::function<void(void)> mirroring_cb);
protected:
Cartridge& m_cartridge;

View file

@ -7,7 +7,7 @@ namespace sn
class MapperMMC3 : public Mapper
{
public:
MapperMMC3(Cartridge &cart, std::function<void(int)> interrupt_cb, std::function<void(void)> mirroring_cb);
MapperMMC3(Cartridge &cart, std::function<void(InterruptType)> interrupt_cb, std::function<void(void)> mirroring_cb);
Byte readPRG(Address addr);
void writePRG(Address addr, Byte value);
@ -57,7 +57,7 @@ namespace sn
std::vector<Byte> m_mirroringRAM;
std::vector<Byte> ramstatic;
std::function<void(void)> m_mirroringCallback;
std::function<void(int)> m_interruptCallback;
std::function<void(InterruptType)> m_interruptCallback;
Byte A12_count;
};

View file

@ -1,4 +1,5 @@
#include "Emulator.h"
#include "CPUOpcodes.h"
#include "Log.h"
#include <thread>
@ -36,7 +37,7 @@ namespace sn
LOG(Error) << "Critical error: Failed to set I/O callbacks" << std::endl;
}
m_ppu.setInterruptCallback([&](){ m_cpu.interrupt(CPU::NMI); });
m_ppu.setInterruptCallback([&](){ m_cpu.interrupt(InterruptType::NMI); });
}
void Emulator::run(std::string rom_path)
@ -46,7 +47,7 @@ namespace sn
m_mapper = Mapper::createMapper(static_cast<Mapper::Type>(m_cartridge.getMapper()),
m_cartridge,
[&](int type){ m_cpu.interrupt(static_cast<CPU::InterruptType>(type)); },
[&](InterruptType type){ m_cpu.interrupt(type); },
[&](){ m_pictureBus.updateMirroring(); });
if (!m_mapper)
{

View file

@ -1,4 +1,5 @@
#include "Mapper.h"
#include "CPUOpcodes.h"
#include "MapperNROM.h"
#include "MapperSxROM.h"
#include "MapperMMC3.h"
@ -15,7 +16,7 @@ namespace sn
return static_cast<NameTableMirroring>(m_cartridge.getNameTableMirroring());
}
std::unique_ptr<Mapper> Mapper::createMapper(Mapper::Type mapper_t, sn::Cartridge& cart, std::function<void(int)> interrupt_cb, std::function<void(void)> mirroring_cb)
std::unique_ptr<Mapper> Mapper::createMapper(Mapper::Type mapper_t, sn::Cartridge& cart, std::function<void(InterruptType)> interrupt_cb, std::function<void(void)> mirroring_cb)
{
std::unique_ptr<Mapper> ret(nullptr);
switch (mapper_t)

View file

@ -1,10 +1,9 @@
#include "MapperMMC3.h"
#include "CPU.h"
namespace sn
{
MapperMMC3::MapperMMC3(Cartridge &cart, std::function<void(int)> interrupt_cb, std::function<void(void)> mirroring_cb) :
MapperMMC3::MapperMMC3(Cartridge &cart, std::function<void(InterruptType)> interrupt_cb, std::function<void(void)> mirroring_cb) :
Mapper(cart, Mapper::MMC3),
m_interruptCallback(interrupt_cb),
m_mirroringCallback(mirroring_cb),
@ -21,7 +20,7 @@ namespace sn
{
ramstatic.resize(32 * 1024);
m_mirroringRAM.resize(0x800);
m_mirroringRAM.resize(0x1000);
prgbank0 = &cart.getROM()[cart.getROM().size() - 0x4000];
prgbank1 = &cart.getROM()[cart.getROM().size() - 0x2000];
@ -40,7 +39,7 @@ chrbank6 = &cart.getVROM()[cart.getVROM().size() * 0x400];
chrbank7 = &cart.getVROM()[cart.getVROM().size() * 0x400];
if (cart.getNameTableMirroring() & 0x8){
mirrormode = NameTableMirroring::FourScreen;
mirrormode = NameTableMirroring::MapperControlled;
}
}
@ -253,11 +252,11 @@ void MapperMMC3::writeCHR(Address addr, Byte value)
{}
void MapperMMC3::writeNameTable(Address addr, Byte value){
m_mirroringRAM[addr-0x2800] = value;
m_mirroringRAM[addr-0x2000] = value;
}
Byte MapperMMC3::readNameTable(Address addr){
return m_mirroringRAM[addr-0x2800];
return m_mirroringRAM[addr-0x2000];
}
bool MapperMMC3::irqState()
@ -274,7 +273,7 @@ void MapperMMC3::irqClear()
void MapperMMC3::scanline()
{
if (nIRQCounter == 0)
{
{
nIRQCounter = nIRQReload;
}
else
@ -289,7 +288,7 @@ void MapperMMC3::scanline()
void MapperMMC3::scanlineIRQ(){
scanline();
if(irqState()){
m_interruptCallback(int(CPU::InterruptType::IRQ));
m_interruptCallback(InterruptType::IRQ);
irqClear();
}
}

View file

@ -19,19 +19,15 @@ namespace sn
else if (addr < 0x3eff) //Name tables upto 0x3000, then mirrored upto 3eff
{
auto index = addr & 0x3ff;
if (addr < 0x2400) //NT0
if (NameTable0 >= m_RAM.size())
return m_mapper->readNameTable(addr);
else if (addr < 0x2400) //NT0
return m_RAM[NameTable0 + index];
else if (addr < 0x2800) //NT1
return m_RAM[NameTable1 + index];
else if (addr < 0x2c00) //NT2
if (NameTable2 == ~0ul)
return m_mapper->readNameTable(addr);
else
return m_RAM[NameTable2 + index];
return m_RAM[NameTable2 + index];
else //NT3
if (NameTable3 == ~0ul)
return m_mapper->readNameTable(addr);
else
return m_RAM[NameTable3 + index];
}
else if (addr < 0x3fff)
@ -55,20 +51,16 @@ namespace sn
else if (addr < 0x3eff) //Name tables upto 0x3000, then mirrored upto 3eff
{
auto index = addr & 0x3ff;
if (addr < 0x2400) //NT0
if (NameTable0 >= m_RAM.size())
m_mapper->writeNameTable(addr, value);
else if (addr < 0x2400) //NT0
m_RAM[NameTable0 + index] = value;
else if (addr < 0x2800) //NT1
m_RAM[NameTable1 + index] = value;
else if (addr < 0x2c00) //NT2
if (NameTable2 == ~0ul)
m_mapper->writeNameTable(addr, value);
else
m_RAM[NameTable2 + index] = value;
m_RAM[NameTable2 + index] = value;
else //NT3
if (NameTable3 == ~0ul)
m_mapper->writeNameTable(addr, value);
else
m_RAM[NameTable3 + index] = value;
m_RAM[NameTable3 + index] = value;
}
else if (addr < 0x3fff)
{
@ -102,10 +94,9 @@ namespace sn
LOG(InfoVerbose) << "Single Screen mirroring set with higher bank." << std::endl;
break;
case FourScreen:
NameTable0 = 0x0;
NameTable1 = 0x400;
NameTable2 = NameTable3 = ~0ul;
LOG(InfoVerbose) << "4 screen mirroring set." << std::endl;
case MapperControlled:
NameTable0 = m_RAM.size();
LOG(InfoVerbose) << "Mapper controlled mirroring." << std::endl;
break;
default:
NameTable0 = NameTable1 = NameTable2 = NameTable3 = 0;