diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index fda754d..b635ba4 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -9,6 +9,7 @@ #include #include #include +#include using namespace ComSquare::CPU; @@ -134,8 +135,19 @@ namespace ComSquare::Debugger return ret; } - void CPUDebug::pause() + void CPUDebug::showError(const DebuggableError &error) { + QMessageBox msg; + msg.setIcon(QMessageBox::Critical); + msg.setText("Invalid rom action"); + msg.setInformativeText(error.what()); + msg.exec(); + } + + void CPUDebug::pause(bool forcePause) + { + if (forcePause && this->_isPaused) + return; this->_isPaused = !this->_isPaused; if (this->_isPaused) this->_ui.actionPause->setText("Continue"); diff --git a/sources/Debugger/CPU/CPUDebug.hpp b/sources/Debugger/CPU/CPUDebug.hpp index 57f403b..9120cec 100644 --- a/sources/Debugger/CPU/CPUDebug.hpp +++ b/sources/Debugger/CPU/CPUDebug.hpp @@ -248,8 +248,10 @@ namespace ComSquare::Debugger std::string _getAbsoluteIndirectLongValue(uint24_t pc); public: + //! @brief Show an error dialog related to an exception. + void showError(const DebuggableError &error); //! @brief Pause/Resume the CPU. - void pause(); + void pause(bool forcePause = false); //! @brief Step - Execute a single instruction. void step(); //! @brief Next - Continue running instructions until the next line is reached. diff --git a/sources/Debugger/CPU/Disassembly.cpp b/sources/Debugger/CPU/Disassembly.cpp index 75aefd2..7df19bb 100644 --- a/sources/Debugger/CPU/Disassembly.cpp +++ b/sources/Debugger/CPU/Disassembly.cpp @@ -251,7 +251,7 @@ namespace ComSquare::Debugger std::string CPUDebug::_getAbsoluteIndirectValue(uint24_t pc) { - uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u); + uint24_t value = this->_bus->read(pc, true) + (this->_bus->read(pc + 1, true) << 8u); return "(" + Utility::to_hex(value, Utility::HexString::AsmPrefix) + ")"; } @@ -266,7 +266,7 @@ namespace ComSquare::Debugger std::string CPUDebug::_getAbsoluteIndirectIndexedByXValue(uint24_t pc) { - uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u); + uint24_t value = this->_bus->read(pc, true) + (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/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index 8ebe6c2..1977eab 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -148,6 +148,13 @@ namespace ComSquare::Debugger return true; } + uint8_t MemoryBusDebug::read(uint24_t addr) + { + if (this->forceSilence) + return MemoryBus::read(addr); + return this->read(addr, false); + } + uint8_t MemoryBusDebug::read(uint24_t addr, bool silence) { if (!silence && !this->forceSilence) { @@ -159,7 +166,7 @@ namespace ComSquare::Debugger this->_model.log(BusLog(false, addr, accessor, value, value)); } } - return MemoryBus::read(addr); + return MemoryBus::read(addr, silence); } void MemoryBusDebug::write(uint24_t addr, uint8_t data) diff --git a/sources/Debugger/MemoryBusDebug.hpp b/sources/Debugger/MemoryBusDebug.hpp index 1f19be1..08fa15c 100644 --- a/sources/Debugger/MemoryBusDebug.hpp +++ b/sources/Debugger/MemoryBusDebug.hpp @@ -127,7 +127,12 @@ namespace ComSquare::Debugger //! @brief Read data at a global address and log it to the debugger. //! @param addr The address to read from. //! @return The value that the component returned for this address. If the address was mapped to ram, it simply returned the value. If the address was mapped to a register the component returned the register. - uint8_t read(uint24_t addr, bool silence = false) override; + uint8_t read(uint24_t addr) override; + + //! @brief Read data at a global address and log it to the debugger. + //! @param addr The address to read from. + //! @return The value that the component returned for this address. If the address was mapped to ram, it simply returned the value. If the address was mapped to a register the component returned the register. + uint8_t read(uint24_t addr, bool silence) override; //! @brief Write a data to a global address and log it to the debugger. //! @param addr The address to write to. diff --git a/sources/Memory/MemoryBus.cpp b/sources/Memory/MemoryBus.cpp index 38d3ccc..856119b 100644 --- a/sources/Memory/MemoryBus.cpp +++ b/sources/Memory/MemoryBus.cpp @@ -8,6 +8,7 @@ #include "../SNES.hpp" #include "MemoryShadow.hpp" #include "RectangleShadow.hpp" +#include "../Exceptions/InvalidAddress.hpp" namespace ComSquare::Memory { @@ -22,20 +23,34 @@ namespace ComSquare::Memory return *it; } - uint8_t MemoryBus::read(uint24_t addr, bool silence) + uint8_t MemoryBus::read(uint24_t addr) { std::shared_ptr handler = this->getAccessor(addr); if (!handler) { - if (!silence) - std::cout << "Unknown memory accessor for address $" << std::hex << addr << ". Using open bus." << std::endl; + std::cout << "Unknown memory accessor for address $" << std::hex << addr << ". Using open bus." << std::endl; return this->_openBus; } - uint8_t data = handler->read(handler->getRelativeAddress(addr)); + uint8_t data = handler->read(handler->getRelativeAddress(addr)); this->_openBus = data; return data; } + uint8_t MemoryBus::read(uint24_t addr, bool silence) + { + if (!silence) + return this->read(addr); + std::shared_ptr handler = this->getAccessor(addr); + + if (!handler) + return this->_openBus; + try { + return handler->read(handler->getRelativeAddress(addr)); + } catch (const InvalidAddress &) { + return 0; + } + } + void MemoryBus::write(uint24_t addr, uint8_t data) { std::shared_ptr handler = this->getAccessor(addr); diff --git a/sources/Memory/MemoryBus.hpp b/sources/Memory/MemoryBus.hpp index 301dcd4..a53e207 100644 --- a/sources/Memory/MemoryBus.hpp +++ b/sources/Memory/MemoryBus.hpp @@ -40,9 +40,14 @@ namespace ComSquare //! @brief Read data at a global address. //! @param addr The address to read from. - //! @param silence Disable login to the memory bus's debugger (if enabled). Should only be used by other debuggers. //! @return The value that the component returned for this address. If the address was mapped to ram, it simply returned the value. If the address was mapped to a register the component returned the register. - virtual uint8_t read(uint24_t addr, bool silence = false); + virtual uint8_t read(uint24_t addr); + + //! @brief Read data at a global address. This form allow read to be silenced. + //! @param addr The address to read from. + //! @param silence Disable login to the memory bus's debugger (if enabled). Should only be used by other debuggers. This also won't affect the open bus. + //! @return The value that the component returned for this address. If the address was mapped to ram, it simply returned the value. If the address was mapped to a register the component returned the register. + virtual uint8_t read(uint24_t addr, bool silence); //! @brief Write a data to a global address. //! @param addr The address to write to. diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 8844a24..731a046 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -211,6 +211,8 @@ namespace ComSquare::PPU this->_registers._setini.raw = data; break; //TODO adding the rest of the registers. oaf ! + case ppuRegisters::stat77: // some roms write here but it is useless + break; default: throw InvalidAddress("PPU Internal Registers write", addr + this->_start); } diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp index 7cbdc5f..adc3f4b 100644 --- a/sources/Renderer/QtRenderer/QtSFML.cpp +++ b/sources/Renderer/QtRenderer/QtSFML.cpp @@ -7,9 +7,8 @@ #include #include #include +#include "../../Exceptions/DebuggableError.hpp" #include "QtSFML.hpp" -#include "../../Exceptions/InvalidOpcode.hpp" -#include "../../Exceptions/InvalidAction.hpp" #ifdef Q_WS_X11 #include @@ -102,9 +101,9 @@ namespace ComSquare::Renderer { try { this->_snes.update(); - } catch (DebuggableError &e) { + } catch (const DebuggableError &e) { std::cout << "Invalid rom's instruction: " << e.what() << std::endl; - this->_snes.enableCPUDebugging(true); + this->_snes.enableCPUDebuggingWithError(e); } 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 d6d321b..004dc1e 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -34,6 +34,15 @@ namespace ComSquare this->apu->update(cycleCount); } + void SNES::enableCPUDebuggingWithError(const DebuggableError &exception) + { + this->enableCPUDebugging(true); + #ifdef DEBUGGER_ENABLED + auto cpuDebug = std::static_pointer_cast(this->cpu); + cpuDebug->showError(exception); + #endif + } + void SNES::enableCPUDebugging(bool pause) { #ifdef DEBUGGER_ENABLED @@ -41,7 +50,7 @@ namespace ComSquare auto cpuDebug = std::static_pointer_cast(this->cpu); cpuDebug->focus(); if (pause) - cpuDebug->pause(); + cpuDebug->pause(true); } else { this->cpu = std::make_shared(*this->cpu, *this); this->bus->mapComponents(*this); diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 7aa41ae..48b45ce 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -18,6 +18,8 @@ #include "Debugger/HeaderViewer.hpp" #include "Debugger/CGramDebug.hpp" #include "Debugger/RegisterViewer.hpp" +#include "Exceptions/DebuggableError.hpp" + #endif namespace ComSquare @@ -61,6 +63,9 @@ namespace ComSquare void disableCPUDebugging(); //! @brief Enable the CPU's debugging window. void enableCPUDebugging(bool pause = false); + //! @brief Enable the CPU's debugger and show an error message related to an exception. + //! @param exception The exception to inform the user about. + void enableCPUDebuggingWithError(const DebuggableError &exception); //! @brief Disable the Ram's debugging window. void disableRamViewer(); //! @brief Enable the Ram's debugging window.