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