Fixed CPU page crossing cycles
This commit is contained in:
parent
5574f1c4bf
commit
16b6ebeb84
2 changed files with 61 additions and 53 deletions
63
Core/CPU.cpp
63
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;
|
||||
}
|
||||
}
|
||||
|
|
51
Core/CPU.h
51
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue