From 80ebfa8064d70a403c4f6dcadfc2a162cfdbb63c Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Thu, 26 Mar 2020 22:19:16 +0100
Subject: [PATCH] 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