Fixed release mode crashes (operation order is undetermined in expression evaluation)
This commit is contained in:
parent
4c5dbdcb42
commit
6ffeb46732
5 changed files with 222 additions and 310 deletions
95
CPU.cpp
95
CPU.cpp
|
@ -2,7 +2,53 @@
|
|||
#include "CPU.h"
|
||||
#include "Timer.h"
|
||||
|
||||
void Core::Reset()
|
||||
CPU::CPU(MemoryManager *memoryManager) : _memoryManager(memoryManager)
|
||||
{
|
||||
Reset();
|
||||
Func opTable[] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
&CPU::BRK, &CPU::ORA_IndX, nullptr, nullptr, nullptr, &CPU::ORA_Zero, &CPU::ASL_Zero, nullptr, &CPU::PHP, &CPU::ORA_Imm, &CPU::ASL_Acc, nullptr, nullptr, &CPU::ORA_Abs, &CPU::ASL_Abs, nullptr, //0
|
||||
&CPU::BPL, &CPU::ORA_IndY, nullptr, nullptr, nullptr, &CPU::ORA_ZeroX, &CPU::ASL_ZeroX, nullptr, &CPU::CLC, &CPU::ORA_AbsY, nullptr, nullptr, nullptr, &CPU::ORA_AbsX, &CPU::ASL_AbsX, nullptr, //1
|
||||
&CPU::JSR, &CPU::AND_IndX, nullptr, nullptr, &CPU::BIT_Zero, &CPU::AND_Zero, &CPU::ROL_Zero, nullptr, &CPU::PLP, &CPU::AND_Imm, &CPU::ROL_Acc, nullptr, &CPU::BIT_Abs, &CPU::AND_Abs, &CPU::ROL_Abs, nullptr, //2
|
||||
&CPU::BMI, &CPU::AND_IndY, nullptr, nullptr, nullptr, &CPU::AND_ZeroX, &CPU::ROL_ZeroX, nullptr, &CPU::SEC, &CPU::AND_AbsY, nullptr, nullptr, nullptr, &CPU::AND_AbsX, &CPU::ROL_AbsX, nullptr, //3
|
||||
&CPU::RTI, &CPU::EOR_IndX, nullptr, nullptr, nullptr, &CPU::EOR_Zero, &CPU::LSR_Zero, nullptr, &CPU::PHA, &CPU::EOR_Imm, &CPU::LSR_Acc, nullptr, &CPU::JMP_Abs, &CPU::EOR_Abs, &CPU::LSR_Abs, nullptr, //4
|
||||
&CPU::BVC, &CPU::EOR_IndY, nullptr, nullptr, nullptr, &CPU::EOR_ZeroX, &CPU::LSR_ZeroX, nullptr, &CPU::CLI, &CPU::EOR_AbsY, nullptr, nullptr, nullptr, &CPU::EOR_AbsX, &CPU::LSR_AbsX, nullptr, //5
|
||||
&CPU::RTS, &CPU::ADC_IndX, nullptr, nullptr, nullptr, &CPU::ADC_Zero, &CPU::ROR_Zero, nullptr, &CPU::PLA, &CPU::ADC_Imm, &CPU::ROR_Acc, nullptr, &CPU::JMP_Ind, &CPU::ADC_Abs, &CPU::ROR_Abs, nullptr, //6
|
||||
&CPU::BVS, &CPU::ADC_IndY, nullptr, nullptr, nullptr, &CPU::ADC_ZeroX, &CPU::ROR_ZeroX, nullptr, &CPU::SEI, &CPU::ADC_AbsY, nullptr, nullptr, nullptr, &CPU::ADC_AbsX, &CPU::ROR_AbsX, nullptr, //7
|
||||
nullptr, &CPU::STA_IndX, nullptr, nullptr, &CPU::STY_Zero, &CPU::STA_Zero, &CPU::STX_Zero, nullptr, &CPU::DEY, nullptr, &CPU::TXA, nullptr, &CPU::STY_Abs, &CPU::STA_Abs, &CPU::STX_Abs, nullptr, //8
|
||||
&CPU::BCC, &CPU::STA_IndY, nullptr, nullptr, &CPU::STY_ZeroX, &CPU::STA_ZeroX, &CPU::STX_ZeroY, nullptr, &CPU::TYA, &CPU::STA_AbsY, &CPU::TXS, nullptr, nullptr, &CPU::STA_AbsX, nullptr, nullptr, //9
|
||||
&CPU::LDY_Imm, &CPU::LDA_IndX, &CPU::LDX_Imm, nullptr, &CPU::LDY_Zero, &CPU::LDA_Zero, &CPU::LDX_Zero, nullptr, &CPU::TAY, &CPU::LDA_Imm, &CPU::TAX, nullptr, &CPU::LDY_Abs, &CPU::LDA_Abs, &CPU::LDX_Abs, nullptr, //A
|
||||
&CPU::BCS, &CPU::LDA_IndY, nullptr, nullptr, &CPU::LDY_ZeroX, &CPU::LDA_ZeroX, &CPU::LDX_ZeroY, nullptr, &CPU::CLV, &CPU::LDA_AbsY, &CPU::TSX, nullptr, &CPU::LDY_AbsX, &CPU::LDA_AbsX, &CPU::LDX_AbsY, nullptr, //B
|
||||
&CPU::CPY_Imm, &CPU::CMP_IndX, nullptr, nullptr, &CPU::CPY_Zero, &CPU::CMP_Zero, &CPU::DEC_Zero, nullptr, &CPU::INY, &CPU::CMP_Imm, &CPU::DEX, nullptr, &CPU::CPY_Abs, &CPU::CMP_Abs, &CPU::DEC_Abs, nullptr, //C
|
||||
&CPU::BNE, &CPU::CMP_IndY, nullptr, nullptr, nullptr, &CPU::CMP_ZeroX, &CPU::DEC_ZeroX, nullptr, &CPU::CLD, &CPU::CMP_AbsY, nullptr, nullptr, nullptr, &CPU::CMP_AbsX, &CPU::DEC_AbsX, nullptr, //D
|
||||
&CPU::CPX_Imm, &CPU::SBC_IndX, nullptr, nullptr, &CPU::CPX_Zero, &CPU::SBC_Zero, &CPU::INC_Zero, nullptr, &CPU::INX, &CPU::SBC_Imm, &CPU::NOP, nullptr, &CPU::CPX_Abs, &CPU::SBC_Abs, &CPU::INC_Abs, nullptr, //E
|
||||
&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
|
||||
};
|
||||
|
||||
memcpy(_opTable, opTable, sizeof(Func) * 256);
|
||||
memcpy(_cycles, cycles, sizeof(uint8_t) * 256);
|
||||
}
|
||||
|
||||
void CPU::Reset()
|
||||
{
|
||||
_state.A = 0;
|
||||
_state.PC = 0x0400;
|
||||
|
@ -12,29 +58,60 @@ void Core::Reset()
|
|||
_state.PS = PSFlags::Zero | PSFlags::Reserved;// | PSFlags::Interrupt;
|
||||
}
|
||||
|
||||
void Core::Exec()
|
||||
void CPU::Exec()
|
||||
{
|
||||
uint16_t lastPC = 65535;
|
||||
int executedCount = 0;
|
||||
std::list<int> pcList;
|
||||
uint32_t cycleCount = 0;
|
||||
|
||||
Timer timer;
|
||||
while(true) {
|
||||
_currentPC = _state.PC;
|
||||
uint8_t opCode = ReadByte();
|
||||
if(_opTable[opCode] != 0) {
|
||||
if(_opTable[opCode] != nullptr) {
|
||||
(this->*_opTable[opCode])();
|
||||
cycleCount += this->_cycles[opCode];
|
||||
//std::cout << "OPCode: " << std::hex << (short)opCode << " PC:" << _currentPC << std::endl;
|
||||
} else {
|
||||
std::cout << "Invalid opcode: PC:" << _currentPC << std::endl;
|
||||
throw;
|
||||
}
|
||||
lastPC = _currentPC;
|
||||
executedCount++;
|
||||
|
||||
if(executedCount >= 200000000) {
|
||||
if(cycleCount >= 200000000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Executed:" << executedCount << " in " << timer.GetElapsedMS() << " ms";
|
||||
std::wstring result = L"Frequency: " + std::to_wstring((int)(cycleCount / timer.GetElapsedMS() * 1000 / 1000000)) + L"mhz\n";
|
||||
OutputDebugString(result.c_str());
|
||||
}
|
||||
|
||||
class Test : public IMemoryHandler
|
||||
{
|
||||
public:
|
||||
int _counter = 0;
|
||||
public:
|
||||
void MemoryRead(uint16_t aa) {
|
||||
//_counter++;
|
||||
}
|
||||
void MemoryWrite(uint16_t aa) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
void CPU::RunBenchmark()
|
||||
{
|
||||
std::ifstream romFile("6502_functional_test.bin", std::ios::in | std::ios::binary);
|
||||
if(!romFile) {
|
||||
std::cout << "Error";
|
||||
}
|
||||
|
||||
uint8_t *romMemory = new uint8_t[65536];
|
||||
romFile.read((char *)romMemory, 65536);
|
||||
|
||||
Test a;
|
||||
|
||||
MemoryManager memoryManager(romMemory);
|
||||
memoryManager.OnMemoryRead()->RegisterHandler(&a, &IMemoryHandler::MemoryRead);
|
||||
CPU core(&memoryManager);
|
||||
core.Exec();
|
||||
}
|
366
CPU.h
366
CPU.h
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include "Memory.h"
|
||||
|
||||
namespace PSFlags
|
||||
{
|
||||
|
@ -25,24 +26,30 @@ struct State
|
|||
uint8_t PS;
|
||||
};
|
||||
|
||||
class Core
|
||||
class CPU
|
||||
{
|
||||
private:
|
||||
typedef void(Core::*Func)();
|
||||
typedef void(CPU::*Func)();
|
||||
|
||||
Func _opTable[256];
|
||||
State _state;
|
||||
int8_t* _memory;
|
||||
uint16_t _currentPC;
|
||||
uint8_t _cycles[256];
|
||||
|
||||
inline uint8_t Core::ReadByte()
|
||||
State _state;
|
||||
|
||||
MemoryManager *_memoryManager = nullptr;
|
||||
|
||||
|
||||
uint16_t _currentPC = 0;
|
||||
uint8_t _cyclePenalty = 0;
|
||||
|
||||
uint8_t ReadByte()
|
||||
{
|
||||
return _memory[_state.PC++];
|
||||
return MemoryRead(_state.PC++);
|
||||
}
|
||||
|
||||
uint16_t Core::ReadWord()
|
||||
uint16_t ReadWord()
|
||||
{
|
||||
uint16_t value = (uint16_t)(((uint8_t)_memory[_state.PC] | (((uint8_t)_memory[_state.PC + 1]) << 8)));
|
||||
uint16_t value = MemoryReadWord(PC());
|
||||
_state.PC += 2;
|
||||
return value;
|
||||
}
|
||||
|
@ -52,12 +59,8 @@ private:
|
|||
_state.PS &= ~flags;
|
||||
}
|
||||
|
||||
uint16_t lastNegative = 0;
|
||||
void SetFlags(uint8_t flags)
|
||||
{
|
||||
if(flags & PSFlags::Negative) {
|
||||
lastNegative = _state.PC;
|
||||
}
|
||||
_state.PS |= flags;
|
||||
}
|
||||
|
||||
|
@ -75,26 +78,29 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
bool IsPageCrossed(uint16_t valA, uint8_t valB)
|
||||
{
|
||||
return (uint8_t)valA + valB >= 0x100;
|
||||
}
|
||||
|
||||
void MemoryWrite(uint16_t addr, uint8_t value)
|
||||
{
|
||||
//SetZeroNegativeFlags(value);
|
||||
_memory[addr] = value;
|
||||
if(addr == 0x200) {
|
||||
_memoryManager->Write(addr, value);
|
||||
/*if(addr == 0x200) {
|
||||
std::cout << "------------------" << std::endl;
|
||||
std::cout << "TEST NUMBER: " << std::dec << (int)value << 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) {
|
||||
//std::cout << "\t\t\t\t(0x" << std::hex << (short)_currentPC << ") R: 0x" << std::hex << (short)addr << " = 0x" << std::hex << (short)_memory[addr] << std::endl;
|
||||
return _memory[addr];
|
||||
return _memoryManager->Read(addr);
|
||||
}
|
||||
|
||||
uint16_t MemoryReadWord(uint16_t addr) {
|
||||
return (_memory[addr] | (_memory[addr + 1] << 8));
|
||||
return _memoryManager->ReadWord(addr);
|
||||
}
|
||||
|
||||
void SetRegister(uint8_t ®, int8_t value) {
|
||||
|
@ -104,7 +110,7 @@ private:
|
|||
}
|
||||
|
||||
void Push(uint8_t value) {
|
||||
_memory[SP() + 0x100] = value;
|
||||
MemoryWrite(SP() + 0x100, value);
|
||||
SetSP(SP() - 1);
|
||||
}
|
||||
|
||||
|
@ -115,12 +121,14 @@ private:
|
|||
|
||||
uint8_t Pop() {
|
||||
SetSP(SP() + 1);
|
||||
int8_t value = _memory[0x100 + SP()];
|
||||
return value;
|
||||
return MemoryRead(0x100 + SP());
|
||||
}
|
||||
|
||||
uint16_t PopWord() {
|
||||
return Pop() | (Pop() << 8);
|
||||
uint8_t lo = Pop();
|
||||
uint8_t hi = Pop();
|
||||
|
||||
return lo | hi << 8;
|
||||
}
|
||||
|
||||
uint8_t A() { return _state.A; }
|
||||
|
@ -145,52 +153,55 @@ private:
|
|||
|
||||
int8_t GetZeroY() { return MemoryRead(GetZeroYAddr()); }
|
||||
int8_t GetZeroYAddr() { return ReadByte() + Y(); }
|
||||
|
||||
|
||||
|
||||
int8_t GetAbs() { return MemoryRead(GetAbsAddr()); }
|
||||
uint16_t GetAbsAddr() { return ReadWord(); }
|
||||
|
||||
int8_t GetAbsX() { return MemoryRead(GetAbsXAddr()); }
|
||||
uint16_t GetAbsXAddr() {
|
||||
return ReadWord() + X();
|
||||
uint16_t GetAbsXAddr() {
|
||||
uint16_t baseAddr = ReadWord();
|
||||
if(IsPageCrossed(baseAddr, X())) {
|
||||
SetCyclePenalty(1);
|
||||
}
|
||||
return baseAddr + X();
|
||||
}
|
||||
|
||||
int8_t GetAbsY() { return MemoryRead(GetAbsYAddr()); }
|
||||
uint16_t GetAbsYAddr() {
|
||||
return ReadWord() + Y();
|
||||
uint16_t GetAbsYAddr() {
|
||||
uint16_t baseAddr = ReadWord();
|
||||
if(IsPageCrossed(baseAddr, Y())) {
|
||||
SetCyclePenalty(1);
|
||||
}
|
||||
|
||||
return baseAddr + Y();
|
||||
}
|
||||
|
||||
uint16_t GetInd() { return MemoryReadWord(ReadByte() | (ReadByte() << 8)); }
|
||||
uint16_t GetInd() { return MemoryReadWord(ReadWord()); }
|
||||
|
||||
int8_t GetIndX() { return MemoryRead(GetIndXAddr()); }
|
||||
uint16_t GetIndXAddr() {
|
||||
uint8_t zero = ReadByte() + X();
|
||||
//std::cout << (int)zero << std::endl;
|
||||
uint16_t addr = MemoryRead(zero) | (MemoryRead(zero + 1) << 8);
|
||||
uint16_t addr = MemoryReadWord(zero);
|
||||
return addr;
|
||||
}
|
||||
|
||||
int8_t GetIndY() { return MemoryRead(GetIndYAddr()); }
|
||||
uint16_t GetIndYAddr() {
|
||||
uint8_t zero = ReadByte();
|
||||
//std::cout << (int)zero << std::endl;
|
||||
uint16_t addr = MemoryRead(zero) | (MemoryRead(zero + 1) << 8);
|
||||
uint16_t addr = MemoryReadWord(zero);
|
||||
if(IsPageCrossed(addr, Y())) {
|
||||
SetCyclePenalty(1);
|
||||
}
|
||||
return addr + Y();
|
||||
}
|
||||
|
||||
|
||||
void AND(int8_t value) { SetA(A() & value); }
|
||||
void XOR(int8_t value) {
|
||||
SetA(A() ^ value);
|
||||
}
|
||||
void XOR(int8_t value) { SetA(A() ^ value); }
|
||||
void OR(int8_t value) { SetA(A() | value); }
|
||||
|
||||
void ADC(uint8_t value) {
|
||||
uint16_t result = (uint16_t)A() + (uint16_t)value + (CheckFlag(PSFlags::Carry) ? PSFlags::Carry : 0x00);
|
||||
if(result == 0x100) {
|
||||
//std::cout << std::hex << (short)A() << " + " << (short)value << (CheckFlag(PSFlags::Carry) ? "(+1) " : "") << " = " << (short)result << std::endl;
|
||||
}
|
||||
|
||||
|
||||
ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Overflow | PSFlags::Zero);
|
||||
SetZeroNegativeFlags((uint8_t)result);
|
||||
if(~(A() ^ value) & (A() ^ result) & 0x80) {
|
||||
|
@ -202,18 +213,7 @@ private:
|
|||
SetA((uint8_t)result);
|
||||
}
|
||||
|
||||
void SBC(int8_t value) {
|
||||
ADC(value ^ 0xFF);
|
||||
/*uint8_t result = A() - (value - ~(CheckFlag(PSFlags::Carry) ? PSFlags::Carry : 0x00));
|
||||
|
||||
ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Overflow | PSFlags::Zero);
|
||||
|
||||
if (result & 0x80) {
|
||||
SetFlags(PSFlags::Overflow);
|
||||
}
|
||||
|
||||
SetA(result);*/
|
||||
}
|
||||
void SBC(int8_t value) { ADC(value ^ 0xFF); }
|
||||
|
||||
void CMP(uint8_t reg, uint8_t value) {
|
||||
ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero);
|
||||
|
@ -315,22 +315,55 @@ private:
|
|||
}
|
||||
|
||||
void JMP(uint16_t addr) {
|
||||
_state.PC = addr;
|
||||
//std::cout << "JMP from 0x" << std::hex << _currentPC << " to " << addr << std::endl;
|
||||
SetPC(addr);
|
||||
}
|
||||
|
||||
void BranchRelative(bool branch) {
|
||||
int8_t offset = GetImmediate();
|
||||
if(branch) {
|
||||
if(IsPageCrossed(PC(), offset)) {
|
||||
SetCyclePenalty(2);
|
||||
} else {
|
||||
SetCyclePenalty(1);
|
||||
}
|
||||
SetPC(PC() + offset);
|
||||
|
||||
if(_currentPC == PC()) {
|
||||
std::cout << "Infinite loop at: 0x" << std::hex << (short)_currentPC;
|
||||
std::cout << std::endl;
|
||||
Reset();
|
||||
if(_currentPC != 0x33a7) {
|
||||
std::cout << "Infinite loop at: 0x" << std::hex << (short)_currentPC;
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region OP Codes
|
||||
void BIT(uint8_t value) {
|
||||
ClearFlags(PSFlags::Zero | PSFlags::Overflow | PSFlags::Negative);
|
||||
if((A() & value) == 0) {
|
||||
SetFlags(PSFlags::Zero);
|
||||
}
|
||||
if(value & 0x40) {
|
||||
SetFlags(PSFlags::Overflow);
|
||||
}
|
||||
if(value & 0x80) {
|
||||
SetFlags(PSFlags::Negative);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCyclePenalty(uint8_t penalty) {
|
||||
_cyclePenalty = penalty;
|
||||
}
|
||||
|
||||
uint8_t GetCyclePenalty() {
|
||||
uint8_t penalty = _cyclePenalty;
|
||||
_cyclePenalty = 0;
|
||||
return penalty;
|
||||
}
|
||||
|
||||
#pragma region OP Codes
|
||||
void LDA_Imm() { SetA(GetImmediate()); }
|
||||
void LDA_Zero() { SetA(GetZero()); }
|
||||
void LDA_ZeroX() { SetA(GetZeroX()); }
|
||||
|
@ -352,21 +385,21 @@ private:
|
|||
void LDY_Abs() { SetY(GetAbs()); }
|
||||
void LDY_AbsX() { SetY(GetAbsX()); }
|
||||
|
||||
void STA_Zero() { MemoryWrite(ReadByte(), A()); }
|
||||
void STA_ZeroX() { MemoryWrite((uint8_t)(ReadByte() + X()), A()); }
|
||||
void STA_Abs() { MemoryWrite(ReadWord(), A()); }
|
||||
void STA_Zero() { MemoryWrite(GetZeroAddr(), A()); }
|
||||
void STA_ZeroX() { MemoryWrite(GetZeroXAddr(), A()); }
|
||||
void STA_Abs() { MemoryWrite(GetAbsAddr(), A()); }
|
||||
void STA_AbsX() { MemoryWrite(GetAbsXAddr(), A()); }
|
||||
void STA_AbsY() { MemoryWrite(GetAbsYAddr(), A()); }
|
||||
void STA_IndX() { MemoryWrite(GetIndXAddr(), A()); }
|
||||
void STA_IndY() { MemoryWrite(GetIndYAddr(), A()); }
|
||||
|
||||
void STX_Zero() { MemoryWrite(ReadByte(), X()); }
|
||||
void STX_ZeroY() { MemoryWrite((uint8_t)(ReadByte() + Y()), X()); }
|
||||
void STX_Abs() { MemoryWrite(ReadWord(), X()); }
|
||||
void STX_Zero() { MemoryWrite(GetZeroAddr(), X()); }
|
||||
void STX_ZeroY() { MemoryWrite(GetZeroYAddr(), X()); }
|
||||
void STX_Abs() { MemoryWrite(GetAbsAddr(), X()); }
|
||||
|
||||
void STY_Zero() { MemoryWrite(ReadByte(), Y()); }
|
||||
void STY_ZeroX() { MemoryWrite((uint8_t)(ReadByte() + X()), Y()); }
|
||||
void STY_Abs() { MemoryWrite(ReadWord(), Y()); }
|
||||
void STY_Zero() { MemoryWrite(GetZeroAddr(), Y()); }
|
||||
void STY_ZeroX() { MemoryWrite(GetZeroXAddr(), Y()); }
|
||||
void STY_Abs() { MemoryWrite(GetAbsAddr(), Y()); }
|
||||
|
||||
void TAX() { SetX(A()); }
|
||||
void TAY() { SetY(A()); }
|
||||
|
@ -410,19 +443,6 @@ private:
|
|||
void ORA_IndX() { OR(GetIndX()); }
|
||||
void ORA_IndY() { OR(GetIndY()); }
|
||||
|
||||
void BIT(uint8_t value) {
|
||||
ClearFlags(PSFlags::Zero | PSFlags::Overflow | PSFlags::Negative);
|
||||
if((A() & value) == 0) {
|
||||
SetFlags(PSFlags::Zero);
|
||||
}
|
||||
if(value & 0x40) {
|
||||
SetFlags(PSFlags::Overflow);
|
||||
}
|
||||
if(value & 0x80) {
|
||||
SetFlags(PSFlags::Negative);
|
||||
}
|
||||
}
|
||||
|
||||
void BIT_Zero() {
|
||||
BIT(GetZero());
|
||||
}
|
||||
|
@ -504,20 +524,19 @@ private:
|
|||
void ROR_AbsX() { RORAddr(GetAbsXAddr()); }
|
||||
|
||||
void JMP_Abs() {
|
||||
auto currentPC = _state.PC - 1;
|
||||
auto newPC = ReadWord();
|
||||
if(currentPC == newPC) {
|
||||
std::cout << "Infinite loop at: " << std::hex << (short)newPC << std::endl;
|
||||
}
|
||||
JMP(newPC);
|
||||
JMP(GetAbsAddr());
|
||||
}
|
||||
void JMP_Ind() { JMP(GetInd()); }
|
||||
void JSR() {
|
||||
Push((uint16_t)(PC() + 1));
|
||||
JMP(GetAbsAddr());
|
||||
uint16_t addr = GetAbsAddr();
|
||||
//std::cout << "JSR from 0x" << std::hex << _currentPC << " to " << addr;
|
||||
Push((uint16_t)(PC() - 1));
|
||||
JMP(addr);
|
||||
}
|
||||
void RTS() {
|
||||
SetPC(PopWord() + 1);
|
||||
uint16_t addr = PopWord();
|
||||
//std::cout << "RTS from 0x" << std::hex << _currentPC << " to " << addr;
|
||||
SetPC(addr + 1);
|
||||
}
|
||||
|
||||
void BCC() {
|
||||
|
@ -566,7 +585,8 @@ private:
|
|||
Push((uint8_t)PS());
|
||||
SetFlags(PSFlags::Interrupt);
|
||||
ClearFlags(PSFlags::Break);
|
||||
SetPC((uint8_t)_memory[0xFFFE] | ((uint8_t)_memory[0xFFFF] << 8));
|
||||
|
||||
SetPC(MemoryReadWord(0xFFFE));
|
||||
}
|
||||
|
||||
void NOP() {}
|
||||
|
@ -574,163 +594,11 @@ private:
|
|||
SetPS(Pop());
|
||||
SetPC(PopWord());
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
|
||||
public:
|
||||
Core(int8_t *memory) : _memory(memory) {
|
||||
Reset();
|
||||
memset(_opTable, 0, 256 * sizeof(void*));
|
||||
_opTable[0x00] = &Core::BRK;
|
||||
_opTable[0x01] = &Core::ORA_IndX;
|
||||
_opTable[0x05] = &Core::ORA_Zero;
|
||||
_opTable[0x06] = &Core::ASL_Zero;
|
||||
_opTable[0x08] = &Core::PHP;
|
||||
_opTable[0x09] = &Core::ORA_Imm;
|
||||
_opTable[0x0A] = &Core::ASL_Acc;
|
||||
_opTable[0x0D] = &Core::ORA_Abs;
|
||||
_opTable[0x0E] = &Core::ASL_Abs;
|
||||
_opTable[0x10] = &Core::BPL;
|
||||
_opTable[0x11] = &Core::ORA_IndY;
|
||||
_opTable[0x15] = &Core::ORA_ZeroX;
|
||||
_opTable[0x16] = &Core::ASL_ZeroX;
|
||||
_opTable[0x18] = &Core::CLC;
|
||||
_opTable[0x19] = &Core::ORA_AbsY;
|
||||
_opTable[0x1D] = &Core::ORA_AbsX;
|
||||
_opTable[0x1E] = &Core::ASL_AbsX;
|
||||
_opTable[0x20] = &Core::JSR;
|
||||
_opTable[0x21] = &Core::AND_IndX;
|
||||
_opTable[0x24] = &Core::BIT_Zero;
|
||||
_opTable[0x25] = &Core::AND_Zero;
|
||||
_opTable[0x26] = &Core::ROL_Zero;
|
||||
_opTable[0x28] = &Core::PLP;
|
||||
_opTable[0x29] = &Core::AND_Imm;
|
||||
_opTable[0x2A] = &Core::ROL_Acc;
|
||||
_opTable[0x2C] = &Core::BIT_Abs;
|
||||
_opTable[0x2D] = &Core::AND_Abs;
|
||||
_opTable[0x2E] = &Core::ROL_Abs;
|
||||
_opTable[0x30] = &Core::BMI;
|
||||
_opTable[0x31] = &Core::AND_IndY;
|
||||
_opTable[0x35] = &Core::AND_ZeroX;
|
||||
_opTable[0x36] = &Core::ROL_ZeroX;
|
||||
_opTable[0x38] = &Core::SEC;
|
||||
_opTable[0x39] = &Core::AND_AbsY;
|
||||
_opTable[0x3D] = &Core::AND_AbsX;
|
||||
_opTable[0x3E] = &Core::ROL_AbsX;
|
||||
_opTable[0x40] = &Core::RTI;
|
||||
_opTable[0x41] = &Core::EOR_IndX;
|
||||
_opTable[0x45] = &Core::EOR_Zero;
|
||||
_opTable[0x46] = &Core::LSR_Zero;
|
||||
_opTable[0x48] = &Core::PHA;
|
||||
_opTable[0x49] = &Core::EOR_Imm;
|
||||
_opTable[0x4A] = &Core::LSR_Acc;
|
||||
_opTable[0x4C] = &Core::JMP_Abs;
|
||||
_opTable[0x4D] = &Core::EOR_Abs;
|
||||
_opTable[0x4E] = &Core::LSR_Abs;
|
||||
_opTable[0x50] = &Core::BVC;
|
||||
_opTable[0x51] = &Core::EOR_IndY;
|
||||
_opTable[0x55] = &Core::EOR_ZeroX;
|
||||
_opTable[0x56] = &Core::LSR_ZeroX;
|
||||
_opTable[0x58] = &Core::CLI;
|
||||
_opTable[0x59] = &Core::EOR_AbsY;
|
||||
_opTable[0x5D] = &Core::EOR_AbsX;
|
||||
_opTable[0x5E] = &Core::LSR_AbsX;
|
||||
_opTable[0x60] = &Core::RTS;
|
||||
_opTable[0x61] = &Core::ADC_IndX;
|
||||
_opTable[0x65] = &Core::ADC_Zero;
|
||||
_opTable[0x66] = &Core::ROR_Zero;
|
||||
_opTable[0x68] = &Core::PLA;
|
||||
_opTable[0x69] = &Core::ADC_Imm;
|
||||
_opTable[0x6A] = &Core::ROR_Acc;
|
||||
_opTable[0x6C] = &Core::JMP_Ind;
|
||||
_opTable[0x6D] = &Core::ADC_Abs;
|
||||
_opTable[0x6E] = &Core::ROR_Abs;
|
||||
_opTable[0x70] = &Core::BVS;
|
||||
_opTable[0x71] = &Core::ADC_IndY;
|
||||
_opTable[0x75] = &Core::ADC_ZeroX;
|
||||
_opTable[0x76] = &Core::ROR_ZeroX;
|
||||
_opTable[0x78] = &Core::SEI;
|
||||
_opTable[0x79] = &Core::ADC_AbsY;
|
||||
_opTable[0x7D] = &Core::ADC_AbsX;
|
||||
_opTable[0x7E] = &Core::ROR_AbsX;
|
||||
_opTable[0x81] = &Core::STA_IndX;
|
||||
_opTable[0x84] = &Core::STY_Zero;
|
||||
_opTable[0x85] = &Core::STA_Zero;
|
||||
_opTable[0x86] = &Core::STX_Zero;
|
||||
_opTable[0x88] = &Core::DEY;
|
||||
_opTable[0x8A] = &Core::TXA;
|
||||
_opTable[0x8C] = &Core::STY_Abs;
|
||||
_opTable[0x8D] = &Core::STA_Abs;
|
||||
_opTable[0x8E] = &Core::STX_Abs;
|
||||
_opTable[0x90] = &Core::BCC;
|
||||
_opTable[0x91] = &Core::STA_IndY;
|
||||
_opTable[0x94] = &Core::STY_ZeroX;
|
||||
_opTable[0x95] = &Core::STA_ZeroX;
|
||||
_opTable[0x96] = &Core::STX_ZeroY;
|
||||
_opTable[0x98] = &Core::TYA;
|
||||
_opTable[0x99] = &Core::STA_AbsY;
|
||||
_opTable[0x9A] = &Core::TXS;
|
||||
_opTable[0x9D] = &Core::STA_AbsX;
|
||||
_opTable[0xA0] = &Core::LDY_Imm;
|
||||
_opTable[0xA1] = &Core::LDA_IndX;
|
||||
_opTable[0xA2] = &Core::LDX_Imm;
|
||||
_opTable[0xA4] = &Core::LDY_Zero;
|
||||
_opTable[0xA5] = &Core::LDA_Zero;
|
||||
_opTable[0xA6] = &Core::LDX_Zero;
|
||||
_opTable[0xA8] = &Core::TAY;
|
||||
_opTable[0xA9] = &Core::LDA_Imm;
|
||||
_opTable[0xAA] = &Core::TAX;
|
||||
_opTable[0xAC] = &Core::LDY_Abs;
|
||||
_opTable[0xAD] = &Core::LDA_Abs;
|
||||
_opTable[0xAE] = &Core::LDX_Abs;
|
||||
_opTable[0xB0] = &Core::BCS;
|
||||
_opTable[0xB1] = &Core::LDA_IndY;
|
||||
_opTable[0xB4] = &Core::LDY_ZeroX;
|
||||
_opTable[0xB5] = &Core::LDA_ZeroX;
|
||||
_opTable[0xB6] = &Core::LDX_ZeroY;
|
||||
_opTable[0xB8] = &Core::CLV;
|
||||
_opTable[0xB9] = &Core::LDA_AbsY;
|
||||
_opTable[0xBA] = &Core::TSX;
|
||||
_opTable[0xBC] = &Core::LDY_AbsX;
|
||||
_opTable[0xBD] = &Core::LDA_AbsX;
|
||||
_opTable[0xBE] = &Core::LDX_AbsY;
|
||||
_opTable[0xC0] = &Core::CPY_Imm;
|
||||
_opTable[0xC1] = &Core::CMP_IndX;
|
||||
_opTable[0xC4] = &Core::CPY_Zero;
|
||||
_opTable[0xC5] = &Core::CMP_Zero;
|
||||
_opTable[0xC6] = &Core::DEC_Zero;
|
||||
_opTable[0xC8] = &Core::INY;
|
||||
_opTable[0xC9] = &Core::CMP_Imm;
|
||||
_opTable[0xCA] = &Core::DEX;
|
||||
_opTable[0xCC] = &Core::CPY_Abs;
|
||||
_opTable[0xCD] = &Core::CMP_Abs;
|
||||
_opTable[0xCE] = &Core::DEC_Abs;
|
||||
_opTable[0xD0] = &Core::BNE;
|
||||
_opTable[0xD1] = &Core::CMP_IndY;
|
||||
_opTable[0xD5] = &Core::CMP_ZeroX;
|
||||
_opTable[0xD6] = &Core::DEC_ZeroX;
|
||||
_opTable[0xD8] = &Core::CLD;
|
||||
_opTable[0xD9] = &Core::CMP_AbsY;
|
||||
_opTable[0xDD] = &Core::CMP_AbsX;
|
||||
_opTable[0xDE] = &Core::DEC_AbsX;
|
||||
_opTable[0xE0] = &Core::CPX_Imm;
|
||||
_opTable[0xE1] = &Core::SBC_IndX;
|
||||
_opTable[0xE4] = &Core::CPX_Zero;
|
||||
_opTable[0xE5] = &Core::SBC_Zero;
|
||||
_opTable[0xE6] = &Core::INC_Zero;
|
||||
_opTable[0xE8] = &Core::INX;
|
||||
_opTable[0xE9] = &Core::SBC_Imm;
|
||||
_opTable[0xEA] = &Core::NOP;
|
||||
_opTable[0xEC] = &Core::CPX_Abs;
|
||||
_opTable[0xED] = &Core::SBC_Abs;
|
||||
_opTable[0xEE] = &Core::INC_Abs;
|
||||
_opTable[0xF0] = &Core::BEQ;
|
||||
_opTable[0xF1] = &Core::SBC_IndY;
|
||||
_opTable[0xF5] = &Core::SBC_ZeroX;
|
||||
_opTable[0xF6] = &Core::INC_ZeroX;
|
||||
_opTable[0xF8] = &Core::SED;
|
||||
_opTable[0xF9] = &Core::SBC_AbsY;
|
||||
_opTable[0xFD] = &Core::SBC_AbsX;
|
||||
_opTable[0xFE] = &Core::INC_AbsX;
|
||||
}
|
||||
CPU(MemoryManager *memoryManager);
|
||||
void Reset();
|
||||
void Exec();
|
||||
static void RunBenchmark();
|
||||
};
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -87,6 +88,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CPU.h" />
|
||||
<ClInclude Include="EventHandler.h" />
|
||||
<ClInclude Include="Memory.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
|
@ -95,6 +98,7 @@
|
|||
<ClCompile Include="CPU.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
<ClInclude Include="CPU.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EventHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Memory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
|
|
59
main.cpp
59
main.cpp
|
@ -2,44 +2,6 @@
|
|||
#include "CPU.h"
|
||||
|
||||
/*
|
||||
template<typename... Types>
|
||||
class Event
|
||||
{
|
||||
typedef void(*Func)(Types...);
|
||||
private:
|
||||
std::list<Func> handlerList;
|
||||
Func lastFunc;
|
||||
|
||||
public:
|
||||
void RegisterHandler(Func handler);
|
||||
void operator+=(Func handler);
|
||||
void operator()(Types ...types);
|
||||
};
|
||||
|
||||
template<typename... Types>
|
||||
void Event<Types...>::RegisterHandler(Func handler)
|
||||
{
|
||||
this->handlerList.push_back(handler);
|
||||
lastFunc = this->handlerList.size() == 1 ? handler : nullptr;
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
void Event<Types...>::operator+=(Func handler) {
|
||||
this->RegisterHandler(handler);
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
void Event<Types...>::operator()(Types... types)
|
||||
{
|
||||
if (lastFunc) {
|
||||
lastFunc(types...);
|
||||
} else {
|
||||
for (auto handler : this->handlerList) {
|
||||
handler(types...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class TemplatedClass
|
||||
{
|
||||
|
@ -103,19 +65,14 @@ void func2(int a)
|
|||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
std::ifstream romFile("6502_functional_test.bin", std::ios::in | std::ios::binary);
|
||||
if(!romFile) {
|
||||
std::cout << "Error";
|
||||
}
|
||||
|
||||
int8_t romMemory[65536];
|
||||
romFile.read((char *)romMemory, 65536);
|
||||
/*int8_t* memory = new int8_t[8000];
|
||||
memory[0x0600] = 0xA9;
|
||||
memory[0x0601] = 0x55;*/
|
||||
|
||||
Core core(romMemory);
|
||||
core.Exec();
|
||||
/* BaseMemoryHandler a;
|
||||
Test b;
|
||||
EventHandler<BaseMemoryHandler, uint16_t> eventHandler;
|
||||
eventHandler.RegisterHandler(&a, &BaseMemoryHandler::CallbackTest);
|
||||
eventHandler.RegisterHandler(&b, &BaseMemoryHandler::CallbackTest);
|
||||
eventHandler(eMemoryOperation::Read, 0);
|
||||
*/
|
||||
CPU::RunBenchmark();
|
||||
|
||||
/*Event<> eventHandler;
|
||||
eventHandler += somefunction;
|
||||
|
|
Loading…
Add table
Reference in a new issue