CPU: Added all idle cycles + added DRAM refresh delay

This commit is contained in:
Sour 2019-02-21 22:10:41 -05:00
parent 97c7d06156
commit 0b7ad7c0db
5 changed files with 666 additions and 174 deletions

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "Cpu.h"
#include "MemoryManager.h"
/************************
Add/substract operations
@ -217,6 +218,12 @@ void Cpu::BranchRelative(bool branch)
{
int8_t offset = _operand;
if(branch) {
Idle();
if(_state.EmulationMode) {
if(((uint16_t)(_state.PC + offset) & 0xFF00) != (_state.PC & 0xFF00)) {
Idle();
}
}
_state.PC = (uint16_t)(_state.PC + offset);
}
}
@ -307,6 +314,16 @@ void Cpu::INC()
IncDec(1);
}
void Cpu::DEC_Acc()
{
SetRegister(_state.A, _state.A - 1, CheckFlag(ProcFlags::MemoryMode8));
}
void Cpu::INC_Acc()
{
SetRegister(_state.A, _state.A + 1, CheckFlag(ProcFlags::MemoryMode8));
}
void Cpu::IncDecReg(uint16_t &reg, int8_t offset)
{
SetRegister(reg, reg + offset, CheckFlag(ProcFlags::IndexMode8));
@ -314,19 +331,17 @@ void Cpu::IncDecReg(uint16_t &reg, int8_t offset)
void Cpu::IncDec(int8_t offset)
{
if(_instAddrMode == AddrMode::Acc) {
SetRegister(_state.A, _state.A + offset, CheckFlag(ProcFlags::MemoryMode8));
} else {
if(CheckFlag(ProcFlags::MemoryMode8)) {
uint8_t value = GetByteValue() + offset;
SetZeroNegativeFlags(value);
Idle();
Write(_operand, value);
} else {
uint16_t value = GetWordValue() + offset;
SetZeroNegativeFlags(value);
Idle();
WriteWord(_operand, value);
}
}
}
/********************
@ -388,6 +403,7 @@ void Cpu::JMP()
void Cpu::JSL()
{
PushByte(_state.K);
Idle();
PushWord(_state.PC - 1);
_state.K = (_operand >> 16) & 0xFF;
_state.PC = (uint16_t)_operand;
@ -401,6 +417,9 @@ void Cpu::JSR()
void Cpu::RTI()
{
Idle();
Idle();
if(_state.EmulationMode) {
SetPS(PopByte());
_state.PC = PopWord();
@ -413,6 +432,9 @@ void Cpu::RTI()
void Cpu::RTL()
{
Idle();
Idle();
_state.PC = PopWord();
_state.PC++;
_state.K = PopByte();
@ -420,7 +442,11 @@ void Cpu::RTL()
void Cpu::RTS()
{
Idle();
Idle();
_state.PC = PopWord();
Idle();
_state.PC++;
}
@ -429,6 +455,9 @@ Interrupts
***********/
void Cpu::ProcessInterrupt(uint16_t vector)
{
Idle();
Idle();
if(_state.EmulationMode) {
PushWord(_state.PC);
PushByte(_state.PS | 0x20);
@ -541,72 +570,84 @@ template<typename T> T Cpu::RollRight(T value)
return result;
}
void Cpu::ASL()
void Cpu::ASL_Acc()
{
if(_instAddrMode == AddrMode::Acc) {
if(CheckFlag(ProcFlags::MemoryMode8)) {
_state.A = (_state.A & 0xFF00) | (ShiftLeft<uint8_t>((uint8_t)_state.A));
} else {
_state.A = ShiftLeft<uint16_t>(_state.A);
}
} else {
}
void Cpu::ASL()
{
if(CheckFlag(ProcFlags::MemoryMode8)) {
Idle();
Write(_operand, ShiftLeft<uint8_t>(GetByteValue()));
} else {
Idle();
WriteWord(_operand, ShiftLeft<uint16_t>(GetWordValue()));
}
}
}
void Cpu::LSR()
void Cpu::LSR_Acc()
{
if(_instAddrMode == AddrMode::Acc) {
if(CheckFlag(ProcFlags::MemoryMode8)) {
_state.A = (_state.A & 0xFF00) | ShiftRight<uint8_t>((uint8_t)_state.A);
} else {
_state.A = ShiftRight<uint16_t>(_state.A);
}
} else {
}
void Cpu::LSR()
{
if(CheckFlag(ProcFlags::MemoryMode8)) {
Idle();
Write(_operand, ShiftRight<uint8_t>(GetByteValue()));
} else {
Idle();
WriteWord(_operand, ShiftRight<uint16_t>(GetWordValue()));
}
}
}
void Cpu::ROL()
void Cpu::ROL_Acc()
{
if(_instAddrMode == AddrMode::Acc) {
if(CheckFlag(ProcFlags::MemoryMode8)) {
_state.A = (_state.A & 0xFF00) | RollLeft<uint8_t>((uint8_t)_state.A);
} else {
_state.A = RollLeft<uint16_t>(_state.A);
}
} else {
}
void Cpu::ROL()
{
if(CheckFlag(ProcFlags::MemoryMode8)) {
Idle();
Write(_operand, RollLeft<uint8_t>(GetByteValue()));
} else {
Idle();
WriteWord(_operand, RollLeft<uint16_t>(GetWordValue()));
}
}
}
void Cpu::ROR()
void Cpu::ROR_Acc()
{
if(_instAddrMode == AddrMode::Acc) {
if(CheckFlag(ProcFlags::MemoryMode8)) {
_state.A = (_state.A & 0xFF00) | RollRight<uint8_t>((uint8_t)_state.A);
} else {
_state.A = RollRight<uint16_t>(_state.A);
}
} else {
}
void Cpu::ROR()
{
if(CheckFlag(ProcFlags::MemoryMode8)) {
Idle();
Write(_operand, RollRight<uint8_t>(GetByteValue()));
} else {
Idle();
WriteWord(_operand, RollRight<uint16_t>(GetWordValue()));
}
}
}
/***************
@ -621,9 +662,19 @@ void Cpu::MVN()
uint8_t value = ReadData(srcBank | _state.X);
Write(destBank | _state.Y, value);
Idle();
Idle();
_state.X++;
_state.Y++;
_state.A--;
if(_state.A != 0xFFFF) {
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
}
} while(_state.A != 0xFFFF);
}
@ -636,9 +687,19 @@ void Cpu::MVP()
uint8_t value = ReadData(srcBank | _state.X);
Write(destBank | _state.Y, value);
Idle();
Idle();
_state.X--;
_state.Y--;
_state.A--;
if(_state.A != 0xFFFF) {
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
}
} while(_state.A != 0xFFFF);
}
@ -654,52 +715,64 @@ void Cpu::PEA()
void Cpu::PEI()
{
//Push Effective Indirect address
Idle();
PushWord(ReadDataWord(_operand));
}
void Cpu::PER()
{
//Push Effective Relative address
Idle();
PushWord((uint16_t)((int16_t)_operand + _state.PC));
}
void Cpu::PHB()
{
Idle();
PushByte(_state.DBR);
}
void Cpu::PHD()
{
Idle();
PushWord(_state.D);
}
void Cpu::PHK()
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
Idle();
PushByte(_state.K);
}
void Cpu::PHP()
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
Idle();
PushByte(_state.PS);
}
void Cpu::PLB()
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
Idle();
Idle();
SetRegister(_state.DBR, PopByte());
}
void Cpu::PLD()
{
//"PHD and PLD push and pull two bytes from the stack."
Idle();
Idle();
SetRegister(_state.D, PopWord(), false);
}
void Cpu::PLP()
{
//"For PLP, (all of) the flags are pulled from the stack. Note that when the e flag is 1, the m and x flag are forced to 1, so after the PLP, both flags will still be 1 no matter what value is pulled from the stack."
Idle();
Idle();
if(_state.EmulationMode) {
SetPS(PopByte() | ProcFlags::MemoryMode8 | ProcFlags::IndexMode8);
} else {
@ -710,32 +783,41 @@ void Cpu::PLP()
void Cpu::PHA()
{
//"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value. "
Idle();
PushRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8));
}
void Cpu::PHX()
{
Idle();
PushRegister(_state.X, CheckFlag(ProcFlags::IndexMode8));
}
void Cpu::PHY()
{
Idle();
PushRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8));
}
void Cpu::PLA()
{
//"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value."
Idle();
Idle();
PullRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8));
}
void Cpu::PLX()
{
Idle();
Idle();
PullRegister(_state.X, CheckFlag(ProcFlags::IndexMode8));
}
void Cpu::PLY()
{
Idle();
Idle();
PullRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8));
}
@ -853,9 +935,9 @@ template<typename T> void Cpu::TestBits(T value, bool alterZeroFlagOnly)
void Cpu::BIT()
{
if(CheckFlag(ProcFlags::MemoryMode8)) {
TestBits<uint8_t>(GetByteValue(), _instAddrMode <= AddrMode::ImmM);
TestBits<uint8_t>(GetByteValue(), _immediateMode);
} else {
TestBits<uint16_t>(GetWordValue(), _instAddrMode <= AddrMode::ImmM);
TestBits<uint16_t>(GetWordValue(), _immediateMode);
}
}
@ -866,12 +948,14 @@ void Cpu::TRB()
uint8_t value = ReadData(_operand);
value &= ~_state.A;
Idle();
Write(_operand, value);
} else {
TestBits<uint16_t>(GetWordValue(), true);
uint16_t value = ReadDataWord(_operand);
value &= ~_state.A;
Idle();
WriteWord(_operand, value);
}
}
@ -958,6 +1042,7 @@ void Cpu::TYX()
void Cpu::XBA()
{
Idle();
_state.A = ((_state.A & 0xFF) << 8) | ((_state.A >> 8) & 0xFF);
SetZeroNegativeFlags((uint8_t)_state.A);
}
@ -1003,3 +1088,178 @@ void Cpu::WAI()
{
//Wait for interrupt
}
/****************
Addressing modes
*****************/
void Cpu::AddrMode_Abs()
{
_operand = GetDataAddress(ReadOperandWord());
}
void Cpu::AddrMode_AbsIdxX()
{
_operand = (GetDataAddress(ReadOperandWord()) + _state.X) & 0xFFFFFF;
Idle();
}
void Cpu::AddrMode_AbsIdxY()
{
_operand = (GetDataAddress(ReadOperandWord()) + _state.Y) & 0xFFFFFF;
Idle();
}
void Cpu::AddrMode_AbsLng()
{
_operand = ReadOperandLong();
}
void Cpu::AddrMode_AbsLngIdxX()
{
_operand = (ReadOperandLong() + _state.X) & 0xFFFFFF;
}
void Cpu::AddrMode_AbsJmp()
{
_operand = GetProgramAddress(ReadOperandWord());
}
void Cpu::AddrMode_AbsLngJmp()
{
_operand = ReadOperandLong();
}
void Cpu::AddrMode_AbsIdxXInd()
{
_operand = GetProgramAddress(ReadDataWord(GetProgramAddress(ReadOperandWord() + _state.X)));
Idle();
}
void Cpu::AddrMode_AbsInd()
{
_operand = ReadDataWord(ReadOperandWord());
}
void Cpu::AddrMode_AbsIndLng()
{
_operand = ReadDataLong(ReadOperandWord());
}
void Cpu::AddrMode_Acc()
{
Idle();
}
void Cpu::AddrMode_BlkMov()
{
_operand = ReadOperandWord();
}
uint8_t Cpu::ReadDirectOperandByte()
{
uint8_t value = ReadOperandByte();
if(_state.D & 0xFF) {
//Add 1 cycle for direct register low (DL) not equal 0
Idle();
}
return value;
}
void Cpu::AddrMode_Dir()
{
_operand = GetDirectAddress(ReadDirectOperandByte());
}
void Cpu::AddrMode_DirIdxX()
{
_operand = GetDirectAddress(ReadDirectOperandByte() + _state.X);
Idle();
}
void Cpu::AddrMode_DirIdxY()
{
_operand = GetDirectAddress(ReadDirectOperandByte() + _state.Y);
Idle();
}
void Cpu::AddrMode_DirInd()
{
_operand = GetDataAddress(GetDirectAddressIndirectWord(ReadDirectOperandByte()));
}
void Cpu::AddrMode_DirIdxIndX()
{
uint8_t operandByte = ReadDirectOperandByte();
Idle();
_operand = GetDataAddress(GetDirectAddressIndirectWord(operandByte + _state.X));
}
void Cpu::AddrMode_DirIndIdxY()
{
_operand = (GetDataAddress(GetDirectAddressIndirectWord(ReadDirectOperandByte())) + _state.Y) & 0xFFFFFF;
Idle();
}
void Cpu::AddrMode_DirIndLng()
{
_operand = GetDirectAddressIndirectLong(ReadDirectOperandByte());
}
void Cpu::AddrMode_DirIndLngIdxY()
{
_operand = (GetDirectAddressIndirectLong(ReadDirectOperandByte()) + _state.Y) & 0xFFFFFF;
}
void Cpu::AddrMode_Imm8()
{
_immediateMode = true;
_operand = ReadOperandByte();
}
void Cpu::AddrMode_Imm16()
{
_immediateMode = true;
_operand = ReadOperandWord();
}
void Cpu::AddrMode_ImmX()
{
_immediateMode = true;
_operand = CheckFlag(ProcFlags::IndexMode8) ? ReadOperandByte() : ReadOperandWord();
}
void Cpu::AddrMode_ImmM()
{
_immediateMode = true;
_operand = CheckFlag(ProcFlags::MemoryMode8) ? ReadOperandByte() : ReadOperandWord();
}
void Cpu::AddrMode_Imp()
{
Idle();
}
void Cpu::AddrMode_RelLng()
{
_operand = ReadOperandWord();
Idle();
}
void Cpu::AddrMode_Rel()
{
_operand = ReadOperandByte();
}
void Cpu::AddrMode_StkRel()
{
_operand = (uint16_t)(ReadOperandByte() + _state.SP);
Idle();
}
void Cpu::AddrMode_StkRelIndIdxY()
{
uint16_t addr = (uint16_t)(ReadOperandByte() + _state.SP);
Idle();
_operand = (GetDataAddress(ReadDataWord(addr)) + _state.Y) & 0xFFFFFF;
Idle();
}

View file

@ -5,51 +5,6 @@
Cpu::Cpu(shared_ptr<MemoryManager> memoryManager)
{
typedef Cpu C;
Func opTable[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
&C::BRK, &C::ORA, &C::COP, &C::ORA, &C::TSB, &C::ORA, &C::ASL, &C::ORA, &C::PHP, &C::ORA, &C::ASL, &C::PHD, &C::TSB, &C::ORA, &C::ASL, &C::ORA, // 0
&C::BPL, &C::ORA, &C::ORA, &C::ORA, &C::TRB, &C::ORA, &C::ASL, &C::ORA, &C::CLC, &C::ORA, &C::INC, &C::TCS, &C::TRB, &C::ORA, &C::ASL, &C::ORA, // 1
&C::JSR, &C::AND, &C::JSL, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::PLP, &C::AND, &C::ROL, &C::PLD, &C::BIT, &C::AND, &C::ROL, &C::AND, // 2
&C::BMI, &C::AND, &C::AND, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::SEC, &C::AND, &C::DEC, &C::TSC, &C::BIT, &C::AND, &C::ROL, &C::AND, // 3
&C::RTI, &C::EOR, &C::WDM, &C::EOR, &C::MVP, &C::EOR, &C::LSR, &C::EOR, &C::PHA, &C::EOR, &C::LSR, &C::PHK, &C::JMP, &C::EOR, &C::LSR, &C::EOR, // 4
&C::BVC, &C::EOR, &C::EOR, &C::EOR, &C::MVN, &C::EOR, &C::LSR, &C::EOR, &C::CLI, &C::EOR, &C::PHY, &C::TCD, &C::JML, &C::EOR, &C::LSR, &C::EOR, // 5
&C::RTS, &C::ADC, &C::PER, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::PLA, &C::ADC, &C::ROR, &C::RTL, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 6
&C::BVS, &C::ADC, &C::ADC, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::SEI, &C::ADC, &C::PLY, &C::TDC, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 7
&C::BRA, &C::STA, &C::BRL, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::DEY, &C::BIT, &C::TXA, &C::PHB, &C::STY, &C::STA, &C::STX, &C::STA, // 8
&C::BCC, &C::STA, &C::STA, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::TYA, &C::STA, &C::TXS, &C::TXY, &C::STZ, &C::STA, &C::STZ, &C::STA, // 9
&C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::TAY, &C::LDA, &C::TAX, &C::PLB, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // A
&C::BCS, &C::LDA, &C::LDA, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::CLV, &C::LDA, &C::TSX, &C::TYX, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // B
&C::CPY, &C::CMP, &C::REP, &C::CMP, &C::CPY, &C::CMP, &C::DEC, &C::CMP, &C::INY, &C::CMP, &C::DEX, &C::WAI, &C::CPY, &C::CMP, &C::DEC, &C::CMP, // C
&C::BNE, &C::CMP, &C::CMP, &C::CMP, &C::PEI, &C::CMP, &C::DEC, &C::CMP, &C::CLD, &C::CMP, &C::PHX, &C::STP, &C::JML, &C::CMP, &C::DEC, &C::CMP, // D
&C::CPX, &C::SBC, &C::SEP, &C::SBC, &C::CPX, &C::SBC, &C::INC, &C::SBC, &C::INX, &C::SBC, &C::NOP, &C::XBA, &C::CPX, &C::SBC, &C::INC, &C::SBC, // E
&C::BEQ, &C::SBC, &C::SBC, &C::SBC, &C::PEA, &C::SBC, &C::INC, &C::SBC, &C::SED, &C::SBC, &C::PLX, &C::XCE, &C::JSR, &C::SBC, &C::INC, &C::SBC // F
};
typedef AddrMode M;
AddrMode addrMode[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
M::Stk, M::DirIdxIndX, M::Stk, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 0
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 1
M::AbsJmp,M::DirIdxIndX, M::AbsLngJmp,M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 2
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 3
M::Stk, M::DirIdxIndX, M::Imm8, M::StkRel, M::BlkMov, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::AbsJmp, M::Abs, M::Abs, M::AbsLng, // 4
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::BlkMov, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsLngJmp, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 5
M::Stk, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::AbsInd, M::Abs, M::Abs, M::AbsLng, // 6
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 7
M::Rel, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 8
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 9
M::ImmX, M::DirIdxIndX, M::ImmX, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // A
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxY, M::AbsLngIdxX, // B
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // C
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIndLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // D
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // E
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Imm16, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX // F
};
memcpy(_opTable, opTable, sizeof(opTable));
memcpy(_addrMode, addrMode, sizeof(addrMode));
_memoryManager = memoryManager;
_state = {};
_state.PC = ReadDataWord(Cpu::ResetVector);
@ -71,12 +26,266 @@ void Cpu::Reset()
void Cpu::Exec()
{
uint8_t opCode = GetOpCode();
_instAddrMode = _addrMode[opCode];
_operand = FetchEffectiveAddress();
(this->*_opTable[opCode])();
_immediateMode = false;
opCount++;
switch(GetOpCode()) {
case 0x00: BRK(); break;
case 0x01: AddrMode_DirIdxIndX(); ORA(); break;
case 0x02: COP(); break;
case 0x03: AddrMode_StkRel(); ORA(); break;
case 0x04: AddrMode_Dir(); TSB(); break;
case 0x05: AddrMode_Dir(); ORA(); break;
case 0x06: AddrMode_Dir(); ASL(); break;
case 0x07: AddrMode_DirIndLng(); ORA(); break;
case 0x08: PHP(); break;
case 0x09: AddrMode_ImmM(); ORA(); break;
case 0x0A: AddrMode_Acc(); ASL_Acc(); break;
case 0x0B: PHD(); break;
case 0x0C: AddrMode_Abs(); TSB(); break;
case 0x0D: AddrMode_Abs(); ORA(); break;
case 0x0E: AddrMode_Abs(); ASL(); break;
case 0x0F: AddrMode_AbsLng(); ORA(); break;
case 0x10: AddrMode_Rel(); BPL(); break;
case 0x11: AddrMode_DirIndIdxY(); ORA(); break;
case 0x12: AddrMode_DirInd(); ORA(); break;
case 0x13: AddrMode_StkRelIndIdxY(); ORA(); break;
case 0x14: AddrMode_Dir(); TRB(); break;
case 0x15: AddrMode_DirIdxX(); ORA(); break;
case 0x16: AddrMode_DirIdxX(); ASL(); break;
case 0x17: AddrMode_DirIndLngIdxY(); ORA(); break;
case 0x18: AddrMode_Imp(); CLC(); break;
case 0x19: AddrMode_AbsIdxY(); ORA(); break;
case 0x1A: AddrMode_Acc(); INC_Acc(); break;
case 0x1B: AddrMode_Imp(); TCS(); break;
case 0x1C: AddrMode_Abs(); TRB(); break;
case 0x1D: AddrMode_AbsIdxX(); ORA(); break;
case 0x1E: AddrMode_AbsIdxX(); ASL(); break;
case 0x1F: AddrMode_AbsLngIdxX(); ORA(); break;
case 0x20: AddrMode_AbsJmp(); Idle(); JSR(); break;
case 0x21: AddrMode_DirIdxIndX(); AND(); break;
case 0x22: AddrMode_AbsLngJmp(); JSL(); break;
case 0x23: AddrMode_StkRel(); AND(); break;
case 0x24: AddrMode_Dir(); BIT(); break;
case 0x25: AddrMode_Dir(); AND(); break;
case 0x26: AddrMode_Dir(); ROL(); break;
case 0x27: AddrMode_DirIndLng(); AND(); break;
case 0x28: PLP(); break;
case 0x29: AddrMode_ImmM(); AND(); break;
case 0x2A: AddrMode_Acc(); ROL_Acc(); break;
case 0x2B: PLD(); break;
case 0x2C: AddrMode_Abs(); BIT(); break;
case 0x2D: AddrMode_Abs(); AND(); break;
case 0x2E: AddrMode_Abs(); ROL(); break;
case 0x2F: AddrMode_AbsLng(); AND(); break;
case 0x30: AddrMode_Rel(); BMI(); break;
case 0x31: AddrMode_DirIndIdxY(); AND(); break;
case 0x32: AddrMode_DirInd(); AND(); break;
case 0x33: AddrMode_StkRelIndIdxY(); AND(); break;
case 0x34: AddrMode_DirIdxX(); BIT(); break;
case 0x35: AddrMode_DirIdxX(); AND(); break;
case 0x36: AddrMode_DirIdxX(); ROL(); break;
case 0x37: AddrMode_DirIndLngIdxY(); AND(); break;
case 0x38: AddrMode_Imp(); SEC(); break;
case 0x39: AddrMode_AbsIdxY(); AND(); break;
case 0x3A: AddrMode_Acc(); DEC_Acc(); break;
case 0x3B: AddrMode_Imp(); TSC(); break;
case 0x3C: AddrMode_AbsIdxX(); BIT(); break;
case 0x3D: AddrMode_AbsIdxX(); AND(); break;
case 0x3E: AddrMode_AbsIdxX(); ROL(); break;
case 0x3F: AddrMode_AbsLngIdxX(); AND(); break;
case 0x40: RTI(); break;
case 0x41: AddrMode_DirIdxIndX(); EOR(); break;
case 0x42: AddrMode_Imm8(); WDM(); break;
case 0x43: AddrMode_StkRel(); EOR(); break;
case 0x44: AddrMode_BlkMov(); MVP(); break;
case 0x45: AddrMode_Dir(); EOR(); break;
case 0x46: AddrMode_Dir(); LSR(); break;
case 0x47: AddrMode_DirIndLng(); EOR(); break;
case 0x48: PHA(); break;
case 0x49: AddrMode_ImmM(); EOR(); break;
case 0x4A: AddrMode_Acc(); LSR_Acc(); break;
case 0x4B: PHK(); break;
case 0x4C: AddrMode_AbsJmp(); JMP(); break;
case 0x4D: AddrMode_Abs(); EOR(); break;
case 0x4E: AddrMode_Abs(); LSR(); break;
case 0x4F: AddrMode_AbsLng(); EOR(); break;
case 0x50: AddrMode_Rel(); BVC(); break;
case 0x51: AddrMode_DirIndIdxY(); EOR(); break;
case 0x52: AddrMode_DirInd(); EOR(); break;
case 0x53: AddrMode_StkRelIndIdxY(); EOR(); break;
case 0x54: AddrMode_BlkMov(); MVN(); break;
case 0x55: AddrMode_DirIdxX(); EOR(); break;
case 0x56: AddrMode_DirIdxX(); LSR(); break;
case 0x57: AddrMode_DirIndLngIdxY(); EOR(); break;
case 0x58: AddrMode_Imp(); CLI(); break;
case 0x59: AddrMode_AbsIdxY(); EOR(); break;
case 0x5A: PHY(); break;
case 0x5B: AddrMode_Imp(); TCD(); break;
case 0x5C: AddrMode_AbsLngJmp(); JML(); break;
case 0x5D: AddrMode_AbsIdxX(); EOR(); break;
case 0x5E: AddrMode_AbsIdxX(); LSR(); break;
case 0x5F: AddrMode_AbsLngIdxX(); EOR(); break;
case 0x60: RTS(); break;
case 0x61: AddrMode_DirIdxIndX(); ADC(); break;
case 0x62: AddrMode_RelLng(); PER(); break;
case 0x63: AddrMode_StkRel(); ADC(); break;
case 0x64: AddrMode_Dir(); STZ(); break;
case 0x65: AddrMode_Dir(); ADC(); break;
case 0x66: AddrMode_Dir(); ROR(); break;
case 0x67: AddrMode_DirIndLng(); ADC(); break;
case 0x68: PLA(); break;
case 0x69: AddrMode_ImmM(); ADC(); break;
case 0x6A: AddrMode_Acc(); ROR_Acc(); break;
case 0x6B: RTL(); break;
case 0x6C: AddrMode_AbsInd(); JMP(); break;
case 0x6D: AddrMode_Abs(); ADC(); break;
case 0x6E: AddrMode_Abs(); ROR(); break;
case 0x6F: AddrMode_AbsLng(); ADC(); break;
case 0x70: AddrMode_Rel(); BVS(); break;
case 0x71: AddrMode_DirIndIdxY(); ADC(); break;
case 0x72: AddrMode_DirInd(); ADC(); break;
case 0x73: AddrMode_StkRelIndIdxY(); ADC(); break;
case 0x74: AddrMode_DirIdxX(); STZ(); break;
case 0x75: AddrMode_DirIdxX(); ADC(); break;
case 0x76: AddrMode_DirIdxX(); ROR(); break;
case 0x77: AddrMode_DirIndLngIdxY(); ADC(); break;
case 0x78: AddrMode_Imp(); SEI(); break;
case 0x79: AddrMode_AbsIdxY(); ADC(); break;
case 0x7A: PLY(); break;
case 0x7B: AddrMode_Imp(); TDC(); break;
case 0x7C: AddrMode_AbsIdxXInd(); JMP(); break;
case 0x7D: AddrMode_AbsIdxX(); ADC(); break;
case 0x7E: AddrMode_AbsIdxX(); ROR(); break;
case 0x7F: AddrMode_AbsLngIdxX(); ADC(); break;
case 0x80: AddrMode_Rel(); BRA(); break;
case 0x81: AddrMode_DirIdxIndX(); STA(); break;
case 0x82: AddrMode_RelLng(); BRL(); break;
case 0x83: AddrMode_StkRel(); STA(); break;
case 0x84: AddrMode_Dir(); STY(); break;
case 0x85: AddrMode_Dir(); STA(); break;
case 0x86: AddrMode_Dir(); STX(); break;
case 0x87: AddrMode_DirIndLng(); STA(); break;
case 0x88: AddrMode_Imp(); DEY(); break;
case 0x89: AddrMode_ImmM(); BIT(); break;
case 0x8A: AddrMode_Imp(); TXA(); break;
case 0x8B: PHB(); break;
case 0x8C: AddrMode_Abs(); STY(); break;
case 0x8D: AddrMode_Abs(); STA(); break;
case 0x8E: AddrMode_Abs(); STX(); break;
case 0x8F: AddrMode_AbsLng(); STA(); break;
case 0x90: AddrMode_Rel(); BCC(); break;
case 0x91: AddrMode_DirIndIdxY(); STA(); break;
case 0x92: AddrMode_DirInd(); STA(); break;
case 0x93: AddrMode_StkRelIndIdxY(); STA(); break;
case 0x94: AddrMode_DirIdxX(); STY(); break;
case 0x95: AddrMode_DirIdxX(); STA(); break;
case 0x96: AddrMode_DirIdxY(); STX(); break;
case 0x97: AddrMode_DirIndLngIdxY(); STA(); break;
case 0x98: AddrMode_Imp(); TYA(); break;
case 0x99: AddrMode_AbsIdxY(); STA(); break;
case 0x9A: AddrMode_Imp(); TXS(); break;
case 0x9B: AddrMode_Imp(); TXY(); break;
case 0x9C: AddrMode_Abs(); STZ(); break;
case 0x9D: AddrMode_AbsIdxX(); STA(); break;
case 0x9E: AddrMode_AbsIdxX(); STZ(); break;
case 0x9F: AddrMode_AbsLngIdxX(); STA(); break;
case 0xA0: AddrMode_ImmX(); LDY(); break;
case 0xA1: AddrMode_DirIdxIndX(); LDA(); break;
case 0xA2: AddrMode_ImmX(); LDX(); break;
case 0xA3: AddrMode_StkRel(); LDA(); break;
case 0xA4: AddrMode_Dir(); LDY(); break;
case 0xA5: AddrMode_Dir(); LDA(); break;
case 0xA6: AddrMode_Dir(); LDX(); break;
case 0xA7: AddrMode_DirIndLng(); LDA(); break;
case 0xA8: AddrMode_Imp(); TAY(); break;
case 0xA9: AddrMode_ImmM(); LDA(); break;
case 0xAA: AddrMode_Imp(); TAX(); break;
case 0xAB: PLB(); break;
case 0xAC: AddrMode_Abs(); LDY(); break;
case 0xAD: AddrMode_Abs(); LDA(); break;
case 0xAE: AddrMode_Abs(); LDX(); break;
case 0xAF: AddrMode_AbsLng(); LDA(); break;
case 0xB0: AddrMode_Rel(); BCS(); break;
case 0xB1: AddrMode_DirIndIdxY(); LDA(); break;
case 0xB2: AddrMode_DirInd(); LDA(); break;
case 0xB3: AddrMode_StkRelIndIdxY(); LDA(); break;
case 0xB4: AddrMode_DirIdxX(); LDY(); break;
case 0xB5: AddrMode_DirIdxX(); LDA(); break;
case 0xB6: AddrMode_DirIdxY(); LDX(); break;
case 0xB7: AddrMode_DirIndLngIdxY(); LDA(); break;
case 0xB8: AddrMode_Imp(); CLV(); break;
case 0xB9: AddrMode_AbsIdxY(); LDA(); break;
case 0xBA: AddrMode_Imp(); TSX(); break;
case 0xBB: AddrMode_Imp(); TYX(); break;
case 0xBC: AddrMode_AbsIdxX(); LDY(); break;
case 0xBD: AddrMode_AbsIdxX(); LDA(); break;
case 0xBE: AddrMode_AbsIdxY(); LDX(); break;
case 0xBF: AddrMode_AbsLngIdxX(); LDA(); break;
case 0xC0: AddrMode_ImmX(); CPY(); break;
case 0xC1: AddrMode_DirIdxIndX(); CMP(); break;
case 0xC2: AddrMode_Imm8(); REP(); break;
case 0xC3: AddrMode_StkRel(); CMP(); break;
case 0xC4: AddrMode_Dir(); CPY(); break;
case 0xC5: AddrMode_Dir(); CMP(); break;
case 0xC6: AddrMode_Dir(); DEC(); break;
case 0xC7: AddrMode_DirIndLng(); CMP(); break;
case 0xC8: AddrMode_Imp(); INY(); break;
case 0xC9: AddrMode_ImmM(); CMP(); break;
case 0xCA: AddrMode_Imp(); DEX(); break;
case 0xCB: AddrMode_Imp(); WAI(); break;
case 0xCC: AddrMode_Abs(); CPY(); break;
case 0xCD: AddrMode_Abs(); CMP(); break;
case 0xCE: AddrMode_Abs(); DEC(); break;
case 0xCF: AddrMode_AbsLng(); CMP(); break;
case 0xD0: AddrMode_Rel(); BNE(); break;
case 0xD1: AddrMode_DirIndIdxY(); CMP(); break;
case 0xD2: AddrMode_DirInd(); CMP(); break;
case 0xD3: AddrMode_StkRelIndIdxY(); CMP(); break;
case 0xD4: AddrMode_Dir(); PEI(); break;
case 0xD5: AddrMode_DirIdxX(); CMP(); break;
case 0xD6: AddrMode_DirIdxX(); DEC(); break;
case 0xD7: AddrMode_DirIndLngIdxY(); CMP(); break;
case 0xD8: AddrMode_Imp(); CLD(); break;
case 0xD9: AddrMode_AbsIdxY(); CMP(); break;
case 0xDA: PHX(); break;
case 0xDB: AddrMode_Imp(); STP(); break;
case 0xDC: AddrMode_AbsIndLng(); JML(); break;
case 0xDD: AddrMode_AbsIdxX(); CMP(); break;
case 0xDE: AddrMode_AbsIdxX(); DEC(); break;
case 0xDF: AddrMode_AbsLngIdxX(); CMP(); break;
case 0xE0: AddrMode_ImmX(); CPX(); break;
case 0xE1: AddrMode_DirIdxIndX(); SBC(); break;
case 0xE2: AddrMode_Imm8(); SEP(); break;
case 0xE3: AddrMode_StkRel(); SBC(); break;
case 0xE4: AddrMode_Dir(); CPX(); break;
case 0xE5: AddrMode_Dir(); SBC(); break;
case 0xE6: AddrMode_Dir(); INC(); break;
case 0xE7: AddrMode_DirIndLng(); SBC(); break;
case 0xE8: AddrMode_Imp(); INX(); break;
case 0xE9: AddrMode_ImmM(); SBC(); break;
case 0xEA: AddrMode_Imp(); NOP(); break;
case 0xEB: AddrMode_Imp(); XBA(); break;
case 0xEC: AddrMode_Abs(); CPX(); break;
case 0xED: AddrMode_Abs(); SBC(); break;
case 0xEE: AddrMode_Abs(); INC(); break;
case 0xEF: AddrMode_AbsLng(); SBC(); break;
case 0xF0: AddrMode_Rel(); BEQ(); break;
case 0xF1: AddrMode_DirIndIdxY(); SBC(); break;
case 0xF2: AddrMode_DirInd(); SBC(); break;
case 0xF3: AddrMode_StkRelIndIdxY(); SBC(); break;
case 0xF4: AddrMode_Imm16(); PEA(); break;
case 0xF5: AddrMode_DirIdxX(); SBC(); break;
case 0xF6: AddrMode_DirIdxX(); INC(); break;
case 0xF7: AddrMode_DirIndLngIdxY(); SBC(); break;
case 0xF8: AddrMode_Imp(); SED(); break;
case 0xF9: AddrMode_AbsIdxY(); SBC(); break;
case 0xFA: PLX(); break;
case 0xFB: AddrMode_Imp(); XCE(); break;
case 0xFC: AddrMode_AbsIdxXInd(); JSR(); break;
case 0xFD: AddrMode_AbsIdxX(); SBC(); break;
case 0xFE: AddrMode_AbsIdxX(); INC(); break;
case 0xFF: AddrMode_AbsLngIdxX(); SBC(); break;
}
if(_nmiFlag) {
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector);
@ -127,9 +336,9 @@ uint8_t Cpu::GetOpCode()
return opCode;
}
void Cpu::DummyRead()
void Cpu::Idle()
{
ReadCode(_state.PC, MemoryOperationType::DummyRead);
_memoryManager->ProcessCpuInternalOperation();
}
uint8_t Cpu::ReadOperandByte()
@ -168,7 +377,7 @@ uint16_t Cpu::ReadCodeWord(uint16_t addr, MemoryOperationType type)
uint8_t Cpu::ReadData(uint32_t addr, MemoryOperationType type)
{
_state.CycleCount++;
return _memoryManager->Read(addr, type);
return _memoryManager->Read(addr & 0xFFFFFF, type);
}
uint16_t Cpu::ReadDataWord(uint32_t addr, MemoryOperationType type)
@ -200,7 +409,7 @@ void Cpu::WriteWord(uint32_t addr, uint16_t value, MemoryOperationType type)
uint8_t Cpu::GetByteValue()
{
if(_instAddrMode <= AddrMode::ImmM) {
if(_immediateMode) {
return (uint8_t)_operand;
} else {
return ReadData(_operand);
@ -209,7 +418,7 @@ uint8_t Cpu::GetByteValue()
uint16_t Cpu::GetWordValue()
{
if(_instAddrMode <= AddrMode::ImmM) {
if(_immediateMode) {
return (uint16_t)_operand;
} else {
return ReadDataWord(_operand);
@ -266,57 +475,6 @@ uint32_t Cpu::GetDirectAddressIndirectLong(uint16_t offset, bool allowEmulationM
return (b3 << 16) | (b2 << 8) | b1;
}
uint32_t Cpu::FetchEffectiveAddress()
{
switch(_instAddrMode) {
case AddrMode::Abs: return GetDataAddress(ReadOperandWord());
case AddrMode::AbsIdxX: return (GetDataAddress(ReadOperandWord()) + _state.X) & 0xFFFFFF;
case AddrMode::AbsIdxY: return (GetDataAddress(ReadOperandWord()) + _state.Y) & 0xFFFFFF;
case AddrMode::AbsLng: return ReadOperandLong();
case AddrMode::AbsLngIdxX: return (ReadOperandLong() + _state.X) & 0xFFFFFF;
case AddrMode::AbsJmp: return GetProgramAddress(ReadOperandWord());
case AddrMode::AbsLngJmp: return ReadOperandLong();
case AddrMode::AbsIdxXInd: return GetProgramAddress(ReadDataWord(GetProgramAddress(ReadOperandWord() + _state.X))); //JMP/JSR
case AddrMode::AbsInd: return ReadDataWord(ReadOperandWord()); //JMP only
case AddrMode::AbsIndLng: return ReadDataLong(ReadOperandWord()); //JML only
case AddrMode::Acc: DummyRead(); return 0;
case AddrMode::BlkMov: return ReadOperandWord();
case AddrMode::Dir: return GetDirectAddress(ReadOperandByte());
case AddrMode::DirIdxX: return GetDirectAddress(ReadOperandByte() + _state.X);
case AddrMode::DirIdxY: return GetDirectAddress(ReadOperandByte() + _state.Y);
case AddrMode::DirInd: return GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte()));
case AddrMode::DirIdxIndX: return GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte() + _state.X));
case AddrMode::DirIndIdxY: return (GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte())) + _state.Y) & 0xFFFFFF;
case AddrMode::DirIndLng: return GetDirectAddressIndirectLong(ReadOperandByte());
case AddrMode::DirIndLngIdxY: return (GetDirectAddressIndirectLong(ReadOperandByte()) + _state.Y) & 0xFFFFFF;
case AddrMode::Imm8: return ReadOperandByte();
case AddrMode::Imm16: return ReadOperandWord();
case AddrMode::ImmX: return CheckFlag(ProcFlags::IndexMode8) ? ReadOperandByte() : ReadOperandWord();
case AddrMode::ImmM: return CheckFlag(ProcFlags::MemoryMode8) ? ReadOperandByte() : ReadOperandWord();
case AddrMode::Imp: DummyRead(); return 0;
case AddrMode::RelLng: return ReadOperandWord();
case AddrMode::Rel: return ReadOperandByte();
case AddrMode::Stk: return 0;
case AddrMode::StkRel: return (uint16_t)(ReadOperandByte() + _state.SP);
case AddrMode::StkRelIndIdxY: {
uint16_t addr = (uint16_t)(ReadOperandByte() + _state.SP);
return (GetDataAddress(ReadDataWord(addr)) + _state.Y) & 0xFFFFFF;
}
}
throw std::runtime_error("Unreacheable code");
}
void Cpu::SetSP(uint16_t sp)
{
if(_state.EmulationMode) {

View file

@ -7,7 +7,6 @@ class MemoryManager;
class Cpu
{
public:
uint64_t opCount = 0;
uint16_t GetPc() { return _state.PC; }
CpuState GetState() { return _state; }
int32_t GetLastOperand() { return (int32_t)_operand; }
@ -27,8 +26,10 @@ private:
typedef void(Cpu::*Func)();
shared_ptr<MemoryManager> _memoryManager;
bool _immediateMode = false;
CpuState _state;
AddrMode _instAddrMode;
uint32_t _operand;
bool _nmiFlag;
uint8_t _irqSource;
@ -46,12 +47,11 @@ private:
uint8_t GetOpCode();
void DummyRead();
void Idle();
uint8_t ReadOperandByte();
uint16_t ReadOperandWord();
uint32_t ReadOperandLong();
uint32_t FetchEffectiveAddress();
void SetSP(uint16_t sp);
void SetPS(uint8_t ps);
@ -128,6 +128,9 @@ private:
void DEC();
void INC();
void DEC_Acc();
void INC_Acc();
void IncDecReg(uint16_t & reg, int8_t offset);
void IncDec(int8_t offset);
@ -162,9 +165,13 @@ private:
template<typename T> T RollRight(T value);
//Shift operations
void ASL_Acc();
void ASL();
void LSR_Acc();
void LSR();
void ROL_Acc();
void ROL();
void ROR_Acc();
void ROR();
//Move operations
@ -237,6 +244,46 @@ private:
void STP();
void WAI();
//Addressing modes
void AddrMode_Abs();
void AddrMode_AbsIdxX();
void AddrMode_AbsIdxY();
void AddrMode_AbsLng();
void AddrMode_AbsLngIdxX();
void AddrMode_AbsJmp();
void AddrMode_AbsLngJmp();
void AddrMode_AbsIdxXInd(); //JMP/JSR
void AddrMode_AbsInd(); //JMP only
void AddrMode_AbsIndLng(); //JML only
void AddrMode_Acc();
void AddrMode_BlkMov();
uint8_t ReadDirectOperandByte();
void AddrMode_Dir();
void AddrMode_DirIdxX();
void AddrMode_DirIdxY();
void AddrMode_DirInd();
void AddrMode_DirIdxIndX();
void AddrMode_DirIndIdxY();
void AddrMode_DirIndLng();
void AddrMode_DirIndLngIdxY();
void AddrMode_Imm8();
void AddrMode_Imm16();
void AddrMode_ImmX();
void AddrMode_ImmM();
void AddrMode_Imp();
void AddrMode_RelLng();
void AddrMode_Rel();
void AddrMode_StkRel();
void AddrMode_StkRelIndIdxY();
public:
Cpu(shared_ptr<MemoryManager> memoryManager);
~Cpu();

View file

@ -101,6 +101,7 @@ private:
uint8_t * _workRam;
uint64_t _masterClock;
uint8_t _previousSpeed;
uint64_t _lastMasterClock;
uint8_t _masterClockTable[2][0x10000];
@ -217,7 +218,26 @@ public:
void IncrementMasterClock(uint32_t addr)
{
_masterClock += _masterClockTable[(uint8_t)_regs->IsFastRomEnabled()][addr >> 8];
_previousSpeed = _masterClockTable[(uint8_t)_regs->IsFastRomEnabled()][addr >> 8];
_masterClock += _previousSpeed;
while(_lastMasterClock < _masterClock - 3) {
_ppu->Exec();
_lastMasterClock += 4;
}
}
void ProcessCpuInternalOperation()
{
_masterClock += 6;
while(_lastMasterClock < _masterClock - 3) {
_ppu->Exec();
_lastMasterClock += 4;
}
}
void ProcessDramRefresh()
{
_masterClock += 40;
while(_lastMasterClock < _masterClock - 3) {
_ppu->Exec();
_lastMasterClock += 4;

View file

@ -90,9 +90,13 @@ void Ppu::Exec()
if(_regs->IsNmiEnabled()) {
_console->GetCpu()->SetNmiFlag();
}
} else if(_scanline == 240 && _cycle == 0 && _frameCount & 0x01) {
//Skip 1 tick every other frame
_cycle++;
} else if(_scanline == 261) {
_regs->SetNmiFlag(false);
_scanline = 0;
if(_mosaicEnabled) {
_mosaicStartScanline = 0;
}
@ -115,6 +119,9 @@ void Ppu::Exec()
if(_cycle == 278 && _scanline < 225) {
_console->GetDmaController()->ProcessHdmaChannels();
} else if(_cycle == 134) {
//TODO Approximation
_console->GetMemoryManager()->ProcessDramRefresh();
}
}