From 1a6d0e907b3205f09435fbea274b33ac1aff0949 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Wed, 25 Mar 2020 22:33:12 +0100
Subject: [PATCH 01/17] Making the debugger spawn on invalid rom exceptions
(invalid address access, invalid opcode...) & starting the dissasembly view
---
sources/Cartridge/Cartridge.cpp | 26 +++++------
sources/Debugger/MemoryBusDebug.cpp | 2 +
sources/Renderer/QtRenderer/QtSFML.cpp | 6 +++
sources/main.cpp | 14 ++++--
ui/cpu.ui | 63 ++++++++++++++++----------
5 files changed, 69 insertions(+), 42 deletions(-)
diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp
index 227903a..91a8036 100644
--- a/sources/Cartridge/Cartridge.cpp
+++ b/sources/Cartridge/Cartridge.cpp
@@ -15,22 +15,18 @@ namespace ComSquare::Cartridge
Cartridge::Cartridge(const std::string &romPath)
: Ram::Ram(0, Rom, "Cartridge")
{
- try {
- if (romPath.empty())
- throw InvalidRomException("Path is empty.");
- size_t size = Cartridge::getRomSize(romPath);
- FILE *rom = fopen(romPath.c_str(), "rb");
+ if (romPath.empty())
+ throw InvalidRomException("Path is empty.");
+ size_t size = Cartridge::getRomSize(romPath);
+ FILE *rom = fopen(romPath.c_str(), "rb");
- if (!rom)
- throw InvalidRomException("Could not open the rom file at " + romPath + ". " + strerror(errno));
- this->_size = size;
- this->_data = new uint8_t[size];
- std::memset(this->_data, 0, size);
- fread(this->_data, 1, size, rom);
- this->_loadHeader();
- } catch (InvalidRomException &ex) {
- std::cerr << "Invalid Rom Error: " << ex.what() << std::endl;
- }
+ if (!rom)
+ throw InvalidRomException("Could not open the rom file at " + romPath + ". " + strerror(errno));
+ this->_size = size;
+ this->_data = new uint8_t[size];
+ std::memset(this->_data, 0, size);
+ fread(this->_data, 1, size, rom);
+ this->_loadHeader();
}
size_t Cartridge::getRomSize(const std::string &romPath)
diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp
index 17314cd..2d520d4 100644
--- a/sources/Debugger/MemoryBusDebug.cpp
+++ b/sources/Debugger/MemoryBusDebug.cpp
@@ -25,6 +25,8 @@ namespace ComSquare::Debugger
this->_ui.setupUi(this->_window);
this->_proxy.setSourceModel(&this->_model);
this->_ui.log->setModel(&this->_proxy);
+ this->_ui.log->setAlternatingRowColors(true);
+ this->_ui.log->verticalHeader()->hide();
this->_ui.log->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
this->_ui.log->horizontalHeader()->setStretchLastSection(true);
this->_ui.log->horizontalHeader()->setSectionsMovable(true);
diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp
index 0471f67..9a333a6 100644
--- a/sources/Renderer/QtRenderer/QtSFML.cpp
+++ b/sources/Renderer/QtRenderer/QtSFML.cpp
@@ -8,6 +8,8 @@
#include
#include
#include "QtSFML.hpp"
+#include "../../Exceptions/InvalidOpcode.hpp"
+#include "../../Exceptions/InvalidAddress.hpp"
#ifdef Q_WS_X11
#include
@@ -84,6 +86,10 @@ namespace ComSquare::Renderer
{
try {
this->_snes.update();
+ } catch (InvalidOpcode &e) {
+ this->_snes.enableCPUDebugging();
+ } catch (InvalidAddress &e) {
+ this->_snes.enableCPUDebugging();
} catch (std::exception &e) {
std::cerr << "An error occurred: " << e.what() << std::endl;
QApplication::quit();
diff --git a/sources/main.cpp b/sources/main.cpp
index ed678cd..8e5930b 100644
--- a/sources/main.cpp
+++ b/sources/main.cpp
@@ -68,8 +68,14 @@ int main(int argc, char **argv)
QApplication app(argc, argv);
QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
Renderer::QtSFML renderer(600, 800);
- SNES snes(argv[1], renderer);
- renderer.createWindow(snes, 60);
- parseArguments(argc, argv, snes);
- return QApplication::exec();
+ try {
+ SNES snes(argv[1], renderer);
+ renderer.createWindow(snes, 60);
+ parseArguments(argc, argv, snes);
+ return QApplication::exec();
+ }
+ catch(std::exception &ex) {
+ std::cerr << ex.what() << std::endl;
+ return 1;
+ }
}
\ No newline at end of file
diff --git a/ui/cpu.ui b/ui/cpu.ui
index 09dd3ed..a3b46d0 100644
--- a/ui/cpu.ui
+++ b/ui/cpu.ui
@@ -6,8 +6,8 @@
0
0
- 420
- 438
+ 971
+ 709
@@ -21,28 +21,18 @@
false
-
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
-
-
-
- Instructions History
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- -
-
-
- Clear History
-
-
-
- -
-
@@ -150,10 +140,37 @@
Qt::RightToLeft
+
+ false
+
+ -
+
+
-
+
+
+ Clear History
+
+
+
+ -
+
+
+ Instructions History
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+
From bd948b520c2352145486c833b1dda6f3b6992273 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 26 Mar 2020 03:39:55 +0100
Subject: [PATCH 02/17] Implementing an array of instructions with method's
pointer for the CPU (it does not work well for now
---
CMakeLists.txt | 4 +-
sources/CPU/AddressingModes.cpp | 5 +
sources/CPU/CPU.cpp | 445 ++++++++------
sources/CPU/CPU.hpp | 565 ++++++++++--------
sources/CPU/Instruction.hpp | 62 ++
sources/CPU/Instructions/BitsInstructions.cpp | 3 +-
.../CPU/Instructions/InternalInstruction.cpp | 118 ++--
sources/CPU/Instructions/Interrupts.cpp | 12 +-
.../Instructions/MathematicalOperations.cpp | 6 +-
.../CPU/Instructions/MemoryInstructions.cpp | 21 +-
.../CPU/Instructions/TransferRegisters.cpp | 9 +-
sources/Debugger/CPUDebug.cpp | 216 +------
sources/Debugger/CPUDebug.hpp | 31 +-
sources/Exceptions/DebuggableError.hpp | 15 +
sources/Exceptions/InvalidAction.hpp | 3 +-
sources/Exceptions/InvalidAddress.hpp | 3 +-
sources/Exceptions/InvalidOpcode.hpp | 3 +-
sources/Exceptions/InvalidRom.hpp | 3 +-
sources/Renderer/QtRenderer/QtSFML.cpp | 8 +-
sources/SNES.cpp | 10 +-
sources/SNES.hpp | 2 +-
tests/CPU/TransferRegisters.cpp | 20 +-
tests/CPU/testInternal.cpp | 74 +--
tests/CPU/testInterupts.cpp | 8 +-
ui/cpu.ui | 2 +-
25 files changed, 924 insertions(+), 724 deletions(-)
create mode 100644 sources/CPU/Instruction.hpp
create mode 100644 sources/Exceptions/DebuggableError.hpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c2d8c4..6533542 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -93,7 +93,7 @@ add_executable(unit_tests
tests/CPU/TransferRegisters.cpp
sources/CPU/AddressingModes.cpp
sources/Models/Components.hpp
-)
+ sources/CPU/Instruction.hpp sources/Exceptions/DebuggableError.hpp)
# include criterion & coverage
target_link_libraries(unit_tests criterion -lgcov)
@@ -200,7 +200,7 @@ add_executable(ComSquare
sources/Debugger/MemoryBusDebug.cpp
sources/Debugger/MemoryBusDebug.hpp
sources/Debugger/ClosableWindow.hpp
- sources/Models/Components.hpp)
+ sources/Models/Components.hpp sources/CPU/Instruction.hpp sources/Exceptions/DebuggableError.hpp)
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp
index edcb35f..9b78aa2 100644
--- a/sources/CPU/AddressingModes.cpp
+++ b/sources/CPU/AddressingModes.cpp
@@ -7,6 +7,11 @@
namespace ComSquare::CPU
{
+ uint24_t CPU::_getImmediateAddr8Bits()
+ {
+ return this->_registers.pac++;
+ }
+
uint24_t CPU::_getImmediateAddrForA()
{
uint24_t effective = this->_registers.pac++;
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index afe5d53..8791036 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -206,191 +206,290 @@ namespace ComSquare::CPU
unsigned CPU::_executeInstruction(uint8_t opcode)
{
+ Instruction instruction = this->_instructions[opcode];
+
this->_hasIndexCrossedPageBoundary = false;
- uint24_t addr;
- switch (opcode) {
- case Instructions::BRK: this->BRK(); return 7 + !this->_isEmulationMode;
+ uint24_t valueAddr = 0;
+ int cycles = instruction.cycleCount + !this->_registers.p.m;
- case Instructions::COP: this->COP(); return 7 + !this->_isEmulationMode;
+ switch (instruction.addressingMode) {
+ case Implied:
+ break;
+ case Immediate8bits:
+ valueAddr = this->_getImmediateAddr8Bits();
+ break;
+ case ImmediateForA:
+ valueAddr = this->_getImmediateAddrForA();
+ break;
+ case ImmediateForX:
+ valueAddr = this->_getImmediateAddrForX();
+ break;
- case Instructions::RTI: this->RTI(); return 6 + !this->_isEmulationMode;
+ // TODO implement the relative addressing mode
+ // TODO implement the relative long addressing mode
- case Instructions::ADC_IM: this->ADC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
- case Instructions::ADC_ABS: this->ADC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::ADC_ABSl: this->ADC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::ADC_DP: this->ADC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_DPi: this->ADC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_DPil: this->ADC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_ABSX: this->ADC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::ADC_ABSXl:this->ADC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::ADC_ABSY: this->ADC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::ADC_DPX: this->ADC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_DPXi: this->ADC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_DPYi: this->ADC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
- case Instructions::ADC_DPYil:this->ADC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::ADC_SR: this->ADC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
- case Instructions::ADC_SRYi: this->ADC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+ case Absolute:
+ valueAddr = this->_getAbsoluteAddr();
+ break;
+ case AbsoluteLong:
+ valueAddr = this->_getAbsoluteLongAddr();
+ break;
+ case AbsoluteIndirect:
+ valueAddr = this->_getAbsoluteIndirectAddr();
+ break;
- case Instructions::STA_ABS: this->STA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::STA_ABSl: this->STA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::STA_DP: this->STA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_DPi: this->STA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_DPil: this->STA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_ABSX: this->STA(this->_getAbsoluteIndexedByXAddr()); return 5 + !this->_registers.p.m;
- case Instructions::STA_ABSXl:this->STA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::STA_ABSY: this->STA(this->_getAbsoluteIndexedByYAddr()); return 5 + !this->_registers.p.m;
- case Instructions::STA_DPX: this->STA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_DPXi: this->STA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_DPYi: this->STA(this->_getDirectIndirectIndexedYAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_DPYil:this->STA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STA_SR: this->STA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
- case Instructions::STA_SRYi: this->STA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+ //TODO implement absolute indirect long addressing mode
- case Instructions::STX_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::STX_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STX_DPY: this->STX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+ case DirectPage:
+ valueAddr = this->_getDirectAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndirect:
+ valueAddr = this->_getDirectIndirectAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndirectLong:
+ valueAddr = this->_getDirectIndirectLongAddr();
+ cycles += this->_registers.dl != 0;
+ break;
- case Instructions::STY_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::STY_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STY_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+ case DirectPageIndexedByX:
+ valueAddr = this->_getDirectIndexedByXAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndexedByY:
+ valueAddr = this->_getDirectIndexedByYAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndirectIndexedByX:
+ valueAddr = this->_getDirectIndirectIndexedXAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndirectIndexedByY:
+ valueAddr = this->_getDirectIndirectIndexedYAddr();
+ cycles += this->_registers.dl != 0;
+ break;
+ case DirectPageIndirectIndexedByYLong:
+ valueAddr = this->_getDirectIndirectIndexedYLongAddr();
+ cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+ break;
- case Instructions::STZ_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::STZ_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STZ_ABSX: this->STX(this->_getAbsoluteIndexedByXAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::STZ_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+ case AbsoluteIndexedByX:
+ valueAddr = this->_getAbsoluteIndexedByXAddr();
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ case AbsoluteIndexedByXLong:
+ valueAddr = this->_getAbsoluteIndexedByXLongAddr();
+ break;
+ case AbsoluteIndexedByY:
+ valueAddr = this->_getAbsoluteIndexedByYAddr();
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
- case Instructions::LDA_IM: this->LDA(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
- case Instructions::LDA_ABS: this->LDA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::LDA_ABSl: this->LDA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::LDA_DP: this->LDA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_DPi: this->LDA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_DPil: this->LDA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_ABSX: this->LDA(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::LDA_ABSXl:this->LDA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::LDA_ABSY: this->LDA(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::LDA_DPX: this->LDA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_DPXi: this->LDA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_DPYi: this->LDA(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
- case Instructions::LDA_DPYil:this->LDA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDA_SR: this->LDA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
- case Instructions::LDA_SRYi: this->LDA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+ case StackRelative:
+ valueAddr = this->_getStackRelativeAddr();
+ break;
+ case StackRelativeIndirectIndexedByY:
+ valueAddr = this->_getStackRelativeIndirectIndexedYAddr();
+ break;
- case Instructions::LDX_IM: this->LDX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
- case Instructions::LDX_ABS: this->LDX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::LDX_DP: this->LDX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDX_ABSY: this->LDX(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::LDX_DPY: this->LDX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-
- case Instructions::LDY_IM: this->LDY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
- case Instructions::LDY_ABS: this->LDY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::LDY_DP: this->LDY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::LDY_ABSY: this->LDY(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::LDY_DPY: this->LDY(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-
- case Instructions::SEP: this->SEP(this->_bus->read(this->_registers.pc++)); return 3;
-
- case Instructions::REP: this->REP(this->_bus->read(this->_registers.pc++)); return 3;
-
- case Instructions::PHA: this->PHA(); return 3 + !this->_registers.p.m;
- case Instructions::PHB: this->PHB(); return 3;
- case Instructions::PHD: this->PHD(); return 4;
- case Instructions::PHK: this->PHK(); return 3;
- case Instructions::PHP: this->PHP(); return 3;
- case Instructions::PHX: this->PHX(); return 3 + !this->_registers.p.x_b;
- case Instructions::PHY: this->PHY(); return 3 + !this->_registers.p.x_b;
-
- case Instructions::PLA: this->PLA(); return 4 + !this->_registers.p.m;
- case Instructions::PLB: this->PLB(); return 4;
- case Instructions::PLD: this->PLD(); return 5;
- case Instructions::PLP: this->PLP(); return 4;
- case Instructions::PLX: this->PLX(); return 4 + !this->_registers.p.x_b;
- case Instructions::PLY: this->PLY(); return 4 + !this->_registers.p.x_b;
-
- case Instructions::JSR_ABS: this->JSR(this->_getAbsoluteAddr()); return 6;
- case Instructions::JSR_ABSXi: this->JSR(this->_getAbsoluteIndirectIndexedByXAddr()); return 8;
-
- case Instructions::JSL: this->JSL(this->_getAbsoluteLongAddr()); return 8;
-
- case Instructions::CLC: this->CLC(); return 2;
- case Instructions::CLI: this->CLI(); return 2;
- case Instructions::CLD: this->CLD(); return 2;
- case Instructions::CLV: this->CLV(); return 2;
-
- case Instructions::SEC: this->SEC(); return 2;
- case Instructions::SED: this->SED(); return 2;
- case Instructions::SEI: this->SEI(); return 2;
-
- case Instructions::AND_IM: this->AND(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
- case Instructions::AND_ABS: this->AND(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::AND_ABSl: this->AND(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::AND_DP: this->AND(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_DPi: this->AND(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_DPil: this->AND(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_ABSX: this->AND(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::AND_ABSXl:this->AND(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::AND_ABSY: this->AND(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::AND_DPX: this->AND(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_DPXi: this->AND(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_DPYi: this->AND(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
- case Instructions::AND_DPYil:this->AND(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::AND_SR: this->AND(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
- case Instructions::AND_SRYi: this->AND(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-
- case Instructions::XCE: this->XCE(); return 2;
-
- case Instructions::SBC_IM: this->SBC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
- case Instructions::SBC_ABS: this->SBC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::SBC_ABSl: this->SBC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::SBC_DP: this->SBC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_DPi: this->SBC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_DPil: this->SBC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_ABSX: this->SBC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::SBC_ABSXl:this->SBC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
- case Instructions::SBC_ABSY: this->SBC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
- case Instructions::SBC_DPX: this->SBC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_DPXi: this->SBC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_DPYi: this->SBC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
- case Instructions::SBC_DPYil:this->SBC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
- case Instructions::SBC_SR: this->SBC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
- case Instructions::SBC_SRYi: this->SBC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-
- case Instructions::TAX: this->TAX(); return 2;
- case Instructions::TAY: this->TAY(); return 2;
- case Instructions::TXS: this->TXS(); return 2;
-
- case Instructions::INX: this->INX(); return 2;
- case Instructions::INY: this->INY(); return 2;
-
- case Instructions::CPX_IM: this->CPX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
- case Instructions::CPX_ABS: this->CPX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::CPX_DP: this->CPX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-
- case Instructions::CPY_IM: this->CPY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
- case Instructions::CPY_ABS: this->CPY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
- case Instructions::CPY_DP: this->CPY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-
- case Instructions::BCC: return this->BCC(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BCS: return this->BCS(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BEQ: return this->BEQ(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BNE: return this->BNE(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BMI: return this->BMI(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BPL: return this->BPL(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BVC: return this->BVC(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BVS: return this->BVS(this->_registers.pc++) + 2 + this->_isEmulationMode;
- case Instructions::BRA: this->BRA(this->_registers.pc++); return 3 + this->_isEmulationMode;
- case Instructions::BRL: this->BRL(this->_registers.pc); this->_registers.pc += 2; return 4;
-
- case Instructions::JMP_ABS: addr = this->_getAbsoluteAddr(); this->JMP(addr); return 3;
- case Instructions::JMP_ABSi: addr = this->_getAbsoluteIndirectAddr(); this->JMP(addr); return 3;
- case Instructions::JMP_ABSXi: addr = this->_getAbsoluteIndexedByXAddr(); this->JMP(addr); return 3;
-
- case Instructions::JML_ABSl: addr = this->_getAbsoluteLongAddr(); this->JML(addr); return 3;
- //case Instructions::JML_ABSil: this->JML(this->_getAbsoluteLong()); return 3;
-
- default:
- throw InvalidOpcode("CPU", opcode);
+ case ProgramCounterRelative:
+ valueAddr = this->_getProgramCounterRelativeAddr();
+ break;
+ case ProgramCounterRelativeLong:
+ valueAddr = this->_getProgramCounterRelativeLongAddr();
+ break;
+ case AbsoluteIndirectIndexedByX:
+ valueAddr = this->_getAbsoluteIndirectIndexedByXAddr();
+ break;
}
+
+ return cycles + (this->*instruction.call)(valueAddr);
+// uint24_t addr;
+//
+// switch (opcode) {
+// case Instructions::BRK: this->BRK(0x0); return 7 + !this->_isEmulationMode;
+//
+// case Instructions::COP: this->COP(); return 7 + !this->_isEmulationMode;
+//
+// case Instructions::RTI: this->RTI(); return 6 + !this->_isEmulationMode;
+//
+// case Instructions::ADC_IM: this->ADC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
+// case Instructions::ADC_ABS: this->ADC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::ADC_ABSl: this->ADC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::ADC_DP: this->ADC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_DPi: this->ADC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_DPil: this->ADC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_ABSX: this->ADC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::ADC_ABSXl:this->ADC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::ADC_ABSY: this->ADC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::ADC_DPX: this->ADC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_DPXi: this->ADC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_DPYi: this->ADC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+// case Instructions::ADC_DPYil:this->ADC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::ADC_SR: this->ADC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::ADC_SRYi: this->ADC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+//
+// case Instructions::STA_ABS: this->STA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::STA_ABSl: this->STA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::STA_DP: this->STA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_DPi: this->STA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_DPil: this->STA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_ABSX: this->STA(this->_getAbsoluteIndexedByXAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::STA_ABSXl:this->STA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::STA_ABSY: this->STA(this->_getAbsoluteIndexedByYAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::STA_DPX: this->STA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_DPXi: this->STA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_DPYi: this->STA(this->_getDirectIndirectIndexedYAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_DPYil:this->STA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STA_SR: this->STA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::STA_SRYi: this->STA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+//
+// case Instructions::STX_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::STX_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STX_DPY: this->STX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::STY_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::STY_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STY_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::STZ_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::STZ_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STZ_ABSX: this->STX(this->_getAbsoluteIndexedByXAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::STZ_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::LDA_IM: this->LDA(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
+// case Instructions::LDA_ABS: this->LDA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::LDA_ABSl: this->LDA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::LDA_DP: this->LDA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_DPi: this->LDA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_DPil: this->LDA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_ABSX: this->LDA(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::LDA_ABSXl:this->LDA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::LDA_ABSY: this->LDA(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::LDA_DPX: this->LDA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_DPXi: this->LDA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_DPYi: this->LDA(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+// case Instructions::LDA_DPYil:this->LDA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDA_SR: this->LDA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::LDA_SRYi: this->LDA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+//
+// case Instructions::LDX_IM: this->LDX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
+// case Instructions::LDX_ABS: this->LDX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::LDX_DP: this->LDX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDX_ABSY: this->LDX(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::LDX_DPY: this->LDX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::LDY_IM: this->LDY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
+// case Instructions::LDY_ABS: this->LDY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::LDY_DP: this->LDY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::LDY_ABSY: this->LDY(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::LDY_DPY: this->LDY(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::SEP: this->SEP(this->_bus->read(this->_registers.pc++)); return 3;
+//
+// case Instructions::REP: this->REP(this->_bus->read(this->_registers.pc++)); return 3;
+//
+// case Instructions::PHA: this->PHA(); return 3 + !this->_registers.p.m;
+// case Instructions::PHB: this->PHB(); return 3;
+// case Instructions::PHD: this->PHD(); return 4;
+// case Instructions::PHK: this->PHK(); return 3;
+// case Instructions::PHP: this->PHP(); return 3;
+// case Instructions::PHX: this->PHX(); return 3 + !this->_registers.p.x_b;
+// case Instructions::PHY: this->PHY(); return 3 + !this->_registers.p.x_b;
+//
+// case Instructions::PLA: this->PLA(); return 4 + !this->_registers.p.m;
+// case Instructions::PLB: this->PLB(); return 4;
+// case Instructions::PLD: this->PLD(); return 5;
+// case Instructions::PLP: this->PLP(); return 4;
+// case Instructions::PLX: this->PLX(); return 4 + !this->_registers.p.x_b;
+// case Instructions::PLY: this->PLY(); return 4 + !this->_registers.p.x_b;
+//
+// case Instructions::JSR_ABS: this->JSR(this->_getAbsoluteAddr()); return 6;
+// case Instructions::JSR_ABSXi: this->JSR(this->_getAbsoluteIndirectIndexedByXAddr()); return 8;
+//
+// case Instructions::JSL: this->JSL(this->_getAbsoluteLongAddr()); return 8;
+//
+// case Instructions::CLC: this->CLC(); return 2;
+// case Instructions::CLI: this->CLI(); return 2;
+// case Instructions::CLD: this->CLD(); return 2;
+// case Instructions::CLV: this->CLV(); return 2;
+//
+// case Instructions::SEC: this->SEC(); return 2;
+// case Instructions::SED: this->SED(); return 2;
+// case Instructions::SEI: this->SEI(); return 2;
+//
+// case Instructions::AND_IM: this->AND(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
+// case Instructions::AND_ABS: this->AND(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::AND_ABSl: this->AND(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::AND_DP: this->AND(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_DPi: this->AND(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_DPil: this->AND(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_ABSX: this->AND(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::AND_ABSXl:this->AND(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::AND_ABSY: this->AND(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::AND_DPX: this->AND(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_DPXi: this->AND(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_DPYi: this->AND(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+// case Instructions::AND_DPYil:this->AND(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::AND_SR: this->AND(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::AND_SRYi: this->AND(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+//
+// case Instructions::XCE: this->XCE(); return 2;
+//
+// case Instructions::SBC_IM: this->SBC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
+// case Instructions::SBC_ABS: this->SBC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::SBC_ABSl: this->SBC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::SBC_DP: this->SBC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_DPi: this->SBC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_DPil: this->SBC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_ABSX: this->SBC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::SBC_ABSXl:this->SBC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
+// case Instructions::SBC_ABSY: this->SBC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
+// case Instructions::SBC_DPX: this->SBC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_DPXi: this->SBC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_DPYi: this->SBC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+// case Instructions::SBC_DPYil:this->SBC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
+// case Instructions::SBC_SR: this->SBC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::SBC_SRYi: this->SBC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
+//
+// case Instructions::TAX: this->TAX(); return 2;
+// case Instructions::TAY: this->TAY(); return 2;
+// case Instructions::TXS: this->TXS(); return 2;
+//
+// case Instructions::INX: this->INX(); return 2;
+// case Instructions::INY: this->INY(); return 2;
+//
+// case Instructions::CPX_IM: this->CPX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
+// case Instructions::CPX_ABS: this->CPX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::CPX_DP: this->CPX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::CPY_IM: this->CPY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
+// case Instructions::CPY_ABS: this->CPY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
+// case Instructions::CPY_DP: this->CPY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
+//
+// case Instructions::BCC: return this->BCC(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BCS: return this->BCS(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BEQ: return this->BEQ(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BNE: return this->BNE(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BMI: return this->BMI(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BPL: return this->BPL(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BVC: return this->BVC(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BVS: return this->BVS(this->_registers.pc++) + 2 + this->_isEmulationMode;
+// case Instructions::BRA: this->BRA(this->_registers.pc++); return 3 + this->_isEmulationMode;
+// case Instructions::BRL: this->BRL(this->_registers.pc); this->_registers.pc += 2; return 4;
+//
+// case Instructions::JMP_ABS: addr = this->_getAbsoluteAddr(); this->JMP(addr); return 3;
+// case Instructions::JMP_ABSi: addr = this->_getAbsoluteIndirectAddr(); this->JMP(addr); return 3;
+// case Instructions::JMP_ABSXi: addr = this->_getAbsoluteIndexedByXAddr(); this->JMP(addr); return 3;
+//
+// case Instructions::JML_ABSl: addr = this->_getAbsoluteLongAddr(); this->JML(addr); return 3;
+// //case Instructions::JML_ABSil: this->JML(this->_getAbsoluteLong()); return 3;
+//
+// default:
+// throw InvalidOpcode("CPU", opcode);
+// }
}
void CPU::_push(uint8_t data)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 84d613f..a14f2c0 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -10,6 +10,7 @@
#include "../Models/Int24.hpp"
#include "../Cartridge/Cartridge.hpp"
#include "../Memory/AMemory.hpp"
+#include "Instruction.hpp"
namespace ComSquare::CPU
{
@@ -180,189 +181,6 @@ namespace ComSquare::CPU
uint8_t joy4h;
};
- //! @brief All the instructions opcode of the main CPU.
- //! @info The name of the instruction followed by their parameters (after an underscore) if any.
- //! @info Addr mode with an i at the end means indirect.
- //! @info Addr mode with an l at the end means long.
- enum Instructions
- {
- BRK = 0x00,
- COP = 0x02,
- RTI = 0x40,
-
- ADC_DPXi = 0x61,
- ADC_SR = 0x63,
- ADC_DP = 0x65,
- ADC_DPil = 0x67,
- ADC_IM = 0x69,
- ADC_ABS = 0x6D,
- ADC_ABSl = 0x6F,
- ADC_DPYi = 0x71,
- ADC_DPi = 0x72,
- ADC_SRYi = 0x73,
- ADC_DPX = 0x75,
- ADC_DPYil = 0x77,
- ADC_ABSY = 0x79,
- ADC_ABSX = 0x7D,
- ADC_ABSXl = 0x7F,
-
- STA_ABS = 0x8D,
- STA_ABSl = 0x8F,
- STA_DP = 0x85,
- STA_DPi = 0x92,
- STA_DPil = 0x87,
- STA_ABSX = 0x9D,
- STA_ABSXl = 0x9F,
- STA_ABSY = 0x99,
- STA_DPX = 0x95,
- STA_DPXi = 0x81,
- STA_DPYi = 0x91,
- STA_DPYil = 0x97,
- STA_SR = 0x83,
- STA_SRYi = 0x93,
-
- STX_ABS = 0x8E,
- STX_DP = 0x86,
- STX_DPY = 0x96,
-
- STY_ABS = 0x8C,
- STY_DP = 0x84,
- STY_DPX = 0x94,
-
- STZ_ABS = 0x9C,
- STZ_DP = 0x64,
- STZ_ABSX = 0x9E,
- STZ_DPX = 0x74,
-
- LDA_IM = 0xA9,
- LDA_ABS = 0xAD,
- LDA_ABSl = 0xAF,
- LDA_DP = 0xA5,
- LDA_DPi = 0xB2,
- LDA_DPil = 0xA7,
- LDA_ABSX = 0xBD,
- LDA_ABSXl = 0xBF,
- LDA_ABSY = 0xB9,
- LDA_DPX = 0xB5,
- LDA_DPXi = 0xA1,
- LDA_DPYi = 0xB1,
- LDA_DPYil = 0xB7,
- LDA_SR = 0xA3,
- LDA_SRYi = 0xB3,
-
- LDX_IM = 0xA2,
- LDX_ABS = 0xAE,
- LDX_DP = 0xA6,
- LDX_ABSY = 0xBE,
- LDX_DPY = 0xB6,
-
- LDY_IM = 0xA0,
- LDY_ABS = 0xAC,
- LDY_DP = 0xA4,
- LDY_ABSY = 0xBC,
- LDY_DPY = 0xB4,
-
- SEP = 0xE2,
-
- REP = 0xC2,
-
- PHA = 0x48,
- PHB = 0x8B,
- PHD = 0x0B,
- PHK = 0x4B,
- PHP = 0x08,
- PHX = 0xDA,
- PHY = 0x5A,
-
- PLA = 0x68,
- PLB = 0xAB,
- PLD = 0x2B,
- PLP = 0x28,
- PLX = 0xFA,
- PLY = 0x7A,
-
- JSR_ABS = 0x20,
- JSR_ABSXi = 0xFC,
-
- JSL = 0x22,
-
- CLC = 0x18,
- CLI = 0x58,
- CLD = 0xD8,
- CLV = 0xB8,
-
- SEC = 0x38,
- SEI = 0x78,
- SED = 0xF8,
-
- AND_IM = 0x29,
- AND_ABS = 0x2D,
- AND_ABSl = 0x2F,
- AND_DP = 0x25,
- AND_DPi = 0x32,
- AND_DPil = 0x27,
- AND_ABSX = 0x3D,
- AND_ABSXl = 0x3F,
- AND_ABSY = 0x39,
- AND_DPX = 0x35,
- AND_DPXi = 0x21,
- AND_DPYi = 0x31,
- AND_DPYil = 0x37,
- AND_SR = 0x23,
- AND_SRYi = 0x33,
-
- XCE = 0xFB,
-
- SBC_IM = 0xE9,
- SBC_ABS = 0xED,
- SBC_ABSl = 0xEF,
- SBC_DP = 0xE5,
- SBC_DPi = 0xF2,
- SBC_DPil = 0xE7,
- SBC_ABSX = 0xFD,
- SBC_ABSXl = 0xFF,
- SBC_ABSY = 0xF9,
- SBC_DPX = 0xF5,
- SBC_DPXi = 0xE1,
- SBC_DPYi = 0xF1,
- SBC_DPYil = 0xF7,
- SBC_SR = 0xE3,
- SBC_SRYi = 0xF3,
-
- TAX = 0xAA,
- TAY = 0xA8,
- TXS = 0x9A,
-
- INX = 0xE8,
- INY = 0xC8,
-
- CPX_IM = 0xE0,
- CPX_ABS = 0xEC,
- CPX_DP = 0xE4,
-
- CPY_IM = 0xC0,
- CPY_ABS = 0xCC,
- CPY_DP = 0xC4,
-
- BCC = 0x90,
- BCS = 0xB0,
- BEQ = 0xF0,
- BNE = 0xD0,
- BMI = 0x30,
- BPL = 0x10,
- BVC = 0x50,
- BVS = 0x70,
- BRA = 0x80,
- BRL = 0x82,
-
- JMP_ABS = 0x4C,
- JMP_ABSi = 0x6C,
- JMP_ABSXi = 0x7C,
-
- JML_ABSl = 0x5C,
- JML_ABSil = 0xDC
- };
-
//! @brief The main CPU
class CPU : public Memory::AMemory {
protected:
@@ -380,6 +198,8 @@ namespace ComSquare::CPU
//! @brief True if an addressing mode with an iterator (x, y) has crossed the page. (Used because crossing the page boundary take one more cycle to run certain instructions).
bool _hasIndexCrossedPageBoundary = false;
+ //! @brief Immediate address mode is specified with a value in 8. (This functions returns the 24bit space address of the value).
+ uint24_t _getImmediateAddr8Bits();
//! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the m flag is unset. (This functions returns the 24bit space address of the value).
uint24_t _getImmediateAddrForA();
//! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the x flag is unset. (This functions returns the 24bit space address of the value).
@@ -439,119 +259,382 @@ namespace ComSquare::CPU
virtual unsigned _executeInstruction(uint8_t opcode);
//! @brief Break instruction - Causes a software break. The PC is loaded from a vector table.
- void BRK();
+ int BRK(uint24_t);
//! @brief Co-Processor Enable instruction - Causes a software break. The PC is loaded from a vector table.
- void COP();
+ int COP(uint24_t);
//! @brief Return from Interrupt - Used to return from a interrupt handler.
- void RTI();
+ int RTI(uint24_t);
//! @brief Add with carry - Adds operand to the Accumulator; adds an additional 1 if carry is set.
- void ADC(uint24_t valueAddr);
+ int ADC(uint24_t valueAddr);
//! @brief Store the accumulator to memory.
- void STA(uint24_t addr);
+ int STA(uint24_t addr);
//! @brief Store the index register X to memory.
- void STX(uint24_t addr);
+ int STX(uint24_t addr);
//! @brief Store the index register Y to memory.
- void STY(uint24_t addr);
+ int STY(uint24_t addr);
//! @brief Store zero to the memory.
- void STZ(uint24_t addr);
+ int STZ(uint24_t addr);
//! @brief Load the accumulator from memory.
- void LDA(uint24_t addr);
+ int LDA(uint24_t addr);
//! @brief Load the X index register from memory.
- void LDX(uint24_t addr);
+ int LDX(uint24_t addr);
//! @brief Load the Y index register from memory.
- void LDY(uint24_t addr);
+ int LDY(uint24_t addr);
//! @brief Set status bits.
- void SEP(uint24_t valueAddr);
+ int SEP(uint24_t valueAddr);
//! @brief Reset status bits.
- void REP(uint24_t valueAddr);
+ int REP(uint24_t valueAddr);
//! @brief Jump to subroutine
- void JSR(uint24_t addr);
+ int JSR(uint24_t addr);
//! @brief Jump to subroutine (long)
- void JSL(uint24_t addr);
+ int JSL(uint24_t addr);
//! @brief Push the accumulator to the stack.
- void PHA();
+ int PHA(uint24_t);
//! @brief Push the data bank register to the stack.
- void PHB();
+ int PHB(uint24_t);
//! @brief Push the direct page register to the stack.
- void PHD();
+ int PHD(uint24_t);
//! @brief Push the program bank register to the stack.
- void PHK();
+ int PHK(uint24_t);
//! @brief Push the processor status register to the stack.
- void PHP();
+ int PHP(uint24_t);
//! @brief Push the x index register to the stack.
- void PHX();
+ int PHX(uint24_t);
//! @brief Push the y index register to the stack.
- void PHY();
+ int PHY(uint24_t);
//! @brief Pull the accumulator to the stack.
- void PLA();
+ int PLA(uint24_t);
//! @brief Pull the data bank register to the stack.
- void PLB();
+ int PLB(uint24_t);
//! @brief Pull the direct page register to the stack.
- void PLD();
+ int PLD(uint24_t);
//! @brief Pull the processor status register to the stack.
- void PLP();
+ int PLP(uint24_t);
//! @brief Pull the x index register to the stack.
- void PLX();
+ int PLX(uint24_t);
//! @brief Pull the y index register to the stack.
- void PLY();
+ int PLY(uint24_t);
//! @brief Clear the carry flag.
- void CLC();
+ int CLC(uint24_t);
//! @brief Clear the Interrupt Disable flag.
- void CLI();
+ int CLI(uint24_t);
//! @brief Clear the decimal flag.
- void CLD();
+ int CLD(uint24_t);
//! @brief Clear the overflow flag.
- void CLV();
+ int CLV(uint24_t);
//! @brief Set the carry Flag.
- void SEC();
+ int SEC(uint24_t);
//! @brief Set the decimal flag.
- void SED();
+ int SED(uint24_t);
//! @brief Set the Interrupt Disable flag.
- void SEI();
+ int SEI(uint24_t);
//! @brief Exchange Carry and Emulation Flags
- void XCE();
+ int XCE(uint24_t);
//! @brief And accumulator with memory.
- void AND(uint24_t valueAddr);
+ int AND(uint24_t valueAddr);
//! @brief Subtract with Borrow from Accumulator.
- void SBC(uint24_t valueAddr);
+ int SBC(uint24_t valueAddr);
//! @brief Transfer A to X
- void TAX();
+ int TAX(uint24_t);
//! @brief Transfer A to Y
- void TAY();
+ int TAY(uint24_t);
//! @brief Transfer X to SP
- void TXS();
+ int TXS(uint24_t);
//! @brief Increment the X register
- void INX();
+ int INX(uint24_t);
//! @brief Increment the Y register
- void INY();
+ int INY(uint24_t);
//! @brief Compare the X register with the memory
- void CPX(uint24_t valueAddr);
+ int CPX(uint24_t valueAddr);
//! @brief Compare the Y register with the memory
- void CPY(uint24_t valueAddr);
+ int CPY(uint24_t valueAddr);
//! @brief Branch if carry clear
- bool BCC(uint24_t valueAddr);
+ int BCC(uint24_t valueAddr);
//! @brief Branch if carry set
- bool BCS(uint24_t valueAddr);
+ int BCS(uint24_t valueAddr);
//! @brief Branch if equal
- bool BEQ(uint24_t valueAddr);
+ int BEQ(uint24_t valueAddr);
//! @brief Branch if not equal
- bool BNE(uint24_t valueAddr);
+ int BNE(uint24_t valueAddr);
//! @brief Branch if minus
- bool BMI(uint24_t valueAddr);
+ int BMI(uint24_t valueAddr);
//! @brief Branch if plus
- bool BPL(uint24_t valueAddr);
+ int BPL(uint24_t valueAddr);
//! @brief Branch if Overflow Clear
- bool BVC(uint24_t valueAddr);
+ int BVC(uint24_t valueAddr);
//! @brief Branch if Overflow Set
- bool BVS(uint24_t valueAddr);
+ int BVS(uint24_t valueAddr);
//! @brief Branch always
- bool BRA(uint24_t valueAddr);
+ int BRA(uint24_t valueAddr);
//! @brief Branch always long
- bool BRL(uint24_t valueAddr);
+ int BRL(uint24_t valueAddr);
//! @brief Jump.
- void JMP(uint24_t valueAddr);
+ int JMP(uint24_t valueAddr);
//! @brief Long jump.
- void JML(uint24_t valueAddr);
+ int JML(uint24_t valueAddr);
+ //! @brief No OP.
+ int NOP(uint24_t);
+
+ //! @brief All the instructions of the CPU.
+ //! @info Instructions are indexed by their opcode
+ Instruction _instructions[0x100] = {
+ {&CPU::BRK, 7, "brk", AddressingMode::Implied, 2}, // 00
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 01
+ {&CPU::COP, 7, "cop", AddressingMode::Implied, 2}, // 02
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 03
+ {&CPU::BRK, 7, "tsb #-#", AddressingMode::Implied, 2}, // 04
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 05
+ {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 06
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 07
+ {&CPU::PHP, 3, "php", AddressingMode::Implied, 3}, // 08
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 09
+ {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0A
+ {&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B
+ {&CPU::BRK, 7, "tsb #-#", AddressingMode::Implied, 2}, // 0C
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 0D
+ {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0E
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 0F
+ {&CPU::BPL, 7, "bpl", AddressingMode::Implied, 2}, // 10
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 11
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 12
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 13
+ {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 14
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 15
+ {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 16
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 17
+ {&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 19
+ {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // 1A
+ {&CPU::BRK, 7, "tcs #-#", AddressingMode::Implied, 2}, // 1B
+ {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 1D
+ {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 1E
+ {&CPU::BRK, 7, "ora #-#", AddressingMode::Implied, 2}, // 1F
+ {&CPU::JSR, 6, "jsr", AddressingMode::Absolute, 3}, // 20
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 21
+ {&CPU::JSL, 8, "jsl", AddressingMode::AbsoluteLong, 4}, // 22
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 23
+ {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 24
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 25
+ {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 26
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 27
+ {&CPU::PLP, 4, "plp", AddressingMode::Implied, 1}, // 28
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 29
+ {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2A
+ {&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B
+ {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 2C
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 2D
+ {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2E
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 2F
+ {&CPU::BMI, 2, "bmi", AddressingMode::Implied, 2}, // 30
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 31
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 32
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 33
+ {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 34
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 35
+ {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 36
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 37
+ {&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 39
+ {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // 3A
+ {&CPU::BRK, 7, "tsc #-#", AddressingMode::Implied, 2}, // 3B
+ {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 3C
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 3D
+ {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E
+ {&CPU::BRK, 7, "and #-#", AddressingMode::Implied, 2}, // 3F
+ {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 41
+ {&CPU::BRK, 7, "wdm #-#", AddressingMode::Implied, 2}, // 42
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 43
+ {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 45
+ {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 46
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 47
+ {&CPU::PHA, 3, "pha", AddressingMode::Implied, 1}, // 48
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 49
+ {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4A
+ {&CPU::PHK, 3, "phk", AddressingMode::Implied, 1}, // 4B
+ {&CPU::JMP, 3, "jmp", AddressingMode::Absolute, 3}, // 4C
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 4D
+ {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4E
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 4F
+ {&CPU::BVC, 2, "bvc", AddressingMode::Implied, 2}, // 50
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 51
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 52
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 53
+ {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // 54
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 55
+ {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 56
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 57
+ {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 59
+ {&CPU::PHY, 3, "phy", AddressingMode::Implied, 1}, // 5A
+ {&CPU::BRK, 7, "tcd #-#", AddressingMode::Implied, 2}, // 5B
+ {&CPU::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 5D
+ {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 5E
+ {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 5F
+ {&CPU::BRK, 7, "rtl #-#", AddressingMode::Implied, 2}, // 60
+ {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61
+ {&CPU::BRK, 7, "per #-#", AddressingMode::Implied, 2}, // 62
+ {&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63
+ {&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64
+ {&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65
+ {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 66
+ {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectLong, 2}, // 67
+ {&CPU::PLA, 4, "pla", AddressingMode::Implied, 1}, // 68
+ {&CPU::ADC, 2, "adc", AddressingMode::ImmediateForA, 2}, // 69
+ {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6A
+ {&CPU::BRK, 7, "rts #-#", AddressingMode::Implied, 2}, // 6B
+ {&CPU::JMP, 5, "jmp", AddressingMode::AbsoluteIndirect, 3}, // 6C
+ {&CPU::ADC, 4, "adc", AddressingMode::Absolute, 3}, // 6D
+ {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6E
+ {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteLong, 4}, // 6F
+ {&CPU::BVS, 2, "bvs", AddressingMode::Implied, 2}, // 70
+ {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 71
+ {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirect, 2}, // 72
+ {&CPU::ADC, 7, "adc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 73
+ {&CPU::STZ, 4, "stz", AddressingMode::DirectPageIndexedByX, 2}, // 74
+ {&CPU::ADC, 4, "adc", AddressingMode::DirectPageIndexedByX, 2}, // 75
+ {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 76
+ {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 77
+ {&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78
+ {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79
+ {&CPU::PLY, 4, "ply", AddressingMode::Implied, 1}, // 7A
+ {&CPU::BRK, 7, "tdc #-#", AddressingMode::Implied, 2}, // 7B
+ {&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C
+ {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D
+ {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 7E
+ {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteIndexedByXLong, 4}, // 7F
+ {&CPU::BRA, 3, "bra", AddressingMode::Implied, 2}, // 80
+ {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 81
+ {&CPU::BRL, 4, "brl", AddressingMode::Implied, 3}, // 82
+ {&CPU::STA, 4, "sta", AddressingMode::StackRelative, 2}, // 83
+ {&CPU::STY, 3, "sty", AddressingMode::DirectPage, 2}, // 84
+ {&CPU::STA, 3, "sta", AddressingMode::DirectPage, 2}, // 85
+ {&CPU::STX, 3, "stx", AddressingMode::DirectPage, 2}, // 86
+ {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectLong, 2}, // 87
+ {&CPU::BRK, 7, "dey #-#", AddressingMode::Implied, 2}, // 88
+ {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 89
+ {&CPU::BRK, 7, "txa #-#", AddressingMode::Implied, 2}, // 8A
+ {&CPU::PHB, 3, "phb", AddressingMode::Implied, 1}, // 8B
+ {&CPU::STY, 4, "sty", AddressingMode::Absolute, 3}, // 8C
+ {&CPU::STA, 4, "sta", AddressingMode::Absolute, 3}, // 8D
+ {&CPU::STX, 4, "stx", AddressingMode::Absolute, 3}, // 8E
+ {&CPU::STA, 5, "sta", AddressingMode::AbsoluteLong, 4}, // 8F
+ {&CPU::BCC, 2, "bcc", AddressingMode::Implied, 2}, // 90
+ {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 91
+ {&CPU::STA, 5, "sta", AddressingMode::DirectPageIndirect, 2}, // 92
+ {&CPU::STA, 7, "sta", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 93
+ {&CPU::STY, 4, "sty", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 94
+ {&CPU::STA, 4, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 95
+ {&CPU::STX, 4, "stx", AddressingMode::DirectPageIndexedByY, 2}, // 96
+ {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 97
+ {&CPU::BRK, 7, "tya #-#", AddressingMode::Implied, 2}, // 98
+ {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByY, 3}, // 99
+ {&CPU::BRK, 7, "txs #-#", AddressingMode::Implied, 2}, // 9A
+ {&CPU::BRK, 7, "txy #-#", AddressingMode::Implied, 2}, // 9B
+ {&CPU::STZ, 4, "stz", AddressingMode::Absolute, 3}, // 9C
+ {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByX, 3}, // 9D
+ {&CPU::STZ, 5, "stz", AddressingMode::AbsoluteIndexedByX, 3}, // 9E
+ {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByXLong, 4}, // 9F
+ {&CPU::LDY, 2, "ldy", AddressingMode::ImmediateForX, 2}, // A0
+ {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByX, 2}, // A1
+ {&CPU::LDX, 2, "ldx", AddressingMode::ImmediateForX, 2}, // A2
+ {&CPU::LDA, 4, "lda", AddressingMode::StackRelative, 2}, // A3
+ {&CPU::LDY, 3, "ldy", AddressingMode::DirectPage, 2}, // A4
+ {&CPU::LDA, 3, "lda", AddressingMode::DirectPage, 2}, // A5
+ {&CPU::LDX, 3, "ldx", AddressingMode::DirectPage, 2}, // A6
+ {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectLong, 2}, // A7
+ {&CPU::BRK, 7, "tay #-#", AddressingMode::Implied, 2}, // A8
+ {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9
+ {&CPU::BRK, 7, "tax #-#", AddressingMode::Implied, 2}, // AA
+ {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // AB
+ {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC
+ {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD
+ {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE
+ {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteLong, 4}, // AF
+ {&CPU::BCS, 2, "bcs", AddressingMode::Implied, 2}, // B0
+ {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirectIndexedByY, 2}, // B1
+ {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirect, 2}, // B2
+ {&CPU::LDA, 7, "lda", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // B3
+ {&CPU::LDY, 4, "ldy", AddressingMode::DirectPageIndexedByX, 2}, // B4
+ {&CPU::LDA, 4, "lda", AddressingMode::DirectPageIndexedByX, 2}, // B5
+ {&CPU::LDX, 4, "ldx", AddressingMode::DirectPageIndexedByY, 2}, // B6
+ {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // B7
+ {&CPU::CLV, 7, "clv", AddressingMode::Implied, 1}, // B8
+ {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByY, 3}, // B9
+ {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // BA
+ {&CPU::BRK, 7, "tyx #-#", AddressingMode::Implied, 2}, // BB
+ {&CPU::LDY, 4, "ldy", AddressingMode::AbsoluteIndexedByX, 3}, // BC
+ {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByX, 3}, // BD
+ {&CPU::LDX, 4, "ldx", AddressingMode::AbsoluteIndexedByY, 3}, // BE
+ {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteIndexedByXLong, 4}, // BF
+ {&CPU::BRK, 7, "cpy #-#", AddressingMode::Implied, 2}, // C0
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C1
+ {&CPU::REP, 3, "rep", AddressingMode::Immediate8bits, 3}, // C2
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C3
+ {&CPU::BRK, 7, "cpy #-#", AddressingMode::Implied, 2}, // C4
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C5
+ {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // C6
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C7
+ {&CPU::BRK, 7, "iny #-#", AddressingMode::Implied, 2}, // C8
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C9
+ {&CPU::BRK, 7, "dex #-#", AddressingMode::Implied, 2}, // CA
+ {&CPU::BRK, 7, "wai #-#", AddressingMode::Implied, 2}, // CB
+ {&CPU::BRK, 7, "cpy #-#", AddressingMode::Implied, 2}, // CC
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // CD
+ {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // CE
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // CF
+ {&CPU::BNE, 2, "bne", AddressingMode::Implied, 2}, // D0
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D1
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D2
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D3
+ {&CPU::BRK, 7, "pei #-#", AddressingMode::Implied, 2}, // D4
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D5
+ {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // D6
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D7
+ {&CPU::CLD, 27, "cld", AddressingMode::Implied, 2}, // D8
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // D9
+ {&CPU::PHX, 3, "phx", AddressingMode::Implied, 1}, // DA
+ {&CPU::BRK, 7, "stp #-#", AddressingMode::Implied, 2}, // DB
+ {&CPU::JML, 7, "jml", AddressingMode::AbsoluteIndirectLong, 2}, // DC
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // DD
+ {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // DE
+ {&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // DF
+ {&CPU::BRK, 7, "cpx #-#", AddressingMode::Implied, 2}, // E0
+ {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // E1
+ {&CPU::SEP, 3, "sep", AddressingMode::Immediate8bits, 2}, // E2
+ {&CPU::SBC, 4, "sbc", AddressingMode::StackRelative, 2}, // E3
+ {&CPU::BRK, 7, "cpx #-#", AddressingMode::Implied, 2}, // E4
+ {&CPU::SBC, 3, "sbc", AddressingMode::DirectPage, 2}, // E5
+ {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // E6
+ {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectLong, 2}, // E7
+ {&CPU::BRK, 7, "inx #-#", AddressingMode::Implied, 2}, // E8
+ {&CPU::SBC, 2, "sbc", AddressingMode::ImmediateForA, 2}, // E9
+ {&CPU::NOP, 2, "nop", AddressingMode::Implied, 1}, // EA
+ {&CPU::BRK, 7, "xba #-#", AddressingMode::Implied, 2}, // EB
+ {&CPU::BRK, 7, "cpx #-#", AddressingMode::Implied, 2}, // EC
+ {&CPU::SBC, 4, "sbc", AddressingMode::Absolute, 3}, // ED
+ {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // EE
+ {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteLong, 4}, // EF
+ {&CPU::BEQ, 2, "beq", AddressingMode::Implied, 2}, // F0
+ {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // F1
+ {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirect, 2}, // F2
+ {&CPU::SBC, 7, "sbc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // F3
+ {&CPU::BRK, 7, "pea #-#", AddressingMode::Implied, 2}, // F4
+ {&CPU::SBC, 4, "sbc", AddressingMode::DirectPageIndexedByX, 2}, // F5
+ {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // F6
+ {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // F7
+ {&CPU::SED, 2, "sed", AddressingMode::Implied, 1}, // F8
+ {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByY, 3}, // F9
+ {&CPU::PLX, 4, "plx", AddressingMode::Implied, 1}, // FA
+ {&CPU::XCE, 2, "xce", AddressingMode::Implied, 1}, // FB
+ {&CPU::JSR, 8, "jsr", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // FC
+ {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByX, 3}, // FD
+ {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // FE
+ {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteIndexedByXLong, 4}, // FF
+ };
public:
explicit CPU(std::shared_ptr bus, Cartridge::Header &cartridgeHeader);
CPU(const CPU &) = default;
@@ -578,7 +661,7 @@ namespace ComSquare::CPU
Component getComponent() override;
//! @brief Reset interrupt - Called on boot and when the reset button is pressed.
- virtual void RESB();
+ virtual int RESB(uint24_t = 0);
//! @brief Return true if the CPU is overloaded with debugging features.
virtual bool isDebugger();
diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp
new file mode 100644
index 0000000..8efd762
--- /dev/null
+++ b/sources/CPU/Instruction.hpp
@@ -0,0 +1,62 @@
+//
+// Created by anonymus-raccoon on 3/25/20.
+//
+
+#ifndef COMSQUARE_INSTRUCTION_HPP
+#define COMSQUARE_INSTRUCTION_HPP
+
+#include
+#include "../Models/Int24.hpp"
+
+namespace ComSquare::CPU
+{
+ class CPU;
+
+ //! @brief Different addressing modes that instructions can use for the main CPU.
+ enum AddressingMode {
+ Implied,
+
+ Immediate8bits,
+ ImmediateForA,
+ ImmediateForX,
+
+ Absolute,
+ AbsoluteLong,
+
+ DirectPage,
+ DirectPageIndirect,
+ DirectPageIndirectLong,
+
+ AbsoluteIndexedByX,
+ AbsoluteIndexedByXLong,
+ AbsoluteIndexedByY,
+
+ DirectPageIndexedByX,
+ DirectPageIndexedByY,
+ DirectPageIndirectIndexedByX,
+ DirectPageIndirectIndexedByY,
+ DirectPageIndirectIndexedByYLong,
+
+ StackRelative,
+ StackRelativeIndirectIndexedByY,
+
+
+ ProgramCounterRelative,
+ ProgramCounterRelativeLong,
+
+ AbsoluteIndirect,
+ AbsoluteIndirectIndexedByX,
+
+ AbsoluteIndirectLong
+ };
+
+ //! @brief Struct containing basic information about instructions.
+ struct Instruction {
+ int (CPU::*call)(uint24_t valueAddr);
+ int cycleCount;
+ std::string name;
+ AddressingMode addressingMode;
+ int size;
+ };
+}
+#endif //COMSQUARE_INSTRUCTION_HPP
diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp
index 46b2b6a..d048dcd 100644
--- a/sources/CPU/Instructions/BitsInstructions.cpp
+++ b/sources/CPU/Instructions/BitsInstructions.cpp
@@ -7,7 +7,7 @@
namespace ComSquare::CPU
{
- void CPU::AND(uint24_t valueAddr)
+ int CPU::AND(uint24_t valueAddr)
{
unsigned negativeMask = this->_isEmulationMode ? 0x80u : 0x8000u;
unsigned value = this->_bus->read(valueAddr);
@@ -17,5 +17,6 @@ namespace ComSquare::CPU
this->_registers.a &= value;
this->_registers.p.n = this->_registers.a & negativeMask;
this->_registers.p.z = this->_registers.a == 0;
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index 6c16c0c..921d2a9 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -6,152 +6,176 @@
namespace ComSquare::CPU
{
- void CPU::SEC()
+ int CPU::SEC(uint24_t)
{
this->_registers.p.c = true;
+ return 0;
}
- void CPU::SED()
+ int CPU::SED(uint24_t)
{
this->_registers.p.d = true;
+ return 0;
}
- void CPU::SEI()
+ int CPU::SEI(uint24_t)
{
this->_registers.p.i = true;
+ return 0;
}
- void CPU::CLC()
+ int CPU::CLC(uint24_t)
{
this->_registers.p.c = false;
+ return 0;
}
- void CPU::CLI()
+ int CPU::CLI(uint24_t)
{
this->_registers.p.i = false;
+ return 0;
}
- void CPU::CLD()
+ int CPU::CLD(uint24_t)
{
this->_registers.p.d = false;
+ return 0;
}
- void CPU::CLV()
+ int CPU::CLV(uint24_t)
{
this->_registers.p.v = false;
+ return 0;
}
- void CPU::SEP(uint24_t value)
+ int CPU::SEP(uint24_t value)
{
this->_registers.p.flags |= value;
+ return 0;
}
- void CPU::REP(uint24_t value)
+ int CPU::REP(uint24_t value)
{
this->_registers.p.flags &= ~value;
if (this->_isEmulationMode) {
this->_registers.p.x_b = true;
this->_registers.p.m = true;
}
+ return 0;
}
- void CPU::JSR(uint24_t value)
+ int CPU::JSR(uint24_t value)
{
this->_push(--this->_registers.pc);
this->_registers.pc = value;
+ return 0;
}
- void CPU::JSL(uint24_t value)
+ int CPU::JSL(uint24_t value)
{
this->_registers.pac--;
this->_push(this->_registers.pbr);
this->_push(this->_registers.pc);
this->_registers.pac = value;
+ return 0;
}
- void CPU::PHA()
+ int CPU::PHA(uint24_t)
{
this->_push(this->_registers.a);
+ return 0;
}
- void CPU::PHB()
+ int CPU::PHB(uint24_t)
{
this->_push(this->_registers.dbr);
+ return 0;
}
- void CPU::PHD()
+ int CPU::PHD(uint24_t)
{
this->_push(this->_registers.d);
+ return 0;
}
- void CPU::PHK()
+ int CPU::PHK(uint24_t)
{
this->_push(this->_registers.pbr);
+ return 0;
}
- void CPU::PHP()
+ int CPU::PHP(uint24_t)
{
this->_push(this->_registers.p.flags);
+ return 0;
}
- void CPU::PHX()
+ int CPU::PHX(uint24_t)
{
this->_push(this->_registers.x);
+ return 0;
}
- void CPU::PHY()
+ int CPU::PHY(uint24_t)
{
this->_push(this->_registers.y);
+ return 0;
}
- void CPU::PLA()
+ int CPU::PLA(uint24_t)
{
// TODO this register should be poped by 8 if the m flag is 1
this->_registers.a = this->_pop16();
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & 0x8000u;
+ return 0;
}
- void CPU::PLB()
+ int CPU::PLB(uint24_t)
{
this->_registers.dbr = this->_pop();
this->_registers.p.z = this->_registers.dbr == 0;
this->_registers.p.n = this->_registers.dbr & 0x80u;
+ return 0;
}
- void CPU::PLD()
+ int CPU::PLD(uint24_t)
{
this->_registers.d = this->_pop16();
this->_registers.p.z = this->_registers.d == 0;
this->_registers.p.n = this->_registers.d & 0x8000u;
+ return 0;
}
- void CPU::PLP()
+ int CPU::PLP(uint24_t)
{
this->_registers.p.flags = this->_pop();
if (this->_isEmulationMode) {
this->_registers.p.m = true;
this->_registers.p.x_b = true;
}
+ return 0;
}
- void CPU::PLX()
+ int CPU::PLX(uint24_t)
{
// TODO this register should be poped by 8 if the x_b is 1
this->_registers.x = this->_pop16();
this->_registers.p.z = this->_registers.x == 0;
this->_registers.p.n = this->_registers.x & 0x8000u;
+ return 0;
}
- void CPU::PLY()
+ int CPU::PLY(uint24_t)
{
// TODO this register should be poped by 8 if the x_b is 1
this->_registers.y = this->_pop16();
this->_registers.p.z = this->_registers.y == 0;
this->_registers.p.n = this->_registers.y & 0x8000u;
+ return 0;
}
- void CPU::XCE()
+ int CPU::XCE(uint24_t)
{
bool oldCarry = this->_registers.p.c;
this->_registers.p.c = this->_isEmulationMode;
@@ -163,9 +187,10 @@ namespace ComSquare::CPU
this->_registers.xh = 0;
this->_registers.yh = 0;
}
+ return 0;
}
- void CPU::INX()
+ int CPU::INX(uint24_t)
{
this->_registers.x++;
@@ -175,9 +200,10 @@ namespace ComSquare::CPU
unsigned negativeFlag = this->_registers.p.x_b ? 0x80u : 0x8000u;
this->_registers.p.z = this->_registers.x == 0;
this->_registers.p.n = this->_registers.x & negativeFlag;
+ return 0;
}
- void CPU::INY()
+ int CPU::INY(uint24_t)
{
this->_registers.y++;
@@ -187,9 +213,10 @@ namespace ComSquare::CPU
unsigned negativeFlag = this->_registers.p.x_b ? 0x80u : 0x8000u;
this->_registers.p.z = this->_registers.y == 0;
this->_registers.p.n = this->_registers.y & negativeFlag;
+ return 0;
}
- void CPU::CPX(uint24_t valueAddr)
+ int CPU::CPX(uint24_t valueAddr)
{
unsigned value = this->_bus->read(valueAddr++);
@@ -206,9 +233,10 @@ namespace ComSquare::CPU
this->_registers.p.n = x & 0x8000u;
}
this->_registers.p.c = this->_registers.x >= value;
+ return 0;
}
- void CPU::CPY(uint24_t valueAddr)
+ int CPU::CPY(uint24_t valueAddr)
{
unsigned value = this->_bus->read(valueAddr++);
@@ -225,57 +253,58 @@ namespace ComSquare::CPU
this->_registers.p.z = y == 0;
this->_registers.p.n = y & 0x8000u;
}
+ return 0;
}
- bool CPU::BCC(uint24_t valueAddr)
+ int CPU::BCC(uint24_t valueAddr)
{
if (!this->_registers.p.c)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.c;
}
- bool CPU::BCS(uint24_t valueAddr)
+ int CPU::BCS(uint24_t valueAddr)
{
if (this->_registers.p.c)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.c;
}
- bool CPU::BEQ(uint24_t valueAddr)
+ int CPU::BEQ(uint24_t valueAddr)
{
if (this->_registers.p.z)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.z;
}
- bool CPU::BNE(uint24_t valueAddr)
+ int CPU::BNE(uint24_t valueAddr)
{
if (!this->_registers.p.z)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.z;
}
- bool CPU::BMI(uint24_t valueAddr)
+ int CPU::BMI(uint24_t valueAddr)
{
if (this->_registers.p.n)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.n;
}
- bool CPU::BPL(uint24_t valueAddr)
+ int CPU::BPL(uint24_t valueAddr)
{
if (!this->_registers.p.n)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.n;
}
- bool CPU::BRA(uint24_t valueAddr)
+ int CPU::BRA(uint24_t valueAddr)
{
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return true;
}
- bool CPU::BRL(uint24_t valueAddr)
+ int CPU::BRL(uint24_t valueAddr)
{
unsigned value = this->_bus->read(valueAddr);
value += this->_bus->read(valueAddr + 1) << 8u;
@@ -284,27 +313,34 @@ namespace ComSquare::CPU
return true;
}
- bool CPU::BVC(uint24_t valueAddr)
+ int CPU::BVC(uint24_t valueAddr)
{
if (!this->_registers.p.v)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.v;
}
- bool CPU::BVS(uint24_t valueAddr)
+ int CPU::BVS(uint24_t valueAddr)
{
if (this->_registers.p.v)
this->_registers.pac += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.v;
}
- void CPU::JMP(uint24_t value)
+ int CPU::JMP(uint24_t value)
{
this->_registers.pc = value;
+ return 0;
}
- void CPU::JML(uint24_t value)
+ int CPU::JML(uint24_t value)
{
this->_registers.pac = value;
+ return 0;
+ }
+
+ int CPU::NOP(uint24_t)
+ {
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/Interrupts.cpp b/sources/CPU/Instructions/Interrupts.cpp
index 1c5d021..02d54ae 100644
--- a/sources/CPU/Instructions/Interrupts.cpp
+++ b/sources/CPU/Instructions/Interrupts.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- void CPU::RESB()
+ int CPU::RESB(uint24_t)
{
this->_registers.p.i = true;
this->_registers.p.d = false;
@@ -18,9 +18,10 @@ namespace ComSquare::CPU
this->_registers.d = 0x0000;
this->_registers.sh = 0x01; // the low bit of the stack pointer is undefined on reset.
this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.reset;
+ return 0;
}
- void CPU::BRK()
+ int CPU::BRK(uint24_t)
{
if (this->_isEmulationMode) {
this->_registers.pc += 2;
@@ -41,9 +42,10 @@ namespace ComSquare::CPU
this->_registers.pbr = 0x0;
this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.brk;
}
+ return !this->_isEmulationMode;
}
- void CPU::COP()
+ int CPU::COP(uint24_t)
{
if (this->_isEmulationMode) {
this->_registers.pc += 2;
@@ -63,14 +65,16 @@ namespace ComSquare::CPU
this->_registers.pbr = 0x0;
this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.cop;
}
+ return !this->_isEmulationMode;
}
- void CPU::RTI()
+ int CPU::RTI(uint24_t)
{
this->_registers.p.flags = this->_pop();
this->_registers.pc = this->_pop16();
if (!this->_isEmulationMode)
this->_registers.pbr = this->_pop16();
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp
index 75835ea..60465d9 100644
--- a/sources/CPU/Instructions/MathematicalOperations.cpp
+++ b/sources/CPU/Instructions/MathematicalOperations.cpp
@@ -7,7 +7,7 @@
namespace ComSquare::CPU
{
- void CPU::ADC(uint24_t valueAddr)
+ int CPU::ADC(uint24_t valueAddr)
{
unsigned value = this->_bus->read(valueAddr) + this->_registers.p.c;
if (!this->_registers.p.m)
@@ -25,9 +25,10 @@ namespace ComSquare::CPU
this->_registers.a %= 0x100;
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & negativeMask;
+ return 0;
}
- void CPU::SBC(uint24_t valueAddr)
+ int CPU::SBC(uint24_t valueAddr)
{
unsigned negativeMask = this->_isEmulationMode ? 0x80u : 0x8000u;
unsigned value = this->_bus->read(valueAddr);
@@ -45,5 +46,6 @@ namespace ComSquare::CPU
this->_registers.a %= 0x100;
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & negativeMask;
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/MemoryInstructions.cpp b/sources/CPU/Instructions/MemoryInstructions.cpp
index 8a7b310..1e29642 100644
--- a/sources/CPU/Instructions/MemoryInstructions.cpp
+++ b/sources/CPU/Instructions/MemoryInstructions.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- void CPU::STA(uint24_t addr)
+ int CPU::STA(uint24_t addr)
{
if (this->_registers.p.m)
this->_bus->write(addr, this->_registers.al);
@@ -14,9 +14,10 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.al);
this->_bus->write(addr + 1, this->_registers.ah);
}
+ return 0;
}
- void CPU::STX(uint24_t addr)
+ int CPU::STX(uint24_t addr)
{
if (this->_registers.p.x_b)
this->_bus->write(addr, this->_registers.xl);
@@ -24,9 +25,10 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.xl);
this->_bus->write(addr + 1, this->_registers.xh);
}
+ return 0;
}
- void CPU::STY(uint24_t addr)
+ int CPU::STY(uint24_t addr)
{
if (this->_registers.p.x_b)
this->_bus->write(addr, this->_registers.yl);
@@ -34,16 +36,18 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.yl);
this->_bus->write(addr + 1, this->_registers.yh);
}
+ return 0;
}
- void CPU::STZ(uint24_t addr)
+ int CPU::STZ(uint24_t addr)
{
this->_bus->write(addr, 0x00);
if (!this->_registers.p.m)
this->_bus->write(addr + 1, 0x00);
+ return 0;
}
- void CPU::LDA(uint24_t addr)
+ int CPU::LDA(uint24_t addr)
{
if (this->_registers.p.m) {
this->_registers.a = this->_bus->read(addr);
@@ -54,9 +58,10 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.a & 0xF000u;
}
this->_registers.p.z = this->_registers.a == 0x0;
+ return 0;
}
- void CPU::LDX(uint24_t addr)
+ int CPU::LDX(uint24_t addr)
{
if (this->_registers.p.x_b) {
this->_registers.x = this->_bus->read(addr);
@@ -67,9 +72,10 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.x & 0xF000u;
}
this->_registers.p.z = this->_registers.x == 0x0;
+ return 0;
}
- void CPU::LDY(uint24_t addr)
+ int CPU::LDY(uint24_t addr)
{
if (this->_registers.p.x_b) {
this->_registers.y = this->_bus->read(addr);
@@ -80,5 +86,6 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.y & 0xF000u;
}
this->_registers.p.z = this->_registers.y == 0x0;
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp
index 4b95092..3e49685 100644
--- a/sources/CPU/Instructions/TransferRegisters.cpp
+++ b/sources/CPU/Instructions/TransferRegisters.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- void CPU::TAX()
+ int CPU::TAX(uint24_t)
{
if (this->_registers.p.x_b) {
this->_registers.xl = this->_registers.al;
@@ -17,9 +17,10 @@ namespace ComSquare::CPU
this->_registers.p.z = this->_registers.x == 0;
this->_registers.p.n = this->_registers.x & 0x8000u;
}
+ return 0;
}
- void CPU::TAY()
+ int CPU::TAY(uint24_t)
{
if (this->_registers.p.x_b) {
this->_registers.yl = this->_registers.al;
@@ -30,9 +31,10 @@ namespace ComSquare::CPU
this->_registers.p.z = this->_registers.y == 0;
this->_registers.p.n = this->_registers.y & 0x8000u;
}
+ return 0;
}
- void CPU::TXS()
+ int CPU::TXS(uint24_t)
{
if (this->_registers.p.x_b) {
this->_registers.sh = 0;
@@ -44,5 +46,6 @@ namespace ComSquare::CPU
this->_registers.p.z = this->_registers.s == 0;
this->_registers.p.n = this->_registers.s & 0x8000u;
}
+ return 0;
}
}
\ No newline at end of file
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 80a4c07..34e091c 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -16,6 +16,7 @@ namespace ComSquare::Debugger
: CPU(basicCPU),
_window(new ClosableWindow(*this, &CPUDebug::disableDebugger)),
_ui(),
+ _model(*this),
_snes(snes)
{
this->_window->setContextMenuPolicy(Qt::NoContextMenu);
@@ -23,6 +24,13 @@ namespace ComSquare::Debugger
this->_window->setAttribute(Qt::WA_DeleteOnClose);
this->_ui.setupUi(this->_window);
+
+ this->_ui.disasembly->setModel(&this->_model);
+ this->_ui.disasembly->setShowGrid(false);
+ this->_ui.disasembly->verticalHeader()->hide();
+ this->_ui.disasembly->horizontalHeader()->hide();
+ this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
+
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
QMainWindow::connect(this->_ui.clear, &QPushButton::released, this, &CPUDebug::clearHistory);
@@ -51,12 +59,15 @@ namespace ComSquare::Debugger
} catch (InvalidOpcode &e) {
if (!this->_isPaused)
this->pause();
+ std::cout << "Invalid Opcode: " << e.what() << std::endl;
return 0xFF;
}
}
unsigned CPUDebug::_executeInstruction(uint8_t opcode)
{
+ if (this->_isPaused)
+ return 0;
if (this->_isStepping) {
this->_isStepping = false;
this->_isPaused = true;
@@ -202,198 +213,37 @@ namespace ComSquare::Debugger
std::string CPUDebug::_getInstructionString(uint24_t pc)
{
uint8_t opcode = this->_bus->read(pc++, true);
-
- switch (opcode) {
- case Instructions::BRK: return "BRK";
-
- case Instructions::COP: return "COP";
-
- case Instructions::RTI: return "RTI";
-
- case Instructions::ADC_IM: return "ADC " + this->_getImmediateValueForA(pc);
- case Instructions::ADC_ABS: return "ADC " + this->_getAbsoluteValue(pc);
- case Instructions::ADC_ABSl: return "ADC " + this->_getAbsoluteLongValue(pc);
- case Instructions::ADC_DP: return "ADC " + this->_getDirectValue(pc);
- case Instructions::ADC_DPi: return "ADC";
- case Instructions::ADC_DPil: return "ADC";
- case Instructions::ADC_ABSX: return "ADC";
- case Instructions::ADC_ABSXl:return "ADC";
- case Instructions::ADC_ABSY: return "ADC";
- case Instructions::ADC_DPX: return "ADC " + this->_getDirectIndexedByXValue(pc);
- case Instructions::ADC_DPXi: return "ADC";
- case Instructions::ADC_DPYi: return "ADC";
- case Instructions::ADC_DPYil:return "ADC";
- case Instructions::ADC_SR: return "ADC";
- case Instructions::ADC_SRYi: return "ADC";
-
- case Instructions::STA_ABS: return "STA " + this->_getAbsoluteValue(pc);
- case Instructions::STA_ABSl: return "STA " + this->_getAbsoluteLongValue(pc);
- case Instructions::STA_DP: return "STA " + this->_getDirectValue(pc);
- case Instructions::STA_DPi: return "STA";
- case Instructions::STA_DPil: return "STA";
- case Instructions::STA_ABSX: return "STA";
- case Instructions::STA_ABSXl:return "STA";
- case Instructions::STA_ABSY: return "STA";
- case Instructions::STA_DPX: return "STA " + this->_getDirectIndexedByXValue(pc);
- case Instructions::STA_DPXi: return "STA";
- case Instructions::STA_DPYi: return "STA";
- case Instructions::STA_DPYil:return "STA";
- case Instructions::STA_SR: return "STA";
- case Instructions::STA_SRYi: return "STA";
-
- case Instructions::STX_ABS: return "STX " + this->_getAbsoluteValue(pc);
- case Instructions::STX_DP: return "STX " + this->_getDirectValue(pc);
- case Instructions::STX_DPY: return "STX";
-
- case Instructions::STY_ABS: return "STY " + this->_getAbsoluteValue(pc);
- case Instructions::STY_DP: return "STY " + this->_getDirectValue(pc);
- case Instructions::STY_DPX: return "STY " + this->_getDirectIndexedByXValue(pc);
-
- case Instructions::STZ_ABS: return "STZ " + this->_getAbsoluteValue(pc);
- case Instructions::STZ_DP: return "STZ " + this->_getDirectValue(pc);
- case Instructions::STZ_ABSX: return "STZ";
- case Instructions::STZ_DPX: return "STZ " + this->_getDirectIndexedByXValue(pc);
-
- case Instructions::LDA_IM: return "LDA " + this->_getImmediateValueForA(pc);
- case Instructions::LDA_ABS: return "LDA " + this->_getAbsoluteValue(pc);
- case Instructions::LDA_ABSl: return "LDA " + this->_getAbsoluteLongValue(pc);
- case Instructions::LDA_DP: return "LDA " + this->_getDirectValue(pc);
- case Instructions::LDA_DPi: return "LDA";
- case Instructions::LDA_DPil: return "LDA";
- case Instructions::LDA_ABSX: return "LDA";
- case Instructions::LDA_ABSXl:return "LDA";
- case Instructions::LDA_ABSY: return "LDA";
- case Instructions::LDA_DPX: return "LDA " + this->_getDirectIndexedByXValue(pc);
- case Instructions::LDA_DPXi: return "LDA";
- case Instructions::LDA_DPYi: return "LDA";
- case Instructions::LDA_DPYil:return "LDA";
- case Instructions::LDA_SR: return "LDA";
- case Instructions::LDA_SRYi: return "LDA";
-
- case Instructions::LDX_IM: return "LDX " + this->_getImmediateValueForX(pc);
- case Instructions::LDX_ABS: return "LDX " + this->_getAbsoluteValue(pc);
- case Instructions::LDX_DP: return "LDX " + this->_getDirectValue(pc);
- case Instructions::LDX_ABSY: return "LDX";
- case Instructions::LDX_DPY: return "LDX";
-
- case Instructions::LDY_IM: return "LDY " + this->_getImmediateValueForX(pc);
- case Instructions::LDY_ABS: return "LDY " + this->_getAbsoluteValue(pc);
- case Instructions::LDY_DP: return "LDY " + this->_getDirectValue(pc);
- case Instructions::LDY_ABSY: return "LDY";
- case Instructions::LDY_DPY: return "LDY";
-
- case Instructions::SEP: return "SEP " + this->_getImmediateValue8Bits(pc);
-
- case Instructions::REP: return "REP " + this->_getImmediateValue8Bits(pc);
-
- case Instructions::PHA: return "PHA";
- case Instructions::PHB: return "PHB";
- case Instructions::PHD: return "PHD";
- case Instructions::PHK: return "PHK";
- case Instructions::PHP: return "PHP";
- case Instructions::PHX: return "PHX";
- case Instructions::PHY: return "PHY";
-
- case Instructions::PLA: return "PLA";
- case Instructions::PLB: return "PLB";
- case Instructions::PLD: return "PLD";
- case Instructions::PLP: return "PLP";
- case Instructions::PLX: return "PLX";
- case Instructions::PLY: return "PLY";
-
- case Instructions::JSR_ABS: return "JSR " + this->_getAbsoluteValue(pc);
- case Instructions::JSR_ABSXi: return "JSR";
-
- case Instructions::JSL: return "JSL " + this->_getAbsoluteLongValue(pc);
-
- case Instructions::CLC: return "CLC";
- case Instructions::CLI: return "CLI";
- case Instructions::CLD: return "CLD";
- case Instructions::CLV: return "CLV";
-
- case Instructions::SEC: return "SEC";
- case Instructions::SED: return "SED";
- case Instructions::SEI: return "SEI";
-
- case Instructions::AND_IM: return "AND " + this->_getImmediateValueForA(pc);
- case Instructions::AND_ABS: return "AND " + this->_getAbsoluteValue(pc);
- case Instructions::AND_ABSl: return "AND " + this->_getAbsoluteLongValue(pc);
- case Instructions::AND_DP: return "AND " + this->_getDirectValue(pc);
- case Instructions::AND_DPi: return "AND";
- case Instructions::AND_DPil: return "AND";
- case Instructions::AND_ABSX: return "AND";
- case Instructions::AND_ABSXl:return "AND";
- case Instructions::AND_ABSY: return "AND";
- case Instructions::AND_DPX: return "AND " + this->_getDirectIndexedByXValue(pc);
- case Instructions::AND_DPXi: return "AND";
- case Instructions::AND_DPYi: return "AND";
- case Instructions::AND_DPYil:return "AND";
- case Instructions::AND_SR: return "AND";
- case Instructions::AND_SRYi: return "AND";
-
- case Instructions::XCE: return "XCE";
-
- case Instructions::SBC_IM: return "SBC " + this->_getImmediateValueForA(pc);
- case Instructions::SBC_ABS: return "SBC " + this->_getAbsoluteValue(pc);
- case Instructions::SBC_ABSl: return "SBC " + this->_getAbsoluteLongValue(pc);
- case Instructions::SBC_DP: return "SBC " + this->_getDirectValue(pc);
- case Instructions::SBC_DPi: return "SBC";
- case Instructions::SBC_DPil: return "SBC";
- case Instructions::SBC_ABSX: return "SBC";
- case Instructions::SBC_ABSXl:return "SBC";
- case Instructions::SBC_ABSY: return "SBC";
- case Instructions::SBC_DPX: return "SBC " + this->_getDirectIndexedByXValue(pc);
- case Instructions::SBC_DPXi: return "SBC";
- case Instructions::SBC_DPYi: return "SBC";
- case Instructions::SBC_DPYil:return "SBC";
- case Instructions::SBC_SR: return "SBC";
- case Instructions::SBC_SRYi: return "SBC";
-
- case Instructions::TAX: return "TAX";
- case Instructions::TAY: return "TAY";
- case Instructions::TXS: return "TXS";
-
- case Instructions::INX: return "INX";
- case Instructions::INY: return "INY";
-
- case Instructions::CPX_IM: return "CPX " + this->_getImmediateValueForX(pc);
- case Instructions::CPX_ABS: return "CPX " + this->_getAbsoluteValue(pc);
- case Instructions::CPX_DP: return "CPX";
-
- case Instructions::CPY_IM: return "CPY " + this->_getImmediateValueForX(pc);
- case Instructions::CPY_ABS: return "CPY " + this->_getAbsoluteValue(pc);
- case Instructions::CPY_DP: return "CPY";
-
- case Instructions::BCC: return "BCC " + this->_getImmediateValue8Bits(pc);
- case Instructions::BCS: return "BCS " + this->_getImmediateValue8Bits(pc);
- case Instructions::BEQ: return "BEQ " + this->_getImmediateValue8Bits(pc);
- case Instructions::BNE: return "BNE " + this->_getImmediateValue8Bits(pc);
- case Instructions::BMI: return "BMI " + this->_getImmediateValue8Bits(pc);
- case Instructions::BPL: return "BPL " + this->_getImmediateValue8Bits(pc);
- case Instructions::BVC: return "BVC " + this->_getImmediateValue8Bits(pc);
- case Instructions::BVS: return "BVS " + this->_getImmediateValue8Bits(pc);
- case Instructions::BRA: return "BRA " + this->_getImmediateValue8Bits(pc);
- case Instructions::BRL: return "BRL " + this->_getImmediateValue16Bits(pc);
-
- case Instructions::JMP_ABS: return "JMP " + this->_getAbsoluteValue(pc);
- case Instructions::JMP_ABSi: return "JMP "; //+ this->_getAbsoluteIndire(pc);
- case Instructions::JMP_ABSXi: return "JMP "; //+ this->_getAbsoluteValue(pc);
-
- case Instructions::JML_ABSl: return "JML";
- case Instructions::JML_ABSil: return "JML";
-
- default: return "Unknown";
- }
+ return this->_instructions[opcode].name;
}
- void CPUDebug::RESB()
+ int CPUDebug::RESB(uint24_t)
{
CPU::RESB();
this->_updateRegistersPanel();
+ return (0);
}
void CPUDebug::focus()
{
this->_window->activateWindow();
}
+}
+
+DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstractTableModel(), _cpu(cpu){ }
+
+int DisassemblyModel::columnCount(const QModelIndex &) const
+{
+ return 4;
+}
+
+int DisassemblyModel::rowCount(const QModelIndex &) const
+{
+ return 0xFFFFFF;
+}
+
+QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ return QString();
}
\ No newline at end of file
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 15fbb7c..82a57a0 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -11,6 +11,31 @@
#include "../../ui/ui_cpu.h"
#include "ClosableWindow.hpp"
+namespace ComSquare::Debugger
+{
+ class CPUDebug;
+}
+
+//! @brief The qt model that show the disassembly.
+class DisassemblyModel : public QAbstractTableModel
+{
+Q_OBJECT
+private:
+ ComSquare::Debugger::CPUDebug &_cpu;
+public:
+ explicit DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu);
+ DisassemblyModel(const DisassemblyModel &) = delete;
+ const DisassemblyModel &operator=(const DisassemblyModel &) = delete;
+ ~DisassemblyModel() override = default;
+
+ //! @brief The number of row the table has.
+ int rowCount(const QModelIndex &parent) const override;
+ //! @brief The number of column the table has.
+ int columnCount(const QModelIndex &parent) const override;
+ //! @brief Return a data representing the table cell.
+ QVariant data(const QModelIndex &index, int role) const override;
+};
+
namespace ComSquare::Debugger
{
//! @brief A custom CPU with a window that show it's registers and the disassembly.
@@ -20,6 +45,8 @@ namespace ComSquare::Debugger
ClosableWindow *_window;
//! @brief A widget that contain the whole UI.
Ui::CPUView _ui;
+ //! @brief The disassembly viewer's model.
+ DisassemblyModel _model;
//! @brief If this is set to true, the execution of the CPU will be paused.
bool _isPaused = true;
//! @brief If this is set to true, the CPU will execute one instruction and pause itself.
@@ -52,7 +79,7 @@ namespace ComSquare::Debugger
//! @brief Return a printable string corresponding to the value of a direct index by x addressing mode.
std::string _getDirectIndexedByXValue(uint24_t pc);
- public slots:
+ public:
//! @brief Pause/Resume the CPU.
void pause();
//! @brief Step - Execute a single instruction.
@@ -63,7 +90,7 @@ namespace ComSquare::Debugger
void disableDebugger();
public:
//! @brief Update the UI when reseting the CPU.
- void RESB() override;
+ int RESB(uint24_t) override;
//! @brief Convert a basic CPU to a debugging CPU.
explicit CPUDebug(ComSquare::CPU::CPU &cpu, SNES &snes);
CPUDebug(const CPUDebug &) = delete;
diff --git a/sources/Exceptions/DebuggableError.hpp b/sources/Exceptions/DebuggableError.hpp
new file mode 100644
index 0000000..fcc9180
--- /dev/null
+++ b/sources/Exceptions/DebuggableError.hpp
@@ -0,0 +1,15 @@
+//
+// Created by anonymus-raccoon on 3/26/20.
+//
+
+#ifndef COMSQUARE_DEBUGGABLEERROR_HPP
+#define COMSQUARE_DEBUGGABLEERROR_HPP
+
+#include
+
+namespace ComSquare
+{
+ class DebuggableError : public std::exception {};
+}
+
+#endif //COMSQUARE_DEBUGGABLEERROR_HPP
diff --git a/sources/Exceptions/InvalidAction.hpp b/sources/Exceptions/InvalidAction.hpp
index 8b9c06a..e74d73d 100644
--- a/sources/Exceptions/InvalidAction.hpp
+++ b/sources/Exceptions/InvalidAction.hpp
@@ -7,11 +7,12 @@
#include
#include
+#include "DebuggableError.hpp"
namespace ComSquare
{
//! @brief Exception thrown when someone tries to load an invalid rom.
- class InvalidAction : public std::exception {
+ class InvalidAction : public DebuggableError {
private:
std::string _msg;
public:
diff --git a/sources/Exceptions/InvalidAddress.hpp b/sources/Exceptions/InvalidAddress.hpp
index 09724ae..b91ce6e 100644
--- a/sources/Exceptions/InvalidAddress.hpp
+++ b/sources/Exceptions/InvalidAddress.hpp
@@ -9,11 +9,12 @@
#include
#include
#include
+#include "DebuggableError.hpp"
namespace ComSquare
{
//! @brief Exception thrown when trying to read/write to an invalid address.
- class InvalidAddress : public std::exception {
+ class InvalidAddress : public DebuggableError {
private:
std::string _msg;
public:
diff --git a/sources/Exceptions/InvalidOpcode.hpp b/sources/Exceptions/InvalidOpcode.hpp
index 00447c4..57e990d 100644
--- a/sources/Exceptions/InvalidOpcode.hpp
+++ b/sources/Exceptions/InvalidOpcode.hpp
@@ -8,11 +8,12 @@
#include
#include
#include
+#include "DebuggableError.hpp"
namespace ComSquare
{
//! @brief Exception thrown when someone tries to load an invalid rom.
- class InvalidOpcode : public std::exception {
+ class InvalidOpcode : public DebuggableError {
private:
std::string _msg;
public:
diff --git a/sources/Exceptions/InvalidRom.hpp b/sources/Exceptions/InvalidRom.hpp
index 433c478..f0f331a 100644
--- a/sources/Exceptions/InvalidRom.hpp
+++ b/sources/Exceptions/InvalidRom.hpp
@@ -7,11 +7,12 @@
#include
#include
+#include "DebuggableError.hpp"
namespace ComSquare
{
//! @brief Exception thrown when someone tries to load an invalid rom.
- class InvalidRomException : public std::exception {
+ class InvalidRomException : public DebuggableError {
private:
std::string _msg;
public:
diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp
index 9a333a6..e74a103 100644
--- a/sources/Renderer/QtRenderer/QtSFML.cpp
+++ b/sources/Renderer/QtRenderer/QtSFML.cpp
@@ -10,6 +10,7 @@
#include "QtSFML.hpp"
#include "../../Exceptions/InvalidOpcode.hpp"
#include "../../Exceptions/InvalidAddress.hpp"
+#include "../../Exceptions/InvalidAction.hpp"
#ifdef Q_WS_X11
#include
@@ -86,10 +87,9 @@ namespace ComSquare::Renderer
{
try {
this->_snes.update();
- } catch (InvalidOpcode &e) {
- this->_snes.enableCPUDebugging();
- } catch (InvalidAddress &e) {
- this->_snes.enableCPUDebugging();
+ } catch (DebuggableError &e) {
+ std::cout << "Invalid rom's instruction: " << e.what() << std::endl;
+ this->_snes.enableCPUDebugging(true);
} catch (std::exception &e) {
std::cerr << "An error occurred: " << e.what() << std::endl;
QApplication::quit();
diff --git a/sources/SNES.cpp b/sources/SNES.cpp
index 3dc9674..b6188fe 100644
--- a/sources/SNES.cpp
+++ b/sources/SNES.cpp
@@ -34,12 +34,14 @@ namespace ComSquare
this->apu->update(cycleCount);
}
- void SNES::enableCPUDebugging()
+ void SNES::enableCPUDebugging(bool pause)
{
#ifdef DEBUGGER_ENABLED
- if (this->cpu->isDebugger())
- std::static_pointer_cast(this->cpu)->focus();
- else
+ if (this->cpu->isDebugger()) {
+ auto cpuDebug = std::static_pointer_cast(this->cpu);
+ cpuDebug->focus();
+ cpuDebug->pause();
+ } else
this->cpu = std::make_shared(*this->cpu, *this);
#else
std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl;
diff --git a/sources/SNES.hpp b/sources/SNES.hpp
index 25fb99e..77c5264 100644
--- a/sources/SNES.hpp
+++ b/sources/SNES.hpp
@@ -53,7 +53,7 @@ namespace ComSquare
//! @brief Disable the CPU's debugging window.
void disableCPUDebugging();
//! @brief Enable the CPU's debugging window.
- void enableCPUDebugging();
+ void enableCPUDebugging(bool pause = false);
//! @brief Disable the Ram's debugging window.
void disableRamViewer();
//! @brief Enable the Ram's debugging window.
diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/TransferRegisters.cpp
index 7ee8e76..5bb6c01 100644
--- a/tests/CPU/TransferRegisters.cpp
+++ b/tests/CPU/TransferRegisters.cpp
@@ -17,7 +17,7 @@ Test(TAX, 16bitsTo16Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.x = 0xABCD;
snes.cpu->_registers.a = 0xFEDC;
- snes.cpu->TAX();
+ snes.cpu->TAX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0xFEDC, "The flags should be 0xFEDC but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -31,7 +31,7 @@ Test(TAX, 16bitsTo8Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.x = 0xFEDC;
snes.cpu->_registers.a = 0xAB00;
- snes.cpu->TAX();
+ snes.cpu->TAX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0xFE00, "The flags should be 0xFE00 but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.");
@@ -45,7 +45,7 @@ Test(TAX, 8bitsTo16Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.x = 0xFEDC;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAX();
+ snes.cpu->TAX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0x00AB, "The flags should be 0x00AB but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -59,7 +59,7 @@ Test(TAX, 8bitsTo8Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.x = 0xFE;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAX();
+ snes.cpu->TAX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0xAB, "The flags should be 0xAB but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -74,7 +74,7 @@ Test(TAY, 16bitsTo16Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.y = 0xABCD;
snes.cpu->_registers.a = 0xFEDC;
- snes.cpu->TAY();
+ snes.cpu->TAY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0xFEDC, "The y register should be 0xFEDC but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -88,7 +88,7 @@ Test(TAY, 16bitsTo8Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.y = 0xFEDC;
snes.cpu->_registers.a = 0xAB00;
- snes.cpu->TAY();
+ snes.cpu->TAY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0xFE00, "The y register should be 0xFE00 but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.");
@@ -102,7 +102,7 @@ Test(TAY, 8bitsTo16Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.y = 0xFEDC;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAY();
+ snes.cpu->TAY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0x00AB, "The y register should be 0x00AB but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -116,7 +116,7 @@ Test(TAY, 8bitsTo8Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.y = 0xFE;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAY();
+ snes.cpu->TAY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0xAB, "The y register should be 0xAB but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -128,7 +128,7 @@ Test(TXS, 16bitsIndex)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.x = 0xABCD;
- snes.cpu->TXS();
+ snes.cpu->TXS(0x0);
cr_assert_eq(snes.cpu->_registers.s, 0xABCD, "The stack pointer should be 0xABCD but it was %x", snes.cpu->_registers.s);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -140,7 +140,7 @@ Test(TXS, 8bitsIndex)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.x = 0xABCD;
- snes.cpu->TXS();
+ snes.cpu->TXS(0x0);
cr_assert_eq(snes.cpu->_registers.s, 0x00CD, "The stack pointer should be 0x00CD but it was %x", snes.cpu->_registers.s);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp
index 7caa8ea..fca58c3 100644
--- a/tests/CPU/testInternal.cpp
+++ b/tests/CPU/testInternal.cpp
@@ -99,7 +99,7 @@ Test(PHA, basic)
Init()
snes.cpu->_registers.a = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHA();
+ snes.cpu->PHA(0x0);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -110,7 +110,7 @@ Test(PHB, basic)
Init()
snes.cpu->_registers.dbr = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHB();
+ snes.cpu->PHB(0x0);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -120,7 +120,7 @@ Test(PHD, basic)
Init()
snes.cpu->_registers.d = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHD();
+ snes.cpu->PHD(0x0);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -131,7 +131,7 @@ Test(PHK, basic)
Init()
snes.cpu->_registers.pbr = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHK();
+ snes.cpu->PHK(0x0);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -141,7 +141,7 @@ Test(PHP, basic)
Init()
snes.cpu->_registers.p.flags = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHP();
+ snes.cpu->PHP(0x0);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -151,7 +151,7 @@ Test(PHX, basic)
Init()
snes.cpu->_registers.x = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHX();
+ snes.cpu->PHX(0x0);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -162,7 +162,7 @@ Test(PHY, basic)
Init()
snes.cpu->_registers.y = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHY();
+ snes.cpu->PHY(0x0);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -174,7 +174,7 @@ Test(PLA, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA();
+ snes.cpu->PLA(0x0);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0x7BCD, "The accumulator should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -188,7 +188,7 @@ Test(PLA, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA();
+ snes.cpu->PLA(0x0);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0x0000, "The accumulator should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -202,7 +202,7 @@ Test(PLA, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA();
+ snes.cpu->PLA(0x0);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0xA000, "The accumulator should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -216,7 +216,7 @@ Test(PLX, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX();
+ snes.cpu->PLX(0x0);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x7BCD, "The X register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -230,7 +230,7 @@ Test(PLX, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX();
+ snes.cpu->PLX(0x0);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x0000, "The x register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -244,7 +244,7 @@ Test(PLX, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX();
+ snes.cpu->PLX(0x0);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0xA000, "The x register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -258,7 +258,7 @@ Test(PLY, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY();
+ snes.cpu->PLY(0x0);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0x7BCD, "The Y register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -272,7 +272,7 @@ Test(PLY, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY();
+ snes.cpu->PLY(0x0);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0x0000, "The y register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -286,7 +286,7 @@ Test(PLY, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY();
+ snes.cpu->PLY(0x0);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0xA000, "The y register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -300,7 +300,7 @@ Test(PLD, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD();
+ snes.cpu->PLD(0x0);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0x7BCD, "The D register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -314,7 +314,7 @@ Test(PLD, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD();
+ snes.cpu->PLD(0x0);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0x0000, "The d register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -328,7 +328,7 @@ Test(PLD, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD();
+ snes.cpu->PLD(0x0);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0xA000, "The D register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -341,7 +341,7 @@ Test(PLB, basic)
Init()
snes.wram->_data[1] = 0x7D;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB();
+ snes.cpu->PLB(0x0);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0x7D, "The DBR should be 0x7D but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -354,7 +354,7 @@ Test(PLB, zero)
Init()
snes.wram->_data[1] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB();
+ snes.cpu->PLB(0x0);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0x00, "The dbr should be 0x00 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -367,7 +367,7 @@ Test(PLB, negative)
Init()
snes.wram->_data[1] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB();
+ snes.cpu->PLB(0x0);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0xA0, "The D register should be 0xA0 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -381,7 +381,7 @@ Test(PLP, basic)
snes.wram->_data[1] = 0x7D;
snes.cpu->_registers.s = 0x00;
snes.cpu->_isEmulationMode = false;
- snes.cpu->PLP();
+ snes.cpu->PLP(0x0);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x7D, "The flags should be 0x7D but it was %x", data);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
@@ -393,7 +393,7 @@ Test(PLP, emulation)
snes.wram->_data[1] = 0x00;
snes.cpu->_registers.s = 0x00;
snes.cpu->_isEmulationMode = true;
- snes.cpu->PLP();
+ snes.cpu->PLP(0x0);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110000, "The flags should be 0b00110000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
@@ -403,7 +403,7 @@ Test(CLC, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLC();
+ snes.cpu->CLC(0x0);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
}
@@ -411,7 +411,7 @@ Test(CLI, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLI();
+ snes.cpu->CLI(0x0);
cr_assert_eq(snes.cpu->_registers.p.i, false, "The interrupt flag should not be set");
}
@@ -419,7 +419,7 @@ Test(CLD, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLD();
+ snes.cpu->CLD(0x0);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set");
}
@@ -427,7 +427,7 @@ Test(CLV, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLV();
+ snes.cpu->CLV(0x0);
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flag should not be set");
}
@@ -435,7 +435,7 @@ Test(SEC, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SEC();
+ snes.cpu->SEC(0x0);
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
}
@@ -443,7 +443,7 @@ Test(SEI, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SEI();
+ snes.cpu->SEI(0x0);
cr_assert_eq(snes.cpu->_registers.p.i, true, "The interrupt disabled flag should be set");
}
@@ -451,7 +451,7 @@ Test(SED, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SED();
+ snes.cpu->SED(0x0);
cr_assert_eq(snes.cpu->_registers.p.d, true, "The decimal flag should be set");
}
@@ -463,7 +463,7 @@ Test(XCE, enableEmulation)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.xh = 0xFF;
snes.cpu->_registers.yh = 0xFF;
- snes.cpu->XCE();
+ snes.cpu->XCE(0x0);
cr_assert_eq(snes.cpu->_isEmulationMode, true, "The e flag should be set");
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.m, false, "The memory width flag should be untouched (unset)");
@@ -479,7 +479,7 @@ Test(XCE, enableNative)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.xh = 0xFF;
snes.cpu->_registers.yh = 0xFF;
- snes.cpu->XCE();
+ snes.cpu->XCE(0x0);
cr_assert_eq(snes.cpu->_isEmulationMode, false, "The e flag should be not set");
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
cr_assert_eq(snes.cpu->_registers.p.m, true, "The memory width flag should be set");
@@ -495,7 +495,7 @@ Test(INX, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.x = 0xFF;
- snes.cpu->INX();
+ snes.cpu->INX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0x0100, "The x register should be equal to 0x0100 but it was 0x%x.", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -508,7 +508,7 @@ Test(INX, 8bits)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.x = 0xFF;
- snes.cpu->INX();
+ snes.cpu->INX(0x0);
cr_assert_eq(snes.cpu->_registers.x, 0x00, "The x register should be equal to 0x00 but it was 0x%x.", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -521,7 +521,7 @@ Test(INY, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.y = 0xFF;
- snes.cpu->INY();
+ snes.cpu->INY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0x0100, "The y register should be equal to 0x0100 but it was 0x%x.", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -534,7 +534,7 @@ Test(INY, 8bits)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.y = 0xFF;
- snes.cpu->INY();
+ snes.cpu->INY(0x0);
cr_assert_eq(snes.cpu->_registers.y, 0x00, "The y register should be equal to 0x00 but it was 0x%x.", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
diff --git a/tests/CPU/testInterupts.cpp b/tests/CPU/testInterupts.cpp
index 9d26dd2..659af73 100644
--- a/tests/CPU/testInterupts.cpp
+++ b/tests/CPU/testInterupts.cpp
@@ -18,7 +18,7 @@ Test(CPU_emulated, BRK)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->BRK();
+ snes.cpu->BRK(0x0);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x15, "The PBR should be 0x15 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -38,7 +38,7 @@ Test(CPU_native, BRK)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->BRK();
+ snes.cpu->BRK(0x0);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x0, "The PBR should be 0x0 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -59,7 +59,7 @@ Test(CPU_emulated, COP)
snes.cpu->_registers.p.flags = 0x0F;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->COP();
+ snes.cpu->COP(0x0);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x15, "The PBR should be 0x15 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -79,7 +79,7 @@ Test(CPU_native, COP)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->COP();
+ snes.cpu->COP(0x0);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x0, "The PBR should be 0x0 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
diff --git a/ui/cpu.ui b/ui/cpu.ui
index a3b46d0..280e858 100644
--- a/ui/cpu.ui
+++ b/ui/cpu.ui
@@ -23,7 +23,7 @@
-
-
+
1
From 04f51efddf7e437f5bd108e48d2ffa2aa07ea088 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 26 Mar 2020 15:29:34 +0100
Subject: [PATCH 03/17] Cleaning the debugger
---
sources/Debugger/CPUDebug.cpp | 25 ++++++++++++++++++-------
sources/Debugger/CPUDebug.hpp | 2 ++
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 34e091c..9455189 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -24,12 +24,12 @@ namespace ComSquare::Debugger
this->_window->setAttribute(Qt::WA_DeleteOnClose);
this->_ui.setupUi(this->_window);
-
- this->_ui.disasembly->setModel(&this->_model);
- this->_ui.disasembly->setShowGrid(false);
- this->_ui.disasembly->verticalHeader()->hide();
- this->_ui.disasembly->horizontalHeader()->hide();
- this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
+//
+// this->_ui.disasembly->setModel(&this->_model);
+// this->_ui.disasembly->setShowGrid(false);
+// this->_ui.disasembly->verticalHeader()->hide();
+// this->_ui.disasembly->horizontalHeader()->hide();
+// this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
@@ -213,7 +213,18 @@ namespace ComSquare::Debugger
std::string CPUDebug::_getInstructionString(uint24_t pc)
{
uint8_t opcode = this->_bus->read(pc++, true);
- return this->_instructions[opcode].name;
+
+ return this->_instructions[opcode].name + this->_getInstructionParameter(pc);
+ }
+
+ std::string CPUDebug::_getInstructionParameter(uint24_t pc)
+ {
+ Instruction instruction = this->_instructions[opcode];
+
+ switch (instruction.addressingMode) {
+ case ImmediateForA:
+ return this->_getImmediateAddrForA(pc);
+ }
}
int CPUDebug::RESB(uint24_t)
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 82a57a0..0e29686 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -57,6 +57,8 @@ namespace ComSquare::Debugger
unsigned _executeInstruction(uint8_t opcode) override;
//! @brief Get a printable string representing an instruction at the program counter given as parameter.
std::string _getInstructionString(uint24_t pc);
+ //! @brief Get the parameter of the instruction as an hexadecimal string.
+ std::string _getInstructionParameter(uint24_t pc);
//! @brief Get a printable string representing the flags.
std::string _getFlagsString();
//! @brief Update the register's panel (accumulator, stack pointer...)
From 80ebfa8064d70a403c4f6dcadfc2a162cfdbb63c Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 26 Mar 2020 22:19:16 +0100
Subject: [PATCH 04/17] Finishing the array of instruction, it now works well
---
sources/APU/APU.cpp | 1 +
sources/CPU/CPU.cpp | 2 +
sources/CPU/CPU.hpp | 6 +-
sources/CPU/Instruction.hpp | 5 ++
.../CPU/Instructions/InternalInstruction.cpp | 16 ++---
sources/Debugger/CPUDebug.cpp | 67 +++++++++++++------
sources/Debugger/CPUDebug.hpp | 20 +++++-
sources/SNES.cpp | 6 +-
tests/CPU/testInternal.cpp | 18 +++--
ui/cpu.ui | 2 +-
10 files changed, 101 insertions(+), 42 deletions(-)
diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp
index c2cacd9..550fc21 100644
--- a/sources/APU/APU.cpp
+++ b/sources/APU/APU.cpp
@@ -709,6 +709,7 @@ namespace ComSquare::APU
cycles -= this->_paddingCycles;
while (total < cycles && this->_state == Running)
total += this->_executeInstruction();
+ std::cout << "Done." << std::endl;
if (this->_state == Running)
this->_paddingCycles = total - cycles;
}
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 8791036..92f3474 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -303,6 +303,8 @@ namespace ComSquare::CPU
case AbsoluteIndirectIndexedByX:
valueAddr = this->_getAbsoluteIndirectIndexedByXAddr();
break;
+ default:
+ break;
}
return cycles + (this->*instruction.call)(valueAddr);
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index a14f2c0..8fab4cb 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -532,7 +532,7 @@ namespace ComSquare::CPU
{&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 97
{&CPU::BRK, 7, "tya #-#", AddressingMode::Implied, 2}, // 98
{&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByY, 3}, // 99
- {&CPU::BRK, 7, "txs #-#", AddressingMode::Implied, 2}, // 9A
+ {&CPU::TXS, 2, "txs", AddressingMode::Implied, 1}, // 9A
{&CPU::BRK, 7, "txy #-#", AddressingMode::Implied, 2}, // 9B
{&CPU::STZ, 4, "stz", AddressingMode::Absolute, 3}, // 9C
{&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByX, 3}, // 9D
@@ -546,9 +546,9 @@ namespace ComSquare::CPU
{&CPU::LDA, 3, "lda", AddressingMode::DirectPage, 2}, // A5
{&CPU::LDX, 3, "ldx", AddressingMode::DirectPage, 2}, // A6
{&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectLong, 2}, // A7
- {&CPU::BRK, 7, "tay #-#", AddressingMode::Implied, 2}, // A8
+ {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8
{&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9
- {&CPU::BRK, 7, "tax #-#", AddressingMode::Implied, 2}, // AA
+ {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA
{&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // AB
{&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC
{&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD
diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp
index 8efd762..c2057d4 100644
--- a/sources/CPU/Instruction.hpp
+++ b/sources/CPU/Instruction.hpp
@@ -57,6 +57,11 @@ namespace ComSquare::CPU
std::string name;
AddressingMode addressingMode;
int size;
+
+ Instruction() = default;
+ Instruction(const Instruction &) = default;
+ Instruction &operator=(const Instruction &) = default;
+ ~Instruction() = default;
};
}
#endif //COMSQUARE_INSTRUCTION_HPP
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index 921d2a9..c83b690 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -48,15 +48,15 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::SEP(uint24_t value)
+ int CPU::SEP(uint24_t valueAddr)
{
- this->_registers.p.flags |= value;
+ this->_registers.p.flags |= this->_bus->read(valueAddr);
return 0;
}
- int CPU::REP(uint24_t value)
+ int CPU::REP(uint24_t valueAddr)
{
- this->_registers.p.flags &= ~value;
+ this->_registers.p.flags &= ~this->_bus->read(valueAddr);
if (this->_isEmulationMode) {
this->_registers.p.x_b = true;
this->_registers.p.m = true;
@@ -64,19 +64,19 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::JSR(uint24_t value)
+ int CPU::JSR(uint24_t valueAddr)
{
this->_push(--this->_registers.pc);
- this->_registers.pc = value;
+ this->_registers.pc = valueAddr;
return 0;
}
- int CPU::JSL(uint24_t value)
+ int CPU::JSL(uint24_t valueAddr)
{
this->_registers.pac--;
this->_push(this->_registers.pbr);
this->_push(this->_registers.pc);
- this->_registers.pac = value;
+ this->_registers.pac = valueAddr;
return 0;
}
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 9455189..63424da 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -7,6 +7,7 @@
#include "../Exceptions/InvalidOpcode.hpp"
#include
#include
+#include
using namespace ComSquare::CPU;
@@ -24,12 +25,16 @@ namespace ComSquare::Debugger
this->_window->setAttribute(Qt::WA_DeleteOnClose);
this->_ui.setupUi(this->_window);
-//
-// this->_ui.disasembly->setModel(&this->_model);
-// this->_ui.disasembly->setShowGrid(false);
-// this->_ui.disasembly->verticalHeader()->hide();
-// this->_ui.disasembly->horizontalHeader()->hide();
-// this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
+
+ this->_ui.disasembly->setModel(&this->_model);
+ this->_ui.disasembly->setShowGrid(false);
+ this->_ui.disasembly->verticalHeader()->hide();
+ this->_ui.disasembly->horizontalHeader()->hide();
+ this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
+
+// uint24_t pc = 0x80800; // The first byte of the ROM //TODO make this work for other rom mapping.
+// while (pc < 0x80800 + this->_cartridgeHeader.romSize)
+// this->_disassembledInstructions.insert(pc, this->_parseInstruction(pc));
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
@@ -72,7 +77,7 @@ namespace ComSquare::Debugger
this->_isStepping = false;
this->_isPaused = true;
}
- this->_ui.logger->append((CPUDebug::_getInstructionString(this->_registers.pac - 1) + " - " + Utility::to_hex(opcode)).c_str());
+ this->_ui.logger->append((this->_parseInstruction(this->_registers.pac - 1).toString() + " - " + Utility::to_hex(opcode)).c_str());
unsigned ret = CPU::_executeInstruction(opcode);
this->_updateRegistersPanel();
return ret;
@@ -162,7 +167,7 @@ namespace ComSquare::Debugger
std::string CPUDebug::_getImmediateValue8Bits(uint24_t pc)
{
std::stringstream ss;
- ss << "#$" << std::hex << static_cast(this->_bus->read(pc), true);
+ ss << "#$" << std::hex << static_cast(this->_bus->read(pc, true));
return ss.str();
}
@@ -179,7 +184,7 @@ namespace ComSquare::Debugger
std::string CPUDebug::_getDirectValue(uint24_t pc)
{
std::stringstream ss;
- ss << "$" << std::hex << static_cast(this->_bus->read(pc), true);
+ ss << "$" << std::hex << static_cast(this->_bus->read(pc, true));
return ss.str();
}
@@ -210,20 +215,36 @@ namespace ComSquare::Debugger
return ss.str();
}
- std::string CPUDebug::_getInstructionString(uint24_t pc)
+ DisassembledInstruction CPUDebug::_parseInstruction(uint24_t pc)
{
- uint8_t opcode = this->_bus->read(pc++, true);
-
- return this->_instructions[opcode].name + this->_getInstructionParameter(pc);
+ uint24_t opcode = this->_bus->read(pc++, true);
+ Instruction instruction = this->_instructions[opcode];
+ std::string argument = this->_getInstructionParameter(instruction, pc);
+ return DisassembledInstruction(instruction, argument, opcode);
}
- std::string CPUDebug::_getInstructionParameter(uint24_t pc)
+ std::string CPUDebug::_getInstructionParameter(Instruction &instruction, uint24_t pc)
{
- Instruction instruction = this->_instructions[opcode];
-
switch (instruction.addressingMode) {
+ case Implied:
+ return "";
case ImmediateForA:
- return this->_getImmediateAddrForA(pc);
+ return this->_getImmediateValueForA(pc);
+ case ImmediateForX:
+ return this->_getImmediateValueForX(pc);
+ case Immediate8bits:
+ return this->_getImmediateValue8Bits(pc);
+ case Absolute:
+ return this->_getAbsoluteValue(pc);
+ case AbsoluteLong:
+ return this->_getAbsoluteLongValue(pc);
+ case DirectPage:
+ return this->_getDirectValue(pc);
+ case DirectPageIndexedByX:
+ return this->_getDirectIndexedByXValue(pc);
+
+ default:
+ return "???";
}
}
@@ -238,6 +259,14 @@ namespace ComSquare::Debugger
{
this->_window->activateWindow();
}
+
+ DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, std::string arg, uint8_t op)
+ : CPU::Instruction(instruction), argument(std::move(arg)), opcode(op) {}
+
+ std::string DisassembledInstruction::toString()
+ {
+ return this->name + " " + this->argument;
+ }
}
DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstractTableModel(), _cpu(cpu){ }
@@ -249,10 +278,10 @@ int DisassemblyModel::columnCount(const QModelIndex &) const
int DisassemblyModel::rowCount(const QModelIndex &) const
{
- return 0xFFFFFF;
+ return 5;
}
-QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
+QVariant DisassemblyModel::data(const QModelIndex &, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 0e29686..3137fa8 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -38,6 +38,18 @@ public:
namespace ComSquare::Debugger
{
+ struct DisassembledInstruction : public CPU::Instruction {
+ std::string argument;
+ uint8_t opcode;
+
+ DisassembledInstruction(const CPU::Instruction &instruction, std::string argument, uint8_t opcode);
+ DisassembledInstruction(const DisassembledInstruction &) = default;
+ DisassembledInstruction &operator=(const DisassembledInstruction &) = default;
+ ~DisassembledInstruction() = default;
+
+ std::string toString();
+ };
+
//! @brief A custom CPU with a window that show it's registers and the disassembly.
class CPUDebug : public CPU::CPU, public QObject {
private:
@@ -47,6 +59,8 @@ namespace ComSquare::Debugger
Ui::CPUView _ui;
//! @brief The disassembly viewer's model.
DisassemblyModel _model;
+ //! @brief The list of disassembled instructions to show on the debugger.
+ std::map _disassembledInstructions;
//! @brief If this is set to true, the execution of the CPU will be paused.
bool _isPaused = true;
//! @brief If this is set to true, the CPU will execute one instruction and pause itself.
@@ -55,10 +69,10 @@ namespace ComSquare::Debugger
SNES &_snes;
//! @brief Reimplement the basic instruction execution method to log instructions inside the logger view.
unsigned _executeInstruction(uint8_t opcode) override;
- //! @brief Get a printable string representing an instruction at the program counter given as parameter.
- std::string _getInstructionString(uint24_t pc);
+ //! @brief Parse the instruction at the program counter given to have human readable information.
+ DisassembledInstruction _parseInstruction(uint24_t pc);
//! @brief Get the parameter of the instruction as an hexadecimal string.
- std::string _getInstructionParameter(uint24_t pc);
+ std::string _getInstructionParameter(ComSquare::CPU::Instruction &instruction, uint24_t pc);
//! @brief Get a printable string representing the flags.
std::string _getFlagsString();
//! @brief Update the register's panel (accumulator, stack pointer...)
diff --git a/sources/SNES.cpp b/sources/SNES.cpp
index b6188fe..7274243 100644
--- a/sources/SNES.cpp
+++ b/sources/SNES.cpp
@@ -31,7 +31,7 @@ namespace ComSquare
{
unsigned cycleCount = this->cpu->update();
this->ppu->update(cycleCount);
- this->apu->update(cycleCount);
+// this->apu->update(cycleCount);
}
void SNES::enableCPUDebugging(bool pause)
@@ -40,11 +40,13 @@ namespace ComSquare
if (this->cpu->isDebugger()) {
auto cpuDebug = std::static_pointer_cast(this->cpu);
cpuDebug->focus();
- cpuDebug->pause();
+ if (pause)
+ cpuDebug->pause();
} else
this->cpu = std::make_shared(*this->cpu, *this);
#else
std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl;
+ (void)pause;
#endif
}
diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp
index fca58c3..42a3c40 100644
--- a/tests/CPU/testInternal.cpp
+++ b/tests/CPU/testInternal.cpp
@@ -15,7 +15,8 @@ using namespace ComSquare;
Test(SEP, setall)
{
Init()
- snes.cpu->SEP(0xFF);
+ snes.wram->_data[0] = 0xFF;
+ snes.cpu->SEP(0x00);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0xFF, "The flag should be 0xFF but it was %x", data);
}
@@ -24,7 +25,8 @@ Test(SEP, setsome)
{
Init()
snes.cpu->_registers.p.flags = 0b01000000;
- snes.cpu->SEP(0b10110101);
+ snes.wram->_data[0] = 0b10110101;
+ snes.cpu->SEP(0x0);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b11110101, "The flag should be 245 but it was %i", data);
}
@@ -33,7 +35,8 @@ Test(REP, resetall)
{
Init()
snes.cpu->_isEmulationMode = false;
- snes.cpu->REP(0xFF);
+ snes.wram->_data[0] = 0xFF;
+ snes.cpu->REP(0x00);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x00, "The flag should be 0x00 but it was %x", data);
}
@@ -43,7 +46,8 @@ Test(REP, resetsome)
Init()
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.flags = 0b01000000;
- snes.cpu->REP(0b01000000);
+ snes.wram->_data[0] = 0b01000000;
+ snes.cpu->REP(0x0);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x0, "The flag should be 0 but it was %x", data);
}
@@ -52,7 +56,8 @@ Test(REP, resetallEmulation)
{
Init()
snes.cpu->_isEmulationMode = true;
- snes.cpu->REP(0xFF);
+ snes.wram->_data[0] = 0xFF;
+ snes.cpu->REP(0x00);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110000, "The flag should be 0b00110000 but it was %x", data);
}
@@ -62,7 +67,8 @@ Test(REP, resetsomeEmulation)
Init()
snes.cpu->_isEmulationMode = true;
snes.cpu->_registers.p.flags = 0b01000101;
- snes.cpu->REP(0b01000001);
+ snes.wram->_data[0] = 0b01000001;
+ snes.cpu->REP(0x0);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110100, "The flag should be 0b00110100 but it was %x", data);
}
diff --git a/ui/cpu.ui b/ui/cpu.ui
index 280e858..e3b719f 100644
--- a/ui/cpu.ui
+++ b/ui/cpu.ui
@@ -141,7 +141,7 @@
Qt::RightToLeft
- false
+ true
From c9a40be3e2677efbc49ac8d8ed7c76f08e2de9ca Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 26 Mar 2020 23:54:10 +0100
Subject: [PATCH 05/17] Fixed a missunderstanding of the pbr use
---
sources/CPU/AddressingModes.cpp | 72 ++++++++++---------
sources/CPU/CPU.cpp | 13 +++-
sources/CPU/CPU.hpp | 2 +
.../CPU/Instructions/InternalInstruction.cpp | 20 +++---
sources/Debugger/CPUDebug.cpp | 38 +++++++---
sources/Debugger/CPUDebug.hpp | 10 +--
tests/CPU/testAddressingMode.cpp | 2 +-
7 files changed, 95 insertions(+), 62 deletions(-)
diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp
index 9b78aa2..0d39b18 100644
--- a/sources/CPU/AddressingModes.cpp
+++ b/sources/CPU/AddressingModes.cpp
@@ -9,50 +9,54 @@ namespace ComSquare::CPU
{
uint24_t CPU::_getImmediateAddr8Bits()
{
- return this->_registers.pac++;
+ uint24_t ret = this->_registers.pac;
+ this->_registers.pc++;
+ return ret;
}
uint24_t CPU::_getImmediateAddrForA()
{
- uint24_t effective = this->_registers.pac++;
+ uint24_t effective = this->_registers.pac;
+ this->_registers.pc++;
if (!this->_registers.p.m)
- this->_registers.pac++;
+ this->_registers.pc++;
return effective;
}
uint24_t CPU::_getImmediateAddrForX()
{
- uint24_t effective = this->_registers.pac++;
+ uint24_t effective = this->_registers.pac;
+ this->_registers.pc++;
if (!this->_registers.p.x_b)
- this->_registers.pac++;
+ this->_registers.pc++;
return effective;
}
uint24_t CPU::_getDirectAddr()
{
- uint8_t addr = this->_bus->read(this->_registers.pac++);
+ uint8_t addr = this->readPC();
return this->_registers.d + addr;
}
uint24_t CPU::_getAbsoluteAddr()
{
uint24_t addr = this->_registers.dbr << 16u;
- addr += this->_bus->read(this->_registers.pac++);
- addr += this->_bus->read(this->_registers.pac++) << 8u;
+ addr += this->readPC();
+ addr += this->readPC() << 8u;
return addr;
}
uint24_t CPU::_getAbsoluteLongAddr()
{
- uint24_t addr = this->_bus->read(this->_registers.pac++);
- addr += this->_bus->read(this->_registers.pac++) << 8u;
- addr += this->_bus->read(this->_registers.pac++) << 16u;
+ uint24_t addr = this->readPC();
+ addr += this->readPC() << 8u;
+ addr += this->readPC() << 16u;
return addr;
}
uint24_t CPU::_getDirectIndirectIndexedYAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
uint24_t base = this->_bus->read(dp);
base += this->_bus->read(dp + 1) << 8u;
base += this->_registers.dbr << 16u;
@@ -63,7 +67,7 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectIndexedYLongAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
uint24_t base = this->_bus->read(dp);
base += this->_bus->read(dp + 1) << 8u;
base += this->_bus->read(dp + 2) << 16u;
@@ -72,7 +76,7 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectIndexedXAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
dp += this->_registers.x;
uint24_t base = this->_bus->read(dp);
base += this->_bus->read(dp + 1) << 8u;
@@ -82,22 +86,22 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndexedByXAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
dp += this->_registers.x;
return dp;
}
uint24_t CPU::_getDirectIndexedByYAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
dp += this->_registers.y;
return dp;
}
uint24_t CPU::_getAbsoluteIndexedByXAddr()
{
- uint16_t abs = this->_bus->read(this->_registers.pac++);
- abs += this->_bus->read(this->_registers.pac++) << 8u;
+ uint16_t abs = this->readPC();
+ abs += this->readPC() << 8u;
uint24_t effective = abs + (this->_registers.dbr << 16u);
if ((effective & 0x80000000u) == (((effective + this->_registers.x) & 0x80000000u)))
this->_hasIndexCrossedPageBoundary = true;
@@ -106,8 +110,8 @@ namespace ComSquare::CPU
uint24_t CPU::_getAbsoluteIndexedByYAddr()
{
- uint16_t abs = this->_bus->read(this->_registers.pac++);
- abs += this->_bus->read(this->_registers.pac++) << 8u;
+ uint16_t abs = this->readPC();
+ abs += this->readPC() << 8u;
uint24_t effective = abs + (this->_registers.dbr << 16u);
if ((effective & 0x80000000u) == (((effective + this->_registers.y) & 0x80000000u)))
this->_hasIndexCrossedPageBoundary = true;
@@ -116,32 +120,32 @@ namespace ComSquare::CPU
uint24_t CPU::_getAbsoluteIndexedByXLongAddr()
{
- uint24_t lng = this->_bus->read(this->_registers.pac++);
- lng += this->_bus->read(this->_registers.pac++) << 8u;
- lng += this->_bus->read(this->_registers.pac++) << 16u;
+ uint24_t lng = this->readPC();
+ lng += this->readPC() << 8u;
+ lng += this->readPC() << 16u;
return lng + this->_registers.x;
}
uint24_t CPU::_getProgramCounterRelativeAddr()
{
uint24_t pc = this->_registers.pac;
- int8_t mod = this->_bus->read(this->_registers.pac++);
+ int8_t mod = this->readPC();
return pc + mod;
}
uint24_t CPU::_getProgramCounterRelativeLongAddr()
{
uint24_t pc = this->_registers.pac;
- uint8_t val1 = this->_bus->read(this->_registers.pac++);
- uint8_t val2 = this->_bus->read(this->_registers.pac++);
+ uint8_t val1 = this->readPC();
+ uint8_t val2 = this->readPC();
int16_t mod = val2 > 0x7F ? (static_cast(val2) * 256 - val1) : (val1 | val2 << 8u);
return pc + mod;
}
uint24_t CPU::_getAbsoluteIndirectAddr()
{
- uint16_t abs = this->_bus->read(this->_registers.pac++);
- abs += this->_bus->read(this->_registers.pac++) << 8u;
+ uint16_t abs = this->readPC();
+ abs += this->readPC() << 8u;
uint24_t effective = this->_bus->read(abs);
effective += this->_bus->read(abs + 1) << 8u;
return effective;
@@ -149,8 +153,8 @@ namespace ComSquare::CPU
uint24_t CPU::_getAbsoluteIndirectIndexedByXAddr()
{
- uint24_t abs = this->_bus->read(this->_registers.pac++);
- abs += this->_bus->read(this->_registers.pac++) << 8u;
+ uint24_t abs = this->readPC();
+ abs += this->readPC() << 8u;
abs += this->_registers.x;
uint24_t effective = this->_bus->read(abs);
effective += this->_bus->read(abs + 1) << 8u;
@@ -159,7 +163,7 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
uint24_t effective = this->_bus->read(dp);
effective += this->_bus->read(dp + 1) << 8u;
effective += this->_registers.dbr << 16u;
@@ -168,7 +172,7 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectLongAddr()
{
- uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
+ uint16_t dp = this->readPC() + this->_registers.d;
uint24_t effective = this->_bus->read(dp);
effective += this->_bus->read(++dp) << 8u;
effective += this->_bus->read(++dp) << 16u;
@@ -177,12 +181,12 @@ namespace ComSquare::CPU
uint24_t CPU::_getStackRelativeAddr()
{
- return this->_bus->read(this->_registers.pac++) + this->_registers.s;
+ return this->readPC() + this->_registers.s;
}
uint24_t CPU::_getStackRelativeIndirectIndexedYAddr()
{
- uint24_t base = this->_bus->read(this->_registers.pac++) + this->_registers.s;
+ uint24_t base = this->readPC() + this->_registers.s;
base += this->_registers.dbr << 16u;
return base + this->_registers.y;
}
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 92f3474..879ed39 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -195,12 +195,21 @@ namespace ComSquare::CPU
}
}
+ uint8_t CPU::readPC()
+ {
+ uint8_t ret = this->_bus->read(this->_registers.pac);
+ this->_registers.pc++;
+ return ret;
+ }
+
unsigned CPU::update()
{
unsigned cycles = 0;
- for (int i = 0; i < 0xFF; i++)
- cycles += this->_executeInstruction(this->_bus->read(this->_registers.pac++));
+ for (int i = 0; i < 0xFF; i++) {
+ cycles += this->_executeInstruction(this->readPC());
+ this->_registers.pc++;
+ }
return cycles;
}
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 8fab4cb..9c32d6c 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -253,6 +253,8 @@ namespace ComSquare::CPU
//! @brief Pop 16 bits of data from the stack.
uint16_t _pop16();
+ //! @brief Return the data at the program bank concatenated with the program counter. It also increment the program counter (the program bank is not incremented on overflows).
+ uint8_t readPC();
//! @brief Execute a single instruction.
//! @return The number of CPU cycles that the instruction took.
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index c83b690..77112ec 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -259,48 +259,48 @@ namespace ComSquare::CPU
int CPU::BCC(uint24_t valueAddr)
{
if (!this->_registers.p.c)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.c;
}
int CPU::BCS(uint24_t valueAddr)
{
if (this->_registers.p.c)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.c;
}
int CPU::BEQ(uint24_t valueAddr)
{
if (this->_registers.p.z)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.z;
}
int CPU::BNE(uint24_t valueAddr)
{
if (!this->_registers.p.z)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.z;
}
int CPU::BMI(uint24_t valueAddr)
{
if (this->_registers.p.n)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.n;
}
int CPU::BPL(uint24_t valueAddr)
{
if (!this->_registers.p.n)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.n;
}
int CPU::BRA(uint24_t valueAddr)
{
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return true;
}
@@ -309,21 +309,21 @@ namespace ComSquare::CPU
unsigned value = this->_bus->read(valueAddr);
value += this->_bus->read(valueAddr + 1) << 8u;
- this->_registers.pac += static_cast(value);
+ this->_registers.pc += static_cast(value);
return true;
}
int CPU::BVC(uint24_t valueAddr)
{
if (!this->_registers.p.v)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return !this->_registers.p.v;
}
int CPU::BVS(uint24_t valueAddr)
{
if (this->_registers.p.v)
- this->_registers.pac += static_cast(this->_bus->read(valueAddr));
+ this->_registers.pc += static_cast(this->_bus->read(valueAddr));
return this->_registers.p.v;
}
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 63424da..d362008 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -31,10 +31,7 @@ namespace ComSquare::Debugger
this->_ui.disasembly->verticalHeader()->hide();
this->_ui.disasembly->horizontalHeader()->hide();
this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
-
-// uint24_t pc = 0x80800; // The first byte of the ROM //TODO make this work for other rom mapping.
-// while (pc < 0x80800 + this->_cartridgeHeader.romSize)
-// this->_disassembledInstructions.insert(pc, this->_parseInstruction(pc));
+ this->disassembledInstructions = this->_disassemble(0x808000, this->_cartridgeHeader.romSize);
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
@@ -59,7 +56,7 @@ namespace ComSquare::Debugger
if (this->_isPaused)
return 0xFF;
if (this->_isStepping)
- return this->_executeInstruction(this->_bus->read(this->_registers.pac++));
+ return this->_executeInstruction(this->readPC());
return CPU::update();
} catch (InvalidOpcode &e) {
if (!this->_isPaused)
@@ -77,7 +74,8 @@ namespace ComSquare::Debugger
this->_isStepping = false;
this->_isPaused = true;
}
- this->_ui.logger->append((this->_parseInstruction(this->_registers.pac - 1).toString() + " - " + Utility::to_hex(opcode)).c_str());
+ uint24_t pc = (this->_registers.pbr << 16u) | (this->_registers.pc - 1u);
+ this->_ui.logger->append((this->_parseInstruction(pc).toString() + " - " + Utility::to_hex(opcode)).c_str());
unsigned ret = CPU::_executeInstruction(opcode);
this->_updateRegistersPanel();
return ret;
@@ -137,6 +135,19 @@ namespace ComSquare::Debugger
return str;
}
+ std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length)
+ {
+ std::vector map;
+ uint24_t endAddr = pc + length;
+
+ while (pc < endAddr) {
+ DisassembledInstruction instruction = this->_parseInstruction(pc);
+ map.push_back(instruction);
+ pc += instruction.size;
+ }
+ return map;
+ }
+
void CPUDebug::clearHistory()
{
this->_ui.logger->clear();
@@ -220,7 +231,7 @@ namespace ComSquare::Debugger
uint24_t opcode = this->_bus->read(pc++, true);
Instruction instruction = this->_instructions[opcode];
std::string argument = this->_getInstructionParameter(instruction, pc);
- return DisassembledInstruction(instruction, argument, opcode);
+ return DisassembledInstruction(instruction, pc, argument, opcode);
}
std::string CPUDebug::_getInstructionParameter(Instruction &instruction, uint24_t pc)
@@ -260,8 +271,8 @@ namespace ComSquare::Debugger
this->_window->activateWindow();
}
- DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, std::string arg, uint8_t op)
- : CPU::Instruction(instruction), argument(std::move(arg)), opcode(op) {}
+ DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, uint24_t addr, std::string arg, uint8_t op)
+ : CPU::Instruction(instruction), address(addr), argument(std::move(arg)), opcode(op) {}
std::string DisassembledInstruction::toString()
{
@@ -278,12 +289,17 @@ int DisassemblyModel::columnCount(const QModelIndex &) const
int DisassemblyModel::rowCount(const QModelIndex &) const
{
- return 5;
+ return this->_cpu.disassembledInstructions.size();
}
-QVariant DisassemblyModel::data(const QModelIndex &, int role) const
+QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
+ ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
+ switch (index.column()) {
+ case 0:
+ return QString(ComSquare::Utility::to_hex(instruction.address).c_str());
+ }
return QString();
}
\ No newline at end of file
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 3137fa8..b9474ad 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -39,10 +39,11 @@ public:
namespace ComSquare::Debugger
{
struct DisassembledInstruction : public CPU::Instruction {
+ uint24_t address;
std::string argument;
uint8_t opcode;
- DisassembledInstruction(const CPU::Instruction &instruction, std::string argument, uint8_t opcode);
+ DisassembledInstruction(const CPU::Instruction &instruction, uint24_t address, std::string argument, uint8_t opcode);
DisassembledInstruction(const DisassembledInstruction &) = default;
DisassembledInstruction &operator=(const DisassembledInstruction &) = default;
~DisassembledInstruction() = default;
@@ -59,8 +60,6 @@ namespace ComSquare::Debugger
Ui::CPUView _ui;
//! @brief The disassembly viewer's model.
DisassemblyModel _model;
- //! @brief The list of disassembled instructions to show on the debugger.
- std::map _disassembledInstructions;
//! @brief If this is set to true, the execution of the CPU will be paused.
bool _isPaused = true;
//! @brief If this is set to true, the CPU will execute one instruction and pause itself.
@@ -75,6 +74,8 @@ namespace ComSquare::Debugger
std::string _getInstructionParameter(ComSquare::CPU::Instruction &instruction, uint24_t pc);
//! @brief Get a printable string representing the flags.
std::string _getFlagsString();
+ //! @brief Disassemble part of the memory (using the bus) and parse it to a map of address and disassembled instruction.
+ std::vector _disassemble(uint24_t startAddr, uint24_t size);
//! @brief Update the register's panel (accumulator, stack pointer...)
void _updateRegistersPanel();
@@ -104,7 +105,8 @@ namespace ComSquare::Debugger
void clearHistory();
//! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU.
void disableDebugger();
- public:
+ //! @brief The list of disassembled instructions to show on the debugger.
+ std::vector disassembledInstructions;
//! @brief Update the UI when reseting the CPU.
int RESB(uint24_t) override;
//! @brief Convert a basic CPU to a debugging CPU.
diff --git a/tests/CPU/testAddressingMode.cpp b/tests/CPU/testAddressingMode.cpp
index 0ae047f..485366e 100644
--- a/tests/CPU/testAddressingMode.cpp
+++ b/tests/CPU/testAddressingMode.cpp
@@ -42,7 +42,7 @@ Test(AddrMode, ImmediateBankChange)
snes.cpu->_registers.pac = 0x00FFFF;
snes.cpu->_registers.p.m = true;
cr_assert_eq(snes.cpu->_getImmediateAddrForA(), 0x00FFFF);
- cr_assert_eq(snes.cpu->_registers.pac, 0x010000);
+ cr_assert_eq(snes.cpu->_registers.pac, 0x000000);
}
Test(AddrMode, Direct)
From da637ed3e40fbc6ae14a1634697685437d8f313f Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Fri, 27 Mar 2020 00:02:32 +0100
Subject: [PATCH 06/17] Implementing a basic dissasembly, emulation of the x
and m flags are not present yet
---
sources/CPU/CPU.hpp | 2 +-
sources/Debugger/CPUDebug.cpp | 13 +++++++++----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 9c32d6c..679b8b3 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -574,7 +574,7 @@ namespace ComSquare::CPU
{&CPU::LDA, 5, "lda", AddressingMode::AbsoluteIndexedByXLong, 4}, // BF
{&CPU::BRK, 7, "cpy #-#", AddressingMode::Implied, 2}, // C0
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C1
- {&CPU::REP, 3, "rep", AddressingMode::Immediate8bits, 3}, // C2
+ {&CPU::REP, 3, "rep", AddressingMode::Immediate8bits, 2}, // C2
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C3
{&CPU::BRK, 7, "cpy #-#", AddressingMode::Implied, 2}, // C4
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C5
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index d362008..a642956 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -26,12 +26,12 @@ namespace ComSquare::Debugger
this->_ui.setupUi(this->_window);
+ this->disassembledInstructions = this->_disassemble(0x808000, 0x7FFF);
this->_ui.disasembly->setModel(&this->_model);
this->_ui.disasembly->setShowGrid(false);
this->_ui.disasembly->verticalHeader()->hide();
this->_ui.disasembly->horizontalHeader()->hide();
this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
- this->disassembledInstructions = this->_disassemble(0x808000, this->_cartridgeHeader.romSize);
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
@@ -228,9 +228,9 @@ namespace ComSquare::Debugger
DisassembledInstruction CPUDebug::_parseInstruction(uint24_t pc)
{
- uint24_t opcode = this->_bus->read(pc++, true);
+ uint24_t opcode = this->_bus->read(pc, true);
Instruction instruction = this->_instructions[opcode];
- std::string argument = this->_getInstructionParameter(instruction, pc);
+ std::string argument = this->_getInstructionParameter(instruction, pc + 1);
return DisassembledInstruction(instruction, pc, argument, opcode);
}
@@ -300,6 +300,11 @@ QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
switch (index.column()) {
case 0:
return QString(ComSquare::Utility::to_hex(instruction.address).c_str());
+ case 1:
+ return QString(instruction.name.c_str());
+ case 2:
+ return QString(instruction.argument.c_str());
+ default:
+ return QVariant();
}
- return QString();
}
\ No newline at end of file
From 2a8736eb6fc5d2b43a8050fe9f303d287c53061a Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Fri, 27 Mar 2020 01:29:04 +0100
Subject: [PATCH 07/17] Implementing a dissasembly context to keep track of
flags durring the disassembly
---
sources/Debugger/CPUDebug.cpp | 155 +++++++++++++++++++---------------
sources/Debugger/CPUDebug.hpp | 36 +++++---
2 files changed, 112 insertions(+), 79 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index a642956..50a7d01 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -5,6 +5,7 @@
#include "CPUDebug.hpp"
#include "../Utility/Utility.hpp"
#include "../Exceptions/InvalidOpcode.hpp"
+#include "../CPU/CPU.hpp"
#include
#include
#include
@@ -75,7 +76,9 @@ namespace ComSquare::Debugger
this->_isPaused = true;
}
uint24_t pc = (this->_registers.pbr << 16u) | (this->_registers.pc - 1u);
- this->_ui.logger->append((this->_parseInstruction(pc).toString() + " - " + Utility::to_hex(opcode)).c_str());
+ DisassemblyContext ctx = {this->_registers.p.m, this->_registers.p.x_b};
+ DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
+ this->_ui.logger->append((instruction.toString() + " - " + Utility::to_hex(opcode)).c_str());
unsigned ret = CPU::_executeInstruction(opcode);
this->_updateRegistersPanel();
return ret;
@@ -135,53 +138,104 @@ namespace ComSquare::Debugger
return str;
}
- std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length)
- {
- std::vector map;
- uint24_t endAddr = pc + length;
-
- while (pc < endAddr) {
- DisassembledInstruction instruction = this->_parseInstruction(pc);
- map.push_back(instruction);
- pc += instruction.size;
- }
- return map;
- }
-
void CPUDebug::clearHistory()
{
this->_ui.logger->clear();
}
- std::string CPUDebug::_getImmediateValueForA(uint24_t pc)
+ std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length)
+ {
+ std::vector map;
+ uint24_t endAddr = pc + length;
+ DisassemblyContext ctx;
+
+ while (pc < endAddr) {
+ DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
+ map.push_back(instruction);
+ pc += instruction.size;
+ if (instruction.addressingMode == ImmediateForA && !ctx.mFlag)
+ pc++;
+ if (instruction.addressingMode == ImmediateForX && !ctx.xFlag)
+ pc++;
+
+ if (instruction.opcode == 0x40 && ctx.isEmulationMode) { // RTI
+ ctx.mFlag = true;
+ ctx.xFlag = true;
+ }
+ if (instruction.opcode == 0xC2) { // REP
+ if (ctx.isEmulationMode) {
+ ctx.mFlag = true;
+ ctx.xFlag = true;
+ } else {
+ uint8_t m = this->_bus->read(pc - 1);
+ ctx.mFlag &= ~m & 0b00100000u;
+ ctx.xFlag &= ~m & 0b00010000u;
+ }
+ }
+ if (instruction.opcode == 0xE2) { // SEP
+ uint8_t m = this->_bus->read(pc - 1);
+ ctx.mFlag |= m & 0b00100000u;
+ ctx.xFlag |= m & 0b00010000u;
+ }
+ if (instruction.opcode == 0x28) { // PLP
+ if (ctx.isEmulationMode) {
+ ctx.mFlag = true;
+ ctx.xFlag = true;
+ } else
+ ctx.compromised = true;
+ }
+ if (instruction.opcode == 0xFB) {// XCE
+ ctx.compromised = true;
+ ctx.isEmulationMode = false; // The most common use of the XCE is to enable native mode at the start of the ROM so we guess that it has done that.
+ }
+ }
+ return map;
+ }
+
+ DisassembledInstruction CPUDebug::_parseInstruction(uint24_t pc, DisassemblyContext &ctx)
+ {
+ uint24_t opcode = this->_bus->read(pc, true);
+ Instruction instruction = this->_instructions[opcode];
+ std::string argument = this->_getInstructionParameter(instruction, pc + 1, ctx);
+ return DisassembledInstruction(instruction, pc, argument, opcode);
+ }
+
+ std::string CPUDebug::_getInstructionParameter(Instruction &instruction, uint24_t pc, DisassemblyContext &ctx)
+ {
+ switch (instruction.addressingMode) {
+ case Implied:
+ return "";
+ case ImmediateForA:
+ return this->_getImmediateValue(pc, !ctx.mFlag);
+ case ImmediateForX:
+ return this->_getImmediateValue(pc, !ctx.xFlag);
+ case Immediate8bits:
+ return this->_getImmediateValue(pc, false);
+ case Absolute:
+ return this->_getAbsoluteValue(pc);
+ case AbsoluteLong:
+ return this->_getAbsoluteLongValue(pc);
+ case DirectPage:
+ return this->_getDirectValue(pc);
+ case DirectPageIndexedByX:
+ return this->_getDirectIndexedByXValue(pc);
+
+ default:
+ return "???";
+ }
+ }
+
+ std::string CPUDebug::_getImmediateValue(uint24_t pc, bool dual)
{
unsigned value = this->_bus->read(pc, true);
- if (!this->_registers.p.m)
+ if (dual)
value += this->_bus->read(pc + 1, true) << 8u;
std::stringstream ss;
ss << "#$" << std::hex << value;
return ss.str();
}
- std::string CPUDebug::_getImmediateValueForX(uint24_t pc)
- {
- unsigned value = this->_bus->read(pc, true);
-
- if (!this->_registers.p.x_b)
- value += this->_bus->read(pc + 1, true) << 8u;
- std::stringstream ss;
- ss << "#$" << std::hex << value;
- return ss.str();
- }
-
- std::string CPUDebug::_getImmediateValue8Bits(uint24_t pc)
- {
- std::stringstream ss;
- ss << "#$" << std::hex << static_cast(this->_bus->read(pc, true));
- return ss.str();
- }
-
std::string CPUDebug::_getImmediateValue16Bits(uint24_t pc)
{
unsigned value = this->_bus->read(pc, true);
@@ -226,39 +280,6 @@ namespace ComSquare::Debugger
return ss.str();
}
- DisassembledInstruction CPUDebug::_parseInstruction(uint24_t pc)
- {
- uint24_t opcode = this->_bus->read(pc, true);
- Instruction instruction = this->_instructions[opcode];
- std::string argument = this->_getInstructionParameter(instruction, pc + 1);
- return DisassembledInstruction(instruction, pc, argument, opcode);
- }
-
- std::string CPUDebug::_getInstructionParameter(Instruction &instruction, uint24_t pc)
- {
- switch (instruction.addressingMode) {
- case Implied:
- return "";
- case ImmediateForA:
- return this->_getImmediateValueForA(pc);
- case ImmediateForX:
- return this->_getImmediateValueForX(pc);
- case Immediate8bits:
- return this->_getImmediateValue8Bits(pc);
- case Absolute:
- return this->_getAbsoluteValue(pc);
- case AbsoluteLong:
- return this->_getAbsoluteLongValue(pc);
- case DirectPage:
- return this->_getDirectValue(pc);
- case DirectPageIndexedByX:
- return this->_getDirectIndexedByXValue(pc);
-
- default:
- return "???";
- }
- }
-
int CPUDebug::RESB(uint24_t)
{
CPU::RESB();
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index b9474ad..d6f05c3 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -38,6 +38,21 @@ public:
namespace ComSquare::Debugger
{
+ //! @brief Struct used to emulate the state of the processor during the disassembly since instructions take a different amount of space depending on some flags.
+ struct DisassemblyContext {
+ //! @brief The accumulator and Memory width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode.
+ //! @info If this flag is set to false, instructions that have the ImmediateByA addressing mode take 1 more bit of space.
+ bool mFlag = true;
+ //! @brief The indeX register width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode OR the Break flag (in emulation mode only)
+ //! @info If this flag is set to false, instructions that have the ImmediateByX addressing mode take 1 more bit of space.
+ bool xFlag = true;
+ //! @brief Is the CPU emulating a 6502? If yes, some instructions don't change flags the same way.
+ bool isEmulationMode = true;
+ //! @brief Sometimes, the flags can't be tracked correctly after an instruction so the next instructions may not be correctly disassembled.
+ bool compromised = false;
+ };
+
+ //! @brief Struct representing an instruction in an human readable way (created by disassembling the rom).
struct DisassembledInstruction : public CPU::Instruction {
uint24_t address;
std::string argument;
@@ -68,23 +83,20 @@ namespace ComSquare::Debugger
SNES &_snes;
//! @brief Reimplement the basic instruction execution method to log instructions inside the logger view.
unsigned _executeInstruction(uint8_t opcode) override;
- //! @brief Parse the instruction at the program counter given to have human readable information.
- DisassembledInstruction _parseInstruction(uint24_t pc);
- //! @brief Get the parameter of the instruction as an hexadecimal string.
- std::string _getInstructionParameter(ComSquare::CPU::Instruction &instruction, uint24_t pc);
- //! @brief Get a printable string representing the flags.
- std::string _getFlagsString();
//! @brief Disassemble part of the memory (using the bus) and parse it to a map of address and disassembled instruction.
std::vector _disassemble(uint24_t startAddr, uint24_t size);
+ //! @brief Parse the instruction at the program counter given to have human readable information.
+ DisassembledInstruction _parseInstruction(uint24_t pc, DisassemblyContext &ctx);
+ //! @brief Get the parameter of the instruction as an hexadecimal string.
+ std::string _getInstructionParameter(ComSquare::CPU::Instruction &instruction, uint24_t pc, DisassemblyContext &ctx);
+ //! @brief Get a printable string representing the flags.
+ std::string _getFlagsString();
//! @brief Update the register's panel (accumulator, stack pointer...)
void _updateRegistersPanel();
- //! @brief Return a printable string corresponding to the value of an immediate addressing mode for a.
- std::string _getImmediateValueForA(uint24_t pc);
- //! @brief Return a printable string corresponding to the value of an immediate addressing mode for x.
- std::string _getImmediateValueForX(uint24_t pc);
- //! @brief Return a printable string corresponding to the value of a 8bits immediate addressing mode (used only with SEP and REP).
- std::string _getImmediateValue8Bits(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a 8 or 16 bits immediate addressing mode.
+ //! @param dual Set this to true if the instruction take 16bits and not 8. (used for the immediate by a when the flag m is not set or the immediate by x if the flag x is not set).
+ std::string _getImmediateValue(uint24_t pc, bool dual);
//! @brief Return a printable string corresponding to the value of a 16bits immediate addressing mode.
std::string _getImmediateValue16Bits(uint24_t pc);
//! @brief Return a printable string corresponding to the value of a direct addressing mode.
From 686e88d7eaf8e944c174b37bc2448c4c34ef40be Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Fri, 27 Mar 2020 01:34:26 +0100
Subject: [PATCH 08/17] Solving a bug with the pc
---
sources/CPU/CPU.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 879ed39..9425cc4 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -206,10 +206,8 @@ namespace ComSquare::CPU
{
unsigned cycles = 0;
- for (int i = 0; i < 0xFF; i++) {
+ for (int i = 0; i < 0xFF; i++)
cycles += this->_executeInstruction(this->readPC());
- this->_registers.pc++;
- }
return cycles;
}
From 0119a5856b33147256889df60092ef817e232826 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 00:54:11 +0100
Subject: [PATCH 09/17] Showing the current PC in the disassembly view
---
CMakeLists.txt | 4 +-
sources/Debugger/CPUDebug.cpp | 75 ++++++++++++++++++++++++-----------
sources/Debugger/CPUDebug.hpp | 23 ++++++++++-
sources/Utility/Utility.cpp | 37 +++++++++++------
sources/Utility/Utility.hpp | 12 ++++--
ui/cpu.ui | 23 ++++++++++-
6 files changed, 133 insertions(+), 41 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6533542..41f0df3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -93,7 +93,9 @@ add_executable(unit_tests
tests/CPU/TransferRegisters.cpp
sources/CPU/AddressingModes.cpp
sources/Models/Components.hpp
- sources/CPU/Instruction.hpp sources/Exceptions/DebuggableError.hpp)
+ sources/CPU/Instruction.hpp
+ sources/Exceptions/DebuggableError.hpp
+)
# include criterion & coverage
target_link_libraries(unit_tests criterion -lgcov)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 50a7d01..1c48db8 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -7,6 +7,7 @@
#include "../Exceptions/InvalidOpcode.hpp"
#include "../CPU/CPU.hpp"
#include
+#include
#include
#include
@@ -19,6 +20,7 @@ namespace ComSquare::Debugger
_window(new ClosableWindow(*this, &CPUDebug::disableDebugger)),
_ui(),
_model(*this),
+ _painter(*this),
_snes(snes)
{
this->_window->setContextMenuPolicy(Qt::NoContextMenu);
@@ -27,12 +29,12 @@ namespace ComSquare::Debugger
this->_ui.setupUi(this->_window);
- this->disassembledInstructions = this->_disassemble(0x808000, 0x7FFF);
- this->_ui.disasembly->setModel(&this->_model);
- this->_ui.disasembly->setShowGrid(false);
- this->_ui.disasembly->verticalHeader()->hide();
- this->_ui.disasembly->horizontalHeader()->hide();
- this->_ui.disasembly->horizontalHeader()->setStretchLastSection(true);
+ this->disassembledInstructions = this->_disassemble(this->_registers.pac, 0x7FFF);
+ this->_ui.disassembly->setModel(&this->_model);
+ this->_ui.disassembly->horizontalHeader()->setStretchLastSection(true);
+ this->_ui.disassembly->resizeColumnsToContents();
+ this->_ui.disassembly->verticalHeader()->setSectionResizeMode (QHeaderView::Fixed);
+ this->_ui.disassembly->setItemDelegate(&this->_painter);
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
@@ -56,8 +58,11 @@ namespace ComSquare::Debugger
try {
if (this->_isPaused)
return 0xFF;
- if (this->_isStepping)
- return this->_executeInstruction(this->readPC());
+ if (this->_isStepping) {
+ unsigned ret = this->_executeInstruction(this->readPC());
+ this->_ui.disassembly->viewport()->repaint();
+ return ret;
+ }
return CPU::update();
} catch (InvalidOpcode &e) {
if (!this->_isPaused)
@@ -91,6 +96,10 @@ namespace ComSquare::Debugger
this->_ui.actionPause->setText("Resume");
else
this->_ui.actionPause->setText("Pause");
+ // TODO reload the disassembly from this point to update items that may be false up to this point
+ // TODO highlight the current line.
+ //this->disassembledInstructions. //= this->_disassemble(0x808000, 0x7FFF);
+ this->_ui.disassembly->viewport()->repaint();
}
void CPUDebug::step()
@@ -236,16 +245,6 @@ namespace ComSquare::Debugger
return ss.str();
}
- std::string CPUDebug::_getImmediateValue16Bits(uint24_t pc)
- {
- unsigned value = this->_bus->read(pc, true);
- value += this->_bus->read(pc + 1, true) << 8u;
-
- std::stringstream ss;
- ss << "#$" << std::hex << value;
- return ss.str();
- }
-
std::string CPUDebug::_getDirectValue(uint24_t pc)
{
std::stringstream ss;
@@ -292,6 +291,11 @@ namespace ComSquare::Debugger
this->_window->activateWindow();
}
+ uint24_t CPUDebug::getPC()
+ {
+ return this->_registers.pac;
+ }
+
DisassembledInstruction::DisassembledInstruction(const CPU::Instruction &instruction, uint24_t addr, std::string arg, uint8_t op)
: CPU::Instruction(instruction), address(addr), argument(std::move(arg)), opcode(op) {}
@@ -305,7 +309,7 @@ DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstra
int DisassemblyModel::columnCount(const QModelIndex &) const
{
- return 4;
+ return 3;
}
int DisassemblyModel::rowCount(const QModelIndex &) const
@@ -320,12 +324,37 @@ QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
switch (index.column()) {
case 0:
- return QString(ComSquare::Utility::to_hex(instruction.address).c_str());
- case 1:
return QString(instruction.name.c_str());
- case 2:
+ case 1:
return QString(instruction.argument.c_str());
default:
return QVariant();
}
-}
\ No newline at end of file
+}
+
+QVariant DisassemblyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal)
+ return QVariant();
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[section];
+ return QString(ComSquare::Utility::to_hex(instruction.address, ComSquare::Utility::HexString::NoPrefix).c_str());
+}
+
+RowPainter::RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent) : QStyledItemDelegate(parent), _cpu(cpu) { }
+
+void RowPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
+
+ if (instruction.address == this->_cpu.getPC())
+ painter->fillRect(option.rect,QColor(Qt::darkGreen));
+ // TODO display breakpoints with the Qt::darkRed color.
+ QStyledItemDelegate::paint(painter, option, index);
+}
+
+QSize RowPainter::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
+{
+ return QSize();
+}
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index d6f05c3..014680a 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -5,6 +5,7 @@
#ifndef COMSQUARE_CPUDEBUG_HPP
#define COMSQUARE_CPUDEBUG_HPP
+#include
#include "../CPU/CPU.hpp"
#include "../Renderer/SFRenderer.hpp"
#include "../SNES.hpp"
@@ -34,6 +35,22 @@ public:
int columnCount(const QModelIndex &parent) const override;
//! @brief Return a data representing the table cell.
QVariant data(const QModelIndex &index, int role) const override;
+ //! @brief Override the headers to use hex values.
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+};
+
+//! @brief The qt class that highlight breakpoints and the PC's position
+class RowPainter : public QStyledItemDelegate {
+ Q_OBJECT
+private:
+ ComSquare::Debugger::CPUDebug &_cpu;
+public:
+ explicit RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent = nullptr);
+ RowPainter &operator=(const RowPainter &) = delete;
+ ~RowPainter() override = default;
+protected:
+ QSize sizeHint(const QStyleOptionViewItem &options, const QModelIndex &index) const override;
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
namespace ComSquare::Debugger
@@ -75,6 +92,8 @@ namespace ComSquare::Debugger
Ui::CPUView _ui;
//! @brief The disassembly viewer's model.
DisassemblyModel _model;
+ //! @brief A custom painter that highlight breakpoints and the PC's position.
+ RowPainter _painter;
//! @brief If this is set to true, the execution of the CPU will be paused.
bool _isPaused = true;
//! @brief If this is set to true, the CPU will execute one instruction and pause itself.
@@ -119,7 +138,9 @@ namespace ComSquare::Debugger
void disableDebugger();
//! @brief The list of disassembled instructions to show on the debugger.
std::vector disassembledInstructions;
- //! @brief Update the UI when reseting the CPU.
+ //! @brief Return the current program counter of this CPU.
+ uint24_t getPC();
+ //! @brief Update the UI when resetting the CPU.
int RESB(uint24_t) override;
//! @brief Convert a basic CPU to a debugging CPU.
explicit CPUDebug(ComSquare::CPU::CPU &cpu, SNES &snes);
diff --git a/sources/Utility/Utility.cpp b/sources/Utility/Utility.cpp
index c66efbc..66500b7 100644
--- a/sources/Utility/Utility.cpp
+++ b/sources/Utility/Utility.cpp
@@ -3,29 +3,42 @@
//
#include
+#include
#include "Utility.hpp"
namespace ComSquare::Utility
{
- std::string to_hex(uint8_t i)
+ std::string to_hex(uint8_t i, HexString prefix)
{
- char buf[5];
- sprintf(buf, "0x%02X", i);
- return buf;
+ std::stringstream ss;
+ if (prefix == AsmPrefix)
+ ss << "$";
+ else if (prefix == StandardPrefix)
+ ss << "0x";
+ ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(i);
+ return ss.str();
}
- std::string to_hex(uint16_t i)
+ std::string to_hex(uint16_t i, HexString prefix)
{
- char buf[7];
- sprintf(buf, "0x%04X", i);
- return buf;
+ std::stringstream ss;
+ if (prefix == AsmPrefix)
+ ss << "$";
+ else if (prefix == StandardPrefix)
+ ss << "0x";
+ ss << std::hex << std::setfill('0') << std::setw(4) << i;
+ return ss.str();
}
- std::string to_hex(uint24_t i)
+ std::string to_hex(uint24_t i, HexString prefix)
{
- char buf[9];
- sprintf(buf, "0x%06X", i);
- return buf;
+ std::stringstream ss;
+ if (prefix == AsmPrefix)
+ ss << "$";
+ else if (prefix == StandardPrefix)
+ ss << "0x";
+ ss << std::hex << std::setfill('0') << std::setw(6) << i;
+ return ss.str();
}
std::string to_binary(uint8_t i)
diff --git a/sources/Utility/Utility.hpp b/sources/Utility/Utility.hpp
index 2fbc8bb..489afc3 100644
--- a/sources/Utility/Utility.hpp
+++ b/sources/Utility/Utility.hpp
@@ -12,11 +12,17 @@
namespace ComSquare::Utility
{
- std::string to_hex(uint8_t i);
+ enum HexString {
+ NoPrefix,
+ AsmPrefix,
+ StandardPrefix
+ };
- std::string to_hex(uint16_t i);
+ std::string to_hex(uint8_t i, HexString prefix = StandardPrefix);
- std::string to_hex(uint24_t i);
+ std::string to_hex(uint16_t i, HexString prefix = StandardPrefix);
+
+ std::string to_hex(uint24_t i, HexString prefix = StandardPrefix);
std::string to_binary(uint8_t i);
diff --git a/ui/cpu.ui b/ui/cpu.ui
index e3b719f..eada993 100644
--- a/ui/cpu.ui
+++ b/ui/cpu.ui
@@ -23,13 +23,34 @@
-
-
+
1
0
+
+
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+ QAbstractItemView::SelectRows
+
+
+ false
+
+
+ Qt::NoPen
+
+
+ false
+
+
+ false
+
-
From 8102a49f87ecee9908ee0c7c0a9dfea83f757dc2 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 15:29:40 +0100
Subject: [PATCH 10/17] Finishing lazy disassembly updating and adding an auto
scroll to the row
---
sources/Debugger/CPUDebug.cpp | 41 +++++++++++++++++++++++++++--------
sources/Debugger/CPUDebug.hpp | 10 ++++++---
2 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 1c48db8..3c180c8 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -29,7 +29,7 @@ namespace ComSquare::Debugger
this->_ui.setupUi(this->_window);
- this->disassembledInstructions = this->_disassemble(this->_registers.pac, 0x7FFF);
+ this->_updateDisassembly(0xFFFF - this->_registers.pc); //Parse the first page of the ROM (the code can't reach the second page without a jump).
this->_ui.disassembly->setModel(&this->_model);
this->_ui.disassembly->horizontalHeader()->setStretchLastSection(true);
this->_ui.disassembly->resizeColumnsToContents();
@@ -60,7 +60,7 @@ namespace ComSquare::Debugger
return 0xFF;
if (this->_isStepping) {
unsigned ret = this->_executeInstruction(this->readPC());
- this->_ui.disassembly->viewport()->repaint();
+ this->_updateDisassembly();
return ret;
}
return CPU::update();
@@ -81,7 +81,7 @@ namespace ComSquare::Debugger
this->_isPaused = true;
}
uint24_t pc = (this->_registers.pbr << 16u) | (this->_registers.pc - 1u);
- DisassemblyContext ctx = {this->_registers.p.m, this->_registers.p.x_b};
+ DisassemblyContext ctx = this->_getDisassemblyContext();
DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
this->_ui.logger->append((instruction.toString() + " - " + Utility::to_hex(opcode)).c_str());
unsigned ret = CPU::_executeInstruction(opcode);
@@ -96,10 +96,7 @@ namespace ComSquare::Debugger
this->_ui.actionPause->setText("Resume");
else
this->_ui.actionPause->setText("Pause");
- // TODO reload the disassembly from this point to update items that may be false up to this point
- // TODO highlight the current line.
- //this->disassembledInstructions. //= this->_disassemble(0x808000, 0x7FFF);
- this->_ui.disassembly->viewport()->repaint();
+ this->_updateDisassembly();
}
void CPUDebug::step()
@@ -152,11 +149,37 @@ namespace ComSquare::Debugger
this->_ui.logger->clear();
}
- std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length)
+ void CPUDebug::_updateDisassembly(uint24_t refreshSize)
+ {
+ auto first = std::find_if(this->disassembledInstructions.begin(), this->disassembledInstructions.end(), [this](DisassembledInstruction &i) {
+ return i.address >= this->_registers.pac;
+ });
+ auto end = std::find_if(this->disassembledInstructions.begin(), this->disassembledInstructions.end(),[this, refreshSize](DisassembledInstruction &i) {
+ return i.address >= this->_registers.pac + refreshSize;
+ });
+ this->disassembledInstructions.erase(first, end);
+
+ auto next = std::find_if(this->disassembledInstructions.begin(), this->disassembledInstructions.end(), [this](DisassembledInstruction &i) {
+ return i.address >= this->_registers.pac;
+ });
+ int row = next - this->disassembledInstructions.begin();
+ DisassemblyContext ctx = this->_getDisassemblyContext();
+ std::vector nextInstructions = this->_disassemble(this->_registers.pac, refreshSize, ctx);
+ this->disassembledInstructions.insert(next, nextInstructions.begin(), nextInstructions.end());
+ if (this->_ui.disassembly->rowAt(0) > row || this->_ui.disassembly->rowAt(this->_ui.disassembly->height()) < row)
+ this->_ui.disassembly->scrollTo(this->_model.index(row, 0), QAbstractItemView::PositionAtCenter);
+ this->_ui.disassembly->viewport()->repaint();
+ }
+
+ DisassemblyContext CPUDebug::_getDisassemblyContext()
+ {
+ return {this->_registers.p.m, this->_registers.p.x_b, false};
+ }
+
+ std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length, DisassemblyContext &ctx)
{
std::vector map;
uint24_t endAddr = pc + length;
- DisassemblyContext ctx;
while (pc < endAddr) {
DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 014680a..4839ee7 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -43,6 +43,7 @@ public:
class RowPainter : public QStyledItemDelegate {
Q_OBJECT
private:
+ //! @brief The CPU to get PC and breakpoints from.
ComSquare::Debugger::CPUDebug &_cpu;
public:
explicit RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent = nullptr);
@@ -102,8 +103,13 @@ namespace ComSquare::Debugger
SNES &_snes;
//! @brief Reimplement the basic instruction execution method to log instructions inside the logger view.
unsigned _executeInstruction(uint8_t opcode) override;
+ //! @brief Return a disassembly context representing the current state of the processor.
+ DisassemblyContext _getDisassemblyContext();
//! @brief Disassemble part of the memory (using the bus) and parse it to a map of address and disassembled instruction.
- std::vector _disassemble(uint24_t startAddr, uint24_t size);
+ //! @param ctx The initial context of the processor before the disassembly begin.
+ std::vector _disassemble(uint24_t startAddr, uint24_t size, DisassemblyContext &ctx);
+ //! @brief Update disassembly with the new state of the processor.
+ void _updateDisassembly(uint24_t refreshSize = 0xFF);
//! @brief Parse the instruction at the program counter given to have human readable information.
DisassembledInstruction _parseInstruction(uint24_t pc, DisassemblyContext &ctx);
//! @brief Get the parameter of the instruction as an hexadecimal string.
@@ -116,8 +122,6 @@ namespace ComSquare::Debugger
//! @brief Return a printable string corresponding to the value of a 8 or 16 bits immediate addressing mode.
//! @param dual Set this to true if the instruction take 16bits and not 8. (used for the immediate by a when the flag m is not set or the immediate by x if the flag x is not set).
std::string _getImmediateValue(uint24_t pc, bool dual);
- //! @brief Return a printable string corresponding to the value of a 16bits immediate addressing mode.
- std::string _getImmediateValue16Bits(uint24_t pc);
//! @brief Return a printable string corresponding to the value of a direct addressing mode.
std::string _getDirectValue(uint24_t pc);
//! @brief Return a printable string corresponding to the value of an absolute addressing mode.
From 4a8a4a98f3e9c7c9d61d204d58f6758396d5b725 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 16:06:33 +0100
Subject: [PATCH 11/17] Implementing an indicator of the trust level
---
resources/appResources.qrc | 1 +
resources/icons/continue.svg | 1 +
sources/Debugger/CPUDebug.cpp | 16 ++++++++++++----
sources/Debugger/CPUDebug.hpp | 13 ++++++++++++-
ui/cpu.ui | 20 ++++++++++++++++++--
5 files changed, 44 insertions(+), 7 deletions(-)
create mode 100644 resources/icons/continue.svg
diff --git a/resources/appResources.qrc b/resources/appResources.qrc
index 8e8574c..52163e6 100644
--- a/resources/appResources.qrc
+++ b/resources/appResources.qrc
@@ -1,5 +1,6 @@
+ icons/continue.svg
icons/step.svg
Logo.png
icons/play.svg
diff --git a/resources/icons/continue.svg b/resources/icons/continue.svg
new file mode 100644
index 0000000..9af8782
--- /dev/null
+++ b/resources/icons/continue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index 3c180c8..cb8392f 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -183,6 +183,7 @@ namespace ComSquare::Debugger
while (pc < endAddr) {
DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
+ instruction.level = ctx.level;
map.push_back(instruction);
pc += instruction.size;
if (instruction.addressingMode == ImmediateForA && !ctx.mFlag)
@@ -214,10 +215,10 @@ namespace ComSquare::Debugger
ctx.mFlag = true;
ctx.xFlag = true;
} else
- ctx.compromised = true;
+ ctx.level = Compromised;
}
if (instruction.opcode == 0xFB) {// XCE
- ctx.compromised = true;
+ ctx.level = Unsafe;
ctx.isEmulationMode = false; // The most common use of the XCE is to enable native mode at the start of the ROM so we guess that it has done that.
}
}
@@ -332,7 +333,7 @@ DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstra
int DisassemblyModel::columnCount(const QModelIndex &) const
{
- return 3;
+ return 4;
}
int DisassemblyModel::rowCount(const QModelIndex &) const
@@ -342,9 +343,16 @@ int DisassemblyModel::rowCount(const QModelIndex &) const
QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
{
- if (role != Qt::DisplayRole)
+ if (role != Qt::DisplayRole && role != Qt::DecorationRole)
return QVariant();
ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
+ if (role == Qt::DecorationRole) {
+ if (index.column() == 3 && instruction.level == ComSquare::Debugger::TrustLevel::Unsafe)
+ return QColor(Qt::yellow);
+ if (index.column() == 3 && instruction.level == ComSquare::Debugger::TrustLevel::Compromised)
+ return QColor(Qt::red);
+ return QVariant();
+ }
switch (index.column()) {
case 0:
return QString(instruction.name.c_str());
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 4839ee7..2ee125b 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -56,6 +56,12 @@ protected:
namespace ComSquare::Debugger
{
+ enum TrustLevel {
+ Safe,
+ Unsafe,
+ Compromised
+ };
+
//! @brief Struct used to emulate the state of the processor during the disassembly since instructions take a different amount of space depending on some flags.
struct DisassemblyContext {
//! @brief The accumulator and Memory width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode.
@@ -67,14 +73,19 @@ namespace ComSquare::Debugger
//! @brief Is the CPU emulating a 6502? If yes, some instructions don't change flags the same way.
bool isEmulationMode = true;
//! @brief Sometimes, the flags can't be tracked correctly after an instruction so the next instructions may not be correctly disassembled.
- bool compromised = false;
+ TrustLevel level = Safe;
};
//! @brief Struct representing an instruction in an human readable way (created by disassembling the rom).
struct DisassembledInstruction : public CPU::Instruction {
+ //! @brief The address of the instruction
uint24_t address;
+ //! @brief A string representing the argument with the right addressing mode.
std::string argument;
+ //! @brief The opcode of the instruction
uint8_t opcode;
+ //! @brief Are we sure that this instruction has been correctly disassembled?
+ TrustLevel level;
DisassembledInstruction(const CPU::Instruction &instruction, uint24_t address, std::string argument, uint8_t opcode);
DisassembledInstruction(const DisassembledInstruction &) = default;
diff --git a/ui/cpu.ui b/ui/cpu.ui
index eada993..bbaf550 100644
--- a/ui/cpu.ui
+++ b/ui/cpu.ui
@@ -220,6 +220,7 @@
false
+
@@ -228,13 +229,13 @@
:/resources/icons/play.svg:/resources/icons/play.svg
- Resume
+ Continue
Pause or Resume instruction execution.
- P
+ C
@@ -252,6 +253,21 @@
S
+
+
+
+ :/resources/icons/continue.svg:/resources/icons/continue.svg
+
+
+ Next
+
+
+ Continue execution to the next line.
+
+
+ N
+
+
From a6556b3ab791da12e009ed2683f0d4afe2fbbec2 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 17:20:52 +0100
Subject: [PATCH 12/17] Adding a next
---
sources/Debugger/CPUDebug.cpp | 42 +++++++++++++++++++++++++++++++----
sources/Debugger/CPUDebug.hpp | 12 ++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index cb8392f..eb5bd12 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -38,6 +38,7 @@ namespace ComSquare::Debugger
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
+ QMainWindow::connect(this->_ui.actionNext, &QAction::triggered, this, &CPUDebug::next);
QMainWindow::connect(this->_ui.clear, &QPushButton::released, this, &CPUDebug::clearHistory);
this->_window->show();
this->_updateRegistersPanel();
@@ -56,14 +57,30 @@ namespace ComSquare::Debugger
unsigned CPUDebug::update()
{
try {
+ unsigned cycles = 0;
+
if (this->_isPaused)
return 0xFF;
if (this->_isStepping) {
- unsigned ret = this->_executeInstruction(this->readPC());
+ cycles = this->_executeInstruction(this->readPC());
this->_updateDisassembly();
- return ret;
+ return cycles;
}
- return CPU::update();
+
+ for (int i = 0; i < 0xFF; i++) {
+ auto breakpoint = std::find_if(this->breakpoints.begin(), this->breakpoints.end(), [this](Breakpoint &brk) {
+ return brk.address == this->_registers.pac;
+ });
+ if (i != 0 && breakpoint != this->breakpoints.end()) {
+ if (breakpoint->oneTime)
+ this->breakpoints.erase(breakpoint);
+ this->_isPaused = false;
+ this->pause();
+ return cycles;
+ }
+ cycles += this->_executeInstruction(this->readPC());
+ }
+ return cycles;
} catch (InvalidOpcode &e) {
if (!this->_isPaused)
this->pause();
@@ -105,6 +122,15 @@ namespace ComSquare::Debugger
this->_isPaused = false;
}
+ void CPUDebug::next()
+ {
+ auto next = std::find_if(this->disassembledInstructions.begin(), this->disassembledInstructions.end(), [this](DisassembledInstruction &i) {
+ return i.address > this->_registers.pac;
+ });
+ this->breakpoints.push_back({next->address, true});
+ this->_isPaused = false;
+ }
+
void CPUDebug::_updateRegistersPanel()
{
if (!this->_registers.p.m)
@@ -378,10 +404,18 @@ RowPainter::RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent) : QS
void RowPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
+ bool isBreakpoint = false;
+
+ auto breakpoint = std::find_if(this->_cpu.breakpoints.begin(), this->_cpu.breakpoints.end(), [instruction](ComSquare::Debugger::Breakpoint brk) {
+ return brk.address == instruction.address;
+ });
+ if (breakpoint != this->_cpu.breakpoints.end())
+ isBreakpoint = true;
if (instruction.address == this->_cpu.getPC())
painter->fillRect(option.rect,QColor(Qt::darkGreen));
- // TODO display breakpoints with the Qt::darkRed color.
+ if (isBreakpoint && !breakpoint->oneTime)
+ painter->fillRect(option.rect,QColor(Qt::darkRed));
QStyledItemDelegate::paint(painter, option, index);
}
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 2ee125b..5cc42ee 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -95,6 +95,14 @@ namespace ComSquare::Debugger
std::string toString();
};
+ //! @brief Struct representing a breakpoint set by the user or by the app
+ struct Breakpoint {
+ //! @brief The address of the breakpoint
+ uint24_t address;
+ //! @brief If this is true, the breakpoint will be deleted on first hit and won't be shown on the disassembly view.
+ bool oneTime;
+ };
+
//! @brief A custom CPU with a window that show it's registers and the disassembly.
class CPUDebug : public CPU::CPU, public QObject {
private:
@@ -147,12 +155,16 @@ namespace ComSquare::Debugger
void pause();
//! @brief Step - Execute a single instruction.
void step();
+ //! @brief Next - Continue running instructions until the next line is reached.
+ void next();
//! @brief Clear the history panel.
void clearHistory();
//! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU.
void disableDebugger();
//! @brief The list of disassembled instructions to show on the debugger.
std::vector disassembledInstructions;
+ //! @brief The list of breakpoints the user has set.
+ std::vector breakpoints;
//! @brief Return the current program counter of this CPU.
uint24_t getPC();
//! @brief Update the UI when resetting the CPU.
From f44cd8a10687abdaafeeff19177b9fd92ce76a6a Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 18:19:09 +0100
Subject: [PATCH 13/17] Adding breakpoints and preventing the selection box to
be drawn on top of special items
---
sources/Debugger/CPUDebug.cpp | 27 +++++++++++++++++++++++----
sources/Debugger/CPUDebug.hpp | 2 ++
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index eb5bd12..f3e1aab 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -34,12 +34,14 @@ namespace ComSquare::Debugger
this->_ui.disassembly->horizontalHeader()->setStretchLastSection(true);
this->_ui.disassembly->resizeColumnsToContents();
this->_ui.disassembly->verticalHeader()->setSectionResizeMode (QHeaderView::Fixed);
+ this->_ui.disassembly->verticalHeader()->setHighlightSections(false);
this->_ui.disassembly->setItemDelegate(&this->_painter);
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
QMainWindow::connect(this->_ui.actionNext, &QAction::triggered, this, &CPUDebug::next);
QMainWindow::connect(this->_ui.clear, &QPushButton::released, this, &CPUDebug::clearHistory);
+ QMainWindow::connect(this->_ui.disassembly->verticalHeader(), &QHeaderView::sectionClicked, this, &CPUDebug::toggleBreakpoint);
this->_window->show();
this->_updateRegistersPanel();
}
@@ -131,6 +133,19 @@ namespace ComSquare::Debugger
this->_isPaused = false;
}
+ void CPUDebug::toggleBreakpoint(int logicalIndex)
+ {
+ DisassembledInstruction instruction = this->disassembledInstructions[logicalIndex];
+ auto existing = std::find_if(this->breakpoints.begin(), this->breakpoints.end(), [instruction](Breakpoint &i) {
+ return i.address == instruction.address;
+ });
+ if (existing == this->breakpoints.end())
+ this->breakpoints.push_back({instruction.address, false});
+ else
+ this->breakpoints.erase(existing);
+ this->_ui.disassembly->viewport()->repaint();
+ }
+
void CPUDebug::_updateRegistersPanel()
{
if (!this->_registers.p.m)
@@ -412,11 +427,15 @@ void RowPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, co
if (breakpoint != this->_cpu.breakpoints.end())
isBreakpoint = true;
- if (instruction.address == this->_cpu.getPC())
- painter->fillRect(option.rect,QColor(Qt::darkGreen));
- if (isBreakpoint && !breakpoint->oneTime)
+ QStyleOptionViewItem style = option;
+ if (instruction.address == this->_cpu.getPC()) {
+ painter->fillRect(option.rect, QColor(Qt::darkGreen));
+ style.state &= ~QStyle::State_Selected;
+ } else if (isBreakpoint && !breakpoint->oneTime) {
painter->fillRect(option.rect,QColor(Qt::darkRed));
- QStyledItemDelegate::paint(painter, option, index);
+ style.state &= ~QStyle::State_Selected;
+ }
+ QStyledItemDelegate::paint(painter, style, index);
}
QSize RowPainter::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 5cc42ee..cb70e8e 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -159,6 +159,8 @@ namespace ComSquare::Debugger
void next();
//! @brief Clear the history panel.
void clearHistory();
+ //! @brief Called when the user clicks on a section header. It enable/disable a breakpoint for this address.
+ void toggleBreakpoint(int logicalIndex);
//! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU.
void disableDebugger();
//! @brief The list of disassembled instructions to show on the debugger.
From 9be49e283d0aa50a1fac237a245fc0a3e47a61b4 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 20:47:13 +0100
Subject: [PATCH 14/17] Solving timing issues
---
sources/CPU/CPU.cpp | 200 +-----------------
sources/CPU/CPU.hpp | 122 +++++------
sources/CPU/Instruction.hpp | 10 +-
sources/CPU/Instructions/BitsInstructions.cpp | 25 ++-
.../CPU/Instructions/InternalInstruction.cpp | 141 ++++++------
sources/CPU/Instructions/Interrupts.cpp | 11 +-
.../Instructions/MathematicalOperations.cpp | 50 ++++-
.../CPU/Instructions/MemoryInstructions.cpp | 91 ++++++--
.../CPU/Instructions/TransferRegisters.cpp | 6 +-
sources/Debugger/CPUDebug.cpp | 2 +-
sources/Debugger/CPUDebug.hpp | 2 +-
tests/CPU/Math/testADC.cpp | 16 +-
tests/CPU/Math/testSBC.cpp | 10 +-
tests/CPU/TransferRegisters.cpp | 20 +-
tests/CPU/testBits.cpp | 6 +-
tests/CPU/testInternal.cpp | 169 ++++++++-------
tests/CPU/testInterupts.cpp | 8 +-
tests/CPU/testStore.cpp | 28 +--
18 files changed, 432 insertions(+), 485 deletions(-)
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 9425cc4..a31bf3f 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -214,12 +214,10 @@ namespace ComSquare::CPU
unsigned CPU::_executeInstruction(uint8_t opcode)
{
Instruction instruction = this->_instructions[opcode];
+ uint24_t valueAddr = 0;
this->_hasIndexCrossedPageBoundary = false;
- uint24_t valueAddr = 0;
- int cycles = instruction.cycleCount + !this->_registers.p.m;
-
switch (instruction.addressingMode) {
case Implied:
break;
@@ -250,48 +248,38 @@ namespace ComSquare::CPU
case DirectPage:
valueAddr = this->_getDirectAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndirect:
valueAddr = this->_getDirectIndirectAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndirectLong:
valueAddr = this->_getDirectIndirectLongAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndexedByX:
valueAddr = this->_getDirectIndexedByXAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndexedByY:
valueAddr = this->_getDirectIndexedByYAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndirectIndexedByX:
valueAddr = this->_getDirectIndirectIndexedXAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndirectIndexedByY:
valueAddr = this->_getDirectIndirectIndexedYAddr();
- cycles += this->_registers.dl != 0;
break;
case DirectPageIndirectIndexedByYLong:
valueAddr = this->_getDirectIndirectIndexedYLongAddr();
- cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
break;
case AbsoluteIndexedByX:
valueAddr = this->_getAbsoluteIndexedByXAddr();
- cycles += this->_hasIndexCrossedPageBoundary;
break;
case AbsoluteIndexedByXLong:
valueAddr = this->_getAbsoluteIndexedByXLongAddr();
break;
case AbsoluteIndexedByY:
valueAddr = this->_getAbsoluteIndexedByYAddr();
- cycles += this->_hasIndexCrossedPageBoundary;
break;
case StackRelative:
@@ -314,191 +302,7 @@ namespace ComSquare::CPU
break;
}
- return cycles + (this->*instruction.call)(valueAddr);
-// uint24_t addr;
-//
-// switch (opcode) {
-// case Instructions::BRK: this->BRK(0x0); return 7 + !this->_isEmulationMode;
-//
-// case Instructions::COP: this->COP(); return 7 + !this->_isEmulationMode;
-//
-// case Instructions::RTI: this->RTI(); return 6 + !this->_isEmulationMode;
-//
-// case Instructions::ADC_IM: this->ADC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
-// case Instructions::ADC_ABS: this->ADC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::ADC_ABSl: this->ADC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::ADC_DP: this->ADC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_DPi: this->ADC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_DPil: this->ADC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_ABSX: this->ADC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::ADC_ABSXl:this->ADC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::ADC_ABSY: this->ADC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::ADC_DPX: this->ADC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_DPXi: this->ADC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_DPYi: this->ADC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
-// case Instructions::ADC_DPYil:this->ADC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::ADC_SR: this->ADC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::ADC_SRYi: this->ADC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-//
-// case Instructions::STA_ABS: this->STA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::STA_ABSl: this->STA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::STA_DP: this->STA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_DPi: this->STA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_DPil: this->STA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_ABSX: this->STA(this->_getAbsoluteIndexedByXAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::STA_ABSXl:this->STA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::STA_ABSY: this->STA(this->_getAbsoluteIndexedByYAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::STA_DPX: this->STA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_DPXi: this->STA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_DPYi: this->STA(this->_getDirectIndirectIndexedYAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_DPYil:this->STA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STA_SR: this->STA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::STA_SRYi: this->STA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-//
-// case Instructions::STX_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::STX_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STX_DPY: this->STX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::STY_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::STY_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STY_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::STZ_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::STZ_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STZ_ABSX: this->STX(this->_getAbsoluteIndexedByXAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::STZ_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::LDA_IM: this->LDA(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
-// case Instructions::LDA_ABS: this->LDA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::LDA_ABSl: this->LDA(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::LDA_DP: this->LDA(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_DPi: this->LDA(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_DPil: this->LDA(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_ABSX: this->LDA(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::LDA_ABSXl:this->LDA(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::LDA_ABSY: this->LDA(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::LDA_DPX: this->LDA(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_DPXi: this->LDA(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_DPYi: this->LDA(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
-// case Instructions::LDA_DPYil:this->LDA(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDA_SR: this->LDA(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::LDA_SRYi: this->LDA(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-//
-// case Instructions::LDX_IM: this->LDX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
-// case Instructions::LDX_ABS: this->LDX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::LDX_DP: this->LDX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDX_ABSY: this->LDX(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::LDX_DPY: this->LDX(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::LDY_IM: this->LDY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
-// case Instructions::LDY_ABS: this->LDY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::LDY_DP: this->LDY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::LDY_ABSY: this->LDY(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::LDY_DPY: this->LDY(this->_getDirectIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::SEP: this->SEP(this->_bus->read(this->_registers.pc++)); return 3;
-//
-// case Instructions::REP: this->REP(this->_bus->read(this->_registers.pc++)); return 3;
-//
-// case Instructions::PHA: this->PHA(); return 3 + !this->_registers.p.m;
-// case Instructions::PHB: this->PHB(); return 3;
-// case Instructions::PHD: this->PHD(); return 4;
-// case Instructions::PHK: this->PHK(); return 3;
-// case Instructions::PHP: this->PHP(); return 3;
-// case Instructions::PHX: this->PHX(); return 3 + !this->_registers.p.x_b;
-// case Instructions::PHY: this->PHY(); return 3 + !this->_registers.p.x_b;
-//
-// case Instructions::PLA: this->PLA(); return 4 + !this->_registers.p.m;
-// case Instructions::PLB: this->PLB(); return 4;
-// case Instructions::PLD: this->PLD(); return 5;
-// case Instructions::PLP: this->PLP(); return 4;
-// case Instructions::PLX: this->PLX(); return 4 + !this->_registers.p.x_b;
-// case Instructions::PLY: this->PLY(); return 4 + !this->_registers.p.x_b;
-//
-// case Instructions::JSR_ABS: this->JSR(this->_getAbsoluteAddr()); return 6;
-// case Instructions::JSR_ABSXi: this->JSR(this->_getAbsoluteIndirectIndexedByXAddr()); return 8;
-//
-// case Instructions::JSL: this->JSL(this->_getAbsoluteLongAddr()); return 8;
-//
-// case Instructions::CLC: this->CLC(); return 2;
-// case Instructions::CLI: this->CLI(); return 2;
-// case Instructions::CLD: this->CLD(); return 2;
-// case Instructions::CLV: this->CLV(); return 2;
-//
-// case Instructions::SEC: this->SEC(); return 2;
-// case Instructions::SED: this->SED(); return 2;
-// case Instructions::SEI: this->SEI(); return 2;
-//
-// case Instructions::AND_IM: this->AND(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
-// case Instructions::AND_ABS: this->AND(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::AND_ABSl: this->AND(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::AND_DP: this->AND(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_DPi: this->AND(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_DPil: this->AND(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_ABSX: this->AND(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::AND_ABSXl:this->AND(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::AND_ABSY: this->AND(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::AND_DPX: this->AND(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_DPXi: this->AND(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_DPYi: this->AND(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
-// case Instructions::AND_DPYil:this->AND(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::AND_SR: this->AND(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::AND_SRYi: this->AND(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-//
-// case Instructions::XCE: this->XCE(); return 2;
-//
-// case Instructions::SBC_IM: this->SBC(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m;
-// case Instructions::SBC_ABS: this->SBC(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::SBC_ABSl: this->SBC(this->_getAbsoluteLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::SBC_DP: this->SBC(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_DPi: this->SBC(this->_getDirectIndirectAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_DPil: this->SBC(this->_getDirectIndirectLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_ABSX: this->SBC(this->_getAbsoluteIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::SBC_ABSXl:this->SBC(this->_getAbsoluteIndexedByXLongAddr()); return 5 + !this->_registers.p.m;
-// case Instructions::SBC_ABSY: this->SBC(this->_getAbsoluteIndexedByYAddr()); return 4 + !this->_registers.p.m + this->_hasIndexCrossedPageBoundary;
-// case Instructions::SBC_DPX: this->SBC(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_DPXi: this->SBC(this->_getDirectIndirectIndexedXAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_DPYi: this->SBC(this->_getDirectIndirectIndexedYAddr()); return 5 + !this->_registers.p.m + this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
-// case Instructions::SBC_DPYil:this->SBC(this->_getDirectIndirectIndexedYLongAddr()); return 6 + !this->_registers.p.m + this->_registers.dl != 0;
-// case Instructions::SBC_SR: this->SBC(this->_getStackRelativeAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::SBC_SRYi: this->SBC(this->_getStackRelativeIndirectIndexedYAddr()); return 7 + !this->_registers.p.m;
-//
-// case Instructions::TAX: this->TAX(); return 2;
-// case Instructions::TAY: this->TAY(); return 2;
-// case Instructions::TXS: this->TXS(); return 2;
-//
-// case Instructions::INX: this->INX(); return 2;
-// case Instructions::INY: this->INY(); return 2;
-//
-// case Instructions::CPX_IM: this->CPX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
-// case Instructions::CPX_ABS: this->CPX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::CPX_DP: this->CPX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::CPY_IM: this->CPY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
-// case Instructions::CPY_ABS: this->CPY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
-// case Instructions::CPY_DP: this->CPY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
-//
-// case Instructions::BCC: return this->BCC(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BCS: return this->BCS(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BEQ: return this->BEQ(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BNE: return this->BNE(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BMI: return this->BMI(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BPL: return this->BPL(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BVC: return this->BVC(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BVS: return this->BVS(this->_registers.pc++) + 2 + this->_isEmulationMode;
-// case Instructions::BRA: this->BRA(this->_registers.pc++); return 3 + this->_isEmulationMode;
-// case Instructions::BRL: this->BRL(this->_registers.pc); this->_registers.pc += 2; return 4;
-//
-// case Instructions::JMP_ABS: addr = this->_getAbsoluteAddr(); this->JMP(addr); return 3;
-// case Instructions::JMP_ABSi: addr = this->_getAbsoluteIndirectAddr(); this->JMP(addr); return 3;
-// case Instructions::JMP_ABSXi: addr = this->_getAbsoluteIndexedByXAddr(); this->JMP(addr); return 3;
-//
-// case Instructions::JML_ABSl: addr = this->_getAbsoluteLongAddr(); this->JML(addr); return 3;
-// //case Instructions::JML_ABSil: this->JML(this->_getAbsoluteLong()); return 3;
-//
-// default:
-// throw InvalidOpcode("CPU", opcode);
-// }
+ return instruction.cycleCount + (this->*instruction.call)(valueAddr, instruction.addressingMode);
}
void CPU::_push(uint8_t data)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 679b8b3..3e45f77 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -261,121 +261,121 @@ namespace ComSquare::CPU
virtual unsigned _executeInstruction(uint8_t opcode);
//! @brief Break instruction - Causes a software break. The PC is loaded from a vector table.
- int BRK(uint24_t);
+ int BRK(uint24_t, AddressingMode);
//! @brief Co-Processor Enable instruction - Causes a software break. The PC is loaded from a vector table.
- int COP(uint24_t);
+ int COP(uint24_t, AddressingMode);
//! @brief Return from Interrupt - Used to return from a interrupt handler.
- int RTI(uint24_t);
+ int RTI(uint24_t, AddressingMode);
//! @brief Add with carry - Adds operand to the Accumulator; adds an additional 1 if carry is set.
- int ADC(uint24_t valueAddr);
+ int ADC(uint24_t valueAddr, AddressingMode);
//! @brief Store the accumulator to memory.
- int STA(uint24_t addr);
+ int STA(uint24_t addr, AddressingMode);
//! @brief Store the index register X to memory.
- int STX(uint24_t addr);
+ int STX(uint24_t addr, AddressingMode);
//! @brief Store the index register Y to memory.
- int STY(uint24_t addr);
+ int STY(uint24_t addr, AddressingMode);
//! @brief Store zero to the memory.
- int STZ(uint24_t addr);
+ int STZ(uint24_t addr, AddressingMode);
//! @brief Load the accumulator from memory.
- int LDA(uint24_t addr);
+ int LDA(uint24_t addr, AddressingMode);
//! @brief Load the X index register from memory.
- int LDX(uint24_t addr);
+ int LDX(uint24_t addr, AddressingMode);
//! @brief Load the Y index register from memory.
- int LDY(uint24_t addr);
+ int LDY(uint24_t addr, AddressingMode);
//! @brief Set status bits.
- int SEP(uint24_t valueAddr);
+ int SEP(uint24_t valueAddr, AddressingMode);
//! @brief Reset status bits.
- int REP(uint24_t valueAddr);
+ int REP(uint24_t valueAddr, AddressingMode);
//! @brief Jump to subroutine
- int JSR(uint24_t addr);
+ int JSR(uint24_t addr, AddressingMode);
//! @brief Jump to subroutine (long)
- int JSL(uint24_t addr);
+ int JSL(uint24_t addr, AddressingMode);
//! @brief Push the accumulator to the stack.
- int PHA(uint24_t);
+ int PHA(uint24_t, AddressingMode);
//! @brief Push the data bank register to the stack.
- int PHB(uint24_t);
+ int PHB(uint24_t, AddressingMode);
//! @brief Push the direct page register to the stack.
- int PHD(uint24_t);
+ int PHD(uint24_t, AddressingMode);
//! @brief Push the program bank register to the stack.
- int PHK(uint24_t);
+ int PHK(uint24_t, AddressingMode);
//! @brief Push the processor status register to the stack.
- int PHP(uint24_t);
+ int PHP(uint24_t, AddressingMode);
//! @brief Push the x index register to the stack.
- int PHX(uint24_t);
+ int PHX(uint24_t, AddressingMode);
//! @brief Push the y index register to the stack.
- int PHY(uint24_t);
+ int PHY(uint24_t, AddressingMode);
//! @brief Pull the accumulator to the stack.
- int PLA(uint24_t);
+ int PLA(uint24_t, AddressingMode);
//! @brief Pull the data bank register to the stack.
- int PLB(uint24_t);
+ int PLB(uint24_t, AddressingMode);
//! @brief Pull the direct page register to the stack.
- int PLD(uint24_t);
+ int PLD(uint24_t, AddressingMode);
//! @brief Pull the processor status register to the stack.
- int PLP(uint24_t);
+ int PLP(uint24_t, AddressingMode);
//! @brief Pull the x index register to the stack.
- int PLX(uint24_t);
+ int PLX(uint24_t, AddressingMode);
//! @brief Pull the y index register to the stack.
- int PLY(uint24_t);
+ int PLY(uint24_t, AddressingMode);
//! @brief Clear the carry flag.
- int CLC(uint24_t);
+ int CLC(uint24_t, AddressingMode);
//! @brief Clear the Interrupt Disable flag.
- int CLI(uint24_t);
+ int CLI(uint24_t, AddressingMode);
//! @brief Clear the decimal flag.
- int CLD(uint24_t);
+ int CLD(uint24_t, AddressingMode);
//! @brief Clear the overflow flag.
- int CLV(uint24_t);
+ int CLV(uint24_t, AddressingMode);
//! @brief Set the carry Flag.
- int SEC(uint24_t);
+ int SEC(uint24_t, AddressingMode);
//! @brief Set the decimal flag.
- int SED(uint24_t);
+ int SED(uint24_t, AddressingMode);
//! @brief Set the Interrupt Disable flag.
- int SEI(uint24_t);
+ int SEI(uint24_t, AddressingMode);
//! @brief Exchange Carry and Emulation Flags
- int XCE(uint24_t);
+ int XCE(uint24_t, AddressingMode);
//! @brief And accumulator with memory.
- int AND(uint24_t valueAddr);
+ int AND(uint24_t valueAddr, AddressingMode);
//! @brief Subtract with Borrow from Accumulator.
- int SBC(uint24_t valueAddr);
+ int SBC(uint24_t valueAddr, AddressingMode);
//! @brief Transfer A to X
- int TAX(uint24_t);
+ int TAX(uint24_t, AddressingMode);
//! @brief Transfer A to Y
- int TAY(uint24_t);
+ int TAY(uint24_t, AddressingMode);
//! @brief Transfer X to SP
- int TXS(uint24_t);
+ int TXS(uint24_t, AddressingMode);
//! @brief Increment the X register
- int INX(uint24_t);
+ int INX(uint24_t, AddressingMode);
//! @brief Increment the Y register
- int INY(uint24_t);
+ int INY(uint24_t, AddressingMode);
//! @brief Compare the X register with the memory
- int CPX(uint24_t valueAddr);
+ int CPX(uint24_t valueAddr, AddressingMode);
//! @brief Compare the Y register with the memory
- int CPY(uint24_t valueAddr);
+ int CPY(uint24_t valueAddr, AddressingMode);
//! @brief Branch if carry clear
- int BCC(uint24_t valueAddr);
+ int BCC(uint24_t valueAddr, AddressingMode);
//! @brief Branch if carry set
- int BCS(uint24_t valueAddr);
+ int BCS(uint24_t valueAddr, AddressingMode);
//! @brief Branch if equal
- int BEQ(uint24_t valueAddr);
+ int BEQ(uint24_t valueAddr, AddressingMode);
//! @brief Branch if not equal
- int BNE(uint24_t valueAddr);
+ int BNE(uint24_t valueAddr, AddressingMode);
//! @brief Branch if minus
- int BMI(uint24_t valueAddr);
+ int BMI(uint24_t valueAddr, AddressingMode);
//! @brief Branch if plus
- int BPL(uint24_t valueAddr);
+ int BPL(uint24_t valueAddr, AddressingMode);
//! @brief Branch if Overflow Clear
- int BVC(uint24_t valueAddr);
+ int BVC(uint24_t valueAddr, AddressingMode);
//! @brief Branch if Overflow Set
- int BVS(uint24_t valueAddr);
+ int BVS(uint24_t valueAddr, AddressingMode);
//! @brief Branch always
- int BRA(uint24_t valueAddr);
+ int BRA(uint24_t valueAddr, AddressingMode);
//! @brief Branch always long
- int BRL(uint24_t valueAddr);
+ int BRL(uint24_t valueAddr, AddressingMode);
//! @brief Jump.
- int JMP(uint24_t valueAddr);
+ int JMP(uint24_t valueAddr, AddressingMode);
//! @brief Long jump.
- int JML(uint24_t valueAddr);
+ int JML(uint24_t valueAddr, AddressingMode);
//! @brief No OP.
- int NOP(uint24_t);
+ int NOP(uint24_t, AddressingMode);
//! @brief All the instructions of the CPU.
//! @info Instructions are indexed by their opcode
@@ -580,7 +580,7 @@ namespace ComSquare::CPU
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C5
{&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // C6
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C7
- {&CPU::BRK, 7, "iny #-#", AddressingMode::Implied, 2}, // C8
+ {&CPU::INY, 2, "iny", AddressingMode::Implied, 1}, // C8
{&CPU::BRK, 7, "cmp #-#", AddressingMode::Implied, 2}, // C9
{&CPU::BRK, 7, "dex #-#", AddressingMode::Implied, 2}, // CA
{&CPU::BRK, 7, "wai #-#", AddressingMode::Implied, 2}, // CB
@@ -612,7 +612,7 @@ namespace ComSquare::CPU
{&CPU::SBC, 3, "sbc", AddressingMode::DirectPage, 2}, // E5
{&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // E6
{&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectLong, 2}, // E7
- {&CPU::BRK, 7, "inx #-#", AddressingMode::Implied, 2}, // E8
+ {&CPU::INX, 2, "inx", AddressingMode::Implied, 1}, // E8
{&CPU::SBC, 2, "sbc", AddressingMode::ImmediateForA, 2}, // E9
{&CPU::NOP, 2, "nop", AddressingMode::Implied, 1}, // EA
{&CPU::BRK, 7, "xba #-#", AddressingMode::Implied, 2}, // EB
@@ -663,7 +663,7 @@ namespace ComSquare::CPU
Component getComponent() override;
//! @brief Reset interrupt - Called on boot and when the reset button is pressed.
- virtual int RESB(uint24_t = 0);
+ virtual int RESB();
//! @brief Return true if the CPU is overloaded with debugging features.
virtual bool isDebugger();
diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp
index c2057d4..5af02f4 100644
--- a/sources/CPU/Instruction.hpp
+++ b/sources/CPU/Instruction.hpp
@@ -52,11 +52,11 @@ namespace ComSquare::CPU
//! @brief Struct containing basic information about instructions.
struct Instruction {
- int (CPU::*call)(uint24_t valueAddr);
- int cycleCount;
- std::string name;
- AddressingMode addressingMode;
- int size;
+ int (CPU::*call)(uint24_t valueAddr, AddressingMode mode) = nullptr;
+ int cycleCount = 0;
+ std::string name = "";
+ AddressingMode addressingMode = Implied;
+ int size = 0;
Instruction() = default;
Instruction(const Instruction &) = default;
diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp
index d048dcd..d3ecefa 100644
--- a/sources/CPU/Instructions/BitsInstructions.cpp
+++ b/sources/CPU/Instructions/BitsInstructions.cpp
@@ -7,7 +7,7 @@
namespace ComSquare::CPU
{
- int CPU::AND(uint24_t valueAddr)
+ int CPU::AND(uint24_t valueAddr, AddressingMode mode)
{
unsigned negativeMask = this->_isEmulationMode ? 0x80u : 0x8000u;
unsigned value = this->_bus->read(valueAddr);
@@ -17,6 +17,27 @@ namespace ComSquare::CPU
this->_registers.a &= value;
this->_registers.p.n = this->_registers.a & negativeMask;
this->_registers.p.z = this->_registers.a == 0;
- return 0;
+
+ int cycles = !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndirect:
+ case DirectPageIndirectLong:
+ case DirectPageIndexedByX:
+ case DirectPageIndirectIndexedByX:
+ case DirectPageIndirectIndexedByYLong:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByX:
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ case DirectPageIndirectIndexedByY:
+ cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index 77112ec..782bfbb 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -6,55 +6,55 @@
namespace ComSquare::CPU
{
- int CPU::SEC(uint24_t)
+ int CPU::SEC(uint24_t, AddressingMode)
{
this->_registers.p.c = true;
return 0;
}
- int CPU::SED(uint24_t)
+ int CPU::SED(uint24_t, AddressingMode)
{
this->_registers.p.d = true;
return 0;
}
- int CPU::SEI(uint24_t)
+ int CPU::SEI(uint24_t, AddressingMode)
{
this->_registers.p.i = true;
return 0;
}
- int CPU::CLC(uint24_t)
+ int CPU::CLC(uint24_t, AddressingMode)
{
this->_registers.p.c = false;
return 0;
}
- int CPU::CLI(uint24_t)
+ int CPU::CLI(uint24_t, AddressingMode)
{
this->_registers.p.i = false;
return 0;
}
- int CPU::CLD(uint24_t)
+ int CPU::CLD(uint24_t, AddressingMode)
{
this->_registers.p.d = false;
return 0;
}
- int CPU::CLV(uint24_t)
+ int CPU::CLV(uint24_t, AddressingMode)
{
this->_registers.p.v = false;
return 0;
}
- int CPU::SEP(uint24_t valueAddr)
+ int CPU::SEP(uint24_t valueAddr, AddressingMode)
{
this->_registers.p.flags |= this->_bus->read(valueAddr);
return 0;
}
- int CPU::REP(uint24_t valueAddr)
+ int CPU::REP(uint24_t valueAddr, AddressingMode)
{
this->_registers.p.flags &= ~this->_bus->read(valueAddr);
if (this->_isEmulationMode) {
@@ -64,14 +64,14 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::JSR(uint24_t valueAddr)
+ int CPU::JSR(uint24_t valueAddr, AddressingMode)
{
this->_push(--this->_registers.pc);
this->_registers.pc = valueAddr;
return 0;
}
- int CPU::JSL(uint24_t valueAddr)
+ int CPU::JSL(uint24_t valueAddr, AddressingMode)
{
this->_registers.pac--;
this->_push(this->_registers.pbr);
@@ -80,58 +80,61 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::PHA(uint24_t)
+ int CPU::PHA(uint24_t, AddressingMode)
{
this->_push(this->_registers.a);
- return 0;
+ return !this->_registers.p.m;
}
- int CPU::PHB(uint24_t)
+ int CPU::PHB(uint24_t, AddressingMode)
{
this->_push(this->_registers.dbr);
return 0;
}
- int CPU::PHD(uint24_t)
+ int CPU::PHD(uint24_t, AddressingMode)
{
this->_push(this->_registers.d);
return 0;
}
- int CPU::PHK(uint24_t)
+ int CPU::PHK(uint24_t, AddressingMode)
{
this->_push(this->_registers.pbr);
return 0;
}
- int CPU::PHP(uint24_t)
+ int CPU::PHP(uint24_t, AddressingMode)
{
this->_push(this->_registers.p.flags);
return 0;
}
- int CPU::PHX(uint24_t)
+ int CPU::PHX(uint24_t, AddressingMode)
{
this->_push(this->_registers.x);
- return 0;
+ return !this->_registers.p.x_b;
}
- int CPU::PHY(uint24_t)
+ int CPU::PHY(uint24_t, AddressingMode)
{
this->_push(this->_registers.y);
- return 0;
+ return !this->_registers.p.x_b;
}
- int CPU::PLA(uint24_t)
+ int CPU::PLA(uint24_t, AddressingMode)
{
- // TODO this register should be poped by 8 if the m flag is 1
- this->_registers.a = this->_pop16();
+ if (this->_registers.p.m) {
+ this->_registers.a = this->_pop();
+ this->_registers.ah = 0;
+ } else
+ this->_registers.a = this->_pop16();
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & 0x8000u;
- return 0;
+ return !this->_registers.p.m;
}
- int CPU::PLB(uint24_t)
+ int CPU::PLB(uint24_t, AddressingMode)
{
this->_registers.dbr = this->_pop();
this->_registers.p.z = this->_registers.dbr == 0;
@@ -139,7 +142,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::PLD(uint24_t)
+ int CPU::PLD(uint24_t, AddressingMode)
{
this->_registers.d = this->_pop16();
this->_registers.p.z = this->_registers.d == 0;
@@ -147,7 +150,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::PLP(uint24_t)
+ int CPU::PLP(uint24_t, AddressingMode)
{
this->_registers.p.flags = this->_pop();
if (this->_isEmulationMode) {
@@ -157,25 +160,31 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::PLX(uint24_t)
+ int CPU::PLX(uint24_t, AddressingMode)
{
- // TODO this register should be poped by 8 if the x_b is 1
- this->_registers.x = this->_pop16();
+ if (this->_registers.p.x_b) {
+ this->_registers.x = this->_pop();
+ this->_registers.xh = 0;
+ } else
+ this->_registers.x = this->_pop16();
this->_registers.p.z = this->_registers.x == 0;
this->_registers.p.n = this->_registers.x & 0x8000u;
- return 0;
+ return !this->_registers.p.x_b;
}
- int CPU::PLY(uint24_t)
+ int CPU::PLY(uint24_t, AddressingMode)
{
- // TODO this register should be poped by 8 if the x_b is 1
- this->_registers.y = this->_pop16();
+ if (this->_registers.p.x_b) {
+ this->_registers.y = this->_pop();
+ this->_registers.yh = 0;
+ } else
+ this->_registers.y = this->_pop16();
this->_registers.p.z = this->_registers.y == 0;
this->_registers.p.n = this->_registers.y & 0x8000u;
- return 0;
+ return !this->_registers.p.x_b;
}
- int CPU::XCE(uint24_t)
+ int CPU::XCE(uint24_t, AddressingMode)
{
bool oldCarry = this->_registers.p.c;
this->_registers.p.c = this->_isEmulationMode;
@@ -190,7 +199,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::INX(uint24_t)
+ int CPU::INX(uint24_t, AddressingMode)
{
this->_registers.x++;
@@ -203,7 +212,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::INY(uint24_t)
+ int CPU::INY(uint24_t, AddressingMode)
{
this->_registers.y++;
@@ -216,7 +225,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::CPX(uint24_t valueAddr)
+ int CPU::CPX(uint24_t valueAddr, AddressingMode mode)
{
unsigned value = this->_bus->read(valueAddr++);
@@ -233,10 +242,10 @@ namespace ComSquare::CPU
this->_registers.p.n = x & 0x8000u;
}
this->_registers.p.c = this->_registers.x >= value;
- return 0;
+ return !this->_registers.p.x_b + (mode == DirectPage && this->_registers.dl != 0);
}
- int CPU::CPY(uint24_t valueAddr)
+ int CPU::CPY(uint24_t valueAddr, AddressingMode mode)
{
unsigned value = this->_bus->read(valueAddr++);
@@ -253,93 +262,93 @@ namespace ComSquare::CPU
this->_registers.p.z = y == 0;
this->_registers.p.n = y & 0x8000u;
}
- return 0;
+ return !this->_registers.p.x_b + (mode == DirectPage && this->_registers.dl != 0);
}
- int CPU::BCC(uint24_t valueAddr)
+ int CPU::BCC(uint24_t valueAddr, AddressingMode)
{
if (!this->_registers.p.c)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return !this->_registers.p.c;
+ return !this->_registers.p.c + this->_isEmulationMode;
}
- int CPU::BCS(uint24_t valueAddr)
+ int CPU::BCS(uint24_t valueAddr, AddressingMode)
{
if (this->_registers.p.c)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return this->_registers.p.c;
+ return this->_registers.p.c + this->_isEmulationMode;
}
- int CPU::BEQ(uint24_t valueAddr)
+ int CPU::BEQ(uint24_t valueAddr, AddressingMode)
{
if (this->_registers.p.z)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return this->_registers.p.z;
+ return this->_registers.p.z + this->_isEmulationMode;
}
- int CPU::BNE(uint24_t valueAddr)
+ int CPU::BNE(uint24_t valueAddr, AddressingMode)
{
if (!this->_registers.p.z)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return !this->_registers.p.z;
+ return !this->_registers.p.z + this->_isEmulationMode;
}
- int CPU::BMI(uint24_t valueAddr)
+ int CPU::BMI(uint24_t valueAddr, AddressingMode)
{
if (this->_registers.p.n)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return this->_registers.p.n;
+ return this->_registers.p.n + this->_isEmulationMode;
}
- int CPU::BPL(uint24_t valueAddr)
+ int CPU::BPL(uint24_t valueAddr, AddressingMode)
{
if (!this->_registers.p.n)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return !this->_registers.p.n;
+ return !this->_registers.p.n + this->_isEmulationMode;
}
- int CPU::BRA(uint24_t valueAddr)
+ int CPU::BRA(uint24_t valueAddr, AddressingMode)
{
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return true;
+ return this->_isEmulationMode;
}
- int CPU::BRL(uint24_t valueAddr)
+ int CPU::BRL(uint24_t valueAddr, AddressingMode)
{
unsigned value = this->_bus->read(valueAddr);
value += this->_bus->read(valueAddr + 1) << 8u;
this->_registers.pc += static_cast(value);
- return true;
+ return 0;
}
- int CPU::BVC(uint24_t valueAddr)
+ int CPU::BVC(uint24_t valueAddr, AddressingMode)
{
if (!this->_registers.p.v)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return !this->_registers.p.v;
+ return !this->_registers.p.v + this->_isEmulationMode;
}
- int CPU::BVS(uint24_t valueAddr)
+ int CPU::BVS(uint24_t valueAddr, AddressingMode)
{
if (this->_registers.p.v)
this->_registers.pc += static_cast(this->_bus->read(valueAddr));
- return this->_registers.p.v;
+ return this->_registers.p.v + this->_isEmulationMode;
}
- int CPU::JMP(uint24_t value)
+ int CPU::JMP(uint24_t value, AddressingMode)
{
this->_registers.pc = value;
return 0;
}
- int CPU::JML(uint24_t value)
+ int CPU::JML(uint24_t value, AddressingMode)
{
this->_registers.pac = value;
return 0;
}
- int CPU::NOP(uint24_t)
+ int CPU::NOP(uint24_t, AddressingMode)
{
return 0;
}
diff --git a/sources/CPU/Instructions/Interrupts.cpp b/sources/CPU/Instructions/Interrupts.cpp
index 02d54ae..1155da4 100644
--- a/sources/CPU/Instructions/Interrupts.cpp
+++ b/sources/CPU/Instructions/Interrupts.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- int CPU::RESB(uint24_t)
+ int CPU::RESB()
{
this->_registers.p.i = true;
this->_registers.p.d = false;
@@ -21,7 +21,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::BRK(uint24_t)
+ int CPU::BRK(uint24_t, AddressingMode)
{
if (this->_isEmulationMode) {
this->_registers.pc += 2;
@@ -31,7 +31,6 @@ namespace ComSquare::CPU
this->_registers.p.i = true;
this->_registers.p.d = false;
this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.brk;
-
} else {
this->_push(this->_registers.pbr);
this->_registers.pc += 2;
@@ -45,7 +44,7 @@ namespace ComSquare::CPU
return !this->_isEmulationMode;
}
- int CPU::COP(uint24_t)
+ int CPU::COP(uint24_t, AddressingMode)
{
if (this->_isEmulationMode) {
this->_registers.pc += 2;
@@ -68,13 +67,13 @@ namespace ComSquare::CPU
return !this->_isEmulationMode;
}
- int CPU::RTI(uint24_t)
+ int CPU::RTI(uint24_t, AddressingMode)
{
this->_registers.p.flags = this->_pop();
this->_registers.pc = this->_pop16();
if (!this->_isEmulationMode)
this->_registers.pbr = this->_pop16();
- return 0;
+ return !this->_isEmulationMode;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp
index 60465d9..5b6e9e1 100644
--- a/sources/CPU/Instructions/MathematicalOperations.cpp
+++ b/sources/CPU/Instructions/MathematicalOperations.cpp
@@ -7,7 +7,7 @@
namespace ComSquare::CPU
{
- int CPU::ADC(uint24_t valueAddr)
+ int CPU::ADC(uint24_t valueAddr, AddressingMode mode)
{
unsigned value = this->_bus->read(valueAddr) + this->_registers.p.c;
if (!this->_registers.p.m)
@@ -25,10 +25,31 @@ namespace ComSquare::CPU
this->_registers.a %= 0x100;
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & negativeMask;
- return 0;
+
+ int cycles = !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndirect:
+ case DirectPageIndirectLong:
+ case DirectPageIndexedByX:
+ case DirectPageIndirectIndexedByX:
+ case DirectPageIndirectIndexedByYLong:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByX:
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ case DirectPageIndirectIndexedByY:
+ cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
- int CPU::SBC(uint24_t valueAddr)
+ int CPU::SBC(uint24_t valueAddr, AddressingMode mode)
{
unsigned negativeMask = this->_isEmulationMode ? 0x80u : 0x8000u;
unsigned value = this->_bus->read(valueAddr);
@@ -46,6 +67,27 @@ namespace ComSquare::CPU
this->_registers.a %= 0x100;
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & negativeMask;
- return 0;
+
+ int cycles = !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndirect:
+ case DirectPageIndirectLong:
+ case DirectPageIndexedByX:
+ case DirectPageIndirectIndexedByX:
+ case DirectPageIndirectIndexedByYLong:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByX:
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ case DirectPageIndirectIndexedByY:
+ cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/MemoryInstructions.cpp b/sources/CPU/Instructions/MemoryInstructions.cpp
index 1e29642..f102d90 100644
--- a/sources/CPU/Instructions/MemoryInstructions.cpp
+++ b/sources/CPU/Instructions/MemoryInstructions.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- int CPU::STA(uint24_t addr)
+ int CPU::STA(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.m)
this->_bus->write(addr, this->_registers.al);
@@ -14,10 +14,24 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.al);
this->_bus->write(addr + 1, this->_registers.ah);
}
- return 0;
+
+ int cycles = !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndirect:
+ case DirectPageIndirectLong:
+ case DirectPageIndexedByX:
+ case DirectPageIndirectIndexedByX:
+ case DirectPageIndirectIndexedByY:
+ case DirectPageIndirectIndexedByYLong:
+ cycles += this->_registers.dl != 0;
+ default:
+ break;
+ }
+ return cycles;
}
- int CPU::STX(uint24_t addr)
+ int CPU::STX(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.x_b)
this->_bus->write(addr, this->_registers.xl);
@@ -25,10 +39,10 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.xl);
this->_bus->write(addr + 1, this->_registers.xh);
}
- return 0;
+ return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0);
}
- int CPU::STY(uint24_t addr)
+ int CPU::STY(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.x_b)
this->_bus->write(addr, this->_registers.yl);
@@ -36,18 +50,20 @@ namespace ComSquare::CPU
this->_bus->write(addr, this->_registers.yl);
this->_bus->write(addr + 1, this->_registers.yh);
}
- return 0;
+ return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0);
}
- int CPU::STZ(uint24_t addr)
+ int CPU::STZ(uint24_t addr, AddressingMode mode)
{
this->_bus->write(addr, 0x00);
if (!this->_registers.p.m)
this->_bus->write(addr + 1, 0x00);
- return 0;
+ if (mode == Absolute || mode == AbsoluteIndexedByX)
+ return !this->_registers.p.m;
+ return !this->_registers.p.m + this->_registers.dl != 0;
}
- int CPU::LDA(uint24_t addr)
+ int CPU::LDA(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.m) {
this->_registers.a = this->_bus->read(addr);
@@ -58,10 +74,31 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.a & 0xF000u;
}
this->_registers.p.z = this->_registers.a == 0x0;
- return 0;
+
+ int cycles = !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndirect:
+ case DirectPageIndirectLong:
+ case DirectPageIndexedByX:
+ case DirectPageIndirectIndexedByX:
+ case DirectPageIndirectIndexedByYLong:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByX:
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ case DirectPageIndirectIndexedByY:
+ cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
- int CPU::LDX(uint24_t addr)
+ int CPU::LDX(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.x_b) {
this->_registers.x = this->_bus->read(addr);
@@ -72,10 +109,23 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.x & 0xF000u;
}
this->_registers.p.z = this->_registers.x == 0x0;
- return 0;
+
+ int cycles = !this->_registers.p.x_b;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndexedByY:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
- int CPU::LDY(uint24_t addr)
+ int CPU::LDY(uint24_t addr, AddressingMode mode)
{
if (this->_registers.p.x_b) {
this->_registers.y = this->_bus->read(addr);
@@ -86,6 +136,19 @@ namespace ComSquare::CPU
this->_registers.p.n = this->_registers.y & 0xF000u;
}
this->_registers.p.z = this->_registers.y == 0x0;
- return 0;
+
+ int cycles = !this->_registers.p.x_b;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndexedByY:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByY:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
}
}
\ No newline at end of file
diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp
index 3e49685..4905071 100644
--- a/sources/CPU/Instructions/TransferRegisters.cpp
+++ b/sources/CPU/Instructions/TransferRegisters.cpp
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
- int CPU::TAX(uint24_t)
+ int CPU::TAX(uint24_t, AddressingMode)
{
if (this->_registers.p.x_b) {
this->_registers.xl = this->_registers.al;
@@ -20,7 +20,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::TAY(uint24_t)
+ int CPU::TAY(uint24_t, AddressingMode)
{
if (this->_registers.p.x_b) {
this->_registers.yl = this->_registers.al;
@@ -34,7 +34,7 @@ namespace ComSquare::CPU
return 0;
}
- int CPU::TXS(uint24_t)
+ int CPU::TXS(uint24_t, AddressingMode)
{
if (this->_registers.p.x_b) {
this->_registers.sh = 0;
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index f3e1aab..170fb23 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -344,7 +344,7 @@ namespace ComSquare::Debugger
return ss.str();
}
- int CPUDebug::RESB(uint24_t)
+ int CPUDebug::RESB()
{
CPU::RESB();
this->_updateRegistersPanel();
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index cb70e8e..fb04acb 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -170,7 +170,7 @@ namespace ComSquare::Debugger
//! @brief Return the current program counter of this CPU.
uint24_t getPC();
//! @brief Update the UI when resetting the CPU.
- int RESB(uint24_t) override;
+ int RESB() override;
//! @brief Convert a basic CPU to a debugging CPU.
explicit CPUDebug(ComSquare::CPU::CPU &cpu, SNES &snes);
CPUDebug(const CPUDebug &) = delete;
diff --git a/tests/CPU/Math/testADC.cpp b/tests/CPU/Math/testADC.cpp
index 67222fd..00a5106 100644
--- a/tests/CPU/Math/testADC.cpp
+++ b/tests/CPU/Math/testADC.cpp
@@ -14,7 +14,7 @@ Test(ADC, addingOne)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.a = 0;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 1, "The accumulator's value should be 0x1 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -28,7 +28,7 @@ Test(ADC, addingOneEmulation)
snes.cpu->_isEmulationMode = true;
snes.cpu->_registers.a = 0;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 1, "The accumulator's value should be 0x1 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -42,7 +42,7 @@ Test(ADC, overflow)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.a = 0xFFFF;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0, "The accumulator's value should be 0x0 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flags should be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -56,7 +56,7 @@ Test(ADC, overflowEmulation)
snes.cpu->_isEmulationMode = true;
snes.cpu->_registers.a = 0xFF;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0, "The accumulator's value should be 0x0 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flags should be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -70,7 +70,7 @@ Test(ADC, signedOverflow)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.a = 0x7FFF;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0x8000, "The accumulator's value should be 0x8000 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flags should be set.");
@@ -84,7 +84,7 @@ Test(ADC, signedOverflowEmulated)
snes.cpu->_isEmulationMode = true;
snes.cpu->_registers.a = 0x007F;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0x0080, "The accumulator's value should be 0x0080 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flags should be set.");
@@ -98,7 +98,7 @@ Test(ADC, negative)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.a = 0x8FFF;
snes.wram->_data[0] = 0x1;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0x9000, "The accumulator's value should be 0x9000 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should be set.");
@@ -114,7 +114,7 @@ Test(ADC, memoryTwoBytes)
snes.cpu->_registers.a = 0x000F;
snes.wram->_data[0] = 0x01;
snes.wram->_data[1] = 0x04;
- snes.cpu->ADC(0x0);
+ snes.cpu->ADC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0x0410, "The accumulator's value should be 0x0410 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
diff --git a/tests/CPU/Math/testSBC.cpp b/tests/CPU/Math/testSBC.cpp
index 22c2a9e..52b0186 100644
--- a/tests/CPU/Math/testSBC.cpp
+++ b/tests/CPU/Math/testSBC.cpp
@@ -15,7 +15,7 @@ Test(SBC, removingOne)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.a = 0x1;
snes.wram->_data[0] = 0x1;
- snes.cpu->SBC(0x0);
+ snes.cpu->SBC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0, "The accumulator's value should be 0x0 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flags should be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -32,7 +32,7 @@ Test(SBC, legitOverflowWithCarry)
snes.cpu->_registers.p.c = true;
snes.wram->_data[0] = 0x03;
snes.wram->_data[1] = 0x20;
- snes.cpu->SBC(0x0);
+ snes.cpu->SBC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0xDFFE, "The accumulator's value should be 0xDFFE but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -49,7 +49,7 @@ Test(SBC, overflowWithCarry)
snes.cpu->_registers.p.c = true;
snes.wram->_data[0] = 0x03;
snes.wram->_data[1] = 0x20;
- snes.cpu->SBC(0x0);
+ snes.cpu->SBC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0xDFFE, "The accumulator's value should be 0xDFFE but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should be not set.");
@@ -65,7 +65,7 @@ Test(SBC, overflowEmulation)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.p.c = false;
snes.wram->_data[0] = 0x02;
- snes.cpu->SBC(0x0);
+ snes.cpu->SBC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0xFE, "The accumulator's value should be 0xFE but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
@@ -83,7 +83,7 @@ Test(SBC, overflowEmulation)
// snes.cpu->_registers.p.m = false;
// snes.wram->_data[0] = 0x03;
// snes.wram->_data[1] = 0x20;
-// snes.cpu->SBC(0x0);
+// snes.cpu->SBC(0x0, ComSquare::CPU::AddressingMode::Implied);
// cr_assert_eq(snes.cpu->_registers.a, 0x7998, "The accumulator's value should be 0x7998 but it was 0x%x.", snes.cpu->_registers.a);
// cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flags should not be set.");
// cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flags should not be set.");
diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/TransferRegisters.cpp
index 5bb6c01..c840e2a 100644
--- a/tests/CPU/TransferRegisters.cpp
+++ b/tests/CPU/TransferRegisters.cpp
@@ -17,7 +17,7 @@ Test(TAX, 16bitsTo16Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.x = 0xABCD;
snes.cpu->_registers.a = 0xFEDC;
- snes.cpu->TAX(0x0);
+ snes.cpu->TAX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0xFEDC, "The flags should be 0xFEDC but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -31,7 +31,7 @@ Test(TAX, 16bitsTo8Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.x = 0xFEDC;
snes.cpu->_registers.a = 0xAB00;
- snes.cpu->TAX(0x0);
+ snes.cpu->TAX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0xFE00, "The flags should be 0xFE00 but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.");
@@ -45,7 +45,7 @@ Test(TAX, 8bitsTo16Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.x = 0xFEDC;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAX(0x0);
+ snes.cpu->TAX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0x00AB, "The flags should be 0x00AB but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -59,7 +59,7 @@ Test(TAX, 8bitsTo8Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.x = 0xFE;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAX(0x0);
+ snes.cpu->TAX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0xAB, "The flags should be 0xAB but it was %x", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -74,7 +74,7 @@ Test(TAY, 16bitsTo16Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.y = 0xABCD;
snes.cpu->_registers.a = 0xFEDC;
- snes.cpu->TAY(0x0);
+ snes.cpu->TAY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0xFEDC, "The y register should be 0xFEDC but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -88,7 +88,7 @@ Test(TAY, 16bitsTo8Bits)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.y = 0xFEDC;
snes.cpu->_registers.a = 0xAB00;
- snes.cpu->TAY(0x0);
+ snes.cpu->TAY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0xFE00, "The y register should be 0xFE00 but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.");
@@ -102,7 +102,7 @@ Test(TAY, 8bitsTo16Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.y = 0xFEDC;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAY(0x0);
+ snes.cpu->TAY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0x00AB, "The y register should be 0x00AB but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
@@ -116,7 +116,7 @@ Test(TAY, 8bitsTo8Bits)
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.y = 0xFE;
snes.cpu->_registers.a = 0xAB;
- snes.cpu->TAY(0x0);
+ snes.cpu->TAY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0xAB, "The y register should be 0xAB but it was %x", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -128,7 +128,7 @@ Test(TXS, 16bitsIndex)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.x = 0xABCD;
- snes.cpu->TXS(0x0);
+ snes.cpu->TXS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.s, 0xABCD, "The stack pointer should be 0xABCD but it was %x", snes.cpu->_registers.s);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
@@ -140,7 +140,7 @@ Test(TXS, 8bitsIndex)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.x = 0xABCD;
- snes.cpu->TXS(0x0);
+ snes.cpu->TXS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.s, 0x00CD, "The stack pointer should be 0x00CD but it was %x", snes.cpu->_registers.s);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set.");
diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp
index 04b3fe6..a06c7af 100644
--- a/tests/CPU/testBits.cpp
+++ b/tests/CPU/testBits.cpp
@@ -15,7 +15,7 @@ Test(AND, emulation)
snes.wram->_data[0] = 0x00;
snes.cpu->_registers.a = 0xFF;
snes.cpu->_isEmulationMode = true;
- snes.cpu->AND(0x0);
+ snes.cpu->AND(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0x00, "The flags should be 0x00 but it was %x", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
@@ -29,7 +29,7 @@ Test(AND, nativeNegative)
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.a = 0xFF00;
snes.cpu->_isEmulationMode = false;
- snes.cpu->AND(0x0);
+ snes.cpu->AND(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0xF000, "The flags should be 0xF000 but it was %x", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
@@ -42,7 +42,7 @@ Test(AND, emulationTest)
snes.wram->_data[0] = 0b00110011;
snes.cpu->_registers.a = 0b00110111;
snes.cpu->_isEmulationMode = true;
- snes.cpu->AND(0x0);
+ snes.cpu->AND(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.a, 0b00110011, "The flags should be 0b00110011 but it was %x", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp
index 42a3c40..0619ece 100644
--- a/tests/CPU/testInternal.cpp
+++ b/tests/CPU/testInternal.cpp
@@ -16,7 +16,7 @@ Test(SEP, setall)
{
Init()
snes.wram->_data[0] = 0xFF;
- snes.cpu->SEP(0x00);
+ snes.cpu->SEP(0x00, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0xFF, "The flag should be 0xFF but it was %x", data);
}
@@ -26,7 +26,7 @@ Test(SEP, setsome)
Init()
snes.cpu->_registers.p.flags = 0b01000000;
snes.wram->_data[0] = 0b10110101;
- snes.cpu->SEP(0x0);
+ snes.cpu->SEP(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b11110101, "The flag should be 245 but it was %i", data);
}
@@ -36,7 +36,7 @@ Test(REP, resetall)
Init()
snes.cpu->_isEmulationMode = false;
snes.wram->_data[0] = 0xFF;
- snes.cpu->REP(0x00);
+ snes.cpu->REP(0x00, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x00, "The flag should be 0x00 but it was %x", data);
}
@@ -47,7 +47,7 @@ Test(REP, resetsome)
snes.cpu->_isEmulationMode = false;
snes.cpu->_registers.p.flags = 0b01000000;
snes.wram->_data[0] = 0b01000000;
- snes.cpu->REP(0x0);
+ snes.cpu->REP(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x0, "The flag should be 0 but it was %x", data);
}
@@ -57,7 +57,7 @@ Test(REP, resetallEmulation)
Init()
snes.cpu->_isEmulationMode = true;
snes.wram->_data[0] = 0xFF;
- snes.cpu->REP(0x00);
+ snes.cpu->REP(0x00, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110000, "The flag should be 0b00110000 but it was %x", data);
}
@@ -68,7 +68,7 @@ Test(REP, resetsomeEmulation)
snes.cpu->_isEmulationMode = true;
snes.cpu->_registers.p.flags = 0b01000101;
snes.wram->_data[0] = 0b01000001;
- snes.cpu->REP(0x0);
+ snes.cpu->REP(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110100, "The flag should be 0b00110100 but it was %x", data);
}
@@ -78,7 +78,7 @@ Test(JSR, jump)
Init()
snes.cpu->_registers.pc = 0xABCD;
snes.cpu->_registers.s = 0x0123;
- snes.cpu->JSR(0xABFF);
+ snes.cpu->JSR(0xABFF, ComSquare::CPU::AddressingMode::Implied);
auto pc = snes.cpu->_registers.pc;
cr_assert_eq(pc, 0xABFF, "The PC should be 0xABFF but it was %x", pc);
cr_assert_eq(snes.cpu->_registers.s, 0x0121, "The stack pointer should be 0x0121 but it was %x", snes.cpu->_registers.s);
@@ -92,7 +92,7 @@ Test(JSL, jump)
snes.cpu->_registers.pbr = 0xFF;
snes.cpu->_registers.pc = 0xABCD;
snes.cpu->_registers.s = 0x0123;
- snes.cpu->JSL(0xCDABFF);
+ snes.cpu->JSL(0xCDABFF, ComSquare::CPU::AddressingMode::Implied);
auto pac = snes.cpu->_registers.pac;
cr_assert_eq(pac, 0xCDABFF, "The PC should be 0xCDABFF but it was %x", pac);
cr_assert_eq(snes.cpu->_registers.s, 0x0120, "The stack pointer should be 0x0120 but it was %x", snes.cpu->_registers.s);
@@ -105,7 +105,7 @@ Test(PHA, basic)
Init()
snes.cpu->_registers.a = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHA(0x0);
+ snes.cpu->PHA(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -116,7 +116,7 @@ Test(PHB, basic)
Init()
snes.cpu->_registers.dbr = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHB(0x0);
+ snes.cpu->PHB(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -126,7 +126,7 @@ Test(PHD, basic)
Init()
snes.cpu->_registers.d = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHD(0x0);
+ snes.cpu->PHD(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -137,7 +137,7 @@ Test(PHK, basic)
Init()
snes.cpu->_registers.pbr = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHK(0x0);
+ snes.cpu->PHK(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -147,7 +147,7 @@ Test(PHP, basic)
Init()
snes.cpu->_registers.p.flags = 0xFF;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHP(0x0);
+ snes.cpu->PHP(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[2], 0xFF, "The first value pushed to the stack should be 0xFF but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
}
@@ -157,7 +157,7 @@ Test(PHX, basic)
Init()
snes.cpu->_registers.x = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHX(0x0);
+ snes.cpu->PHX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -168,7 +168,7 @@ Test(PHY, basic)
Init()
snes.cpu->_registers.y = 0xABCD;
snes.cpu->_registers.s = 0x02;
- snes.cpu->PHY(0x0);
+ snes.cpu->PHY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]);
cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]);
cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s);
@@ -180,7 +180,8 @@ Test(PLA, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA(0x0);
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0x7BCD, "The accumulator should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -194,7 +195,8 @@ Test(PLA, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA(0x0);
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0x0000, "The accumulator should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -208,7 +210,8 @@ Test(PLA, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLA(0x0);
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.a;
cr_assert_eq(data, 0xA000, "The accumulator should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -222,7 +225,8 @@ Test(PLX, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x7BCD, "The X register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -236,7 +240,8 @@ Test(PLX, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x0000, "The x register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -250,7 +255,8 @@ Test(PLX, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLX(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0xA000, "The x register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -264,7 +270,8 @@ Test(PLY, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0x7BCD, "The Y register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -278,7 +285,8 @@ Test(PLY, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0x0000, "The y register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -292,7 +300,8 @@ Test(PLY, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLY(0x0);
+ snes.cpu->_registers.p.x_b = false;
+ snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.y;
cr_assert_eq(data, 0xA000, "The y register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -306,7 +315,7 @@ Test(PLD, basic)
snes.wram->_data[1] = 0xCD;
snes.wram->_data[2] = 0x7B;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD(0x0);
+ snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0x7BCD, "The D register should be 0x7BCD but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -320,7 +329,7 @@ Test(PLD, zero)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD(0x0);
+ snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0x0000, "The d register should be 0x0000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -334,7 +343,7 @@ Test(PLD, negative)
snes.wram->_data[1] = 0x00;
snes.wram->_data[2] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLD(0x0);
+ snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.d;
cr_assert_eq(data, 0xA000, "The D register should be 0xA000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -347,7 +356,7 @@ Test(PLB, basic)
Init()
snes.wram->_data[1] = 0x7D;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB(0x0);
+ snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0x7D, "The DBR should be 0x7D but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z);
@@ -360,7 +369,7 @@ Test(PLB, zero)
Init()
snes.wram->_data[1] = 0x00;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB(0x0);
+ snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0x00, "The dbr should be 0x00 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z);
@@ -373,7 +382,7 @@ Test(PLB, negative)
Init()
snes.wram->_data[1] = 0xA0;
snes.cpu->_registers.s = 0x00;
- snes.cpu->PLB(0x0);
+ snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.dbr;
cr_assert_eq(data, 0xA0, "The D register should be 0xA0 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z);
@@ -387,7 +396,7 @@ Test(PLP, basic)
snes.wram->_data[1] = 0x7D;
snes.cpu->_registers.s = 0x00;
snes.cpu->_isEmulationMode = false;
- snes.cpu->PLP(0x0);
+ snes.cpu->PLP(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0x7D, "The flags should be 0x7D but it was %x", data);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
@@ -399,7 +408,7 @@ Test(PLP, emulation)
snes.wram->_data[1] = 0x00;
snes.cpu->_registers.s = 0x00;
snes.cpu->_isEmulationMode = true;
- snes.cpu->PLP(0x0);
+ snes.cpu->PLP(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.p.flags;
cr_assert_eq(data, 0b00110000, "The flags should be 0b00110000 but it was %x", data);
cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s);
@@ -409,7 +418,7 @@ Test(CLC, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLC(0x0);
+ snes.cpu->CLC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
}
@@ -417,7 +426,7 @@ Test(CLI, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLI(0x0);
+ snes.cpu->CLI(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.i, false, "The interrupt flag should not be set");
}
@@ -425,7 +434,7 @@ Test(CLD, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLD(0x0);
+ snes.cpu->CLD(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set");
}
@@ -433,7 +442,7 @@ Test(CLV, clear)
{
Init()
snes.cpu->_registers.p.flags = 0xFF;
- snes.cpu->CLV(0x0);
+ snes.cpu->CLV(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flag should not be set");
}
@@ -441,7 +450,7 @@ Test(SEC, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SEC(0x0);
+ snes.cpu->SEC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
}
@@ -449,7 +458,7 @@ Test(SEI, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SEI(0x0);
+ snes.cpu->SEI(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.i, true, "The interrupt disabled flag should be set");
}
@@ -457,7 +466,7 @@ Test(SED, set)
{
Init()
snes.cpu->_registers.p.flags = 0x00;
- snes.cpu->SED(0x0);
+ snes.cpu->SED(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.d, true, "The decimal flag should be set");
}
@@ -469,7 +478,7 @@ Test(XCE, enableEmulation)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.xh = 0xFF;
snes.cpu->_registers.yh = 0xFF;
- snes.cpu->XCE(0x0);
+ snes.cpu->XCE(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_isEmulationMode, true, "The e flag should be set");
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.m, false, "The memory width flag should be untouched (unset)");
@@ -485,7 +494,7 @@ Test(XCE, enableNative)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.xh = 0xFF;
snes.cpu->_registers.yh = 0xFF;
- snes.cpu->XCE(0x0);
+ snes.cpu->XCE(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_isEmulationMode, false, "The e flag should be not set");
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
cr_assert_eq(snes.cpu->_registers.p.m, true, "The memory width flag should be set");
@@ -501,7 +510,7 @@ Test(INX, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.x = 0xFF;
- snes.cpu->INX(0x0);
+ snes.cpu->INX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0x0100, "The x register should be equal to 0x0100 but it was 0x%x.", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -514,7 +523,7 @@ Test(INX, 8bits)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.x = 0xFF;
- snes.cpu->INX(0x0);
+ snes.cpu->INX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.x, 0x00, "The x register should be equal to 0x00 but it was 0x%x.", snes.cpu->_registers.x);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -527,7 +536,7 @@ Test(INY, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.y = 0xFF;
- snes.cpu->INY(0x0);
+ snes.cpu->INY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0x0100, "The y register should be equal to 0x0100 but it was 0x%x.", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -540,7 +549,7 @@ Test(INY, 8bits)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.y = 0xFF;
- snes.cpu->INY(0x0);
+ snes.cpu->INY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.y, 0x00, "The y register should be equal to 0x00 but it was 0x%x.", snes.cpu->_registers.y);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
@@ -553,7 +562,7 @@ Test(CPX, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.x = 0xFF;
snes.wram->_data[0] = 0xFF;
- snes.cpu->CPX(0x0);
+ snes.cpu->CPX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
@@ -566,7 +575,7 @@ Test(CPX, negative)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.x = 0x80;
snes.wram->_data[0] = 0xFF;
- snes.cpu->CPX(0x0);
+ snes.cpu->CPX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set");
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
@@ -580,7 +589,7 @@ Test(CPX, 16bits)
snes.cpu->_registers.x = 0x8888;
snes.wram->_data[0] = 0x88;
snes.wram->_data[1] = 0x98;
- snes.cpu->CPX(0x0);
+ snes.cpu->CPX(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set");
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
@@ -593,7 +602,7 @@ Test(CPY, basic)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.y = 0xFF;
snes.wram->_data[0] = 0xFF;
- snes.cpu->CPY(0x0);
+ snes.cpu->CPY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set");
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set");
@@ -606,7 +615,7 @@ Test(CPY, negative)
snes.cpu->_registers.p.flags = 0;
snes.cpu->_registers.y = 0x80;
snes.wram->_data[0] = 0xFF;
- snes.cpu->CPY(0x0);
+ snes.cpu->CPY(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set");
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set");
cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set");
@@ -618,7 +627,7 @@ Test(BCC, basic)
snes.cpu->_registers.p.c = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BCC(0x0);
+ snes.cpu->BCC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -628,7 +637,7 @@ Test(BCC, negativeJump)
snes.cpu->_registers.p.c = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BCC(0x0);
+ snes.cpu->BCC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -638,7 +647,7 @@ Test(BCC, noJump)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BCC(0x0);
+ snes.cpu->BCC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -648,7 +657,7 @@ Test(BCS, basic)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BCS(0x0);
+ snes.cpu->BCS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -658,7 +667,7 @@ Test(BCS, negativeJump)
snes.cpu->_registers.p.c = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BCS(0x0);
+ snes.cpu->BCS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -668,7 +677,7 @@ Test(BCS, noJump)
snes.cpu->_registers.p.c = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BCS(0x0);
+ snes.cpu->BCS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -678,7 +687,7 @@ Test(BEQ, basic)
snes.cpu->_registers.p.z = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BEQ(0x0);
+ snes.cpu->BEQ(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -688,7 +697,7 @@ Test(BEQ, negativeJump)
snes.cpu->_registers.p.z = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BEQ(0x0);
+ snes.cpu->BEQ(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -698,7 +707,7 @@ Test(BEQ, noJump)
snes.cpu->_registers.p.z = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BEQ(0x0);
+ snes.cpu->BEQ(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -708,7 +717,7 @@ Test(BNE, basic)
snes.cpu->_registers.p.z = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BNE(0x0);
+ snes.cpu->BNE(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -718,7 +727,7 @@ Test(BNE, negativeJump)
snes.cpu->_registers.p.z = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BNE(0x0);
+ snes.cpu->BNE(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -728,7 +737,7 @@ Test(BNE, noJump)
snes.cpu->_registers.p.z = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BNE(0x0);
+ snes.cpu->BNE(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -738,7 +747,7 @@ Test(BMI, basic)
snes.cpu->_registers.p.n = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BMI(0x0);
+ snes.cpu->BMI(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -748,7 +757,7 @@ Test(BMI, negativeJump)
snes.cpu->_registers.p.n = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BMI(0x0);
+ snes.cpu->BMI(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -758,7 +767,7 @@ Test(BMI, noJump)
snes.cpu->_registers.p.n = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BMI(0x0);
+ snes.cpu->BMI(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -768,7 +777,7 @@ Test(BPL, basic)
snes.cpu->_registers.p.n = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BPL(0x0);
+ snes.cpu->BPL(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -778,7 +787,7 @@ Test(BPL, negativeJump)
snes.cpu->_registers.p.n = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BPL(0x0);
+ snes.cpu->BPL(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -788,7 +797,7 @@ Test(BPL, noJump)
snes.cpu->_registers.p.n = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BPL(0x0);
+ snes.cpu->BPL(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -797,7 +806,7 @@ Test(BRA, basic)
Init()
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BRA(0x0);
+ snes.cpu->BRA(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -806,7 +815,7 @@ Test(BRA, negativeJump)
Init()
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BRA(0x0);
+ snes.cpu->BRA(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -816,7 +825,7 @@ Test(BRL, basic)
snes.cpu->_registers.pc = 0x8080;
snes.wram->_data[0] = 0x00;
snes.wram->_data[1] = 0x10;
- snes.cpu->BRL(0x0);
+ snes.cpu->BRL(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x9080, "The program counter should be equal to 0x9080 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -826,7 +835,7 @@ Test(BRL, negativeJump)
snes.cpu->_registers.pc = 0x8080;
snes.wram->_data[0] = 0x00;
snes.wram->_data[1] = 0xF0;
- snes.cpu->BRL(0x0);
+ snes.cpu->BRL(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x7080, "The program counter should be equal to 0x7080 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -836,7 +845,7 @@ Test(BVC, basic)
snes.cpu->_registers.p.v = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BVC(0x0);
+ snes.cpu->BVC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -846,7 +855,7 @@ Test(BVC, negativeJump)
snes.cpu->_registers.p.v = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BVC(0x0);
+ snes.cpu->BVC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -856,7 +865,7 @@ Test(BVC, noJump)
snes.cpu->_registers.p.v = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BVC(0x0);
+ snes.cpu->BVC(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -867,7 +876,7 @@ Test(BVS, basic)
snes.cpu->_registers.p.v = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x50;
- snes.cpu->BVS(0x0);
+ snes.cpu->BVS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0xD0, "The program counter should be equal to 0xD0 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -877,7 +886,7 @@ Test(BVS, negativeJump)
snes.cpu->_registers.p.v = true;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0xF0;
- snes.cpu->BVS(0x0);
+ snes.cpu->BVS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x70, "The program counter should be equal to 0x70 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -887,7 +896,7 @@ Test(BVS, noJump)
snes.cpu->_registers.p.v = false;
snes.cpu->_registers.pc = 0x80;
snes.wram->_data[0] = 0x90;
- snes.cpu->BVS(0x0);
+ snes.cpu->BVS(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x80, "The program counter should be equal to 0x80 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -895,7 +904,7 @@ Test(JMP, simpleJump)
{
Init()
snes.cpu->_registers.pc = 0x8000;
- snes.cpu->JMP(0x1000);
+ snes.cpu->JMP(0x1000, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x1000, "The program counter should be equal to 0x9000 but it was 0x%x.", snes.cpu->_registers.pc);
}
@@ -903,6 +912,6 @@ Test(JML, simpleJump)
{
Init()
snes.cpu->_registers.pc = 0x8000;
- snes.cpu->JML(0x10AB00);
+ snes.cpu->JML(0x10AB00, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pac, 0x10AB00, "The program counter should be equal to 0x10AB00 but it was 0x%x.", snes.cpu->_registers.pac);
}
\ No newline at end of file
diff --git a/tests/CPU/testInterupts.cpp b/tests/CPU/testInterupts.cpp
index 659af73..cfb7a77 100644
--- a/tests/CPU/testInterupts.cpp
+++ b/tests/CPU/testInterupts.cpp
@@ -18,7 +18,7 @@ Test(CPU_emulated, BRK)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->BRK(0x0);
+ snes.cpu->BRK(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x15, "The PBR should be 0x15 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -38,7 +38,7 @@ Test(CPU_native, BRK)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->BRK(0x0);
+ snes.cpu->BRK(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x0, "The PBR should be 0x0 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -59,7 +59,7 @@ Test(CPU_emulated, COP)
snes.cpu->_registers.p.flags = 0x0F;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->COP(0x0);
+ snes.cpu->COP(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x15, "The PBR should be 0x15 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
@@ -79,7 +79,7 @@ Test(CPU_native, COP)
snes.cpu->_registers.p.flags = 0xF1;
snes.cpu->_registers.pc = 0x156u;
snes.cpu->_registers.pbr = 0x15;
- snes.cpu->COP(0x0);
+ snes.cpu->COP(0x0, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pc, 0x123u, "The program counter should be 0x123u but it was 0x%X", snes.cpu->_registers.pc);
cr_assert_eq(snes.cpu->_registers.pbr, 0x0, "The PBR should be 0x0 but it was 0x%X", snes.cpu->_registers.pbr);
cr_assert_eq(snes.cpu->_registers.p.d, false, "The decimal flag should not be set.");
diff --git a/tests/CPU/testStore.cpp b/tests/CPU/testStore.cpp
index 3bd0a97..4f0af93 100644
--- a/tests/CPU/testStore.cpp
+++ b/tests/CPU/testStore.cpp
@@ -14,7 +14,7 @@ Test(STA, 8bits)
Init()
snes.cpu->_registers.p.m = true;
snes.cpu->_registers.a = 0x11;
- snes.cpu->STA(0x0);
+ snes.cpu->STA(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0];
cr_assert_eq(data, 0x11, "The stored value should be 0x11 but it was 0x%x.", data);
}
@@ -24,7 +24,7 @@ Test(STA, 16bits)
Init()
snes.cpu->_registers.p.m = false;
snes.cpu->_registers.a = 0x11AB;
- snes.cpu->STA(0x0);
+ snes.cpu->STA(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0] + (snes.wram->_data[1] << 8u);
cr_assert_eq(data, 0x11AB, "The stored value should be 0x11AB but it was 0x%x.", data);
}
@@ -34,7 +34,7 @@ Test(STX, 8bits)
Init()
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.x = 0x11;
- snes.cpu->STX(0x0);
+ snes.cpu->STX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0];
cr_assert_eq(data, 0x11, "The stored value should be 0x11 but it was 0x%x.", data);
}
@@ -44,7 +44,7 @@ Test(STX, 16bits)
Init()
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.x = 0x11AB;
- snes.cpu->STX(0x0);
+ snes.cpu->STX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0] + (snes.wram->_data[1] << 8u);
cr_assert_eq(data, 0x11AB, "The stored value should be 0x11AB but it was 0x%x.", data);
}
@@ -54,7 +54,7 @@ Test(STY, 8bits)
Init()
snes.cpu->_registers.p.x_b = true;
snes.cpu->_registers.y = 0x11;
- snes.cpu->STY(0x0);
+ snes.cpu->STY(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0];
cr_assert_eq(data, 0x11, "The stored value should be 0x11 but it was 0x%x.", data);
}
@@ -64,7 +64,7 @@ Test(STY, 16bits)
Init()
snes.cpu->_registers.p.x_b = false;
snes.cpu->_registers.y = 0x11AB;
- snes.cpu->STY(0x0);
+ snes.cpu->STY(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0] + (snes.wram->_data[1] << 8u);
cr_assert_eq(data, 0x11AB, "The stored value should be 0x11AB but it was 0x%x.", data);
}
@@ -74,7 +74,7 @@ Test(STZ, 8bits)
Init()
snes.cpu->_registers.p.m = true;
snes.wram->_data[0] = 0x11;
- snes.cpu->STZ(0x0);
+ snes.cpu->STZ(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0];
cr_assert_eq(data, 0x00, "The stored value should be 0x00 but it was 0x%x.", data);
}
@@ -85,7 +85,7 @@ Test(STZ, 16bits)
snes.cpu->_registers.p.m = false;
snes.wram->_data[0] = 0x11;
snes.wram->_data[1] = 0x11;
- snes.cpu->STZ(0x0);
+ snes.cpu->STZ(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.wram->_data[0] + (snes.wram->_data[1] << 8u);
cr_assert_eq(data, 0x00, "The stored value should be 0x00 but it was 0x%x.", data);
}
@@ -95,7 +95,7 @@ Test(LDX, 8bits)
Init()
snes.cpu->_registers.p.x_b = true;
snes.wram->_data[0] = 0x01;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x01, "The stored value should be 0x01 but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag register should not be set.");
@@ -107,7 +107,7 @@ Test(LDX, 8bitsNegative)
Init()
snes.cpu->_registers.p.x_b = true;
snes.wram->_data[0] = 0x11;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x11, "The stored value should be 0x11 but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag register should not be set.");
@@ -120,7 +120,7 @@ Test(LDX, 8bitsZero)
snes.cpu->_registers.p.x_b = true;
snes.wram->_data[0] = 0x00;
snes.wram->_data[1] = 0x11;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x00, "The stored value should be 0x00 but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag register should be set.");
@@ -133,7 +133,7 @@ Test(LDX, 16bits)
snes.cpu->_registers.p.x_b = false;
snes.wram->_data[0] = 0xAB;
snes.wram->_data[1] = 001;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x01AB, "The stored value should be 0x01AB but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag register should not be set.");
@@ -146,7 +146,7 @@ Test(LDX, 16bitsNegative)
snes.cpu->_registers.p.x_b = false;
snes.wram->_data[0] = 0xAB;
snes.wram->_data[1] = 0x11;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x11AB, "The stored value should be 0x11AB but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag register should not be set.");
@@ -159,7 +159,7 @@ Test(LDX, 16bitsZero)
snes.cpu->_registers.p.x_b = false;
snes.wram->_data[0] = 0x00;
snes.wram->_data[1] = 0x00;
- snes.cpu->LDX(0x0);
+ snes.cpu->LDX(0x0, ComSquare::CPU::AddressingMode::Implied);
auto data = snes.cpu->_registers.x;
cr_assert_eq(data, 0x0000, "The stored value should be 0x0000 but it was 0x%x.", data);
cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag register should be set.");
From 4f56cef3f23a692a8afb135d9443388f31cda822 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 20:49:18 +0100
Subject: [PATCH 15/17] Re-enbaling the APU
---
sources/SNES.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sources/SNES.cpp b/sources/SNES.cpp
index 7274243..bcbce3c 100644
--- a/sources/SNES.cpp
+++ b/sources/SNES.cpp
@@ -31,7 +31,7 @@ namespace ComSquare
{
unsigned cycleCount = this->cpu->update();
this->ppu->update(cycleCount);
-// this->apu->update(cycleCount);
+ this->apu->update(cycleCount);
}
void SNES::enableCPUDebugging(bool pause)
From 15f6b85d9a8e8d1c17f3abafeef26f2c9caa623e Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 20:51:42 +0100
Subject: [PATCH 16/17] Cleaning the CMake
---
CMakeLists.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 41f0df3..17a4bc3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -202,7 +202,10 @@ add_executable(ComSquare
sources/Debugger/MemoryBusDebug.cpp
sources/Debugger/MemoryBusDebug.hpp
sources/Debugger/ClosableWindow.hpp
- sources/Models/Components.hpp sources/CPU/Instruction.hpp sources/Exceptions/DebuggableError.hpp)
+ sources/Models/Components.hpp
+ sources/CPU/Instruction.hpp
+ sources/Exceptions/DebuggableError.hpp
+)
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
From 686b70dbfdc601a61f018db493ce3bc7a00828cc Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 21:32:43 +0100
Subject: [PATCH 17/17] Oups
---
sources/APU/APU.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp
index 1136d8c..cc56ec6 100644
--- a/sources/APU/APU.cpp
+++ b/sources/APU/APU.cpp
@@ -713,7 +713,6 @@ namespace ComSquare::APU
cycles -= this->_paddingCycles;
while (total < cycles && this->_state == Running)
total += this->_executeInstruction();
- std::cout << "Done." << std::endl;
if (this->_state == Running)
this->_paddingCycles = total - cycles;
}