From 16b6ebeb845b7e2cd1f34dfd7f1209ba09c4d300 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sat, 21 Jun 2014 00:37:20 -0400 Subject: [PATCH] Fixed CPU page crossing cycles --- Core/CPU.cpp | 63 ++++++++++++++++++++++++++++++++++++---------------- Core/CPU.h | 51 ++++++++++++++---------------------------- 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/Core/CPU.cpp b/Core/CPU.cpp index 8c202caf..4febf335 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -27,27 +27,47 @@ CPU::CPU(MemoryManager *memoryManager) : _memoryManager(memoryManager) &CPU::BEQ, &CPU::SBC_IndY, nullptr, nullptr, nullptr, &CPU::SBC_ZeroX, &CPU::INC_ZeroX, nullptr, &CPU::SED, &CPU::SBC_AbsY, nullptr, nullptr, nullptr, &CPU::SBC_AbsX, &CPU::INC_AbsX, nullptr //F }; - uint8_t cycles[] = { - 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7, - 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7, - 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7, - 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7, - 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4, - 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5, - 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4, - 2,5,2,5,4,4,4,4,2,4,2,5,4,4,4,4, - 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7, - 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6, - 2,5,2,8,4,4,6,6,2,4,2,7,5,5,7,7 + uint8_t cycles[] { + 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, + 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, + 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, + 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, + 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + 2, 6, 3, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, + 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, + }; + + uint8_t cyclesPageCrossed[] { + 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, + 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, + 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, + 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, + 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, + 2, 6, 2, 5, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, + 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, + 2, 6, 3, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, + 2, 6, 2, 8, 4, 4, 6, 6, 2, 5, 2, 7, 5, 5, 7, 7, }; memcpy(_opTable, opTable, sizeof(Func) * 256); memcpy(_cycles, cycles, sizeof(uint8_t) * 256); + memcpy(_cyclesPageCrossed, cyclesPageCrossed, sizeof(uint8_t) * 256); } void CPU::Reset() @@ -63,11 +83,15 @@ void CPU::Reset() void CPU::Exec() { - if(!CPU::NMIFlag) { + if(!_runNMI) { + if(CPU::NMIFlag) { + _runNMI = true; + } uint8_t opCode = ReadByte(); if(_opTable[opCode] != nullptr) { (this->*_opTable[opCode])(); - CPU::CycleCount += this->_cycles[opCode]; + + CPU::CycleCount += GetPageCrossed() ? this->_cyclesPageCrossed[opCode] : this->_cycles[opCode]; } else { //std::cout << "Invalid opcode: " << std::hex << (short)opCode; //throw exception("Invalid opcode"); @@ -75,6 +99,7 @@ void CPU::Exec() } else { NMI(); CPU::CycleCount += 7; + _runNMI = false; CPU::NMIFlag = false; } } diff --git a/Core/CPU.h b/Core/CPU.h index d5bd99a4..1530e993 100644 --- a/Core/CPU.h +++ b/Core/CPU.h @@ -35,6 +35,7 @@ private: Func _opTable[256]; uint8_t _cycles[256]; + uint8_t _cyclesPageCrossed[256]; State _state; @@ -42,9 +43,10 @@ private: static uint64_t CycleCount; static bool NMIFlag; + bool _runNMI = false; uint16_t _currentPC = 0; - uint8_t _cyclePenalty = 0; + bool _pageCrossed = false; uint8_t ReadByte() { @@ -82,21 +84,14 @@ private: } } - bool IsPageCrossed(uint16_t valA, uint8_t valB) + bool IsPageCrossed(uint16_t valA, int8_t valB) { - return (uint8_t)valA + valB >= 0x100; + return ((valA + valB) & 0xFF00) != (valA & 0xFF00); } void MemoryWrite(uint16_t addr, uint8_t value) { _memoryManager->Write(addr, value); - /*if(addr == 0x200) { - std::cout << "------------------" << std::endl; - std::cout << "(0x" << std::hex << (short)_currentPC << ") TEST NUMBER: " << std::dec << (int)value << std::endl; - std::cout << "------------------" << std::endl; - } else { - //std::cout << "(0x" << std::hex << (short)_currentPC << ") W: 0x" << std::hex << (short)addr << " = 0x" << std::hex << (short)value << std::endl; - }*/ } uint8_t MemoryRead(uint16_t addr) { @@ -165,7 +160,7 @@ private: uint16_t GetAbsXAddr() { uint16_t baseAddr = ReadWord(); if(IsPageCrossed(baseAddr, X())) { - SetCyclePenalty(1); + SetPageCrossed(); } return baseAddr + X(); } @@ -174,7 +169,7 @@ private: uint16_t GetAbsYAddr() { uint16_t baseAddr = ReadWord(); if(IsPageCrossed(baseAddr, Y())) { - SetCyclePenalty(1); + SetPageCrossed(); } return baseAddr + Y(); @@ -213,7 +208,7 @@ private: addr = MemoryReadWord(zero); } if(IsPageCrossed(addr, Y())) { - SetCyclePenalty(1); + SetPageCrossed(); } return addr + Y(); } @@ -341,7 +336,6 @@ private: } void JMP(uint16_t addr) { - //std::cout << "JMP from 0x" << std::hex << _currentPC << " to " << addr << std::endl; SetPC(addr); } @@ -349,20 +343,11 @@ private: int8_t offset = GetImmediate(); if(branch) { if(IsPageCrossed(PC(), offset)) { - SetCyclePenalty(2); - } else { - SetCyclePenalty(1); + SetPageCrossed(); } - SetPC(PC() + offset); + CPU::CycleCount++; - if(_currentPC == PC()) { - if(_currentPC != 0x33a7) { - std::cout << "Infinite loop at: 0x" << std::hex << (short)_currentPC; - std::cout << std::endl; - } else { - Reset(); - } - } + SetPC(PC() + offset); } } @@ -379,14 +364,14 @@ private: } } - void SetCyclePenalty(uint8_t penalty) { - _cyclePenalty = penalty; + void SetPageCrossed() { + _pageCrossed = true; } - uint8_t GetCyclePenalty() { - uint8_t penalty = _cyclePenalty; - _cyclePenalty = 0; - return penalty; + bool GetPageCrossed() { + bool pageCrossed = _pageCrossed; + _pageCrossed = false; + return pageCrossed; } #pragma region OP Codes @@ -555,13 +540,11 @@ private: void JMP_Ind() { JMP(GetInd()); } void JSR() { uint16_t addr = GetAbsAddr(); - //std::cout << "JSR from 0x" << std::hex << _currentPC << " to " << addr; Push((uint16_t)(PC() - 1)); JMP(addr); } void RTS() { uint16_t addr = PopWord(); - //std::cout << "RTS from 0x" << std::hex << _currentPC << " to " << addr; SetPC(addr + 1); }