From cb6fb8a2406d118253de6b2a1e8ceb4cea80d5da Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 5 Jul 2021 00:23:48 +0200 Subject: [PATCH] Enabling the memory bus debugger --- CMakeLists.txt | 8 +- sources/CPU/AddressingModes.cpp | 38 +-- sources/CPU/CPU.cpp | 22 +- sources/CPU/CPU.hpp | 16 +- sources/CPU/DMA/DMA.cpp | 19 +- sources/CPU/DMA/DMA.hpp | 13 +- sources/CPU/Instructions/BitsInstructions.cpp | 52 +-- .../CPU/Instructions/InternalInstruction.cpp | 30 +- .../Instructions/MathematicalOperations.cpp | 56 ++-- .../CPU/Instructions/MemoryInstructions.cpp | 40 +-- .../CPU/Instructions/TransferRegisters.cpp | 8 +- sources/Debugger/MemoryBusDebug.cpp | 311 ++++++++---------- sources/Debugger/MemoryBusDebug.hpp | 160 ++++----- sources/Memory/IMemory.hpp | 7 +- sources/Memory/IMemoryBus.hpp | 47 +++ sources/Memory/MemoryBus.cpp | 5 +- sources/Memory/MemoryBus.hpp | 16 +- sources/Renderer/QtRenderer/QtSFML.cpp | 2 +- sources/SNES.cpp | 31 +- sources/SNES.hpp | 12 +- 20 files changed, 475 insertions(+), 418 deletions(-) create mode 100644 sources/Memory/IMemoryBus.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index da0b10c..3c6d99a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ set(SOURCES sources/PPU/TileRenderer.hpp sources/PPU/Tile.hpp sources/CPU/Registers.hpp - ) + sources/Memory/IMemoryBus.hpp) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -129,8 +129,8 @@ add_executable(comsquare sources/Debugger/HeaderViewer.hpp # sources/Debugger/APUDebug.hpp # sources/Debugger/APUDebug.cpp -# sources/Debugger/MemoryBusDebug.cpp -# sources/Debugger/MemoryBusDebug.hpp + sources/Debugger/MemoryBusDebug.cpp + sources/Debugger/MemoryBusDebug.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp sources/Debugger/RegisterViewer.cpp @@ -148,7 +148,7 @@ add_executable(comsquare ui/busView.ui resources/appResources.qrc ) -target_include_directories(comsquare PRIVATE ./) +target_include_directories(comsquare PUBLIC ${PROJECT_BINARY_DIR}) target_compile_definitions(comsquare PUBLIC DEBUGGER_ENABLED) find_package(Qt5 COMPONENTS Widgets REQUIRED) diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp index 7cdd538..38d746f 100644 --- a/sources/CPU/AddressingModes.cpp +++ b/sources/CPU/AddressingModes.cpp @@ -64,8 +64,8 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedYAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t base = this->_bus.read(dp); - base += this->_bus.read(dp + 1) << 8u; + uint24_t base = this->getBus().read(dp); + base += this->getBus().read(dp + 1) << 8u; base += this->_registers.dbr << 16u; if ((base & 0x80000000u) == (((base + this->_registers.y) & 0x80000000u))) this->_hasIndexCrossedPageBoundary = true; @@ -75,9 +75,9 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedYLongAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t base = this->_bus.read(dp); - base += this->_bus.read(dp + 1) << 8u; - base += this->_bus.read(dp + 2) << 16u; + uint24_t base = this->getBus().read(dp); + base += this->getBus().read(dp + 1) << 8u; + base += this->getBus().read(dp + 2) << 16u; return base; } @@ -85,8 +85,8 @@ namespace ComSquare::CPU { uint16_t dp = this->readPC() + this->_registers.d; dp += this->_registers.x; - uint24_t base = this->_bus.read(dp); - base += this->_bus.read(dp + 1) << 8u; + uint24_t base = this->getBus().read(dp); + base += this->getBus().read(dp + 1) << 8u; base += this->_registers.dbr << 16u; return base; } @@ -137,8 +137,8 @@ namespace ComSquare::CPU { uint16_t abs = this->readPC(); abs += this->readPC() << 8u; - uint24_t effective = this->_bus.read(abs); - effective += this->_bus.read(abs + 1) << 8u; + uint24_t effective = this->getBus().read(abs); + effective += this->getBus().read(abs + 1) << 8u; return effective; } @@ -146,9 +146,9 @@ namespace ComSquare::CPU { uint16_t abs = this->readPC(); abs += this->readPC() << 8u; - uint24_t effective = this->_bus.read(abs); - effective += this->_bus.read(abs + 1) << 8u; - effective += this->_bus.read(abs + 2) << 16u; + uint24_t effective = this->getBus().read(abs); + effective += this->getBus().read(abs + 1) << 8u; + effective += this->getBus().read(abs + 2) << 16u; return effective; } @@ -157,16 +157,16 @@ namespace ComSquare::CPU uint24_t abs = this->readPC(); abs += this->readPC() << 8u; abs += this->_registers.x; - uint24_t effective = this->_bus.read(abs); - effective += this->_bus.read(abs + 1) << 8u; + uint24_t effective = this->getBus().read(abs); + effective += this->getBus().read(abs + 1) << 8u; return effective; } uint24_t CPU::_getDirectIndirectAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t effective = this->_bus.read(dp); - effective += this->_bus.read(dp + 1) << 8u; + uint24_t effective = this->getBus().read(dp); + effective += this->getBus().read(dp + 1) << 8u; effective += this->_registers.dbr << 16u; return effective; } @@ -174,9 +174,9 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectLongAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t effective = this->_bus.read(dp); - effective += this->_bus.read(++dp) << 8u; - effective += this->_bus.read(++dp) << 16u; + uint24_t effective = this->getBus().read(dp); + effective += this->getBus().read(++dp) << 8u; + effective += this->getBus().read(++dp) << 16u; return effective; } diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 9fceaa3..c5d7a68 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -10,7 +10,7 @@ namespace ComSquare::CPU { - CPU::CPU(Memory::MemoryBus &bus, Cartridge::Header &cartridgeHeader) + CPU::CPU(Memory::IMemoryBus &bus, Cartridge::Header &cartridgeHeader) : _bus(bus), _cartridgeHeader(cartridgeHeader), _dmaChannels({DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus)}) @@ -18,6 +18,12 @@ namespace ComSquare::CPU this->RESB(); } + void CPU::setBus(Memory::IMemoryBus &bus) + { + this->_bus = bus; + for (auto &dma : this->_dmaChannels) + dma.setBus(bus); + } //! @bref The CPU's internal registers starts at $4200 and finish at $421F. uint8_t CPU::read(uint24_t addr) @@ -203,7 +209,7 @@ namespace ComSquare::CPU uint8_t CPU::readPC() { - uint8_t ret = this->_bus.read(this->_registers.pac); + uint8_t ret = this->getBus().read(this->_registers.pac); this->_registers.pc++; return ret; } @@ -322,24 +328,24 @@ namespace ComSquare::CPU void CPU::_push(uint8_t data) { - this->_bus.write(this->_registers.s--, data); + this->getBus().write(this->_registers.s--, data); } void CPU::_push(uint16_t data) { - this->_bus.write(this->_registers.s--, data >> 8u); - this->_bus.write(this->_registers.s--, data); + this->getBus().write(this->_registers.s--, data >> 8u); + this->getBus().write(this->_registers.s--, data); } uint8_t CPU::_pop() { - return this->_bus.read(++this->_registers.s); + return this->getBus().read(++this->_registers.s); } uint16_t CPU::_pop16() { - uint16_t value = this->_bus.read(++this->_registers.s); - value += this->_bus.read(++this->_registers.s) << 8u; + uint16_t value = this->getBus().read(++this->_registers.s); + value += this->getBus().read(++this->_registers.s) << 8u; return value; } diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 9cf2cdb..0fc1be1 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -36,7 +36,8 @@ namespace ComSquare::CPU bool _isWaitingForInterrupt = false; //! @brief The memory bus to use for read/write. - Memory::MemoryBus &_bus; + std::reference_wrapper _bus; + private: //! @brief The cartridge header (stored for interrupt vectors..) Cartridge::Header &_cartridgeHeader; @@ -117,7 +118,6 @@ namespace ComSquare::CPU //! @return The address of the data to read on the instruction. uint24_t _getValueAddr(Instruction &instruction); - public: //! @brief Break instruction - Causes a software break. The PC is loaded from a vector table. int BRK(uint24_t, AddressingMode); //! @brief Co-Processor Enable instruction - Causes a software break. The PC is loaded from a vector table. @@ -309,6 +309,16 @@ namespace ComSquare::CPU //! @param C_register (16 bits accumulator) Length -1 int MVP(uint24_t, AddressingMode); + public: + //! @brief Get the memory bus used by this CPU. + [[nodiscard]] inline Memory::IMemoryBus &getBus() + { + return this->_bus; + } + //! @brief Set the memory bus used by this CPU + //! @param bus The bus to use. + void setBus(Memory::IMemoryBus &bus); + //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode const Instruction instructions[0x100] = { @@ -573,7 +583,7 @@ namespace ComSquare::CPU //! @brief Construct a new generic CPU. //! @param bus The memory bus to use to transfer data. //! @param cartridgeHeader The header used to know interrupts, main entry point etc... - CPU(Memory::MemoryBus &bus, Cartridge::Header &cartridgeHeader); + CPU(Memory::IMemoryBus &bus, Cartridge::Header &cartridgeHeader); //! @brief A default copy constructor CPU(const CPU &) = default; //! @brief A CPU is not assignable diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index cfd52df..baf5909 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -7,11 +7,16 @@ namespace ComSquare::CPU { - DMA::DMA(Memory::MemoryBus &bus) + DMA::DMA(Memory::IMemoryBus &bus) : _bus(bus), enabled(false) {} + void DMA::setBus(Memory::IMemoryBus &bus) + { + this->_bus = bus; + } + uint8_t DMA::read(uint8_t addr) const { switch (addr) { @@ -68,22 +73,22 @@ namespace ComSquare::CPU // Address $2180 refers to the WRam data register. // Write to/Read from this port when the a address is on the vram cause different behaviors. if (this->_port == 0x80) { - auto accessor = this->_bus.getAccessor(aAddress); + auto accessor = this->getBus().getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { // WRAM->$2180 The write is not performed but the time is consumed anyway. if (this->_controlRegister.direction == AtoB) return 8; // $2180->WRAM No read is performed (so only 4 master cycles are needed) but the value written is invalid. - this->_bus.write(aAddress, 0xFF); + this->getBus().write(aAddress, 0xFF); return 4; } } if (this->_controlRegister.direction == AtoB) { - uint8_t data = this->_bus.read(aAddress); - this->_bus.write(bAddress, data); + uint8_t data = this->getBus().read(aAddress); + this->getBus().write(bAddress, data); } else { - uint8_t data = this->_bus.read(bAddress); - this->_bus.write(aAddress, data); + uint8_t data = this->getBus().read(bAddress); + this->getBus().write(aAddress, data); } return 8; } diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index 26a8d3a..b612966 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -93,9 +93,18 @@ namespace ComSquare::CPU } _count {}; //! @brief The memory bus to use for read/write. - Memory::MemoryBus &_bus; + Memory::IMemoryBus &_bus; public: + //! @brief Get the memory bus used by this CPU. + [[nodiscard]] inline Memory::IMemoryBus &getBus() + { + return this->_bus; + } + //! @brief Set the memory bus used by this CPU + //! @param bus The bus to use. + void setBus(Memory::IMemoryBus &bus); + //! @brief Is this channel set to run? bool enabled; @@ -116,7 +125,7 @@ namespace ComSquare::CPU //! @brief Create a DMA channel with a given bus //! @param bus The memory bus to use. - explicit DMA(Memory::MemoryBus &bus); + explicit DMA(Memory::IMemoryBus &bus); //! @brief A DMA is copy constructable. DMA(const DMA &) = default; //! @brief A DMA is not assignable diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 82ce7be..681da65 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -10,13 +10,13 @@ namespace ComSquare::CPU { int CPU::TSB(uint24_t valueAddr, AddressingMode mode) { - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; value |= this->_registers.a; - this->_bus.write(valueAddr, value); + this->getBus().write(valueAddr, value); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, value >> 8u); + this->getBus().write(valueAddr + 1, value >> 8u); this->_registers.p.z = value == 0; @@ -30,14 +30,14 @@ namespace ComSquare::CPU int CPU::TRB(uint24_t valueAddr, AddressingMode mode) { - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; uint16_t newValue = value & ~this->_registers.a; - this->_bus.write(valueAddr, newValue); + this->getBus().write(valueAddr, newValue); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, newValue >> 8u); + this->getBus().write(valueAddr + 1, newValue >> 8u); this->_registers.p.z = (value & this->_registers.a) == 0; @@ -52,9 +52,9 @@ namespace ComSquare::CPU int CPU::BIT(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; if (mode != ImmediateForA) { this->_registers.p.n = value & negativeMask; @@ -89,18 +89,18 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.p.c = value & highByte; value <<= 1u; this->_registers.p.n = value & highByte; this->_registers.p.z = value == 0; - this->_bus.write(valueAddr, value); + this->getBus().write(valueAddr, value); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, value >> 8u); + this->getBus().write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -128,17 +128,17 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.p.c = value & 1u; value >>= 1u; this->_registers.p.z = value == 0; - this->_bus.write(valueAddr, value); + this->getBus().write(valueAddr, value); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, value >> 8u); + this->getBus().write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -169,9 +169,9 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.p.c = value & highByte; value <<= 1u; @@ -179,9 +179,9 @@ namespace ComSquare::CPU this->_registers.p.n = value & highByte; this->_registers.p.z = value == 0; - this->_bus.write(valueAddr, value); + this->getBus().write(valueAddr, value); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, value >> 8u); + this->getBus().write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -212,18 +212,18 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus.read(valueAddr); + uint16_t value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.p.c = value & 1u; value >>= 1u; value |= oldCarry << highByteIndex; this->_registers.p.z = value == 0; - this->_bus.write(valueAddr, value); + this->getBus().write(valueAddr, value); if (!this->_registers.p.m) - this->_bus.write(valueAddr + 1, value >> 8u); + this->getBus().write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index c03e21b..1ce1df9 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -50,13 +50,13 @@ namespace ComSquare::CPU int CPU::SEP(uint24_t valueAddr, AddressingMode) { - this->_registers.p.flags |= this->_bus.read(valueAddr); + this->_registers.p.flags |= this->getBus().read(valueAddr); return 0; } int CPU::REP(uint24_t valueAddr, AddressingMode) { - this->_registers.p.flags &= ~this->_bus.read(valueAddr); + this->_registers.p.flags &= ~this->getBus().read(valueAddr); if (this->_isEmulationMode) { this->_registers.p.x_b = true; this->_registers.p.m = true; @@ -189,8 +189,8 @@ namespace ComSquare::CPU int CPU::PER(uint24_t valueAddr, AddressingMode) { - uint16_t value = this->_bus.read(valueAddr); - value += this->_bus.read(valueAddr + 1) << 8u; + uint16_t value = this->getBus().read(valueAddr); + value += this->getBus().read(valueAddr + 1) << 8u; value += this->_registers.pc; this->_push(value); return 0; @@ -226,55 +226,55 @@ namespace ComSquare::CPU int CPU::BCC(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.c) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return !this->_registers.p.c + this->_isEmulationMode; } int CPU::BCS(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.c) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return this->_registers.p.c + this->_isEmulationMode; } int CPU::BEQ(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.z) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return this->_registers.p.z + this->_isEmulationMode; } int CPU::BNE(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.z) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return !this->_registers.p.z + this->_isEmulationMode; } int CPU::BMI(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.n) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return this->_registers.p.n + this->_isEmulationMode; } int CPU::BPL(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.n) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return !this->_registers.p.n + this->_isEmulationMode; } int CPU::BRA(uint24_t valueAddr, AddressingMode) { - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return this->_isEmulationMode; } int CPU::BRL(uint24_t valueAddr, AddressingMode) { - unsigned value = this->_bus.read(valueAddr); - value += this->_bus.read(valueAddr + 1) << 8u; + unsigned value = this->getBus().read(valueAddr); + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.pc += static_cast(value); return 0; @@ -283,14 +283,14 @@ namespace ComSquare::CPU int CPU::BVC(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.v) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return !this->_registers.p.v + this->_isEmulationMode; } int CPU::BVS(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.v) - this->_registers.pc += static_cast(this->_bus.read(valueAddr)); + this->_registers.pc += static_cast(this->getBus().read(valueAddr)); return this->_registers.p.v + this->_isEmulationMode; } diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp index f102399..ea5ce93 100644 --- a/sources/CPU/Instructions/MathematicalOperations.cpp +++ b/sources/CPU/Instructions/MathematicalOperations.cpp @@ -9,9 +9,9 @@ namespace ComSquare::CPU { int CPU::ADC(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus.read(valueAddr) + this->_registers.p.c; + unsigned value = this->getBus().read(valueAddr) + this->_registers.p.c; if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; unsigned maxValue = this->_registers.p.m ? UINT8_MAX : UINT16_MAX; @@ -52,9 +52,9 @@ namespace ComSquare::CPU int CPU::SBC(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; bool oldCarry = this->_registers.p.c; this->_registers.p.c = this->_registers.a >= value; @@ -94,9 +94,9 @@ namespace ComSquare::CPU int CPU::ORA(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.a |= value; this->_registers.p.z = this->_registers.a == 0; this->_registers.p.n = this->_registers.a & negativeMask; @@ -151,9 +151,9 @@ namespace ComSquare::CPU int CPU::CMP(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; unsigned result = this->_registers.a - value; if (this->_registers.p.m) result %= 0x100; @@ -214,7 +214,7 @@ namespace ComSquare::CPU int CPU::CPX(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus.read(valueAddr++); + unsigned value = this->getBus().read(valueAddr++); if (this->_registers.p.x_b) { uint8_t x = this->_registers.x; @@ -222,7 +222,7 @@ namespace ComSquare::CPU this->_registers.p.z = x == 0; this->_registers.p.n = x & 0x80u; } else { - value += this->_bus.read(valueAddr) << 8u; + value += this->getBus().read(valueAddr) << 8u; uint16_t x = this->_registers.x; x -= value; this->_registers.p.z = x == 0; @@ -234,7 +234,7 @@ namespace ComSquare::CPU int CPU::CPY(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus.read(valueAddr++); + unsigned value = this->getBus().read(valueAddr++); this->_registers.p.c = this->_registers.y >= value; if (this->_registers.p.x_b) { @@ -243,7 +243,7 @@ namespace ComSquare::CPU this->_registers.p.z = y == 0; this->_registers.p.n = y & 0x80u; } else { - value += this->_bus.read(valueAddr) << 8u; + value += this->getBus().read(valueAddr) << 8u; uint16_t y = this->_registers.y; y -= value; this->_registers.p.z = y == 0; @@ -255,9 +255,9 @@ namespace ComSquare::CPU int CPU::AND(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.a &= value; this->_registers.p.n = this->_registers.a & negativeMask; @@ -297,15 +297,15 @@ namespace ComSquare::CPU this->_registers.ah = 0; result = this->_registers.a; } else if (!this->_registers.p.m) { - result = this->_bus.read(valueAddr); - result += this->_bus.read(valueAddr + 1) << 8u; + result = this->getBus().read(valueAddr); + result += this->getBus().read(valueAddr + 1) << 8u; result = (uint16_t)(result + 1); - this->_bus.write(valueAddr, result); - this->_bus.write(valueAddr + 1, result << 8u); + this->getBus().write(valueAddr, result); + this->getBus().write(valueAddr + 1, result << 8u); } else { - result = this->_bus.read(valueAddr); + result = this->getBus().read(valueAddr); result = (uint8_t)(result + 1); - this->_bus.write(valueAddr, result); + this->getBus().write(valueAddr, result); } this->_registers.p.z = result == 0; @@ -337,15 +337,15 @@ namespace ComSquare::CPU this->_registers.ah = 0; result = this->_registers.a; } else if (!this->_registers.p.m) { - result = this->_bus.read(valueAddr); - result += this->_bus.read(valueAddr + 1) << 8u; + result = this->getBus().read(valueAddr); + result += this->getBus().read(valueAddr + 1) << 8u; result = (uint16_t)(result - 1); - this->_bus.write(valueAddr, result); - this->_bus.write(valueAddr + 1, result << 8u); + this->getBus().write(valueAddr, result); + this->getBus().write(valueAddr + 1, result << 8u); } else { - result = this->_bus.read(valueAddr); + result = this->getBus().read(valueAddr); result = (uint8_t)(result - 1); - this->_bus.write(valueAddr, result); + this->getBus().write(valueAddr, result); } this->_registers.p.z = result == 0; @@ -369,9 +369,9 @@ namespace ComSquare::CPU int CPU::EOR(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus.read(valueAddr); + unsigned value = this->getBus().read(valueAddr); if (!this->_registers.p.m) - value += this->_bus.read(valueAddr + 1) << 8u; + value += this->getBus().read(valueAddr + 1) << 8u; this->_registers.a ^= value; this->_registers.p.z = this->_registers.a == 0; this->_registers.p.n = this->_registers.a & negativeMask; diff --git a/sources/CPU/Instructions/MemoryInstructions.cpp b/sources/CPU/Instructions/MemoryInstructions.cpp index 92253ff..737f114 100644 --- a/sources/CPU/Instructions/MemoryInstructions.cpp +++ b/sources/CPU/Instructions/MemoryInstructions.cpp @@ -9,10 +9,10 @@ namespace ComSquare::CPU int CPU::STA(uint24_t addr, AddressingMode mode) { if (this->_registers.p.m) - this->_bus.write(addr, this->_registers.al); + this->getBus().write(addr, this->_registers.al); else { - this->_bus.write(addr, this->_registers.al); - this->_bus.write(addr + 1, this->_registers.ah); + this->getBus().write(addr, this->_registers.al); + this->getBus().write(addr + 1, this->_registers.ah); } int cycles = !this->_registers.p.m; @@ -34,10 +34,10 @@ namespace ComSquare::CPU int CPU::STX(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) - this->_bus.write(addr, this->_registers.xl); + this->getBus().write(addr, this->_registers.xl); else { - this->_bus.write(addr, this->_registers.xl); - this->_bus.write(addr + 1, this->_registers.xh); + this->getBus().write(addr, this->_registers.xl); + this->getBus().write(addr + 1, this->_registers.xh); } return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0); } @@ -45,19 +45,19 @@ namespace ComSquare::CPU int CPU::STY(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) - this->_bus.write(addr, this->_registers.yl); + this->getBus().write(addr, this->_registers.yl); else { - this->_bus.write(addr, this->_registers.yl); - this->_bus.write(addr + 1, this->_registers.yh); + this->getBus().write(addr, this->_registers.yl); + this->getBus().write(addr + 1, this->_registers.yh); } return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0); } int CPU::STZ(uint24_t addr, AddressingMode mode) { - this->_bus.write(addr, 0x00); + this->getBus().write(addr, 0x00); if (!this->_registers.p.m) - this->_bus.write(addr + 1, 0x00); + this->getBus().write(addr + 1, 0x00); if (mode == Absolute || mode == AbsoluteIndexedByX) return !this->_registers.p.m; return !this->_registers.p.m + this->_registers.dl != 0; @@ -66,11 +66,11 @@ namespace ComSquare::CPU int CPU::LDA(uint24_t addr, AddressingMode mode) { if (this->_registers.p.m) { - this->_registers.a = this->_bus.read(addr); + this->_registers.a = this->getBus().read(addr); this->_registers.p.n = this->_registers.al & 0xF0u; } else { - this->_registers.al = this->_bus.read(addr); - this->_registers.ah = this->_bus.read(addr + 1); + this->_registers.al = this->getBus().read(addr); + this->_registers.ah = this->getBus().read(addr + 1); this->_registers.p.n = this->_registers.a & 0xF000u; } this->_registers.p.z = this->_registers.a == 0x0; @@ -101,11 +101,11 @@ namespace ComSquare::CPU int CPU::LDX(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) { - this->_registers.x = this->_bus.read(addr); + this->_registers.x = this->getBus().read(addr); this->_registers.p.n = this->_registers.xl & 0xF0u; } else { - this->_registers.xl = this->_bus.read(addr); - this->_registers.xh = this->_bus.read(addr + 1); + this->_registers.xl = this->getBus().read(addr); + this->_registers.xh = this->getBus().read(addr + 1); this->_registers.p.n = this->_registers.x & 0xF000u; } this->_registers.p.z = this->_registers.x == 0x0; @@ -128,11 +128,11 @@ namespace ComSquare::CPU int CPU::LDY(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) { - this->_registers.y = this->_bus.read(addr); + this->_registers.y = this->getBus().read(addr); this->_registers.p.n = this->_registers.yl & 0xF0u; } else { - this->_registers.yl = this->_bus.read(addr); - this->_registers.yh = this->_bus.read(addr + 1); + this->_registers.yl = this->getBus().read(addr); + this->_registers.yh = this->getBus().read(addr + 1); this->_registers.p.n = this->_registers.y & 0xF000u; } this->_registers.p.z = this->_registers.y == 0x0; diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 95b2aff..e0ecb55 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -160,8 +160,8 @@ namespace ComSquare::CPU this->_registers.dbr = destBank; while (this->_registers.a != 0xFFFF) { - uint8_t data = this->_bus.read(srcBank << 24u | this->_registers.x); - this->_bus.write(destBank << 24u | this->_registers.y, data); + uint8_t data = this->getBus().read(srcBank << 24u | this->_registers.x); + this->getBus().write(destBank << 24u | this->_registers.y, data); this->_registers.x++; this->_registers.y++; this->_registers.a--; @@ -177,8 +177,8 @@ namespace ComSquare::CPU this->_registers.dbr = destBank; while (this->_registers.a != 0xFFFF) { - uint8_t data = this->_bus.read(srcBank << 24u | this->_registers.x); - this->_bus.write(destBank << 24u | this->_registers.y, data); + uint8_t data = this->getBus().read(srcBank << 24u | this->_registers.x); + this->getBus().write(destBank << 24u | this->_registers.y, data); this->_registers.x--; this->_registers.y--; this->_registers.a--; diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index 1977eab..9c4fc65 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -3,25 +3,19 @@ // #include "MemoryBusDebug.hpp" -#include "../SNES.hpp" -#include "../Utility/Utility.hpp" -#include "../Exceptions/InvalidAction.hpp" -#include "../Exceptions/InvalidAddress.hpp" +#include "SNES.hpp" +#include "Utility/Utility.hpp" +#include "Exceptions/InvalidAction.hpp" namespace ComSquare::Debugger { - MemoryBusDebug::MemoryBusDebug(SNES &snes, const Memory::MemoryBus &bus) - : MemoryBus(bus), - _window(new ClosableWindow(*this, &MemoryBusDebug::disableViewer)), - _snes(snes), - _ui(), - _model(), - _proxy(this->_model) + MemoryBusDebug::MemoryBusDebug(SNES &snes, Memory::IMemoryBus &bus) + : _window(new ClosableWindow([&snes] { snes.disableMemoryBusDebugging(); })), + _bus(bus), + _ui(), + _model(), + _proxy(this->_model) { - this->_window->setContextMenuPolicy(Qt::NoContextMenu); - this->_window->setAttribute(Qt::WA_QuitOnClose, false); - this->_window->setAttribute(Qt::WA_DeleteOnClose); - this->_ui.setupUi(this->_window); this->_proxy.setSourceModel(&this->_model); this->_ui.log->setModel(&this->_proxy); @@ -133,178 +127,165 @@ namespace ComSquare::Debugger this->_window->show(); } - void MemoryBusDebug::disableViewer() - { - this->_snes.disableMemoryBusDebugging(); - } - void MemoryBusDebug::focus() { this->_window->activateWindow(); } - bool MemoryBusDebug::isDebugger() - { - return true; - } - uint8_t MemoryBusDebug::read(uint24_t addr) { - if (this->forceSilence) - return MemoryBus::read(addr); - return this->read(addr, false); + uint8_t value = this->_bus.read(addr); + this->_model.log(BusLog(false, addr, this->getAccessor(addr), value, value)); + return value; } - uint8_t MemoryBusDebug::read(uint24_t addr, bool silence) + std::optional MemoryBusDebug::peek(uint24_t addr) { - if (!silence && !this->forceSilence) { - auto accessor = this->getAccessor(addr); - if (!accessor) { - this->_model.log(BusLog(true, addr, accessor, this->_openBus, this->_openBus)); - } else { - uint8_t value = accessor->read(accessor->getRelativeAddress(addr)); - this->_model.log(BusLog(false, addr, accessor, value, value)); - } - } - return MemoryBus::read(addr, silence); + return this->_bus.peek(addr); } void MemoryBusDebug::write(uint24_t addr, uint8_t data) { - auto accessor = this->getAccessor(addr); - std::optional value = std::nullopt; - try { - if (accessor) - value = accessor->read(accessor->getRelativeAddress(addr)); - } catch (InvalidAddress &) { - value = std::nullopt; - } - if (!forceSilence) - this->_model.log(BusLog(true, addr, accessor, value, data)); - MemoryBus::write(addr, data); + std::optional value = this->peek(addr); + this->_model.log(BusLog(true, addr, this->getAccessor(addr), value, data)); + this->_bus.write(addr, data); } - BusLog::BusLog(bool _write, uint24_t _addr, std::shared_ptr &_accessor, std::optional _oldData, uint8_t _newData) : - write(_write), addr(_addr), accessor(std::move(_accessor)), oldData(_oldData), newData(_newData) + Memory::IMemory *MemoryBusDebug::getAccessor(uint24_t addr) + { + return this->_bus.getAccessor(addr); + } + + BusLog::BusLog(bool _write, uint24_t _addr, + Memory::IMemory *_accessor, + std::optional _oldData, + uint8_t _newData) + : write(_write), + addr(_addr), + accessor(_accessor), + oldData(_oldData), + newData(_newData) {} -} -int BusLogModel::rowCount(const QModelIndex &) const -{ - return this->_logs.size(); -} - -int BusLogModel::columnCount(const QModelIndex &) const -{ - return this->column; -} - -QVariant BusLogModel::data(const QModelIndex &index, int role) const -{ - if (role == Qt::TextAlignmentRole) - return Qt::AlignCenter; - if (role != Qt::DisplayRole) - return QVariant(); - ComSquare::Debugger::BusLog log = this->_logs[index.row()]; - switch (index.column()) { - case 0: - return QString(log.write ? "Write" : "Read"); - case 1: - return QString(ComSquare::Utility::to_hex(log.addr).c_str()); - case 2: - return QString(log.accessor ? log.accessor->getName().c_str() : "Bus"); - case 3: { - uint24_t addr = log.accessor->getRelativeAddress(log.addr); - return QString(log.accessor ? log.accessor->getValueName(addr).c_str() : "Open bus"); + int BusLogModel::rowCount(const QModelIndex &) const + { + return static_cast(this->_logs.size()); } - case 4: - if (!log.oldData) - return QString("???"); - return QString(ComSquare::Utility::to_hex(*log.oldData).c_str()); - case 5: - return QString(ComSquare::Utility::to_hex(log.newData).c_str()); - default: - return QVariant(); + + int BusLogModel::columnCount(const QModelIndex &) const + { + return this->column; } -} -QVariant BusLogModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole || orientation == Qt::Vertical) - return QVariant(); - switch (section) { - case 0: - return QString("Type"); - case 1: - return QString("Address"); - case 2: - return QString("Component"); - case 3: - return QString("Data Name"); - case 4: - return QString("Old Data"); - case 5: - return QString("New Data"); - default: - return QString(""); + QVariant BusLogModel::data(const QModelIndex &index, int role) const + { + if (role == Qt::TextAlignmentRole) + return Qt::AlignCenter; + if (role != Qt::DisplayRole) + return QVariant(); + BusLog log = this->_logs[index.row()]; + switch (index.column()) { + case 0: + return QString(log.write ? "Write" : "Read"); + case 1: + return QString(ComSquare::Utility::to_hex(log.addr).c_str()); + case 2: + return QString(log.accessor ? log.accessor->getName().c_str() : "Bus"); + case 3: { + uint24_t addr = log.accessor->getRelativeAddress(log.addr); + return QString(log.accessor ? log.accessor->getValueName(addr).c_str() : "Open bus"); + } + case 4: + if (!log.oldData) + return QString("???"); + return QString(ComSquare::Utility::to_hex(*log.oldData).c_str()); + case 5: + return QString(ComSquare::Utility::to_hex(log.newData).c_str()); + default: + return QVariant(); + } } -} -void BusLogModel::log(const ComSquare::Debugger::BusLog& log) -{ - int row = this->_logs.size(); - this->beginInsertRows(QModelIndex(), row, row); - this->_logs.push_back(log); - this->insertRow(row); - this->endInsertRows(); -} - -ComSquare::Debugger::BusLog BusLogModel::getLogAt(int index) -{ - return this->_logs[index]; -} - -void BusLogModel::clearLogs() -{ - this->beginResetModel(); - this->_logs.clear(); - this->endResetModel(); -} - -BusLoggerProxy::BusLoggerProxy(BusLogModel &parent) : QSortFilterProxyModel(), _parent(parent) {} - -bool BusLoggerProxy::filterAcceptsRow(int sourceRow, const QModelIndex &) const -{ - ComSquare::Debugger::BusLog log = this->_parent.getLogAt(sourceRow); - - if (!log.accessor) - return true; - ComSquare::Component component = log.accessor->getComponent(); - switch (component) { - case ComSquare::Component::Cpu: - return this->filters[log.write].cpu; - case ComSquare::Component::Ppu: - return this->filters[log.write].ppu; - case ComSquare::Component::Apu: - return this->filters[log.write].apu; - case ComSquare::Component::Rom: - return this->filters[log.write].rom; - case ComSquare::Component::WRam: - return this->filters[log.write].wram; - case ComSquare::Component::VRam: - return this->filters[log.write].vram; - case ComSquare::Component::CGRam: - return this->filters[log.write].cgram; - case ComSquare::Component::OAMRam: - return this->filters[log.write].oamram; - case ComSquare::Component::SRam: - return this->filters[log.write].sram; - default: - return true; + QVariant BusLogModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role != Qt::DisplayRole || orientation == Qt::Vertical) + return QVariant(); + switch (section) { + case 0: + return QString("Type"); + case 1: + return QString("Address"); + case 2: + return QString("Component"); + case 3: + return QString("Data Name"); + case 4: + return QString("Old Data"); + case 5: + return QString("New Data"); + default: + return QString(""); + } } -} -void BusLoggerProxy::refresh() -{ - this->invalidateFilter(); -} + void BusLogModel::log(const BusLog &log) + { + int row = static_cast(this->_logs.size()); + this->beginInsertRows(QModelIndex(), row, row); + this->_logs.push_back(log); + this->insertRow(row); + this->endInsertRows(); + } + + BusLog BusLogModel::getLogAt(int index) + { + return this->_logs[index]; + } + + void BusLogModel::clearLogs() + { + this->beginResetModel(); + this->_logs.clear(); + this->endResetModel(); + } + + BusLoggerProxy::BusLoggerProxy(BusLogModel &parent) + : QSortFilterProxyModel(), _parent(parent) + {} + + bool BusLoggerProxy::filterAcceptsRow(int sourceRow, const QModelIndex &) const + { + BusLog log = this->_parent.getLogAt(sourceRow); + + if (!log.accessor) + return true; + Component component = log.accessor->getComponent(); + switch (component) { + case Component::Cpu: + return this->filters[log.write].cpu; + case Component::Ppu: + return this->filters[log.write].ppu; + case Component::Apu: + return this->filters[log.write].apu; + case Component::Rom: + return this->filters[log.write].rom; + case Component::WRam: + return this->filters[log.write].wram; + case Component::VRam: + return this->filters[log.write].vram; + case Component::CGRam: + return this->filters[log.write].cgram; + case Component::OAMRam: + return this->filters[log.write].oamram; + case Component::SRam: + return this->filters[log.write].sram; + default: + return true; + } + } + + void BusLoggerProxy::refresh() + { + this->invalidateFilter(); + } +} \ No newline at end of file diff --git a/sources/Debugger/MemoryBusDebug.hpp b/sources/Debugger/MemoryBusDebug.hpp index 6da6f77..12814dd 100644 --- a/sources/Debugger/MemoryBusDebug.hpp +++ b/sources/Debugger/MemoryBusDebug.hpp @@ -2,35 +2,37 @@ // Created by anonymus-raccoon on 3/20/20. // -#ifndef COMSQUARE_MEMORYBUSDEBUG_HPP -#define COMSQUARE_MEMORYBUSDEBUG_HPP +#pragma once #include #include -#include "../Memory/MemoryBus.hpp" -#include "../../ui/ui_busView.h" +#include "Memory/MemoryBus.hpp" +#include "Memory/IMemory.hpp" +#include "ui/ui_busView.h" #include "ClosableWindow.hpp" #include namespace ComSquare::Debugger { //! @brief The struct used to represent memory bus logs. - struct BusLog { + struct BusLog + { BusLog(bool write, - uint24_t addr, - std::shared_ptr &accessor, - std::optional oldData, - uint8_t newData); + uint24_t addr, + Memory::IMemory *accessor, + std::optional oldData, + uint8_t newData); bool write; uint24_t addr; - std::shared_ptr accessor; + Memory::IMemory *accessor; std::optional oldData; uint8_t newData; }; //! @brief The struct representing filters of the memory bus's logger. - struct BusLoggerFilters { + struct BusLoggerFilters + { bool cpu = true; bool apu = true; bool ppu = true; @@ -41,75 +43,75 @@ namespace ComSquare::Debugger bool oamram = true; bool cgram = true; }; -} - -//! @brief The qt model that bind the logs to the view. -class BusLogModel : public QAbstractTableModel -{ + //! @brief The qt model that bind the logs to the view. + class BusLogModel : public QAbstractTableModel + { Q_OBJECT -private: - //! @brief The logs to display. - std::vector _logs; -public: - BusLogModel() = default; - BusLogModel(const BusLogModel &) = delete; - const BusLogModel &operator=(const BusLogModel &) = delete; - ~BusLogModel() override = default; + private: + //! @brief The logs to display. + std::vector _logs; + public: + BusLogModel() = default; + BusLogModel(const BusLogModel &) = delete; + const BusLogModel &operator=(const BusLogModel &) = delete; + ~BusLogModel() override = default; - //! @brief The number of column; - const int column = 6; + //! @brief The number of column; + const int column = 6; - //! @brief Add a log to the model - void log(const ComSquare::Debugger::BusLog& log); + //! @brief Add a log to the model + void log(const ComSquare::Debugger::BusLog &log); - //! @brief Get a log at an index. - ComSquare::Debugger::BusLog getLogAt(int index); - //! @brief Clear all the logs - void clearLogs(); + //! @brief Get a log at an index. + ComSquare::Debugger::BusLog getLogAt(int index); + //! @brief Clear all the logs + void clearLogs(); - //! @brief The number of row the table has. - int rowCount(const QModelIndex &parent) const override; - //! @brief The number of column the table has. - int columnCount(const QModelIndex &parent) const override; - //! @brief Return a data representing the table cell. - 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; -}; + //! @brief The number of row the table has. + [[nodiscard]] int rowCount(const QModelIndex &parent) const override; + //! @brief The number of column the table has. + [[nodiscard]] int columnCount(const QModelIndex &parent) const override; + //! @brief Return a data representing the table cell. + [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; + //! @brief Override the headers to use hex values. + [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + }; -//! @brief A class to filter logs from the memory bus's debugger. -class BusLoggerProxy : public QSortFilterProxyModel { + //! @brief A class to filter logs from the memory bus's debugger. + class BusLoggerProxy : public QSortFilterProxyModel + { Q_OBJECT -private: - //! @brief The parent to get the original data for filters - BusLogModel &_parent; -protected: - //! @brief Function that filter logs. - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; -public: - //! @brief Currently enabled filters, index 0 is for reads, index 1 for writes. - ComSquare::Debugger::BusLoggerFilters filters[2] = {ComSquare::Debugger::BusLoggerFilters(), ComSquare::Debugger::BusLoggerFilters()}; + private: + //! @brief The parent to get the original data for filters + BusLogModel &_parent; + protected: + //! @brief Function that filter logs. + [[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + public: + //! @brief Currently enabled filters, index 0 is for reads, index 1 for writes. + ComSquare::Debugger::BusLoggerFilters filters[2] = { + ComSquare::Debugger::BusLoggerFilters(), + ComSquare::Debugger::BusLoggerFilters() + }; - //! @brief Refresh the view after a change of filters. - void refresh(); + //! @brief Refresh the view after a change of filters. + void refresh(); - explicit BusLoggerProxy(BusLogModel &parent); - BusLoggerProxy(const BusLoggerProxy &) = delete; - const BusLoggerProxy &operator=(const BusLoggerProxy &) = delete; - ~BusLoggerProxy() override = default; -}; + explicit BusLoggerProxy(BusLogModel &parent); + BusLoggerProxy(const BusLoggerProxy &) = delete; + const BusLoggerProxy &operator=(const BusLoggerProxy &) = delete; + ~BusLoggerProxy() override = default; + }; - -namespace ComSquare::Debugger -{ //! @brief window that allow the user to view all data going through the memory bus. - class MemoryBusDebug : public Memory::MemoryBus { + class MemoryBusDebug : public Memory::IMemoryBus + { private: //! @brief The QT window for this debugger. - ClosableWindow *_window; - //! @brief A reference to the snes (to disable the debugger). - SNES &_snes; + ClosableWindow *_window; + //! @brief A reference to the underlying bus.. + Memory::IMemoryBus &_bus; //! @brief A widget that contain the whole UI. Ui::BusView _ui; //! @brief The Log visualizer model for QT. @@ -117,35 +119,33 @@ namespace ComSquare::Debugger //! @brief A QT proxy to filter the logs. BusLoggerProxy _proxy; public: - //! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU. - void disableViewer(); - public: - explicit MemoryBusDebug(SNES &snes, const Memory::MemoryBus &bus); + explicit MemoryBusDebug(SNES &snes, Memory::IMemoryBus &bus); MemoryBusDebug(const MemoryBusDebug &) = delete; MemoryBusDebug &operator=(const MemoryBusDebug &) = delete; - ~MemoryBusDebug() = default; + ~MemoryBusDebug() override = default; - //! @brief Read data at a global address and log it to the debugger. + //! @brief Read data at a global address. This form allow read to be silenced. //! @param addr The address to read from. + //! @throws InvalidAddress If the address is not mapped to the bus, this exception is thrown. //! @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) override; - //! @brief Read data at a global address and log it to the debugger. + //! @brief This as the same purpose as a read but it does not change the open bus and won't throw an exception. //! @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; + std::optional peek(uint24_t addr) override; - //! @brief Write a data to a global address and log it to the debugger. + //! @brief Write a data to a global address. //! @param addr The address to write to. //! @param data The data to write. void write(uint24_t addr, uint8_t data) override; + //! @brief Helper function to get the components that is responsible of read/write at an address. + //! @param addr The address you want to look for. + //! @return The components responsible for the address param or nullptr if none was found. + Memory::IMemory *getAccessor(uint24_t addr) override; + //! @brief Focus the debugger's window. void focus(); - - //! @brief Return true if the Bus is overloaded with debugging features. - bool isDebugger() override; }; } - -#endif //COMSQUARE_MEMORYBUSDEBUG_HPP diff --git a/sources/Memory/IMemory.hpp b/sources/Memory/IMemory.hpp index a0cfe5e..8b59811 100644 --- a/sources/Memory/IMemory.hpp +++ b/sources/Memory/IMemory.hpp @@ -8,13 +8,14 @@ #include #include #include -#include "../Models/Int24.hpp" -#include "../Models/Components.hpp" +#include "Models/Int24.hpp" +#include "Models/Components.hpp" namespace ComSquare::Memory { //! @brief Common interface implemented by all components mapping memory. - class IMemory { + class IMemory + { public: //! @brief Read data from the component. //! @param addr The local address to read from (0x0 should refer to the first byte of this component). diff --git a/sources/Memory/IMemoryBus.hpp b/sources/Memory/IMemoryBus.hpp new file mode 100644 index 0000000..d6900fd --- /dev/null +++ b/sources/Memory/IMemoryBus.hpp @@ -0,0 +1,47 @@ +// +// Created by Zoe Roux on 2021-07-04. +// + + +#pragma once + +#include +#include +#include "IMemory.hpp" + +namespace ComSquare +{ + class SNES; + + namespace Memory + { + //! @brief The memory bus is the component responsible of mapping addresses to components address and transmitting the data. + class IMemoryBus + { + public: + //! @brief A virtual default destructor. + virtual ~IMemoryBus() = default; + + //! @brief Read data at a global address. This form allow read to be silenced. + //! @param addr The address to read from. + //! @throws InvalidAddress If the address is not mapped to the bus, this exception is thrown. + //! @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) = 0; + + //! @brief This as the same purpose as a read but it does not change the open bus and won't throw an exception. + //! @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. + virtual std::optional peek(uint24_t addr) = 0; + + //! @brief Write a data to a global address. + //! @param addr The address to write to. + //! @param data The data to write. + virtual void write(uint24_t addr, uint8_t data) = 0; + + //! @brief Helper function to get the components that is responsible of read/write at an address. + //! @param addr The address you want to look for. + //! @return The components responsible for the address param or nullptr if none was found. + virtual IMemory *getAccessor(uint24_t addr) = 0; + }; + } +} \ No newline at end of file diff --git a/sources/Memory/MemoryBus.cpp b/sources/Memory/MemoryBus.cpp index 2032006..ba07ae4 100644 --- a/sources/Memory/MemoryBus.cpp +++ b/sources/Memory/MemoryBus.cpp @@ -2,7 +2,6 @@ // Created by anonymus-raccoon on 1/23/20. // -#include #include #include "SNES.hpp" #include "Memory/MemoryBus.hpp" @@ -36,7 +35,7 @@ namespace ComSquare::Memory return data; } - uint8_t MemoryBus::peek(uint24_t addr) + std::optional MemoryBus::peek(uint24_t addr) { IMemory *handler = this->getAccessor(addr); @@ -45,7 +44,7 @@ namespace ComSquare::Memory try { return handler->read(handler->getRelativeAddress(addr)); } catch (const InvalidAddress &) { - return 0; + return std::nullopt; } } diff --git a/sources/Memory/MemoryBus.hpp b/sources/Memory/MemoryBus.hpp index e222027..03d72d6 100644 --- a/sources/Memory/MemoryBus.hpp +++ b/sources/Memory/MemoryBus.hpp @@ -7,6 +7,7 @@ #include "AMemory.hpp" #include "RectangleShadow.hpp" #include "MemoryShadow.hpp" +#include "IMemoryBus.hpp" #include #include #include @@ -18,7 +19,7 @@ namespace ComSquare namespace Memory { //! @brief The memory bus is the component responsible of mapping addresses to components address and transmitting the data. - class MemoryBus + class MemoryBus : public IMemoryBus { private: //! @brief The list of components registered inside the bus. Every components that can read/write to a public address should be in this vector. @@ -44,26 +45,23 @@ namespace ComSquare //! @brief A memory bus is assignable. MemoryBus &operator=(const MemoryBus &) = default; //! @brief A default destructor - ~MemoryBus() = default; - - //! @brief Force silencing read to the bus. - bool forceSilence = false; + ~MemoryBus() override = default; //! @brief Read data at a global address. This form allow read to be silenced. //! @param addr The address to read from. //! @throws InvalidAddress If the address is not mapped to the bus, this exception is thrown. //! @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); + uint8_t read(uint24_t addr) override; //! @brief This as the same purpose as a read but it does not change the open bus and won't throw an exception. //! @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 peek(uint24_t addr); + std::optional peek(uint24_t addr) override; //! @brief Write a data to a global address. //! @param addr The address to write to. //! @param data The data to write. - void write(uint24_t addr, uint8_t data); + void write(uint24_t addr, uint8_t data) override; //! @brief Map components to the address space using the currently loaded cartridge to set the right mapping mode. //! @param console All the components. @@ -72,7 +70,7 @@ namespace ComSquare //! @brief Helper function to get the components that is responsible of read/write at an address. //! @param addr The address you want to look for. //! @return The components responsible for the address param or nullptr if none was found. - IMemory *getAccessor(uint24_t addr); + IMemory *getAccessor(uint24_t addr) override; }; } } diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp index 93285f9..9dec948 100644 --- a/sources/Renderer/QtRenderer/QtSFML.cpp +++ b/sources/Renderer/QtRenderer/QtSFML.cpp @@ -95,7 +95,7 @@ namespace ComSquare::Renderer void QtFullSFML::enableDebugBus() { -// this->_snes.enableMemoryBusDebugging(); + this->_snes.enableMemoryBusDebugging(); } void QtFullSFML::enableCgramViewer() diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 9d7d1ae..b7fcbfa 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -116,22 +116,21 @@ namespace ComSquare // this->apu = std::make_shared(*this->apu); // this->bus.mapComponents(*this); // } -// -// void SNES::enableMemoryBusDebugging() -// { -// if (this->bus.isDebugger()) -// std::static_pointer_cast(this->bus)->focus(); -// else { -// this->bus = std::make_shared(*this, *this->bus); -// this->cpu->setMemoryBus(this->bus); -// } -// } -// -// void SNES::disableMemoryBusDebugging() -// { -// this->bus = std::make_shared(*this->bus); -// this->cpu->setMemoryBus(this->bus); -// } + + void SNES::enableMemoryBusDebugging() + { + if (this->_busDebugger) + this->_busDebugger->focus(); + else + this->_busDebugger.emplace(*this, this->bus); + this->cpu.setBus(this->_busDebugger.value()); + } + + void SNES::disableMemoryBusDebugging() + { + this->_busDebugger = std::nullopt; + this->cpu.setBus(this->bus); + } void SNES::enableCgramViewer() { diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 41e5e54..a9b376d 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -18,7 +18,7 @@ //#include #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" -//#include "Debugger/MemoryBusDebug.hpp" +#include "Debugger/MemoryBusDebug.hpp" #include "Debugger/CGramDebug.hpp" #include "Debugger/RegisterViewer.hpp" #include "Debugger/TileViewer/TileViewer.hpp" @@ -33,6 +33,8 @@ namespace ComSquare #ifdef DEBUGGER_ENABLED //! @brief The CPU's debugger with disassembly, pause, step by step... // std::optional _cpuDebugger; + //! @brief A debugger that shows every read and write made over the bus. + std::optional _busDebugger; //! @brief The window that allow the user to view a memory. std::optional _ramViewer; @@ -104,10 +106,10 @@ namespace ComSquare // void disableAPUDebugging(); // //! @brief Enable the APU's debugging window. // void enableAPUDebugging(); -// //! @brief Disable the Memory Bus's debugging window. -// void disableMemoryBusDebugging(); -// //! @brief Enable the Memory Bus's debugging window. -// void enableMemoryBusDebugging(); + //! @brief Disable the Memory Bus's debugging window. + void disableMemoryBusDebugging(); + //! @brief Enable the Memory Bus's debugging window. + void enableMemoryBusDebugging(); //! @brief Disable the CGRAM's debugging window. void disableCgramViewer(); //! @brief Enable the CGRAM's debugging window.