diff --git a/CMakeLists.txt b/CMakeLists.txt index 09d4aca..86d8ff1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ add_executable(ComSquare sources/CPU/Instructions/InternalInstruction.cpp sources/Ram/ExtendedRam.cpp sources/Ram/ExtendedRam.hpp -) +sources/Debugger/DebugCpu.cpp sources/Debugger/DebugCpu.hpp) target_link_libraries(ComSquare sfml-graphics diff --git a/main.cpp b/main.cpp index d9be8d4..a383b9a 100644 --- a/main.cpp +++ b/main.cpp @@ -11,13 +11,14 @@ using namespace ComSquare; int main(int argc, char **argv) { - if (argc != 2) { + if (argc < 2) { std::cout << "ComSquare:" << std::endl << "\tUsage: " << argv[0] << " rom_path" << std::endl; return 1; } try { Renderer::SFRenderer renderer(600, 800, 60); SNES snes(std::make_shared(), argv[1], renderer); + snes.enableCPUDebugging(); while (!renderer.shouldExit) { unsigned cycleCount = snes.cpu->update(); snes.ppu->update(cycleCount); diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 248d812..64cb902 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -292,7 +292,7 @@ namespace ComSquare::CPU //! @brief The main CPU class CPU : public Memory::IMemory { - private: + protected: //! @brief All the registers of the CPU Registers _registers{}; //! @brief Is the CPU running in emulation mode (in 8bits) @@ -435,7 +435,7 @@ namespace ComSquare::CPU ~CPU() = default; //! @brief This function continue to execute the Cartridge code. //! @return The number of CPU cycles that elapsed - unsigned update(); + virtual unsigned update(); //! @brief Read from the internal CPU register. //! @param addr The address to read from. The address 0x0 should refer to the first byte of the register. //! @throw InvalidAddress will be thrown if the address is more than $1F (the number of register). diff --git a/sources/Debugger/DebugCpu.cpp b/sources/Debugger/DebugCpu.cpp new file mode 100644 index 0000000..1f160c4 --- /dev/null +++ b/sources/Debugger/DebugCpu.cpp @@ -0,0 +1,30 @@ +// +// Created by anonymus-raccoon on 2/14/20. +// + +#include +#include "DebugCpu.hpp" + +namespace ComSquare::Debugger +{ + CPUDebug::CPUDebug(ComSquare::CPU::CPU &basicCPU, SNES &snes) + : CPU::CPU(basicCPU), _renderer(600, 1000, 60), _snes(snes) + { + this->_renderer.setWindowName("CPU's Debugger"); + std::cout << "CPU debugging enabled!" << std::endl; + } + + unsigned CPUDebug::update() + { + if (this->_renderer.shouldExit) { + this->_snes.disableCPUDebugging (); + return 0; + } + + this->_renderer.drawScreen(); + this->_renderer.getEvents(); + if (this->_isPaused) + return 0xFF; + return CPU::update(); + } +} \ No newline at end of file diff --git a/sources/Debugger/DebugCpu.hpp b/sources/Debugger/DebugCpu.hpp new file mode 100644 index 0000000..44da0b6 --- /dev/null +++ b/sources/Debugger/DebugCpu.hpp @@ -0,0 +1,35 @@ +// +// Created by anonymus-raccoon on 2/14/20. +// + +#ifndef COMSQUARE_DEBUGCPU_HPP +#define COMSQUARE_DEBUGCPU_HPP + +#include "../CPU/CPU.hpp" +#include "../Renderer/SFRenderer.hpp" +#include "../SNES.hpp" + +namespace ComSquare::Debugger +{ + //! @brief A custom CPU with a window that show it's registers and the disassembly. + class CPUDebug : public CPU::CPU { + private: + //! @brief The debug window. + Renderer::SFRenderer _renderer; + //! @brief If this is set to true, the execution of the CPU will be paused. + bool _isPaused = true; + //! @brief A reference to the snes (to disable the debugger). + SNES &_snes; + public: + //! @brief Convert a basic CPU to a debugging CPU. + explicit CPUDebug(ComSquare::CPU::CPU &cpu, SNES &snes); + CPUDebug(const CPUDebug &) = delete; + CPUDebug &operator=(const CPUDebug &) = delete; + ~CPUDebug() = default; + + //! @brief Override the basic cpu's update to allow pausing of the CPU only. + unsigned update() override; + }; +} + +#endif //COMSQUARE_DEBUGCPU_HPP diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 49adcf5..2f5adc7 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -206,7 +206,6 @@ namespace ComSquare::PPU int inc = 0; //uint32_t pixelTmp = 0xFFFFFFFF; //pixelTmp |= this->_inidisp.brightness; - std::cout << "update" << std::endl; if (!this->_inidisp.fblank) { for (int x = 0; x < 448; x++) { for (int y = 0; y < 512; y++) { @@ -217,7 +216,6 @@ namespace ComSquare::PPU } } } - std::cout << "cgadata2" << std::endl; this->_renderer.drawScreen(); } diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 20646a2..49adc22 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -5,6 +5,7 @@ #include #include #include "SNES.hpp" +#include "Debugger/DebugCpu.hpp" namespace ComSquare { @@ -19,4 +20,14 @@ namespace ComSquare bus->mapComponents(*this); renderer.setWindowName(this->cartridge->header.gameName); } + + void SNES::enableCPUDebugging() + { + this->cpu = std::make_shared(*this->cpu, *this); + } + + void SNES::disableCPUDebugging() + { + this->cpu = std::make_shared(*this->cpu); + } } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index c863d88..41b6d53 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -30,6 +30,11 @@ namespace ComSquare std::shared_ptr wram; //! @brief Save Ram residing inside the Cartridge in a real SNES. std::shared_ptr sram; + + //! @brief Enable the CPU's debugging window. + void enableCPUDebugging(); + //! @brief Disable the CPU's debugging window. + void disableCPUDebugging(); //! @brief Create all the components using a common memory bus for all of them. SNES(const std::shared_ptr &bus, const std::string &ramPath, Renderer::IRenderer &renderer); SNES(const SNES &) = default;