PPU VRAM, partially fixes tests
This commit is contained in:
parent
cc674a7467
commit
3ad6418726
9 changed files with 160 additions and 71 deletions
|
@ -27,6 +27,7 @@ class BaseMapper : public IMemoryHandler
|
||||||
class DefaultMapper : public BaseMapper
|
class DefaultMapper : public BaseMapper
|
||||||
{
|
{
|
||||||
vector<MemoryBank*> _mappedRomBanks;
|
vector<MemoryBank*> _mappedRomBanks;
|
||||||
|
MemoryBank *_mappedVromBank;
|
||||||
private:
|
private:
|
||||||
void InitMapper()
|
void InitMapper()
|
||||||
{
|
{
|
||||||
|
@ -35,23 +36,40 @@ class DefaultMapper : public BaseMapper
|
||||||
} else {
|
} else {
|
||||||
_mappedRomBanks = { &_romBanks[0], &_romBanks[1] };
|
_mappedRomBanks = { &_romBanks[0], &_romBanks[1] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_mappedVromBank = &_vromBanks[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::array<int, 2> GetIOAddresses()
|
vector<std::array<uint16_t, 2>> GetRAMAddresses()
|
||||||
{
|
{
|
||||||
return std::array<int, 2> {{ 0x8000, 0xFFFF }};
|
return { { { 0x8000, 0xFFFF } } };
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<std::array<uint16_t, 2>> GetVRAMAddresses()
|
||||||
|
{
|
||||||
|
return { { { 0x0000, 0x1FFF } } };
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t MemoryRead(uint16_t addr)
|
uint8_t ReadRAM(uint16_t addr)
|
||||||
{
|
{
|
||||||
return (*_mappedRomBanks[(addr >> 14) & 0x01])[addr & 0x3FFF];
|
return (*_mappedRomBanks[(addr >> 14) & 0x01])[addr & 0x3FFF];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryWrite(uint16_t addr, uint8_t value)
|
void WriteRAM(uint16_t addr, uint8_t value)
|
||||||
{
|
{
|
||||||
(*_mappedRomBanks[(addr >> 14) & 0x01])[addr & 0x3FFF] = value;
|
(*_mappedRomBanks[(addr >> 14) & 0x01])[addr & 0x3FFF] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t ReadVRAM(uint16_t addr)
|
||||||
|
{
|
||||||
|
return (*_mappedVromBank)[addr & 0x1FFF];
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteVRAM(uint16_t addr, uint8_t value)
|
||||||
|
{
|
||||||
|
(*_mappedVromBank)[addr & 0x1FFF] = value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapperFactory
|
class MapperFactory
|
||||||
|
|
17
Core/CPU.h
17
Core/CPU.h
|
@ -144,7 +144,7 @@ private:
|
||||||
uint8_t SP() { return _state.SP; }
|
uint8_t SP() { return _state.SP; }
|
||||||
void SetSP(uint8_t value) { _state.SP = value; }
|
void SetSP(uint8_t value) { _state.SP = value; }
|
||||||
uint8_t PS() { return _state.PS; }
|
uint8_t PS() { return _state.PS; }
|
||||||
void SetPS(uint8_t value) { _state.PS = value | PSFlags::Reserved; }
|
void SetPS(uint8_t value) { _state.PS = (value & 0xDF) | PSFlags::Reserved; }
|
||||||
uint16_t PC() { return _state.PC; }
|
uint16_t PC() { return _state.PC; }
|
||||||
void SetPC(uint16_t value) { _state.PC = value; }
|
void SetPC(uint16_t value) { _state.PC = value; }
|
||||||
|
|
||||||
|
@ -182,8 +182,7 @@ private:
|
||||||
|
|
||||||
uint16_t GetInd() {
|
uint16_t GetInd() {
|
||||||
uint16_t addr = ReadWord();
|
uint16_t addr = ReadWord();
|
||||||
if(addr & 0xFF == 0xFF) {
|
if((addr & 0xFF) == 0xFF) {
|
||||||
//Emulate a CPU bug when crossing page boundary
|
|
||||||
auto lo = MemoryRead(addr);
|
auto lo = MemoryRead(addr);
|
||||||
auto hi = MemoryRead(addr - 0xFF);
|
auto hi = MemoryRead(addr - 0xFF);
|
||||||
return (lo | hi << 8);
|
return (lo | hi << 8);
|
||||||
|
@ -250,7 +249,7 @@ private:
|
||||||
if(reg == value) {
|
if(reg == value) {
|
||||||
SetFlags(PSFlags::Zero);
|
SetFlags(PSFlags::Zero);
|
||||||
}
|
}
|
||||||
if(result & 0x80 == 0x80) {
|
if((result & 0x80) == 0x80) {
|
||||||
SetFlags(PSFlags::Negative);
|
SetFlags(PSFlags::Negative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,8 +436,8 @@ private:
|
||||||
|
|
||||||
void PHA() { Push(A()); }
|
void PHA() { Push(A()); }
|
||||||
void PHP() {
|
void PHP() {
|
||||||
SetFlags(PSFlags::Break);
|
uint8_t flags = PS() | PSFlags::Break;
|
||||||
Push((uint8_t)PS());
|
Push((uint8_t)flags);
|
||||||
}
|
}
|
||||||
void PLA() { SetA(Pop()); }
|
void PLA() { SetA(Pop()); }
|
||||||
void PLP() { SetPS(Pop()); }
|
void PLP() { SetPS(Pop()); }
|
||||||
|
@ -607,11 +606,11 @@ private:
|
||||||
void SEI() { SetFlags(PSFlags::Interrupt); }
|
void SEI() { SetFlags(PSFlags::Interrupt); }
|
||||||
|
|
||||||
void BRK() {
|
void BRK() {
|
||||||
SetFlags(PSFlags::Break);
|
|
||||||
Push((uint16_t)(PC() + 1));
|
Push((uint16_t)(PC() + 1));
|
||||||
Push((uint8_t)PS());
|
|
||||||
|
uint8_t flags = PS() | PSFlags::Break;
|
||||||
|
Push((uint8_t)flags);
|
||||||
SetFlags(PSFlags::Interrupt);
|
SetFlags(PSFlags::Interrupt);
|
||||||
ClearFlags(PSFlags::Break);
|
|
||||||
|
|
||||||
SetPC(MemoryReadWord(0xFFFE));
|
SetPC(MemoryReadWord(0xFFFE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ Console::Console(string filename)
|
||||||
{
|
{
|
||||||
_mapper = MapperFactory::InitializeFromFile(filename);
|
_mapper = MapperFactory::InitializeFromFile(filename);
|
||||||
_memoryManager.RegisterIODevice(_mapper.get());
|
_memoryManager.RegisterIODevice(_mapper.get());
|
||||||
_memoryManager.RegisterIODevice(&_ppu);
|
|
||||||
_cpu.reset(new CPU(&_memoryManager));
|
_cpu.reset(new CPU(&_memoryManager));
|
||||||
|
_ppu.reset(new PPU(&_memoryManager));
|
||||||
|
_memoryManager.RegisterIODevice(_ppu.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::~Console()
|
Console::~Console()
|
||||||
{
|
{
|
||||||
_cpu.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::Reset()
|
void Console::Reset()
|
||||||
|
@ -24,65 +24,72 @@ void Console::Run()
|
||||||
{
|
{
|
||||||
while(true) {
|
while(true) {
|
||||||
_cpu->Exec();
|
_cpu->Exec();
|
||||||
_ppu.Exec();
|
_ppu->Exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::RunTest(bool callback(Console*))
|
void Console::RunTest(bool callback(Console*))
|
||||||
{
|
{
|
||||||
while(true) {
|
while(true) {
|
||||||
_cpu->Exec();
|
|
||||||
_ppu.Exec();
|
|
||||||
|
|
||||||
if(callback(this)) {
|
if(callback(this)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cpu->Exec();
|
||||||
|
_ppu->Exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::RunTests()
|
void Console::RunTests()
|
||||||
{
|
{
|
||||||
/*Console *console = new Console("mario.nes");
|
vector<string> testROMs {
|
||||||
console->Run();
|
//"mario"
|
||||||
delete console;*/
|
|
||||||
|
|
||||||
vector<std::string> testROMs = { {
|
|
||||||
"01-basics",
|
"01-basics",
|
||||||
"02-implied",
|
"02-implied",
|
||||||
//"03-immediate",
|
"03-immediate",
|
||||||
//"04-zero_page",
|
"04-zero_page",
|
||||||
//"05-zp_xy",
|
"05-zp_xy",
|
||||||
//"06-absolute",
|
"06-absolute",
|
||||||
//"07-abs_xy",
|
"07-abs_xy",
|
||||||
"08-ind_x",
|
"08-ind_x",
|
||||||
"09-ind_y",
|
"09-ind_y",
|
||||||
"10-branches",
|
"10-branches",
|
||||||
"11-stack",
|
"11-stack",
|
||||||
"12-jmp_jsr",
|
"12-jmp_jsr",
|
||||||
"13-rts",
|
"13-rts",
|
||||||
"14-rti",
|
"14-rti",
|
||||||
//"15-brk",
|
"15-brk",
|
||||||
"16-special"
|
"16-special"
|
||||||
} };
|
};
|
||||||
|
|
||||||
for(string testROM : testROMs) {
|
for(string testROM : testROMs) {
|
||||||
Console *console = new Console(string("TestSuite/") + testROM + ".nes");
|
Console *console = new Console(string("TestSuite/") + testROM + ".nes");
|
||||||
if(testROM == "nestest") {
|
if(testROM == "nestest") {
|
||||||
console->RunTest([] (Console *console) {
|
console->RunTest([] (Console *console) {
|
||||||
auto state = console->_cpu->GetState();
|
State state = console->_cpu->GetState();
|
||||||
std::stringstream ss;
|
std::cout << std::hex << std::uppercase <<
|
||||||
ss << std::hex << (short)state.PC << " A:" << (short)state.A << " X:" << (short)state.X << " Y:" << (short)state.Y << std::endl;
|
"A:" << std::setfill('0') << std::setw(2) << (short)state.A <<
|
||||||
OutputDebugStringA(ss.str().c_str());
|
" X:" << std::setfill('0') << std::setw(2) << (short)state.X <<
|
||||||
|
" Y:" << std::setfill('0') << std::setw(2) << (short)state.Y <<
|
||||||
|
" S:" << std::setfill('0') << std::setw(2) << (short)state.SP <<
|
||||||
|
" P:........ $" <<
|
||||||
|
std::setfill('0') << std::setw(4) << (short)state.PC <<std::endl;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console->RunTest([] (Console *console) {
|
console->RunTest([] (Console *console) {
|
||||||
//static std::ofstream output("test.log", ios::out | ios::binary);
|
static std::ofstream output("test.log", ios::out | ios::binary);
|
||||||
static bool testStarted = false;
|
static bool testStarted = false;
|
||||||
uint8_t testStatus = console->_memoryManager.Read(0x6000);
|
uint8_t testStatus = console->_memoryManager.Read(0x6000);
|
||||||
|
|
||||||
State state = console->_cpu->GetState();
|
State state = console->_cpu->GetState();
|
||||||
//output << std::hex << (short)state.PC << " A:" << (short)state.A << " X:" << (short)state.X << " Y:" << (short)state.Y << std::endl;
|
/*output << std::hex << std::uppercase <<
|
||||||
|
"A:" << std::setfill('0') << std::setw(2) << (short)state.A <<
|
||||||
|
" X:" << std::setfill('0') << std::setw(2) << (short)state.X <<
|
||||||
|
" Y:" << std::setfill('0') << std::setw(2) << (short)state.Y <<
|
||||||
|
" S:" << std::setfill('0') << std::setw(2) << (short)state.SP <<
|
||||||
|
" P:........ $" <<
|
||||||
|
std::setfill('0') << std::setw(4) << (short)state.PC <<std::endl;*/
|
||||||
|
|
||||||
if(testStatus == 0x81) {
|
if(testStatus == 0x81) {
|
||||||
//need reset
|
//need reset
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Console
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
unique_ptr<CPU> _cpu;
|
unique_ptr<CPU> _cpu;
|
||||||
PPU _ppu;
|
unique_ptr<PPU> _ppu;
|
||||||
shared_ptr<BaseMapper> _mapper;
|
shared_ptr<BaseMapper> _mapper;
|
||||||
MemoryManager _memoryManager;
|
MemoryManager _memoryManager;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
|
|
||||||
class IMemoryHandler
|
class IMemoryHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual std::array<int, 2> GetIOAddresses() = 0;
|
virtual vector<std::array<uint16_t, 2>> GetRAMAddresses() = 0;
|
||||||
virtual uint8_t MemoryRead(uint16_t addr) = 0;
|
virtual vector<std::array<uint16_t, 2>> GetVRAMAddresses() { return{}; }
|
||||||
virtual void MemoryWrite(uint16_t addr, uint8_t value) = 0;
|
virtual uint8_t ReadRAM(uint16_t addr) = 0;
|
||||||
|
virtual void WriteRAM(uint16_t addr, uint8_t value) = 0;
|
||||||
|
virtual uint8_t ReadVRAM(uint16_t addr) { return 0; }
|
||||||
|
virtual void WriteVRAM(uint16_t addr, uint8_t value) { }
|
||||||
};
|
};
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
uint8_t MemoryManager::ReadRegister(uint16_t addr)
|
uint8_t MemoryManager::ReadRegister(uint16_t addr)
|
||||||
{
|
{
|
||||||
if(_registerHandlers[addr]) {
|
if(_ramHandlers[addr]) {
|
||||||
return _registerHandlers[addr]->MemoryRead(addr);
|
return _ramHandlers[addr]->ReadRAM(addr);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,24 @@ uint8_t MemoryManager::ReadRegister(uint16_t addr)
|
||||||
|
|
||||||
void MemoryManager::WriteRegister(uint16_t addr, uint8_t value)
|
void MemoryManager::WriteRegister(uint16_t addr, uint8_t value)
|
||||||
{
|
{
|
||||||
if(_registerHandlers[addr]) {
|
if(_ramHandlers[addr]) {
|
||||||
_registerHandlers[addr]->MemoryWrite(addr, value);
|
_ramHandlers[addr]->WriteRAM(addr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MemoryManager::ReadMappedVRAM(uint16_t addr)
|
||||||
|
{
|
||||||
|
if(_vramHandlers[addr]) {
|
||||||
|
return _vramHandlers[addr]->ReadVRAM(addr);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryManager::WriteMappedVRAM(uint16_t addr, uint8_t value)
|
||||||
|
{
|
||||||
|
if(_vramHandlers[addr]) {
|
||||||
|
_vramHandlers[addr]->WriteVRAM(addr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,13 +37,19 @@ MemoryManager::MemoryManager()
|
||||||
{
|
{
|
||||||
_internalRAM = new uint8_t[InternalRAMSize];
|
_internalRAM = new uint8_t[InternalRAMSize];
|
||||||
_SRAM = new uint8_t[SRAMSize];
|
_SRAM = new uint8_t[SRAMSize];
|
||||||
|
_videoRAM = new uint8_t[VRAMSize];
|
||||||
_expansionRAM = new uint8_t[0x2000];
|
_expansionRAM = new uint8_t[0x2000];
|
||||||
ZeroMemory(_internalRAM, InternalRAMSize);
|
ZeroMemory(_internalRAM, InternalRAMSize);
|
||||||
ZeroMemory(_SRAM, SRAMSize);
|
ZeroMemory(_SRAM, SRAMSize);
|
||||||
|
ZeroMemory(_videoRAM, VRAMSize);
|
||||||
ZeroMemory(_expansionRAM, 0x2000);
|
ZeroMemory(_expansionRAM, 0x2000);
|
||||||
|
|
||||||
for(int i = 0; i <= 0xFFFF; i++) {
|
for(int i = 0; i <= 0xFFFF; i++) {
|
||||||
_registerHandlers.push_back(nullptr);
|
_ramHandlers.push_back(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i <= 0x3FFF; i++) {
|
||||||
|
_vramHandlers.push_back(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +62,18 @@ MemoryManager::~MemoryManager()
|
||||||
|
|
||||||
void MemoryManager::RegisterIODevice(IMemoryHandler *handler)
|
void MemoryManager::RegisterIODevice(IMemoryHandler *handler)
|
||||||
{
|
{
|
||||||
std::array<int, 2> addresses = handler->GetIOAddresses();
|
vector<std::array<uint16_t, 2>> addresses = handler->GetRAMAddresses();
|
||||||
for(int i = addresses[0]; i < addresses[1]; i++) {
|
for(std::array<uint16_t, 2> startEndAddr : addresses) {
|
||||||
_registerHandlers[i] = handler;
|
for(int i = startEndAddr[0]; i <= startEndAddr[1]; i++) {
|
||||||
|
_ramHandlers[i] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses = handler->GetVRAMAddresses();
|
||||||
|
for(std::array<uint16_t, 2> startEndAddr : addresses) {
|
||||||
|
for(int i = startEndAddr[0]; i <= startEndAddr[1]; i++) {
|
||||||
|
_vramHandlers[i] = handler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,4 +113,21 @@ uint16_t MemoryManager::ReadWord(uint16_t addr)
|
||||||
uint8_t hi = Read(addr+1);
|
uint8_t hi = Read(addr+1);
|
||||||
return lo | hi << 8;
|
return lo | hi << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t MemoryManager::ReadVRAM(uint16_t addr)
|
||||||
|
{
|
||||||
|
if(addr <= 0x1FFF) {
|
||||||
|
return ReadMappedVRAM(addr & 0x1FFF);
|
||||||
|
} else {
|
||||||
|
return _videoRAM[addr & 0x3FFF];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryManager::WriteVRAM(uint16_t addr, uint8_t value)
|
||||||
|
{
|
||||||
|
if(addr <= 0x1FFF) {
|
||||||
|
WriteMappedVRAM(addr, value);
|
||||||
|
} else {
|
||||||
|
_videoRAM[addr & 0x3FFF] = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,15 +8,21 @@ class MemoryManager
|
||||||
private:
|
private:
|
||||||
const int InternalRAMSize = 0x800;
|
const int InternalRAMSize = 0x800;
|
||||||
const int SRAMSize = 0x2000;
|
const int SRAMSize = 0x2000;
|
||||||
|
const int VRAMSize = 0x4000;
|
||||||
|
|
||||||
uint8_t *_internalRAM;
|
uint8_t *_internalRAM;
|
||||||
uint8_t *_expansionRAM;
|
uint8_t *_expansionRAM;
|
||||||
uint8_t *_SRAM;
|
uint8_t *_SRAM;
|
||||||
|
uint8_t *_videoRAM;
|
||||||
|
|
||||||
vector<IMemoryHandler*> _registerHandlers;
|
vector<IMemoryHandler*> _ramHandlers;
|
||||||
|
vector<IMemoryHandler*> _vramHandlers;
|
||||||
|
|
||||||
inline uint8_t ReadRegister(uint16_t addr);
|
uint8_t ReadRegister(uint16_t addr);
|
||||||
inline void WriteRegister(uint16_t addr, uint8_t value);
|
void WriteRegister(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
|
uint8_t ReadMappedVRAM(uint16_t addr);
|
||||||
|
void WriteMappedVRAM(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryManager();
|
MemoryManager();
|
||||||
|
@ -25,8 +31,12 @@ class MemoryManager
|
||||||
void RegisterIODevice(IMemoryHandler *handler);
|
void RegisterIODevice(IMemoryHandler *handler);
|
||||||
|
|
||||||
uint8_t Read(uint16_t addr);
|
uint8_t Read(uint16_t addr);
|
||||||
void Write(uint16_t addr, uint8_t value);
|
|
||||||
uint16_t ReadWord(uint16_t addr);
|
uint16_t ReadWord(uint16_t addr);
|
||||||
|
void Write(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
|
uint8_t ReadVRAM(uint16_t addr);
|
||||||
|
void WriteVRAM(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
|
|
||||||
char* GetTestResult()
|
char* GetTestResult()
|
||||||
{
|
{
|
||||||
|
|
17
Core/PPU.cpp
17
Core/PPU.cpp
|
@ -2,8 +2,9 @@
|
||||||
#include "PPU.h"
|
#include "PPU.h"
|
||||||
#include "CPU.h"
|
#include "CPU.h"
|
||||||
|
|
||||||
PPU::PPU()
|
PPU::PPU(MemoryManager *memoryManager)
|
||||||
{
|
{
|
||||||
|
_memoryManager = memoryManager;
|
||||||
_state = {};
|
_state = {};
|
||||||
_flags = {};
|
_flags = {};
|
||||||
_statusFlags = {};
|
_statusFlags = {};
|
||||||
|
@ -21,7 +22,7 @@ bool PPU::CheckFlag(PPUControlFlags flag)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t PPU::MemoryRead(uint16_t addr)
|
uint8_t PPU::ReadRAM(uint16_t addr)
|
||||||
{
|
{
|
||||||
switch(GetRegisterID(addr)) {
|
switch(GetRegisterID(addr)) {
|
||||||
case PPURegisters::Control:
|
case PPURegisters::Control:
|
||||||
|
@ -36,13 +37,14 @@ uint8_t PPU::MemoryRead(uint16_t addr)
|
||||||
return _spriteRAM[_state.SpriteRamAddr];
|
return _spriteRAM[_state.SpriteRamAddr];
|
||||||
case PPURegisters::VideoMemoryData:
|
case PPURegisters::VideoMemoryData:
|
||||||
uint8_t returnValue = _memoryReadBuffer;
|
uint8_t returnValue = _memoryReadBuffer;
|
||||||
_memoryReadBuffer = _videoRAM[_state.VideoRamAddr];
|
_memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr);
|
||||||
|
_state.VideoRamAddr += _flags.VerticalWrite ? 32 : 1;
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPU::MemoryWrite(uint16_t addr, uint8_t value)
|
void PPU::WriteRAM(uint16_t addr, uint8_t value)
|
||||||
{
|
{
|
||||||
switch(GetRegisterID(addr)) {
|
switch(GetRegisterID(addr)) {
|
||||||
case PPURegisters::Control:
|
case PPURegisters::Control:
|
||||||
|
@ -72,7 +74,8 @@ void PPU::MemoryWrite(uint16_t addr, uint8_t value)
|
||||||
_writeLow = !_writeLow;
|
_writeLow = !_writeLow;
|
||||||
break;
|
break;
|
||||||
case PPURegisters::VideoMemoryData:
|
case PPURegisters::VideoMemoryData:
|
||||||
_videoRAM[_state.VideoRamAddr&0x3FFF] = value;
|
_memoryManager->WriteVRAM(_state.VideoRamAddr, value);
|
||||||
|
_state.VideoRamAddr += _flags.VerticalWrite ? 32 : 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,8 +128,8 @@ void PPU::Exec()
|
||||||
/*if(_flags.BackgroundEnabled || _flags.SpritesEnabled) {
|
/*if(_flags.BackgroundEnabled || _flags.SpritesEnabled) {
|
||||||
//p->registers.vramAddress = p->registers.vramLatch;
|
//p->registers.vramAddress = p->registers.vramLatch;
|
||||||
}*/
|
}*/
|
||||||
} else if(_cycle == 339 && (_frameCount % 2 == 1)) {
|
} else if(_cycle == 339 && _flags.BackgroundEnabled && (_frameCount % 2 == 1)) {
|
||||||
//Skip a cycle for odd frames
|
//Skip a cycle for odd frames, if background drawing is enabled
|
||||||
_cycle++;
|
_cycle++;
|
||||||
}
|
}
|
||||||
} else if(_scanline < 240) {
|
} else if(_scanline < 240) {
|
||||||
|
|
17
Core/PPU.h
17
Core/PPU.h
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "IMemoryHandler.h"
|
#include "MemoryManager.h"
|
||||||
|
|
||||||
enum PPURegisters
|
enum PPURegisters
|
||||||
{
|
{
|
||||||
|
@ -53,12 +53,13 @@ struct PPUState
|
||||||
class PPU : public IMemoryHandler
|
class PPU : public IMemoryHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
MemoryManager *_memoryManager;
|
||||||
|
|
||||||
PPUState _state;
|
PPUState _state;
|
||||||
uint64_t _cycleCount;
|
uint64_t _cycleCount;
|
||||||
|
|
||||||
uint8_t _memoryReadBuffer;
|
uint8_t _memoryReadBuffer;
|
||||||
uint8_t _spriteRAM[0x100];
|
uint8_t _spriteRAM[0x100];
|
||||||
uint8_t _videoRAM[0x4000];
|
|
||||||
|
|
||||||
uint8_t *_outputBuffer;
|
uint8_t *_outputBuffer;
|
||||||
|
|
||||||
|
@ -82,16 +83,16 @@ class PPU : public IMemoryHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PPU();
|
PPU(MemoryManager *memoryManager);
|
||||||
~PPU();
|
~PPU();
|
||||||
|
|
||||||
std::array<int, 2> GetIOAddresses()
|
vector<std::array<uint16_t, 2>> GetRAMAddresses()
|
||||||
{
|
{
|
||||||
return std::array<int, 2> {{ 0x2000, 0x3FFF }};
|
return{ { { 0x2000, 0x3FFF } }, { {0x4014, 0x4014 } } };
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t MemoryRead(uint16_t addr);
|
uint8_t ReadRAM(uint16_t addr);
|
||||||
void MemoryWrite(uint16_t addr, uint8_t value);
|
void WriteRAM(uint16_t addr, uint8_t value);
|
||||||
|
|
||||||
void Exec();
|
void Exec();
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue