This commit is contained in:
Souryo 2014-06-15 09:35:17 -04:00
parent 177d53e8bf
commit 608c9a03cf
5 changed files with 62 additions and 36 deletions

View file

@ -3,6 +3,7 @@
#include "Timer.h" #include "Timer.h"
uint64_t CPU::CycleCount = 0; uint64_t CPU::CycleCount = 0;
bool CPU::NMIFlag = false;
CPU::CPU(MemoryManager *memoryManager) : _memoryManager(memoryManager) CPU::CPU(MemoryManager *memoryManager) : _memoryManager(memoryManager)
{ {
@ -63,11 +64,17 @@ void CPU::Reset()
void CPU::Exec() void CPU::Exec()
{ {
uint8_t opCode = ReadByte(); if(!CPU::NMIFlag) {
if(_opTable[opCode] != nullptr) { uint8_t opCode = ReadByte();
(this->*_opTable[opCode])(); if(_opTable[opCode] != nullptr) {
CPU::CycleCount += this->_cycles[opCode]; (this->*_opTable[opCode])();
CPU::CycleCount += this->_cycles[opCode];
} else {
//throw std::exception("Invalid opcode");
}
} else { } else {
//throw std::exception("Invalid opcode"); NMI();
CPU::CycleCount += 7;
CPU::NMIFlag = false;
} }
} }

View file

@ -41,6 +41,7 @@ private:
MemoryManager *_memoryManager = nullptr; MemoryManager *_memoryManager = nullptr;
static uint64_t CycleCount; static uint64_t CycleCount;
static bool NMIFlag;
uint16_t _currentPC = 0; uint16_t _currentPC = 0;
uint8_t _cyclePenalty = 0; uint8_t _cyclePenalty = 0;
@ -592,6 +593,14 @@ private:
SetPC(MemoryReadWord(0xFFFE)); SetPC(MemoryReadWord(0xFFFE));
} }
void NMI() {
Push((uint16_t)(PC() + 1));
Push((uint8_t)PS());
SetFlags(PSFlags::Interrupt);
SetPC(MemoryReadWord(0xFFFA));
}
void NOP() {} void NOP() {}
void RTI() { void RTI() {
SetPS(Pop()); SetPS(Pop());
@ -601,13 +610,10 @@ private:
public: public:
CPU(MemoryManager *memoryManager); CPU(MemoryManager *memoryManager);
static uint64_t GetCycleCount() { static uint64_t GetCycleCount() { return CPU::CycleCount; }
return CPU::CycleCount; static void SetNMIFlag() { CPU::NMIFlag = true; }
}
void Reset(); void Reset();
void Exec(); void Exec();
State GetState() State GetState() { return _state; }
{
return _state;
}
}; };

View file

