From 7407c3cfaaeefc6896160269fea6a6dab8e466c4 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Fri, 3 Apr 2020 14:32:18 +0200
Subject: [PATCH] Implementing missing addressings modes inside the debugger
---
CMakeLists.txt | 6 +-
sources/CPU/AddressingModes.cpp | 16 --
sources/CPU/CPU.cpp | 6 -
sources/CPU/CPU.hpp | 4 -
sources/CPU/Instruction.hpp | 3 -
sources/Debugger/{ => CPU}/CPUDebug.cpp | 152 +-----------
sources/Debugger/{ => CPU}/CPUDebug.hpp | 45 +++-
sources/Debugger/CPU/Disassembly.cpp | 272 +++++++++++++++++++++
sources/SNES.cpp | 2 +-
tests/CPU/testAddressingMode.cpp | 78 +++---
ui/ui_cpu.h | 306 ++++++++++++++++++++++++
11 files changed, 659 insertions(+), 231 deletions(-)
rename sources/Debugger/{ => CPU}/CPUDebug.cpp (71%)
rename sources/Debugger/{ => CPU}/CPUDebug.hpp (77%)
create mode 100644 sources/Debugger/CPU/Disassembly.cpp
create mode 100644 ui/ui_cpu.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17a4bc3..4f38620 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -159,8 +159,8 @@ add_executable(ComSquare
sources/CPU/Instructions/InternalInstruction.cpp
sources/Ram/ExtendedRam.cpp
sources/Ram/ExtendedRam.hpp
- sources/Debugger/CPUDebug.cpp
- sources/Debugger/CPUDebug.hpp
+ sources/Debugger/CPU/CPUDebug.cpp
+ sources/Debugger/CPU/CPUDebug.hpp
sources/Renderer/QtRenderer/QtSFML.cpp
sources/Renderer/QtRenderer/QtSFML.hpp
sources/Renderer/QtRenderer/QtWidgetSFML.cpp
@@ -205,7 +205,7 @@ add_executable(ComSquare
sources/Models/Components.hpp
sources/CPU/Instruction.hpp
sources/Exceptions/DebuggableError.hpp
-)
+ sources/Debugger/CPU/Disassembly.cpp)
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp
index 4cba032..d19a985 100644
--- a/sources/CPU/AddressingModes.cpp
+++ b/sources/CPU/AddressingModes.cpp
@@ -126,22 +126,6 @@ namespace ComSquare::CPU
return lng + this->_registers.x;
}
- uint24_t CPU::_getProgramCounterRelativeAddr()
- {
- uint24_t pc = 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->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->readPC();
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index ccb315e..9fdb770 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -287,12 +287,6 @@ namespace ComSquare::CPU
valueAddr = this->_getStackRelativeIndirectIndexedYAddr();
break;
- case ProgramCounterRelative:
- valueAddr = this->_getProgramCounterRelativeAddr();
- break;
- case ProgramCounterRelativeLong:
- valueAddr = this->_getProgramCounterRelativeLongAddr();
- break;
case AbsoluteIndirectIndexedByX:
valueAddr = this->_getAbsoluteIndirectIndexedByXAddr();
break;
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index e9159ba..6c60e09 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -226,10 +226,6 @@ namespace ComSquare::CPU
uint24_t _getAbsoluteIndexedByYAddr();
//! @brief The effective address is formed by adding the with X.
uint24_t _getAbsoluteIndexedByXLongAddr();
- //! @brief The <8-bit signed exp> is added to PC (program counter) to form the new location.
- uint24_t _getProgramCounterRelativeAddr();
- //! @brief The <16-bit signed exp> is added to PC (program counter) to form the new location.
- uint24_t _getProgramCounterRelativeLongAddr();
//! @brief 2 bytes are pulled from the to form the effective address.
uint24_t _getAbsoluteIndirectAddr();
//! @brief 3 bytes are pulled from the to form the effective address.
diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp
index 5af02f4..8061d1e 100644
--- a/sources/CPU/Instruction.hpp
+++ b/sources/CPU/Instruction.hpp
@@ -41,9 +41,6 @@ namespace ComSquare::CPU
StackRelativeIndirectIndexedByY,
- ProgramCounterRelative,
- ProgramCounterRelativeLong,
-
AbsoluteIndirect,
AbsoluteIndirectIndexedByX,
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp
similarity index 71%
rename from sources/Debugger/CPUDebug.cpp
rename to sources/Debugger/CPU/CPUDebug.cpp
index 1eb696d..098c434 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPU/CPUDebug.cpp
@@ -3,9 +3,9 @@
//
#include "CPUDebug.hpp"
-#include "../Utility/Utility.hpp"
-#include "../Exceptions/InvalidOpcode.hpp"
-#include "../CPU/CPU.hpp"
+#include "../../Utility/Utility.hpp"
+#include "../../Exceptions/InvalidOpcode.hpp"
+#include "../../CPU/CPU.hpp"
#include
#include
#include
@@ -221,133 +221,6 @@ namespace ComSquare::Debugger
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;
-
- 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)
- 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.level = Compromised;
- }
- if (instruction.opcode == 0xFB) {// XCE
- 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.
- }
- }
- 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 (dual)
- 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;
- ss << "$" << std::hex << static_cast(this->_bus->read(pc, true));
- return ss.str();
- }
-
- std::string CPUDebug::_getAbsoluteValue(uint24_t pc)
- {
- std::stringstream ss;
- ss << "$" << std::hex << (this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u));
- return ss.str();
- }
-
- std::string CPUDebug::_getAbsoluteLongValue(uint24_t pc)
- {
- unsigned value = this->_bus->read(pc++, true);
- value += this->_bus->read(pc++, true) << 8u;
- value += this->_bus->read(pc, true) << 16u;
-
- std::stringstream ss;
- ss << "$" << std::hex << value;
- return ss.str();
- }
-
- std::string CPUDebug::_getDirectIndexedByXValue(uint24_t pc)
- {
- unsigned value = this->_bus->read(pc, true);
-
- std::stringstream ss;
- ss << "$" << std::hex << value << ", x";
- return ss.str();
- }
-
int CPUDebug::RESB()
{
CPU::RESB();
@@ -366,14 +239,6 @@ namespace ComSquare::Debugger
{
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), level(Safe) {}
-
- std::string DisassembledInstruction::toString()
- {
- return this->name + " " + this->argument;
- }
}
DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstractTableModel(), _cpu(cpu){ }
@@ -420,17 +285,6 @@ QVariant DisassemblyModel::headerData(int section, Qt::Orientation orientation,
return QString(ComSquare::Utility::to_hex(instruction.address, ComSquare::Utility::HexString::NoPrefix).c_str());
}
-void DisassemblyModel::beginReset()
-{
- this->beginResetModel();
-}
-
-void DisassemblyModel::endReset()
-{
- this->endResetModel();
- emit this->dataChanged(this->index(0, 0), this->index(this->_cpu.disassembledInstructions.size(), this->columnCount(QModelIndex())));
-}
-
RowPainter::RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent) : QStyledItemDelegate(parent), _cpu(cpu) { }
void RowPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPU/CPUDebug.hpp
similarity index 77%
rename from sources/Debugger/CPUDebug.hpp
rename to sources/Debugger/CPU/CPUDebug.hpp
index 6d7ab99..469ffe1 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPU/CPUDebug.hpp
@@ -6,11 +6,11 @@
#define COMSQUARE_CPUDEBUG_HPP
#include
-#include "../CPU/CPU.hpp"
-#include "../Renderer/SFRenderer.hpp"
-#include "../SNES.hpp"
-#include "../../ui/ui_cpu.h"
-#include "ClosableWindow.hpp"
+#include "../../CPU/CPU.hpp"
+#include "../../Renderer/SFRenderer.hpp"
+#include "../../SNES.hpp"
+#include "../../../ui/ui_cpu.h"
+#include "../ClosableWindow.hpp"
namespace ComSquare::Debugger
{
@@ -37,9 +37,6 @@ public:
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;
-
- void beginReset();
- void endReset();
};
//! @brief The qt class that highlight breakpoints and the PC's position
@@ -144,14 +141,42 @@ 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 direct addressing mode.
- std::string _getDirectValue(uint24_t pc);
//! @brief Return a printable string corresponding to the value of an absolute addressing mode.
std::string _getAbsoluteValue(uint24_t pc);
//! @brief Return a printable string corresponding to the value of an absolute long addressing mode.
std::string _getAbsoluteLongValue(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 a direct indirect addressing mode.
+ std::string _getDirectIndirectValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a direct indirect long addressing mode.
+ std::string _getDirectIndirectLongValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indexed by x addressing mode.
+ std::string _getAbsoluteIndexByXValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indexed by x long addressing mode.
+ std::string _getAbsoluteIndexByXLongValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indexed by y addressing mode.
+ std::string _getAbsoluteIndexByYValue(uint24_t pc);
//! @brief Return a printable string corresponding to the value of a direct index by x addressing mode.
std::string _getDirectIndexedByXValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a direct index by y addressing mode.
+ std::string _getDirectIndexedByYValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a direct indirect index by x addressing mode.
+ std::string _getDirectIndexedByXIndirectValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a direct indirect index by y addressing mode.
+ std::string _getDirectIndirectIndexedByYValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a direct indirect index by y long addressing mode.
+ std::string _getDirectIndirectIndexedByYLongValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a stack relative addressing mode.
+ std::string _getStackRelativeValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a stack relative indirect indexed by y addressing mode.
+ std::string _getStackRelativeIndiretIndexdeByYValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indirect addressing mode.
+ std::string _getAbsoluteIndirectValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indirect indexed by x addressing mode.
+ std::string _getAbsoluteIndirectIndexedByXValue(uint24_t pc);
+ //! @brief Return a printable string corresponding to the value of a absolute indirect long addressing mode.
+ std::string _getAbsoluteIndirectLongValue(uint24_t pc);
public:
//! @brief Pause/Resume the CPU.
diff --git a/sources/Debugger/CPU/Disassembly.cpp b/sources/Debugger/CPU/Disassembly.cpp
new file mode 100644
index 0000000..7541dd7
--- /dev/null
+++ b/sources/Debugger/CPU/Disassembly.cpp
@@ -0,0 +1,272 @@
+//
+// Created by anonymus-raccoon on 4/3/20.
+//
+
+#include
+#include "CPUDebug.hpp"
+#include "../../Utility/Utility.hpp"
+
+using namespace ComSquare::CPU;
+
+namespace ComSquare::Debugger
+{
+ 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), level(Safe) {}
+
+ std::string DisassembledInstruction::toString()
+ {
+ return this->name + " " + this->argument;
+ }
+
+ std::vector CPUDebug::_disassemble(uint24_t pc, uint24_t length, DisassemblyContext &ctx)
+ {
+ std::vector map;
+ uint24_t endAddr = pc + length;
+
+ 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)
+ 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.level = Compromised;
+ }
+ if (instruction.opcode == 0xFB) {// XCE
+ 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.
+ }
+ }
+ 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 Immediate8bits:
+ return this->_getImmediateValue(pc, false);
+ case ImmediateForA:
+ return this->_getImmediateValue(pc, !ctx.mFlag);
+ case ImmediateForX:
+ return this->_getImmediateValue(pc, !ctx.xFlag);
+
+ case Absolute:
+ return this->_getAbsoluteValue(pc);
+ case AbsoluteLong:
+ return this->_getAbsoluteLongValue(pc);
+
+ case DirectPage:
+ return this->_getDirectValue(pc);
+ case DirectPageIndexedByX:
+ return this->_getDirectIndexedByXValue(pc);
+
+ case DirectPageIndirect:
+ return this->_getDirectIndirectValue(pc);
+ case DirectPageIndirectLong:
+ return this->_getDirectIndirectLongValue(pc);
+ case AbsoluteIndexedByX:
+ return this->_getAbsoluteIndexByXValue(pc);
+ case AbsoluteIndexedByXLong:
+ return this->_getAbsoluteIndexByXLongValue(pc);
+ case AbsoluteIndexedByY:
+ return this->_getAbsoluteIndexByYValue(pc);
+ case DirectPageIndexedByY:
+ return this->_getDirectIndexedByYValue(pc);
+ case DirectPageIndirectIndexedByX:
+ return this->_getDirectIndexedByXIndirectValue(pc);
+ case DirectPageIndirectIndexedByY:
+ return this->_getDirectIndirectIndexedByYValue(pc);
+ case DirectPageIndirectIndexedByYLong:
+ return this->_getDirectIndirectIndexedByYLongValue(pc);
+ case StackRelative:
+ return this->_getStackRelativeValue(pc);
+ case StackRelativeIndirectIndexedByY:
+ return this->_getStackRelativeIndiretIndexdeByYValue(pc);
+ case AbsoluteIndirect:
+ return this->_getAbsoluteIndirectValue(pc);
+ case AbsoluteIndirectIndexedByX:
+ return this->_getAbsoluteIndirectIndexedByXValue(pc);
+ case AbsoluteIndirectLong:
+ return this->_getAbsoluteIndirectLongValue(pc);
+
+ default:
+ return "???";
+ }
+ }
+
+ std::string CPUDebug::_getImmediateValue(uint24_t pc, bool dual)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ if (dual)
+ 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)
+ {
+ return Utility::to_hex(this->_bus->read(pc, true), Utility::HexString::AsmPrefix);
+ }
+
+ std::string CPUDebug::_getAbsoluteValue(uint24_t pc)
+ {
+ uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u);
+ return Utility::to_hex(value, Utility::HexString::AsmPrefix);
+ }
+
+ std::string CPUDebug::_getAbsoluteLongValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc++, true);
+ value += this->_bus->read(pc++, true) << 8u;
+ value += this->_bus->read(pc, true) << 16u;
+
+ return Utility::to_hex(value, Utility::HexString::AsmPrefix);
+ }
+
+ std::string CPUDebug::_getDirectIndexedByXValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ std::stringstream ss;
+ ss << "$" << std::hex << value << ", x";
+ return ss.str();
+ }
+
+ std::string CPUDebug::_getDirectIndexedByYValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ std::stringstream ss;
+ ss << "$" << std::hex << value << ", y";
+ return ss.str();
+ }
+
+ std::string CPUDebug::_getDirectIndirectValue(uint24_t pc)
+ {
+ return "(" + Utility::to_hex(this->_bus->read(pc, true), Utility::AsmPrefix) + ")";
+ }
+
+ std::string CPUDebug::_getDirectIndirectLongValue(uint24_t pc)
+ {
+ return "[" + Utility::to_hex(this->_bus->read(pc, true), Utility::AsmPrefix) + "]";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndexByXValue(uint24_t pc)
+ {
+ uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u);
+ return Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", x";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndexByYValue(uint24_t pc)
+ {
+ uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u);
+ return Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", y";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndexByXLongValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc++, true);
+ value += this->_bus->read(pc++, true) << 8u;
+ value += this->_bus->read(pc, true) << 16u;
+
+ return Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", x";
+ }
+
+ std::string CPUDebug::_getDirectIndexedByXIndirectValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ std::stringstream ss;
+ ss << "($" << std::hex << value << ", x)";
+ return ss.str();
+ }
+
+ std::string CPUDebug::_getDirectIndirectIndexedByYValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ std::stringstream ss;
+ ss << "($" << std::hex << value << "), y";
+ return ss.str();
+ }
+
+ std::string CPUDebug::_getDirectIndirectIndexedByYLongValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc, true);
+
+ std::stringstream ss;
+ ss << "[$" << std::hex << value << "], y";
+ return ss.str();
+ }
+
+ std::string CPUDebug::_getStackRelativeValue(uint24_t pc)
+ {
+ return Utility::to_hex(this->_bus->read(pc, true), Utility::AsmPrefix) + ", s";
+ }
+
+ std::string CPUDebug::_getStackRelativeIndiretIndexdeByYValue(uint24_t pc)
+ {
+ return "(" + Utility::to_hex(this->_bus->read(pc, true), Utility::AsmPrefix) + ", s), y";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndirectValue(uint24_t pc)
+ {
+ uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u);
+ return "(" + Utility::to_hex(value, Utility::HexString::AsmPrefix) + ")";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndirectLongValue(uint24_t pc)
+ {
+ unsigned value = this->_bus->read(pc++, true);
+ value += this->_bus->read(pc++, true) << 8u;
+ value += this->_bus->read(pc, true) << 16u;
+
+ return "(" + Utility::to_hex(value, Utility::HexString::AsmPrefix) + ")";
+ }
+
+ std::string CPUDebug::_getAbsoluteIndirectIndexedByXValue(uint24_t pc)
+ {
+ uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u);
+ return "(" + Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", x)";
+ }
+}
\ No newline at end of file
diff --git a/sources/SNES.cpp b/sources/SNES.cpp
index bcbce3c..0687305 100644
--- a/sources/SNES.cpp
+++ b/sources/SNES.cpp
@@ -6,7 +6,7 @@
#include
#include "SNES.hpp"
#ifdef DEBUGGER_ENABLED
-#include "Debugger/CPUDebug.hpp"
+#include "Debugger/CPU/CPUDebug.hpp"
#include "Debugger/APUDebug.hpp"
#include "Debugger/MemoryBusDebug.hpp"
diff --git a/tests/CPU/testAddressingMode.cpp b/tests/CPU/testAddressingMode.cpp
index 485366e..f4ed3e4 100644
--- a/tests/CPU/testAddressingMode.cpp
+++ b/tests/CPU/testAddressingMode.cpp
@@ -181,45 +181,45 @@ Test(AddrMode, AbsoluteLongIndexByX)
cr_assert_eq(snes.cpu->_registers.pac, 0x808003);
}
-Test(AddrMode, ProgramCounterRelativePositive)
-{
- Init()
- snes.cpu->_registers.pac = 0x808010;
- snes.cartridge->_data[0x10] = 0x15;
- cr_assert_eq(snes.cpu->_getProgramCounterRelativeAddr(), 0x808025, "Returned address was %x but was expecting 0x808025.", snes.cpu->_getProgramCounterRelativeAddr());
- cr_assert_eq(snes.cpu->_registers.pac, 0x808011);
-}
-
-Test(AddrMode, ProgramCounterRelativeNegative)
-{
- Init()
- snes.cpu->_registers.pac = 0x808010;
- snes.cartridge->_data[0x10] = -0x15;
- cr_assert_eq(snes.cpu->_getProgramCounterRelativeAddr(), 0x807FFB, "Returned address was %x but was expecting 0x807FFB.", snes.cpu->_getProgramCounterRelativeAddr());
- cr_assert_eq(snes.cpu->_registers.pac, 0x808011);
-}
-
-Test(AddrMode, ProgramCounterRelativeLongPositive)
-{
- Init()
- snes.cpu->_registers.pac = 0x808010;
- snes.cartridge->_data[0x10] = 0x15;
- snes.cartridge->_data[0x11] = 0x10;
- auto addr = snes.cpu->_getProgramCounterRelativeLongAddr();
- cr_assert_eq(addr, 0x809025, "Returned address was %x but was expecting 0x809025.", addr);
- cr_assert_eq(snes.cpu->_registers.pac, 0x808012);
-}
-
-Test(AddrMode, ProgramCounterRelativeLongNegative)
-{
- Init()
- snes.cpu->_registers.pac = 0x808010;
- snes.cartridge->_data[0x10] = 0x10;
- snes.cartridge->_data[0x11] = -0x15;
- auto addr = snes.cpu->_getProgramCounterRelativeLongAddr();
- cr_assert_eq(addr, 0x806B00, "Returned address was %x but was expecting 0x806B00.", addr);
- cr_assert_eq(snes.cpu->_registers.pac, 0x808012);
-}
+//Test(AddrMode, ProgramCounterRelativePositive)
+//{
+// Init()
+// snes.cpu->_registers.pac = 0x808010;
+// snes.cartridge->_data[0x10] = 0x15;
+// cr_assert_eq(snes.cpu->_getProgramCounterRelativeAddr(), 0x808025, "Returned address was %x but was expecting 0x808025.", snes.cpu->_getProgramCounterRelativeAddr());
+// cr_assert_eq(snes.cpu->_registers.pac, 0x808011);
+//}
+//
+//Test(AddrMode, ProgramCounterRelativeNegative)
+//{
+// Init()
+// snes.cpu->_registers.pac = 0x808010;
+// snes.cartridge->_data[0x10] = -0x15;
+// cr_assert_eq(snes.cpu->_getProgramCounterRelativeAddr(), 0x807FFB, "Returned address was %x but was expecting 0x807FFB.", snes.cpu->_getProgramCounterRelativeAddr());
+// cr_assert_eq(snes.cpu->_registers.pac, 0x808011);
+//}
+//
+//Test(AddrMode, ProgramCounterRelativeLongPositive)
+//{
+// Init()
+// snes.cpu->_registers.pac = 0x808010;
+// snes.cartridge->_data[0x10] = 0x15;
+// snes.cartridge->_data[0x11] = 0x10;
+// auto addr = snes.cpu->_getProgramCounterRelativeLongAddr();
+// cr_assert_eq(addr, 0x809025, "Returned address was %x but was expecting 0x809025.", addr);
+// cr_assert_eq(snes.cpu->_registers.pac, 0x808012);
+//}
+//
+//Test(AddrMode, ProgramCounterRelativeLongNegative)
+//{
+// Init()
+// snes.cpu->_registers.pac = 0x808010;
+// snes.cartridge->_data[0x10] = 0x10;
+// snes.cartridge->_data[0x11] = -0x15;
+// auto addr = snes.cpu->_getProgramCounterRelativeLongAddr();
+// cr_assert_eq(addr, 0x806B00, "Returned address was %x but was expecting 0x806B00.", addr);
+// cr_assert_eq(snes.cpu->_registers.pac, 0x808012);
+//}
Test(AddrMode, AbsoluteIndirect)
{
diff --git a/ui/ui_cpu.h b/ui/ui_cpu.h
new file mode 100644
index 0000000..50bfe74
--- /dev/null
+++ b/ui/ui_cpu.h
@@ -0,0 +1,306 @@
+/********************************************************************************
+** Form generated from reading UI file 'cpu.ui'
+**
+** Created by: Qt User Interface Compiler version 5.14.1
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_CPU_H
+#define UI_CPU_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+class Ui_CPUView
+{
+public:
+ QAction *actionPause;
+ QAction *actionStep;
+ QAction *actionNext;
+ QWidget *centralwidget;
+ QGridLayout *gridLayout_2;
+ QTableView *disassembly;
+ QFormLayout *formLayout;
+ QLabel *accumulatorLabel;
+ QLineEdit *accumulatorLineEdit;
+ QLabel *programBankRegisterLabel;
+ QLineEdit *programBankRegisterLineEdit;
+ QLabel *programCounterLabel;
+ QLineEdit *programCounterLineEdit;
+ QLabel *directBankLabel;
+ QLineEdit *directBankLineEdit;
+ QLabel *directPageLabel;
+ QLineEdit *directPageLineEdit;
+ QLabel *stackPointerLabel;
+ QLineEdit *stackPointerLineEdit;
+ QLabel *xIndexLabel;
+ QLineEdit *xIndexLineEdit;
+ QLabel *yIndexLabel;
+ QLineEdit *yIndexLineEdit;
+ QLabel *flagsLabel;
+ QLineEdit *flagsLineEdit;
+ QLabel *emulationModeLabel;
+ QCheckBox *emulationModeCheckBox;
+ QGridLayout *gridLayout;
+ QPushButton *clear;
+ QLabel *loggerLabel;
+ QTextBrowser *logger;
+ QToolBar *toolBar;
+
+ void setupUi(QMainWindow *CPUView)
+ {
+ if (CPUView->objectName().isEmpty())
+ CPUView->setObjectName(QString::fromUtf8("CPUView"));
+ CPUView->resize(971, 709);
+ QIcon icon;
+ icon.addFile(QString::fromUtf8(":/resources/Logo.png"), QSize(), QIcon::Normal, QIcon::Off);
+ CPUView->setWindowIcon(icon);
+ CPUView->setAutoFillBackground(false);
+ actionPause = new QAction(CPUView);
+ actionPause->setObjectName(QString::fromUtf8("actionPause"));
+ QIcon icon1;
+ icon1.addFile(QString::fromUtf8(":/resources/icons/play.svg"), QSize(), QIcon::Normal, QIcon::Off);
+ actionPause->setIcon(icon1);
+ actionStep = new QAction(CPUView);
+ actionStep->setObjectName(QString::fromUtf8("actionStep"));
+ QIcon icon2;
+ icon2.addFile(QString::fromUtf8(":/resources/icons/step.svg"), QSize(), QIcon::Normal, QIcon::Off);
+ actionStep->setIcon(icon2);
+ actionNext = new QAction(CPUView);
+ actionNext->setObjectName(QString::fromUtf8("actionNext"));
+ QIcon icon3;
+ icon3.addFile(QString::fromUtf8(":/resources/icons/continue.svg"), QSize(), QIcon::Normal, QIcon::Off);
+ actionNext->setIcon(icon3);
+ centralwidget = new QWidget(CPUView);
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
+ gridLayout_2 = new QGridLayout(centralwidget);
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
+ disassembly = new QTableView(centralwidget);
+ disassembly->setObjectName(QString::fromUtf8("disassembly"));
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ sizePolicy.setHorizontalStretch(1);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(disassembly->sizePolicy().hasHeightForWidth());
+ disassembly->setSizePolicy(sizePolicy);
+ disassembly->setStyleSheet(QString::fromUtf8(""));
+ disassembly->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ disassembly->setSelectionBehavior(QAbstractItemView::SelectRows);
+ disassembly->setShowGrid(false);
+ disassembly->setGridStyle(Qt::NoPen);
+ disassembly->horizontalHeader()->setVisible(false);
+ disassembly->horizontalHeader()->setHighlightSections(false);
+
+ gridLayout_2->addWidget(disassembly, 0, 0, 2, 1);
+
+ formLayout = new QFormLayout();
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
+ accumulatorLabel = new QLabel(centralwidget);
+ accumulatorLabel->setObjectName(QString::fromUtf8("accumulatorLabel"));
+
+ formLayout->setWidget(0, QFormLayout::LabelRole, accumulatorLabel);
+
+ accumulatorLineEdit = new QLineEdit(centralwidget);
+ accumulatorLineEdit->setObjectName(QString::fromUtf8("accumulatorLineEdit"));
+
+ formLayout->setWidget(0, QFormLayout::FieldRole, accumulatorLineEdit);
+
+ programBankRegisterLabel = new QLabel(centralwidget);
+ programBankRegisterLabel->setObjectName(QString::fromUtf8("programBankRegisterLabel"));
+
+ formLayout->setWidget(1, QFormLayout::LabelRole, programBankRegisterLabel);
+
+ programBankRegisterLineEdit = new QLineEdit(centralwidget);
+ programBankRegisterLineEdit->setObjectName(QString::fromUtf8("programBankRegisterLineEdit"));
+
+ formLayout->setWidget(1, QFormLayout::FieldRole, programBankRegisterLineEdit);
+
+ programCounterLabel = new QLabel(centralwidget);
+ programCounterLabel->setObjectName(QString::fromUtf8("programCounterLabel"));
+
+ formLayout->setWidget(2, QFormLayout::LabelRole, programCounterLabel);
+
+ programCounterLineEdit = new QLineEdit(centralwidget);
+ programCounterLineEdit->setObjectName(QString::fromUtf8("programCounterLineEdit"));
+
+ formLayout->setWidget(2, QFormLayout::FieldRole, programCounterLineEdit);
+
+ directBankLabel = new QLabel(centralwidget);
+ directBankLabel->setObjectName(QString::fromUtf8("directBankLabel"));
+
+ formLayout->setWidget(3, QFormLayout::LabelRole, directBankLabel);
+
+ directBankLineEdit = new QLineEdit(centralwidget);
+ directBankLineEdit->setObjectName(QString::fromUtf8("directBankLineEdit"));
+
+ formLayout->setWidget(3, QFormLayout::FieldRole, directBankLineEdit);
+
+ directPageLabel = new QLabel(centralwidget);
+ directPageLabel->setObjectName(QString::fromUtf8("directPageLabel"));
+
+ formLayout->setWidget(4, QFormLayout::LabelRole, directPageLabel);
+
+ directPageLineEdit = new QLineEdit(centralwidget);
+ directPageLineEdit->setObjectName(QString::fromUtf8("directPageLineEdit"));
+
+ formLayout->setWidget(4, QFormLayout::FieldRole, directPageLineEdit);
+
+ stackPointerLabel = new QLabel(centralwidget);
+ stackPointerLabel->setObjectName(QString::fromUtf8("stackPointerLabel"));
+
+ formLayout->setWidget(5, QFormLayout::LabelRole, stackPointerLabel);
+
+ stackPointerLineEdit = new QLineEdit(centralwidget);
+ stackPointerLineEdit->setObjectName(QString::fromUtf8("stackPointerLineEdit"));
+
+ formLayout->setWidget(5, QFormLayout::FieldRole, stackPointerLineEdit);
+
+ xIndexLabel = new QLabel(centralwidget);
+ xIndexLabel->setObjectName(QString::fromUtf8("xIndexLabel"));
+
+ formLayout->setWidget(6, QFormLayout::LabelRole, xIndexLabel);
+
+ xIndexLineEdit = new QLineEdit(centralwidget);
+ xIndexLineEdit->setObjectName(QString::fromUtf8("xIndexLineEdit"));
+
+ formLayout->setWidget(6, QFormLayout::FieldRole, xIndexLineEdit);
+
+ yIndexLabel = new QLabel(centralwidget);
+ yIndexLabel->setObjectName(QString::fromUtf8("yIndexLabel"));
+
+ formLayout->setWidget(7, QFormLayout::LabelRole, yIndexLabel);
+
+ yIndexLineEdit = new QLineEdit(centralwidget);
+ yIndexLineEdit->setObjectName(QString::fromUtf8("yIndexLineEdit"));
+
+ formLayout->setWidget(7, QFormLayout::FieldRole, yIndexLineEdit);
+
+ flagsLabel = new QLabel(centralwidget);
+ flagsLabel->setObjectName(QString::fromUtf8("flagsLabel"));
+
+ formLayout->setWidget(8, QFormLayout::LabelRole, flagsLabel);
+
+ flagsLineEdit = new QLineEdit(centralwidget);
+ flagsLineEdit->setObjectName(QString::fromUtf8("flagsLineEdit"));
+
+ formLayout->setWidget(8, QFormLayout::FieldRole, flagsLineEdit);
+
+ emulationModeLabel = new QLabel(centralwidget);
+ emulationModeLabel->setObjectName(QString::fromUtf8("emulationModeLabel"));
+
+ formLayout->setWidget(9, QFormLayout::LabelRole, emulationModeLabel);
+
+ emulationModeCheckBox = new QCheckBox(centralwidget);
+ emulationModeCheckBox->setObjectName(QString::fromUtf8("emulationModeCheckBox"));
+ emulationModeCheckBox->setLayoutDirection(Qt::RightToLeft);
+ emulationModeCheckBox->setCheckable(true);
+
+ formLayout->setWidget(9, QFormLayout::FieldRole, emulationModeCheckBox);
+
+
+ gridLayout_2->addLayout(formLayout, 0, 1, 1, 1);
+
+ gridLayout = new QGridLayout();
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ clear = new QPushButton(centralwidget);
+ clear->setObjectName(QString::fromUtf8("clear"));
+
+ gridLayout->addWidget(clear, 2, 0, 1, 1);
+
+ loggerLabel = new QLabel(centralwidget);
+ loggerLabel->setObjectName(QString::fromUtf8("loggerLabel"));
+ loggerLabel->setAlignment(Qt::AlignCenter);
+
+ gridLayout->addWidget(loggerLabel, 0, 0, 1, 1);
+
+ logger = new QTextBrowser(centralwidget);
+ logger->setObjectName(QString::fromUtf8("logger"));
+
+ gridLayout->addWidget(logger, 1, 0, 1, 1);
+
+
+ gridLayout_2->addLayout(gridLayout, 1, 1, 1, 1);
+
+ CPUView->setCentralWidget(centralwidget);
+ toolBar = new QToolBar(CPUView);
+ toolBar->setObjectName(QString::fromUtf8("toolBar"));
+ toolBar->setMinimumSize(QSize(0, 0));
+ toolBar->setMovable(false);
+ toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ toolBar->setFloatable(true);
+ CPUView->addToolBar(Qt::TopToolBarArea, toolBar);
+
+ toolBar->addAction(actionPause);
+ toolBar->addAction(actionNext);
+ toolBar->addAction(actionStep);
+
+ retranslateUi(CPUView);
+
+ QMetaObject::connectSlotsByName(CPUView);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *CPUView)
+ {
+ CPUView->setWindowTitle(QCoreApplication::translate("CPUView", "CPU's Debugger", nullptr));
+ actionPause->setText(QCoreApplication::translate("CPUView", "Continue", nullptr));
+#if QT_CONFIG(tooltip)
+ actionPause->setToolTip(QCoreApplication::translate("CPUView", "Pause or Resume instruction execution.", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ actionPause->setShortcut(QCoreApplication::translate("CPUView", "C", nullptr));
+#endif // QT_CONFIG(shortcut)
+ actionStep->setText(QCoreApplication::translate("CPUView", "Step", nullptr));
+#if QT_CONFIG(tooltip)
+ actionStep->setToolTip(QCoreApplication::translate("CPUView", "Execute a single instruction", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ actionStep->setShortcut(QCoreApplication::translate("CPUView", "S", nullptr));
+#endif // QT_CONFIG(shortcut)
+ actionNext->setText(QCoreApplication::translate("CPUView", "Next", nullptr));
+#if QT_CONFIG(tooltip)
+ actionNext->setToolTip(QCoreApplication::translate("CPUView", "Continue execution to the next line.", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ actionNext->setShortcut(QCoreApplication::translate("CPUView", "N", nullptr));
+#endif // QT_CONFIG(shortcut)
+ accumulatorLabel->setText(QCoreApplication::translate("CPUView", "Accumulator", nullptr));
+ accumulatorLineEdit->setText(QString());
+ programBankRegisterLabel->setText(QCoreApplication::translate("CPUView", "Program Bank", nullptr));
+ programCounterLabel->setText(QCoreApplication::translate("CPUView", "Program Counter", nullptr));
+ directBankLabel->setText(QCoreApplication::translate("CPUView", "Direct Bank", nullptr));
+ directPageLabel->setText(QCoreApplication::translate("CPUView", "Direct Page", nullptr));
+ stackPointerLabel->setText(QCoreApplication::translate("CPUView", "Stack Pointer", nullptr));
+ xIndexLabel->setText(QCoreApplication::translate("CPUView", "X Index", nullptr));
+ yIndexLabel->setText(QCoreApplication::translate("CPUView", "Y Index", nullptr));
+ flagsLabel->setText(QCoreApplication::translate("CPUView", "Flags", nullptr));
+ emulationModeLabel->setText(QCoreApplication::translate("CPUView", "Emulation mode", nullptr));
+ clear->setText(QCoreApplication::translate("CPUView", "Clear History", nullptr));
+ loggerLabel->setText(QCoreApplication::translate("CPUView", "Instructions History", nullptr));
+ toolBar->setWindowTitle(QCoreApplication::translate("CPUView", "toolBar", nullptr));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class CPUView: public Ui_CPUView {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_CPU_H