@ -12,7 +12,7 @@ Console::Console(string filename)
Console::~Console() Console::~Console()
{ {
_cpu.release();
} }
void Console::Reset() void Console::Reset()
@ -46,7 +46,7 @@ void Console::RunTests()
console->Run(); console->Run();
delete console;*/ delete console;*/
vector<std::string> testROMs = { { "nestest", "01-basics", "02-implied", "03-immediate", "04-zero_page", "05-zp_xy", "06-absolute", "07-abs_xy", "08-ind_x", "09-ind_y", "10-branches", "11-stack", "12-jmp_jsr", "13-rts", "14-rti", "15-brk", "16-special" } }; vector<std::string> testROMs = { { "01-basics", "02-implied", "03-immediate", "04-zero_page", "05-zp_xy", "06-absolute", "07-abs_xy", "08-ind_x", "09-ind_y", "10-branches", "11-stack", "12-jmp_jsr", "13-rts", "14-rti", "15-brk", "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");
@ -64,7 +64,7 @@ void Console::RunTests()
uint8_t testStatus = console->_memoryManager.Read(0x6000); uint8_t testStatus = console->_memoryManager.Read(0x6000);
if(testStatus == 0x81) { if(testStatus == 0x81) {
//need reset //need reset
throw std::exception("reset needed"); OutputDebugStringA("reset needed");
} else if(testStatus == 0x80) { } else if(testStatus == 0x80) {
testStarted = true; testStarted = true;
} else if(testStatus < 0x80 && testStarted) { } else if(testStatus < 0x80 && testStarted) {

View file

@ -5,7 +5,9 @@
PPU::PPU() PPU::PPU()
{ {
_state = {}; _state = {};
_flags = {};
_statusFlags = {};
_outputBuffer = new uint8_t[256 * 240 * 4]; _outputBuffer = new uint8_t[256 * 240 * 4];
} }
@ -105,7 +107,8 @@ void PPU::UpdateStatusFlag()
{ {
_state.Status = ((uint8_t)_statusFlags.SpriteOverflow << 5) | _state.Status = ((uint8_t)_statusFlags.SpriteOverflow << 5) |
((uint8_t)_statusFlags.Sprite0Hit << 6) | ((uint8_t)_statusFlags.Sprite0Hit << 6) |
((uint8_t)_statusFlags.VerticalBlank << 7)); ((uint8_t)_statusFlags.VerticalBlank << 7);
_statusFlags.VerticalBlank = false;
} }
void PPU::Exec() void PPU::Exec()
@ -113,14 +116,19 @@ void PPU::Exec()
uint64_t equivalentCycleCount = CPU::GetCycleCount() * 3; uint64_t equivalentCycleCount = CPU::GetCycleCount() * 3;
while(_cycleCount < equivalentCycleCount) { while(_cycleCount < equivalentCycleCount) {
if(_scanline == -1) { if(_scanline == -1) {
//Pre-render scanline
if(_cycle == 1) { if(_cycle == 1) {
_statusFlags.SpriteOverflow = false; _statusFlags.SpriteOverflow = false;
_statusFlags.Sprite0Hit = false; _statusFlags.Sprite0Hit = false;
_statusFlags.VerticalBlank = false;
} else if(_cycle == 304) { } else if(_cycle == 304) {
// Copy scroll latch into VRAMADDR register // Copy scroll latch into VRAMADDR register
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)) {
//Skip a cycle for odd frames
_cycle++;
} }
} else if(_scanline < 240) { } else if(_scanline < 240) {
if(_cycle == 254) { if(_cycle == 254) {
@ -136,38 +144,42 @@ void PPU::Exec()
//Ppu_updateEndScanlineRegisters(p); //Ppu_updateEndScanlineRegisters(p);
} }
} }
} else if(_scanline == 240) { } else if(_scanline == 241) {
//Start of VBlank
if(_cycle == 1) { if(_cycle == 1) {
if(!_suppressVBlank) { _statusFlags.VerticalBlank = true;
/*if(!_suppressVBlank) {
// We're in VBlank // We're in VBlank
Ppu_setStatus(p, STATUS_VBLANK_STARTED); Ppu_setStatus(p, STATUS_VBLANK_STARTED);
p->cycleCount = 0; p->cycleCount = 0;
}*/
if(_flags.VBlank) {
CPU::SetNMIFlag();
} }
if(_flags.VBlank && !_suppressNMI) { /*if(_flags.VBlank && !_suppressNMI) {
VBlankInterrupt(); VBlankInterrupt();
} }*/
//Ppu_raster(p); //Ppu_raster(p);
} }
} else if(_scanline == 260) { } else if(_scanline == 260) {
// End of vblank //End of VBlank
if(_cycle == 1) { if(_cycle == 340) {
// Clear VBlank flag
Ppu_clearStatus(p, STATUS_VBLANK_STARTED);
_cycleCount = 0;
} else if(_cycle == 341) {
_scanline = -1;
_cycle = 1;
_frameCount++; _frameCount++;
return;
} }
} }
if(_cycle == 341) { if(_cycle == 340) {
_cycle = 0; _cycle = 0;
_scanline++; _scanline++;
if(_scanline == 261) {
_scanline = -1;
_frameCount++;
}
} else {
_cycle++;
} }
_cycle++;
_cycleCount++; _cycleCount++;
} }
} }

View file

@ -64,9 +64,10 @@ class PPU : public IMemoryHandler
int16_t _scanline = -1; int16_t _scanline = -1;
uint16_t _cycle = 0; uint16_t _cycle = 0;
uint32_t _frameCount = 0;
PPUControlFlags _flags = {}; PPUControlFlags _flags;
PPUStatusFlags _statusFlags = {}; PPUStatusFlags _statusFlags;
void PPU::UpdateStatusFlag(); void PPU::UpdateStatusFlag();