From 291426a3928a2ffe86176ec9fe6f23d177471fab Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 27 May 2020 18:52:11 +0200 Subject: [PATCH 01/30] Handling a basic DMA --- sources/CPU/CPU.cpp | 20 ++++++++++++++------ sources/CPU/CPU.hpp | 3 --- sources/CPU/DMA/DMA.cpp | 42 +++++++++++++++++++++++++++++++++++++++-- sources/CPU/DMA/DMA.hpp | 39 ++++++++++++++++++++++++++++++-------- 4 files changed, 85 insertions(+), 19 deletions(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index e507265..5962413 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -12,9 +12,12 @@ namespace ComSquare::CPU { CPU::CPU(std::shared_ptr bus, Cartridge::Header &cartridgeHeader) - : _bus(std::move(bus)), _cartridgeHeader(cartridgeHeader) + : _bus(std::move(bus)), + _cartridgeHeader(cartridgeHeader) { this->RESB(); + for (DMA &channel : this->_dmaChannels) + channel.setBus(_bus); } bool CPU::isDebugger() @@ -30,6 +33,8 @@ namespace ComSquare::CPU //! @bref The CPU's internal registers starts at $4200 and finish at $421F. uint8_t CPU::read(uint24_t addr) { + uint8_t tmp = 0; + switch (addr) { case 0x0: return this->_internalRegisters.nmitimen; @@ -54,7 +59,9 @@ namespace ComSquare::CPU case 0xA: return this->_internalRegisters.vtimeh; case 0xB: - return this->_internalRegisters.dmaEnableRegister; + for (int i = 0; i < 8; i++) + tmp |= this->_dmaChannels[i].enabled << i; + return tmp; case 0xC: return this->_internalRegisters.hdmaen; case 0xD: @@ -135,7 +142,8 @@ namespace ComSquare::CPU this->_internalRegisters.vtimeh = data; break; case 0xB: - this->_internalRegisters.dmaEnableRegister = data; + for (int i = 0; i < 8; i++) + this->_dmaChannels[i].enabled = data & (0b1 << i); break; case 0xC: this->_internalRegisters.hdmaen = data; @@ -211,10 +219,10 @@ namespace ComSquare::CPU unsigned cycles = 0; const unsigned maxCycles = 0x17; - for (int i = 0; i < 8; i++) { - if (!(this->_internalRegisters.dmaEnableRegister & (0xF << i))) + for (DMA &channel : this->_dmaChannels) { + if (!channel.enabled) continue; - cycles += this->_dmaChannels[i].run(maxCycles - cycles); + cycles += channel.run(maxCycles - cycles); } for (unsigned i = 0; i < maxCycles; i++) { if (this->_isStopped) { diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index f4af358..8aec2fa 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -131,9 +131,6 @@ namespace ComSquare::CPU //! @brief IRQ Timer Registers (Vertical - High) uint8_t vtimeh; - //! @brief DMA Enable Register - uint8_t dmaEnableRegister; - //! @brief HDMA Enable Register uint8_t hdmaen; diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index eda81d6..a9eee1d 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -7,6 +7,13 @@ namespace ComSquare::CPU { + DMA::DMA(std::shared_ptr bus) : _bus(std::move(bus)) {} + + void DMA::setBus(std::shared_ptr bus) + { + this->_bus = std::move(bus); + } + uint8_t DMA::read(uint8_t addr) { switch (addr) { @@ -58,8 +65,39 @@ namespace ComSquare::CPU } } - uint8_t DMA::run(unsigned int cycles) + unsigned DMA::_writeOneByte() { - return 0; + // 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(this->aAddress.raw); + if (accessor && accessor->getComponent() == WRam) { + if (this->controlRegister.direction == AToB) + return 8; + this->_bus->write(this->aAddress.raw, 0xFF); + return 4; + } + } + if (this->controlRegister.direction == AToB) { + uint8_t data = this->_bus->read(this->aAddress.raw); + this->_bus->write(0x2100 | this->port, data); + } else { + uint8_t data = this->_bus->read(0x2100 | this->port); + this->_bus->write(this->aAddress.raw, data); + } + return 8; + } + + uint8_t DMA::run(unsigned int maxCycles) + { + unsigned cycles = 8; + + do { + cycles += this->_writeOneByte(); + if (!this->controlRegister.fixed) + this->aAddress.page += this->controlRegister.increment ? -1 : 1; + this->count.raw--; + } while (this->count.raw > 0 && cycles < maxCycles); + this->enabled = false; + return cycles; } } \ No newline at end of file diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index f152757..da9e8be 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -6,7 +6,9 @@ #define COMSQUARE_DMA_HPP #include +#include #include "../../Models/Int24.hpp" +#include "../../Memory/MemoryBus.hpp" namespace ComSquare::CPU { @@ -24,22 +26,31 @@ namespace ComSquare::CPU FourToFour = 0b100 }; + enum Direction { + AToB, + BToA + }; + //! @brief Class handling all DMA/HDMA transfers (Direct Memory Access or H-Blank Direct Memory Access) class DMA { + private: + //! @brief Write one byte using the A address, the port and the direction. Handle special cases where no write occurs. + //! @return The number of cycles used. + unsigned _writeOneByte(); public: //! @brief DMA Control register (various information about the transfer) union { struct { - //! @brief The direction of the transfer (0: CPU to PPU aka A to B, 1: PPU to CPU aka B to A). - bool direction: 1; - //! @brief Two unused bites. - bool _: 2; - //! @brief if this flag is 0: increment. Else: decrement. (The A address) - bool increment: 1; + //! @brief DMA's mode: how many bytes/registers there is, how many writes... + DMAMode mode: 3; //! @brief If this flag is set, no increment/decrement will be done. bool fixed: 1; - //! @brief DMA's mode: how many bytes/registers there is, how many writes... - enum DMAMode mode: 3; + //! @brief if this flag is 0: increment. Else: decrement. (The A address) + bool increment: 1; + //! @brief Two unused bites. + bool _: 2; + //! @brief The direction of the transfer. + Direction direction: 1; }; uint8_t raw; } controlRegister; @@ -48,6 +59,10 @@ namespace ComSquare::CPU //! @brief The absolute long address of the data from the A bus. union { uint8_t bytes[3]; + struct { + uint16_t page; + uint8_t bank; + }; uint24_t raw: 24; } aAddress; //! @brief The number of bytes to be transferred. @@ -55,6 +70,13 @@ namespace ComSquare::CPU uint8_t bytes[2]; uint16_t raw; } count; + //! @brief Is this channel set to run? + bool enabled; + + //! @brief The memory bus to use for read/write. + std::shared_ptr _bus; + //! @brief Set the memory bus used by this dma channel. + void setBus(std::shared_ptr bus); //! @brief Bus helper to read from this channel. uint8_t read(uint8_t addr); @@ -67,6 +89,7 @@ namespace ComSquare::CPU uint8_t run(unsigned cycles); DMA() = default; + DMA(std::shared_ptr bus); DMA(const DMA &) = default; DMA &operator=(const DMA &) = default; ~DMA() = default; From 5ef1ba8d4fbfea0bd5ae1cd16437422f99b8ef2b Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 28 May 2020 01:17:45 +0200 Subject: [PATCH 02/30] Handling DMA's modes --- sources/CPU/DMA/DMA.cpp | 35 +++++++++++++++++++++++++++-------- sources/CPU/DMA/DMA.hpp | 4 +++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index a9eee1d..3d21402 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -65,24 +65,24 @@ namespace ComSquare::CPU } } - unsigned DMA::_writeOneByte() + unsigned DMA::_writeOneByte(uint24_t aAddress, uint24_t bAddress) { // 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(this->aAddress.raw); + auto accessor = this->_bus->getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { if (this->controlRegister.direction == AToB) return 8; - this->_bus->write(this->aAddress.raw, 0xFF); + this->_bus->write(aAddress, 0xFF); return 4; } } if (this->controlRegister.direction == AToB) { - uint8_t data = this->_bus->read(this->aAddress.raw); - this->_bus->write(0x2100 | this->port, data); + uint8_t data = this->_bus->read(aAddress); + this->_bus->write(bAddress, data); } else { - uint8_t data = this->_bus->read(0x2100 | this->port); - this->_bus->write(this->aAddress.raw, data); + uint8_t data = this->_bus->read(bAddress); + this->_bus->write(aAddress, data); } return 8; } @@ -90,14 +90,33 @@ namespace ComSquare::CPU uint8_t DMA::run(unsigned int maxCycles) { unsigned cycles = 8; + int i = 0; do { - cycles += this->_writeOneByte(); + cycles += this->_writeOneByte(this->aAddress.raw, 0x2100 | this->port + this->getModeOffset(i)); if (!this->controlRegister.fixed) this->aAddress.page += this->controlRegister.increment ? -1 : 1; this->count.raw--; + i++; } while (this->count.raw > 0 && cycles < maxCycles); this->enabled = false; return cycles; } + + int DMA::getModeOffset(int index) + { + switch (this->controlRegister.mode) { + case OneToOne: + return 0; + case TwoToTwo: + return index % 2; + case TwoToOne: + return 0; + case FourToTwo: + return (index & 0b11) > 1; + case FourToFour: + return (index & 0b11); + } + return 0; + } } \ No newline at end of file diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index da9e8be..1daaf86 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -36,7 +36,9 @@ namespace ComSquare::CPU private: //! @brief Write one byte using the A address, the port and the direction. Handle special cases where no write occurs. //! @return The number of cycles used. - unsigned _writeOneByte(); + unsigned _writeOneByte(uint24_t aAddress, uint24_t bAddress); + //! @brief Get an offset corresponding to the current DMAMode and the index of the currently transferred byte. + int getModeOffset(int index); public: //! @brief DMA Control register (various information about the transfer) union { From 627fac8f2df00e2a8478762e310e5943b674808e Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 28 May 2020 03:45:37 +0200 Subject: [PATCH 03/30] Fixing the PHA --- sources/CPU/CPU.hpp | 2 +- sources/CPU/Instructions/InternalInstruction.cpp | 5 ++++- sources/PPU/PPU.cpp | 4 ++-- tests/CPU/testInternal.cpp | 12 ++++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 8aec2fa..f2afc1b 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -478,7 +478,7 @@ namespace ComSquare::CPU {&CPU::ORA, 3, "ora", AddressingMode::DirectPage, 2}, // 05 {&CPU::ASL, 5, "asl", AddressingMode::DirectPage, 2}, // 06 {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectLong, 2}, // 07 - {&CPU::PHP, 3, "php", AddressingMode::Implied, 3}, // 08 + {&CPU::PHP, 3, "php", AddressingMode::Implied, 1}, // 08 {&CPU::ORA, 2, "ora", AddressingMode::ImmediateForA, 2}, // 09 {&CPU::ASL, 2, "asl", AddressingMode::Implied, 1}, // 0A {&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 8430522..03fb101 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -82,7 +82,10 @@ namespace ComSquare::CPU int CPU::PHA(uint24_t, AddressingMode) { - this->_push(this->_registers.a); + if (this->_registers.p.m) + this->_push(this->_registers.al); + else + this->_push(this->_registers.a); return !this->_registers.p.m; } diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index c0a5661..9075adc 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -45,7 +45,7 @@ namespace ComSquare::PPU case ppuRegisters::stat78: return 0; default: - throw InvalidAddress("PPU Internal Registers read ", addr); + throw InvalidAddress("PPU Internal Registers read ", addr + this->getStart()); } } @@ -215,7 +215,7 @@ namespace ComSquare::PPU break; //TODO adding the rest of the registers. oaf ! default: - throw InvalidAddress("PPU Internal Registers write", addr); + throw InvalidAddress("PPU Internal Registers write", addr + this->getStart()); } } diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp index 63f6f5c..5b38be7 100644 --- a/tests/CPU/testInternal.cpp +++ b/tests/CPU/testInternal.cpp @@ -105,12 +105,24 @@ Test(PHA, basic) Init() snes.cpu->_registers.a = 0xABCD; snes.cpu->_registers.s = 0x02; + snes.cpu->_registers.p.m = false; snes.cpu->PHA(0x0, ComSquare::CPU::AddressingMode::Implied); cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]); cr_assert_eq(snes.wram->_data[2], 0xAB, "The first value pushed to the stack should be 0xAB but it was %x", snes.wram->_data[2]); cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s); } +Test(PHA, 8bits) +{ + Init() + snes.cpu->_registers.a = 0xCD; + snes.cpu->_registers.s = 0x02; + snes.cpu->_registers.p.m = false; + snes.cpu->PHA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.wram->_data[1], 0xCD, "The second value pushed to the stack should be 0xCD but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.s, 0x0, "The Stack pointer should be equal to 0x0 but it was %x", snes.cpu->_registers.s); +} + Test(PHB, basic) { Init() From 29540ce9db81a11f0369f35a6029b9caadc6fd45 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 28 May 2020 04:53:16 +0200 Subject: [PATCH 04/30] Cleaning up --- sources/CPU/DMA/DMA.cpp | 50 +++++++++++++++++++++-------------------- sources/CPU/DMA/DMA.hpp | 21 +++++++++-------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index 3d21402..5815b67 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -2,6 +2,7 @@ // Created by anonymus-raccoon on 5/26/20. // +#include #include "DMA.hpp" #include "../../Exceptions/InvalidAddress.hpp" @@ -18,19 +19,19 @@ namespace ComSquare::CPU { switch (addr) { case 0x0: - return this->controlRegister.raw; + return this->_controlRegister.raw; case 0x1: - return this->port; + return this->_port; case 0x2: - return this->aAddress.bytes[0]; + return this->_aAddress.bytes[0]; case 0x3: - return this->aAddress.bytes[1]; + return this->_aAddress.bytes[1]; case 0x4: - return this->aAddress.bytes[2]; + return this->_aAddress.bytes[2]; case 0x5: - return this->count.bytes[0]; + return this->_count.bytes[0]; case 0x6: - return this->count.bytes[1]; + return this->_count.bytes[1]; default: throw InvalidAddress("DMA read", addr); } @@ -40,25 +41,25 @@ namespace ComSquare::CPU { switch (addr) { case 0x0: - this->controlRegister.raw = data; + this->_controlRegister.raw = data; break; case 0x1: - this->port = data; + this->_port = data; break; case 0x2: - this->aAddress.bytes[0] = data; + this->_aAddress.bytes[0] = data; break; case 0x3: - this->aAddress.bytes[1] = data; + this->_aAddress.bytes[1] = data; break; case 0x4: - this->aAddress.bytes[2] = data; + this->_aAddress.bytes[2] = data; break; case 0x5: - this->count.bytes[0] = data; + this->_count.bytes[0] = data; break; case 0x6: - this->count.bytes[1] = data; + this->_count.bytes[1] = data; break; default: throw InvalidAddress("DMA read", addr); @@ -68,16 +69,16 @@ namespace ComSquare::CPU unsigned DMA::_writeOneByte(uint24_t aAddress, uint24_t bAddress) { // 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) { + if (this->_port == 0x80) { auto accessor = this->_bus->getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { - if (this->controlRegister.direction == AToB) + if (this->_controlRegister.direction == AToB) return 8; this->_bus->write(aAddress, 0xFF); return 4; } } - if (this->controlRegister.direction == AToB) { + if (this->_controlRegister.direction == AToB) { uint8_t data = this->_bus->read(aAddress); this->_bus->write(bAddress, data); } else { @@ -91,21 +92,22 @@ namespace ComSquare::CPU { unsigned cycles = 8; int i = 0; + std::cout << "Starting a DMA transfer" << std::endl; do { - cycles += this->_writeOneByte(this->aAddress.raw, 0x2100 | this->port + this->getModeOffset(i)); - if (!this->controlRegister.fixed) - this->aAddress.page += this->controlRegister.increment ? -1 : 1; - this->count.raw--; + cycles += this->_writeOneByte(this->_aAddress.raw, 0x2100 | (this->_port + this->_getModeOffset(i))); + if (!this->_controlRegister.fixed) + this->_aAddress.page += this->_controlRegister.increment ? -1 : 1; + this->_count.raw--; i++; - } while (this->count.raw > 0 && cycles < maxCycles); + } while (this->_count.raw > 0); this->enabled = false; return cycles; } - int DMA::getModeOffset(int index) + int DMA::_getModeOffset(int index) { - switch (this->controlRegister.mode) { + switch (this->_controlRegister.mode) { case OneToOne: return 0; case TwoToTwo: diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index 1daaf86..caa2dcb 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -34,12 +34,12 @@ namespace ComSquare::CPU //! @brief Class handling all DMA/HDMA transfers (Direct Memory Access or H-Blank Direct Memory Access) class DMA { private: - //! @brief Write one byte using the A address, the port and the direction. Handle special cases where no write occurs. + //! @brief Write one byte using the A address, the port and the _direction. Handle special cases where no write occurs. //! @return The number of cycles used. unsigned _writeOneByte(uint24_t aAddress, uint24_t bAddress); //! @brief Get an offset corresponding to the current DMAMode and the index of the currently transferred byte. - int getModeOffset(int index); - public: + int _getModeOffset(int index); + //! @brief DMA Control register (various information about the transfer) union { struct { @@ -55,9 +55,9 @@ namespace ComSquare::CPU Direction direction: 1; }; uint8_t raw; - } controlRegister; + } _controlRegister; //! @brief If this is 'xx', the register accessed will be $21xx. - uint8_t port; + uint8_t _port; //! @brief The absolute long address of the data from the A bus. union { uint8_t bytes[3]; @@ -66,17 +66,20 @@ namespace ComSquare::CPU uint8_t bank; }; uint24_t raw: 24; - } aAddress; + } _aAddress; //! @brief The number of bytes to be transferred. union { uint8_t bytes[2]; uint16_t raw; - } count; - //! @brief Is this channel set to run? - bool enabled; + } _count; //! @brief The memory bus to use for read/write. std::shared_ptr _bus; + + public: + //! @brief Is this channel set to run? + bool enabled; + //! @brief Set the memory bus used by this dma channel. void setBus(std::shared_ptr bus); From 5e0f6104fe4851cf8ad2b302eba2a65489b173be Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 28 May 2020 14:13:12 +0200 Subject: [PATCH 05/30] Creating the layout of a DMA viewer --- CMakeLists.txt | 17 +++- sources/Debugger/CPU/CPUDebug.hpp | 2 +- sources/Debugger/CPU/DMA/DMADebug.cpp | 32 +++++++ sources/Debugger/CPU/DMA/DMADebug.hpp | 43 +++++++++ sources/Renderer/QtRenderer/QtSFML.cpp | 17 ++++ sources/Renderer/QtRenderer/QtSFML.hpp | 4 + sources/SNES.cpp | 17 ++++ sources/SNES.hpp | 7 ++ ui/{cpu.ui => cpuView.ui} | 0 ui/dmaView.ui | 125 +++++++++++++++++++++++++ ui/{ui_cpu.h => ui_cpuView.h} | 12 +-- 11 files changed, 264 insertions(+), 12 deletions(-) create mode 100644 sources/Debugger/CPU/DMA/DMADebug.cpp create mode 100644 sources/Debugger/CPU/DMA/DMADebug.hpp rename ui/{cpu.ui => cpuView.ui} (100%) create mode 100644 ui/dmaView.ui rename ui/{ui_cpu.h => ui_cpuView.h} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2f7462..2a26978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,11 @@ add_executable(unit_tests tests/testRectangleMemory.cpp tests/CPU/Math/testCMP.cpp sources/PPU/Backgrounds.cpp - sources/PPU/Background.cpp sources/PPU/Background.hpp sources/CPU/DMA/DMA.cpp sources/CPU/DMA/DMA.hpp) + sources/PPU/Background.cpp + sources/PPU/Background.hpp + sources/CPU/DMA/DMA.cpp + sources/CPU/DMA/DMA.hpp +) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -169,7 +173,7 @@ add_executable(ComSquare sources/Renderer/QtRenderer/QtSFML.hpp sources/Renderer/QtRenderer/QtWidgetSFML.cpp sources/Renderer/QtRenderer/QtWidgetSFML.hpp - ui/cpu.ui + ui/cpuView.ui ui/ramView.ui ui/cartridgeView.ui ui/apuView.ui @@ -215,7 +219,14 @@ add_executable(ComSquare sources/Debugger/CGramDebug.hpp sources/Models/Vector2.hpp sources/PPU/Backgrounds.cpp - sources/PPU/Background.cpp sources/PPU/Background.hpp sources/CPU/DMA/DMA.cpp sources/CPU/DMA/DMA.hpp) + sources/PPU/Background.cpp + sources/PPU/Background.hpp + sources/CPU/DMA/DMA.cpp + sources/CPU/DMA/DMA.hpp + sources/Debugger/CPU/DMA/DMADebug.cpp + sources/Debugger/CPU/DMA/DMADebug.hpp + ui/dmaView.ui +) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/Debugger/CPU/CPUDebug.hpp b/sources/Debugger/CPU/CPUDebug.hpp index db00d37..69d3e0e 100644 --- a/sources/Debugger/CPU/CPUDebug.hpp +++ b/sources/Debugger/CPU/CPUDebug.hpp @@ -9,7 +9,7 @@ #include "../../CPU/CPU.hpp" #include "../../Renderer/SFRenderer.hpp" #include "../../SNES.hpp" -#include "../../../ui/ui_cpu.h" +#include "../../../ui/ui_cpuView.h" #include "../ClosableWindow.hpp" namespace ComSquare::Debugger diff --git a/sources/Debugger/CPU/DMA/DMADebug.cpp b/sources/Debugger/CPU/DMA/DMADebug.cpp new file mode 100644 index 0000000..4222c97 --- /dev/null +++ b/sources/Debugger/CPU/DMA/DMADebug.cpp @@ -0,0 +1,32 @@ +// +// Created by anonymus-raccoon on 5/28/20. +// + +#include "DMADebug.hpp" +#include "../../../SNES.hpp" + +namespace ComSquare::Debugger +{ + DMADebug::DMADebug(SNES &snes) + : _window(new ClosableWindow(*this, &DMADebug::disableDebugger)), + _ui(), + _snes(snes) + { + this->_window->setContextMenuPolicy(Qt::NoContextMenu); + this->_window->setAttribute(Qt::WA_QuitOnClose, false); + this->_window->setAttribute(Qt::WA_DeleteOnClose); + + this->_ui.setupUi(this->_window); + this->_window->show(); + } + + void DMADebug::focus() + { + this->_window->activateWindow(); + } + + void DMADebug::disableDebugger() + { + this->_snes.disableDMADebugging(); + } +} \ No newline at end of file diff --git a/sources/Debugger/CPU/DMA/DMADebug.hpp b/sources/Debugger/CPU/DMA/DMADebug.hpp new file mode 100644 index 0000000..6bf2aa0 --- /dev/null +++ b/sources/Debugger/CPU/DMA/DMADebug.hpp @@ -0,0 +1,43 @@ +// +// Created by anonymus-raccoon on 5/28/20. +// + +#ifndef COMSQUARE_DMADEBUG_HPP +#define COMSQUARE_DMADEBUG_HPP + +#include +#include "../../ClosableWindow.hpp" +#include "../../../../ui/ui_dmaView.h" + +namespace ComSquare +{ + class SNES; + + namespace Debugger + { + class DMADebug : public QObject { + private: + //! @brief The QT window for this debugger. + ClosableWindow *_window; + //! @brief A widget that contain the whole UI. + Ui::DMAView _ui; + + //! @brief The snes instance to read/write to DMA channels. + SNES &_snes; + public: + //! @brief Called when the window is closed. Turn off the debugger. + void disableDebugger(); + + explicit DMADebug(SNES &snes); + DMADebug( + const DMADebug &) = delete; + DMADebug &operator=(const DMADebug &) = delete; + ~DMADebug() =default; + + //! @brief Focus the debugger's window. + void focus(); + }; + }; +} + +#endif //COMSQUARE_DMADEBUG_HPP diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp index 760bfd8..8c234a4 100644 --- a/sources/Renderer/QtRenderer/QtSFML.cpp +++ b/sources/Renderer/QtRenderer/QtSFML.cpp @@ -41,32 +41,44 @@ namespace ComSquare::Renderer QMainWindow::connect(reset, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::reset); game->addAction(reset); + + QMenu *debugger = this->_window.menuBar()->addMenu("&Debugger"); QAction *cpuDebugger = new QAction("CPU's Debugger", &this->_window); cpuDebugger->setShortcut(Qt::Key_F1); QMainWindow::connect(cpuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugCPU); debugger->addAction(cpuDebugger); + QAction *ramViewer = new QAction("Memory viewer", &this->_window); ramViewer->setShortcut(Qt::Key_F2); QMainWindow::connect(ramViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRamViewer); debugger->addAction(ramViewer); + QAction *headerViewer = new QAction("Header viewer", &this->_window); headerViewer->setShortcut(Qt::Key_F3); QMainWindow::connect(headerViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableHeaderViewer); debugger->addAction(headerViewer); + QAction *apuDebugger = new QAction("APU's Debugger", &this->_window); apuDebugger->setShortcut(Qt::Key_F4); QMainWindow::connect(apuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugAPU); debugger->addAction(apuDebugger); + QAction *busDebugger = new QAction("Memory bus Viewer", &this->_window); busDebugger->setShortcut(Qt::Key_F5); QMainWindow::connect(busDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugBus); debugger->addAction(busDebugger); + QAction *cgramDebugger = new QAction("Palette Viewer", &this->_window); cgramDebugger->setShortcut(Qt::Key_F6); QMainWindow::connect(cgramDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableCgramViewer); debugger->addAction(cgramDebugger); + QAction *dmaDebugger = new QAction("DMA Viewer", &this->_window); + dmaDebugger->setShortcut(Qt::Key_F7); + QMainWindow::connect(dmaDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDMAViewer); + debugger->addAction(dmaDebugger); + this->_window.show(); } @@ -134,4 +146,9 @@ namespace ComSquare::Renderer { this->_snes.enableCgramDebugging(); } + + void QtFullSFML::enableDMAViewer() + { + this->_snes.enableDMADebugging(); + } } \ No newline at end of file diff --git a/sources/Renderer/QtRenderer/QtSFML.hpp b/sources/Renderer/QtRenderer/QtSFML.hpp index 661422c..fc9d45a 100644 --- a/sources/Renderer/QtRenderer/QtSFML.hpp +++ b/sources/Renderer/QtRenderer/QtSFML.hpp @@ -35,8 +35,12 @@ namespace ComSquare::Renderer void enableDebugBus(); //! @brief Action called when clicking on the enable Palette viewer button. void enableCgramViewer(); + //! @brief Action called when clicking on the enable DMA viewer button. + void enableDMAViewer(); + //! @brief Action called when clicking on the reset button. void reset(); + QtFullSFML(SNES &snes, QWidget* parent, const QPoint& position, const QSize& size, int frameRate = 0); QtFullSFML(const QtFullSFML &) = delete; QtFullSFML &operator=(const QtFullSFML &) = delete; diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 153c1e8..8ccbed3 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -153,4 +153,21 @@ namespace ComSquare this->_cgramViewer = nullptr; #endif } + + void SNES::disableDMADebugging() + { + #ifdef DEBUGGER_ENABLED + this->_dmaViewer = nullptr; + #endif + } + + void SNES::enableDMADebugging() + { + #ifdef DEBUGGER_ENABLED + if (this->_dmaViewer) + this->_dmaViewer->focus(); + else + this->_dmaViewer = std::make_unique(*this); + #endif + } } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 5babc05..3755434 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -16,6 +16,7 @@ #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" #include "Debugger/CGramDebug.hpp" +#include "Debugger/CPU/DMA/DMADebug.hpp" #endif @@ -31,6 +32,8 @@ namespace ComSquare std::unique_ptr _headerViewer; //! @brief The window that allow the user to view the CGRAM. std::unique_ptr _cgramViewer; + //! @brief The window that allow the user to view the DMA's properties. + std::unique_ptr _dmaViewer; #endif //! @brief The memory bus that map addresses to components. std::shared_ptr _bus; @@ -77,6 +80,10 @@ namespace ComSquare void disableCgramDebugging(); //! @brief Enable the Cgram's debugging window. void enableCgramDebugging(); + //! @brief Disable the DMA's debugging window. + void disableDMADebugging(); + //! @brief Enable the DMA's debugging window. + void enableDMADebugging(); //! @brief Create all the components using a common memory bus for all of them. SNES(const std::string &ramPath, Renderer::IRenderer &renderer); diff --git a/ui/cpu.ui b/ui/cpuView.ui similarity index 100% rename from ui/cpu.ui rename to ui/cpuView.ui diff --git a/ui/dmaView.ui b/ui/dmaView.ui new file mode 100644 index 0000000..10f622e --- /dev/null +++ b/ui/dmaView.ui @@ -0,0 +1,125 @@ + + + DMAView + + + + 0 + 0 + 795 + 534 + + + + DMA's Debugger + + + + :/resources/Logo.png:/resources/Logo.png + + + + + + + QAbstractScrollArea::AdjustIgnored + + + 28 + + + 86 + + + 61 + + + + Channel 1 + + + + + Channel 2 + + + + + Channel 3 + + + + + Channel 4 + + + + + Channel 5 + + + + + Channel 6 + + + + + Channel 7 + + + + + Channel 8 + + + + + Mode + + + + + Fixed + + + + + Increment + + + + + Direction + + + + + Port + + + + + A Address + + + + + Count + + + + + Enabled + + + + + + + + + + + + diff --git a/ui/ui_cpu.h b/ui/ui_cpuView.h similarity index 98% rename from ui/ui_cpu.h rename to ui/ui_cpuView.h index 54b8db8..00998e3 100644 --- a/ui/ui_cpu.h +++ b/ui/ui_cpuView.h @@ -1,17 +1,13 @@ /******************************************************************************** -** Form generated from reading UI file 'cpu.ui' +** Form generated from reading UI file 'cpuView.ui' ** -<<<<<<< HEAD -** Created by: Qt User Interface Compiler version 5.13.2 -======= ** Created by: Qt User Interface Compiler version 5.14.2 ->>>>>>> 24bcafeea3896022704904815d263f69f22e5096 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ -#ifndef UI_CPU_H -#define UI_CPU_H +#ifndef UI_CPUVIEW_H +#define UI_CPUVIEW_H #include #include @@ -458,4 +454,4 @@ namespace Ui { QT_END_NAMESPACE -#endif // UI_CPU_H +#endif // UI_CPUVIEW_H From 3fb36e1be312acec8770ed29868291fd20a14936 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 28 May 2020 14:51:44 +0200 Subject: [PATCH 06/30] Remplacing the DMA viewer by a registers viewer --- CMakeLists.txt | 6 +- .../DMA/DMADebug.cpp => RegisterViewer.cpp} | 14 +- .../DMA/DMADebug.hpp => RegisterViewer.hpp} | 26 ++-- sources/Renderer/QtRenderer/QtSFML.cpp | 15 +-- sources/Renderer/QtRenderer/QtSFML.hpp | 2 +- sources/SNES.cpp | 12 +- sources/SNES.hpp | 14 +- ui/dmaView.ui | 125 ------------------ ui/registersView.ui | 75 +++++++++++ 9 files changed, 119 insertions(+), 170 deletions(-) rename sources/Debugger/{CPU/DMA/DMADebug.cpp => RegisterViewer.cpp} (56%) rename sources/Debugger/{CPU/DMA/DMADebug.hpp => RegisterViewer.hpp} (51%) delete mode 100644 ui/dmaView.ui create mode 100644 ui/registersView.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a26978..72fa0bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,9 +223,9 @@ add_executable(ComSquare sources/PPU/Background.hpp sources/CPU/DMA/DMA.cpp sources/CPU/DMA/DMA.hpp - sources/Debugger/CPU/DMA/DMADebug.cpp - sources/Debugger/CPU/DMA/DMADebug.hpp - ui/dmaView.ui + ui/registersView.ui + sources/Debugger/RegisterViewer.cpp + sources/Debugger/RegisterViewer.hpp ) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/Debugger/CPU/DMA/DMADebug.cpp b/sources/Debugger/RegisterViewer.cpp similarity index 56% rename from sources/Debugger/CPU/DMA/DMADebug.cpp rename to sources/Debugger/RegisterViewer.cpp index 4222c97..56178a9 100644 --- a/sources/Debugger/CPU/DMA/DMADebug.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -2,13 +2,13 @@ // Created by anonymus-raccoon on 5/28/20. // -#include "DMADebug.hpp" -#include "../../../SNES.hpp" +#include "RegisterViewer.hpp" +#include "../SNES.hpp" namespace ComSquare::Debugger { - DMADebug::DMADebug(SNES &snes) - : _window(new ClosableWindow(*this, &DMADebug::disableDebugger)), + RegisterViewer::RegisterViewer(SNES &snes) + : _window(new ClosableWindow(*this, &RegisterViewer::disableDebugger)), _ui(), _snes(snes) { @@ -20,13 +20,13 @@ namespace ComSquare::Debugger this->_window->show(); } - void DMADebug::focus() + void RegisterViewer::focus() { this->_window->activateWindow(); } - void DMADebug::disableDebugger() + void RegisterViewer::disableDebugger() { - this->_snes.disableDMADebugging(); + this->_snes.disableRegisterDebugging(); } } \ No newline at end of file diff --git a/sources/Debugger/CPU/DMA/DMADebug.hpp b/sources/Debugger/RegisterViewer.hpp similarity index 51% rename from sources/Debugger/CPU/DMA/DMADebug.hpp rename to sources/Debugger/RegisterViewer.hpp index 6bf2aa0..e1853ab 100644 --- a/sources/Debugger/CPU/DMA/DMADebug.hpp +++ b/sources/Debugger/RegisterViewer.hpp @@ -2,12 +2,12 @@ // Created by anonymus-raccoon on 5/28/20. // -#ifndef COMSQUARE_DMADEBUG_HPP -#define COMSQUARE_DMADEBUG_HPP +#ifndef COMSQUARE_REGISTERVIEWER_HPP +#define COMSQUARE_REGISTERVIEWER_HPP #include -#include "../../ClosableWindow.hpp" -#include "../../../../ui/ui_dmaView.h" +#include "ClosableWindow.hpp" +#include "../../ui/ui_registersView.h" namespace ComSquare { @@ -15,12 +15,12 @@ namespace ComSquare namespace Debugger { - class DMADebug : public QObject { + class RegisterViewer : public QObject { private: //! @brief The QT window for this debugger. - ClosableWindow *_window; + ClosableWindow *_window; //! @brief A widget that contain the whole UI. - Ui::DMAView _ui; + Ui::RegistersView _ui; //! @brief The snes instance to read/write to DMA channels. SNES &_snes; @@ -28,11 +28,11 @@ namespace ComSquare //! @brief Called when the window is closed. Turn off the debugger. void disableDebugger(); - explicit DMADebug(SNES &snes); - DMADebug( - const DMADebug &) = delete; - DMADebug &operator=(const DMADebug &) = delete; - ~DMADebug() =default; + explicit RegisterViewer(SNES &snes); + RegisterViewer( + const RegisterViewer &) = delete; + RegisterViewer &operator=(const RegisterViewer &) = delete; + ~RegisterViewer() =default; //! @brief Focus the debugger's window. void focus(); @@ -40,4 +40,4 @@ namespace ComSquare }; } -#endif //COMSQUARE_DMADEBUG_HPP +#endif //COMSQUARE_REGISTERVIEWER_HPP diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp index 8c234a4..7cbdc5f 100644 --- a/sources/Renderer/QtRenderer/QtSFML.cpp +++ b/sources/Renderer/QtRenderer/QtSFML.cpp @@ -9,7 +9,6 @@ #include #include "QtSFML.hpp" #include "../../Exceptions/InvalidOpcode.hpp" -#include "../../Exceptions/InvalidAddress.hpp" #include "../../Exceptions/InvalidAction.hpp" #ifdef Q_WS_X11 @@ -33,7 +32,7 @@ namespace ComSquare::Renderer this->_window.setCentralWidget(this->_sfWidget.get()); QMenu *file = this->_window.menuBar()->addMenu("&File"); - //TODO implement rom openning from this menu. + //TODO implement rom opening from this menu. (void)file; QMenu *game = this->_window.menuBar()->addMenu("&Game"); @@ -74,10 +73,10 @@ namespace ComSquare::Renderer QMainWindow::connect(cgramDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableCgramViewer); debugger->addAction(cgramDebugger); - QAction *dmaDebugger = new QAction("DMA Viewer", &this->_window); - dmaDebugger->setShortcut(Qt::Key_F7); - QMainWindow::connect(dmaDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDMAViewer); - debugger->addAction(dmaDebugger); + QAction *registerDebugger = new QAction("Registers Viewer", &this->_window); + registerDebugger->setShortcut(Qt::Key_F7); + QMainWindow::connect(registerDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRegisterViewer); + debugger->addAction(registerDebugger); this->_window.show(); } @@ -147,8 +146,8 @@ namespace ComSquare::Renderer this->_snes.enableCgramDebugging(); } - void QtFullSFML::enableDMAViewer() + void QtFullSFML::enableRegisterViewer() { - this->_snes.enableDMADebugging(); + this->_snes.enableRegisterDebugging(); } } \ No newline at end of file diff --git a/sources/Renderer/QtRenderer/QtSFML.hpp b/sources/Renderer/QtRenderer/QtSFML.hpp index fc9d45a..4d4e077 100644 --- a/sources/Renderer/QtRenderer/QtSFML.hpp +++ b/sources/Renderer/QtRenderer/QtSFML.hpp @@ -36,7 +36,7 @@ namespace ComSquare::Renderer //! @brief Action called when clicking on the enable Palette viewer button. void enableCgramViewer(); //! @brief Action called when clicking on the enable DMA viewer button. - void enableDMAViewer(); + void enableRegisterViewer(); //! @brief Action called when clicking on the reset button. void reset(); diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 8ccbed3..a107aaf 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -154,20 +154,20 @@ namespace ComSquare #endif } - void SNES::disableDMADebugging() + void SNES::disableRegisterDebugging() { #ifdef DEBUGGER_ENABLED - this->_dmaViewer = nullptr; + this->_registerViewer = nullptr; #endif } - void SNES::enableDMADebugging() + void SNES::enableRegisterDebugging() { #ifdef DEBUGGER_ENABLED - if (this->_dmaViewer) - this->_dmaViewer->focus(); + if (this->_registerViewer) + this->_registerViewer->focus(); else - this->_dmaViewer = std::make_unique(*this); + this->_registerViewer = std::make_unique(*this); #endif } } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 3755434..146ffb5 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -16,7 +16,7 @@ #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" #include "Debugger/CGramDebug.hpp" -#include "Debugger/CPU/DMA/DMADebug.hpp" +#include "Debugger/RegisterViewer.hpp" #endif @@ -32,8 +32,8 @@ namespace ComSquare std::unique_ptr _headerViewer; //! @brief The window that allow the user to view the CGRAM. std::unique_ptr _cgramViewer; - //! @brief The window that allow the user to view the DMA's properties. - std::unique_ptr _dmaViewer; + //! @brief The window that allow the user to view registers. + std::unique_ptr _registerViewer; #endif //! @brief The memory bus that map addresses to components. std::shared_ptr _bus; @@ -80,10 +80,10 @@ namespace ComSquare void disableCgramDebugging(); //! @brief Enable the Cgram's debugging window. void enableCgramDebugging(); - //! @brief Disable the DMA's debugging window. - void disableDMADebugging(); - //! @brief Enable the DMA's debugging window. - void enableDMADebugging(); + //! @brief Disable the Register's debugging window. + void disableRegisterDebugging(); + //! @brief Enable the Register's debugging window. + void enableRegisterDebugging(); //! @brief Create all the components using a common memory bus for all of them. SNES(const std::string &ramPath, Renderer::IRenderer &renderer); diff --git a/ui/dmaView.ui b/ui/dmaView.ui deleted file mode 100644 index 10f622e..0000000 --- a/ui/dmaView.ui +++ /dev/null @@ -1,125 +0,0 @@ - - - DMAView - - - - 0 - 0 - 795 - 534 - - - - DMA's Debugger - - - - :/resources/Logo.png:/resources/Logo.png - - - - - - - QAbstractScrollArea::AdjustIgnored - - - 28 - - - 86 - - - 61 - - - - Channel 1 - - - - - Channel 2 - - - - - Channel 3 - - - - - Channel 4 - - - - - Channel 5 - - - - - Channel 6 - - - - - Channel 7 - - - - - Channel 8 - - - - - Mode - - - - - Fixed - - - - - Increment - - - - - Direction - - - - - Port - - - - - A Address - - - - - Count - - - - - Enabled - - - - - - - - - - - - diff --git a/ui/registersView.ui b/ui/registersView.ui new file mode 100644 index 0000000..44e26db --- /dev/null +++ b/ui/registersView.ui @@ -0,0 +1,75 @@ + + + RegistersView + + + + 0 + 0 + 431 + 646 + + + + Registers's Debugger + + + + :/resources/Logo.png:/resources/Logo.png + + + + + + + 0 + + + false + + + false + + + true + + + + CPU + + + + + + + + + + PPU + + + + + + + + + + DMA + + + + + + + + + + + + + + + + + From c38b100c14c93fb126498e510384b35072bf8bd5 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 29 May 2020 18:52:58 +0200 Subject: [PATCH 07/30] Creating the structures of the register viewer --- sources/CPU/CPU.hpp | 6 ++ sources/CPU/DMA/DMA.hpp | 5 ++ sources/Debugger/RegisterViewer.cpp | 104 ++++++++++++++++++++++++++++ sources/Debugger/RegisterViewer.hpp | 79 ++++++++++++++++++++- sources/SNES.cpp | 28 ++++---- sources/SNES.hpp | 5 +- sources/Utility/Utility.hpp | 6 +- sources/main.cpp | 33 +++++---- tests/CPU/testAddressingMode.cpp | 2 +- tests/PPU/testPpuWrite.cpp | 62 ++++++++--------- tests/PPU/testPpuWriteFromVmain.cpp | 68 +++++++++--------- tests/testMemoryBus.cpp | 98 +++++++++++++------------- ui/registersView.ui | 86 ++++++++++++++++++++++- 13 files changed, 431 insertions(+), 151 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index f2afc1b..761684f 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -12,6 +12,7 @@ #include "../Memory/AMemory.hpp" #include "Instruction.hpp" #include "DMA/DMA.hpp" +#include "../Debugger/RegisterViewer.hpp" namespace ComSquare::CPU { @@ -199,6 +200,7 @@ namespace ComSquare::CPU //! @brief The cartridge header (stored for interrupt vectors.. Cartridge::Header &_cartridgeHeader; + //! @brief DMA channels witch are mapped to the bus. std::array _dmaChannels; //! @brief True if an addressing mode with an iterator (x, y) has crossed the page. (Used because crossing the page boundary take one more cycle to run certain instructions). @@ -768,6 +770,10 @@ namespace ComSquare::CPU //! @brief Change the memory bus used by the CPU. virtual void setMemoryBus(std::shared_ptr bus); + + #ifdef DEBUGGER_ENABLED + friend Debugger::RegisterViewer; + #endif }; } diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index caa2dcb..99fdbc3 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -9,6 +9,7 @@ #include #include "../../Models/Int24.hpp" #include "../../Memory/MemoryBus.hpp" +#include "../../Debugger/RegisterViewer.hpp" namespace ComSquare::CPU { @@ -98,6 +99,10 @@ namespace ComSquare::CPU DMA(const DMA &) = default; DMA &operator=(const DMA &) = default; ~DMA() = default; + + #ifdef DEBUGGER_ENABLED + friend Debugger::RegisterViewer; + #endif }; } diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index 56178a9..d6ae10f 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -4,6 +4,7 @@ #include "RegisterViewer.hpp" #include "../SNES.hpp" +#include "../Utility/Utility.hpp" namespace ComSquare::Debugger { @@ -17,9 +18,22 @@ namespace ComSquare::Debugger this->_window->setAttribute(Qt::WA_DeleteOnClose); this->_ui.setupUi(this->_window); + this->_setupUi(); this->_window->show(); } + void RegisterViewer::_setupUi() + { + for (int i = 0; i < 8; i++) { + RegistersViewerModel *model = new RegistersViewerModel(this->_snes); + model->addRegister(Register(0x420B, "-0", "Enabled", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i].enabled; + }, nullptr, Boolean)); + this->_ui.dmaChannel1->setModel(model); + this->_models.push_back(model); + } + } + void RegisterViewer::focus() { this->_window->activateWindow(); @@ -29,4 +43,94 @@ namespace ComSquare::Debugger { this->_snes.disableRegisterDebugging(); } + + RegisterViewer::~RegisterViewer() + { + for (auto &model : this->_models) + delete model; + } + + Register::Register(uint24_t addr, + const std::string &usedBits, + const std::string ®Name, + const std::function &getValue, + const std::function &setValue, + RegisterType regType) + : address(addr), + bits(usedBits), + name(regName), + get(getValue), + set(setValue), + type(regType) {} +} + +using namespace ComSquare; +using namespace ComSquare::Debugger; + +RegistersViewerModel::RegistersViewerModel(SNES &snes, QObject *parent) : QAbstractTableModel(parent), _snes(snes) { } + + +void RegistersViewerModel::addRegister(Register reg) +{ + int row = this->_registers.size(); + this->beginInsertRows(QModelIndex(), row, row); + this->_registers.push_back(reg); + this->insertRow(row); + this->endInsertRows(); +} + +int RegistersViewerModel::rowCount(const QModelIndex &) const +{ + return this->_registers.size(); +} + +int RegistersViewerModel::columnCount(const QModelIndex &) const +{ + return 3; +} + +QVariant RegistersViewerModel::data(const QModelIndex &index, int role) const +{ + Register reg = this->_registers[index.row()]; + + if (role == Qt::CheckStateRole && reg.type == Boolean && index.column() == 2) + return reg.get(this->_snes) ? Qt::Checked : Qt::Unchecked; + + if (role != Qt::DisplayRole) + return QVariant(); + + switch (index.column()) { + case 0: + return QString((Utility::to_hex(reg.address) + reg.bits).c_str()); + case 1: + return QString(reg.name.c_str()); + case 2: + switch (reg.type) { + case Boolean: + return QString(reg.get(this->_snes) ? "True" : "False"); + case EightBits: + return QString(Utility::to_hex(static_cast(reg.get(this->_snes))).c_str()); + case SixteenBits: + return QString(Utility::to_hex(static_cast(reg.get(this->_snes))).c_str()); + case TwentyFourBits: + return QString(Utility::to_hex(static_cast(reg.get(this->_snes))).c_str()); + } + } + return QVariant(); +} + +QVariant RegistersViewerModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Vertical || role != Qt::DisplayRole) + return QVariant(); + switch (section) { + case 0: + return QString("Address"); + case 1: + return QString("Name"); + case 2: + return QString("Value"); + default: + return QVariant(); + } } \ No newline at end of file diff --git a/sources/Debugger/RegisterViewer.hpp b/sources/Debugger/RegisterViewer.hpp index e1853ab..e98390e 100644 --- a/sources/Debugger/RegisterViewer.hpp +++ b/sources/Debugger/RegisterViewer.hpp @@ -8,6 +8,41 @@ #include #include "ClosableWindow.hpp" #include "../../ui/ui_registersView.h" +#include "../Models/Int24.hpp" +#include "../Memory/MemoryBus.hpp" + +namespace ComSquare::Debugger +{ + struct Register; +} + +class RegistersViewerModel : public QAbstractTableModel +{ +Q_OBJECT +private: + //! @brief The list of registers to display / update. + std::vector _registers; + //! @brief Reference to the snes to get information from registers. + ComSquare::SNES &_snes; +public: + //! @brief Add a register. + void addRegister(ComSquare::Debugger::Register reg); + + RegistersViewerModel(ComSquare::SNES &snes, QObject *parent = nullptr); + RegistersViewerModel(const RegistersViewerModel &) = delete; + const RegistersViewerModel &operator=(const RegistersViewerModel &) = delete; + ~RegistersViewerModel() override = default; + + //! @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; +}; + namespace ComSquare { @@ -21,9 +56,14 @@ namespace ComSquare ClosableWindow *_window; //! @brief A widget that contain the whole UI. Ui::RegistersView _ui; + //! @brief The list of models used by different panels. + std::vector _models; //! @brief The snes instance to read/write to DMA channels. SNES &_snes; + + //! @brief Set models to the different tables and initialize them. + void _setupUi(); public: //! @brief Called when the window is closed. Turn off the debugger. void disableDebugger(); @@ -32,12 +72,47 @@ namespace ComSquare RegisterViewer( const RegisterViewer &) = delete; RegisterViewer &operator=(const RegisterViewer &) = delete; - ~RegisterViewer() =default; + ~RegisterViewer(); //! @brief Focus the debugger's window. void focus(); }; - }; + + //! @brief The types of registers + enum RegisterType { + //! @brief This type display a checkbox + Boolean, + //! @brief A 8 bits hexadecimal value. + EightBits, + //! @brief A 16 bits hexadecimal value. + SixteenBits, + //! @brief A 24 bits hexadecimal value. + TwentyFourBits + }; + + //! @brief Struct containing information about a register. + struct Register { + Register(uint24_t addr, + const std::string &usedBits, + const std::string ®Name, + const std::function &getValue, + const std::function &setValue, + RegisterType regType); + + //! @brief Where this register is located on the bus. + uint24_t address; + //! @brief Specify witch bits are concerned if not all bytes are concerned. + std::string bits; + //! @brief The name of this register. + std::string name; + //! @brief How to get this value. + std::function get; + //! @brief How to set this value. + std::function set; + //! @brief How this value should be displayed/asked for input. + RegisterType type; + }; + } } #endif //COMSQUARE_REGISTERVIEWER_HPP diff --git a/sources/SNES.cpp b/sources/SNES.cpp index a107aaf..d6d321b 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -15,16 +15,16 @@ namespace ComSquare { SNES::SNES(const std::string &romPath, Renderer::IRenderer &renderer) : - _bus(std::make_shared()), + bus(std::make_shared()), cartridge(new Cartridge::Cartridge(romPath)), wram(new Ram::Ram(16384, WRam, "WRam")), sram(new Ram::Ram(this->cartridge->header.sramSize, SRam, "SRam")), apuRam(new APU::MemoryMap()), - cpu(new CPU::CPU(this->_bus, cartridge->header)), + cpu(new CPU::CPU(this->bus, cartridge->header)), ppu(new PPU::PPU(renderer)), apu(new APU::APU(this->apuRam)) { - this->_bus->mapComponents(*this); + this->bus->mapComponents(*this); } void SNES::update() @@ -44,7 +44,7 @@ namespace ComSquare cpuDebug->pause(); } else { this->cpu = std::make_shared(*this->cpu, *this); - this->_bus->mapComponents(*this); + this->bus->mapComponents(*this); } #else std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; @@ -55,7 +55,7 @@ namespace ComSquare void SNES::disableCPUDebugging() { this->cpu = std::make_shared(*this->cpu); - this->_bus->mapComponents(*this); + this->bus->mapComponents(*this); } void SNES::enableRamViewer() @@ -64,7 +64,7 @@ namespace ComSquare if (this->_ramViewer) this->_ramViewer->focus(); else - this->_ramViewer = std::make_unique(*this, *this->_bus); + this->_ramViewer = std::make_unique(*this, *this->bus); #endif } @@ -99,7 +99,7 @@ namespace ComSquare std::static_pointer_cast(this->apu)->focus(); else { this->apu = std::make_shared(*this->apu, *this); - this->_bus->mapComponents(*this); + this->bus->mapComponents(*this); } #else std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; @@ -109,18 +109,18 @@ namespace ComSquare void SNES::disableAPUDebugging() { this->apu = std::make_shared(*this->apu); - this->_bus->mapComponents(*this); + this->bus->mapComponents(*this); } void SNES::enableMemoryBusDebugging() { #ifdef DEBUGGER_ENABLED - if (this->_bus->isDebugger()) - std::static_pointer_cast(this->_bus)->focus(); + 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); + this->bus = std::make_shared(*this, *this->bus); + this->cpu->setMemoryBus(this->bus); } #else std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; @@ -130,8 +130,8 @@ namespace ComSquare void SNES::disableMemoryBusDebugging() { #ifdef DEBUGGER_ENABLED - this->_bus = std::make_shared(*this->_bus); - this->cpu->setMemoryBus(this->_bus); + this->bus = std::make_shared(*this->bus); + this->cpu->setMemoryBus(this->bus); #else std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; #endif diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 146ffb5..c3d3ed5 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -35,9 +35,10 @@ namespace ComSquare //! @brief The window that allow the user to view registers. std::unique_ptr _registerViewer; #endif - //! @brief The memory bus that map addresses to components. - std::shared_ptr _bus; public: + //! @brief The memory bus that map addresses to components. + std::shared_ptr bus; + //! @brief Cartridge containing instructions (ROM). std::shared_ptr cartridge; //! @brief Work Ram shared by all the components. diff --git a/sources/Utility/Utility.hpp b/sources/Utility/Utility.hpp index 489afc3..78b1ced 100644 --- a/sources/Utility/Utility.hpp +++ b/sources/Utility/Utility.hpp @@ -18,11 +18,11 @@ namespace ComSquare::Utility StandardPrefix }; - std::string to_hex(uint8_t i, HexString prefix = StandardPrefix); + std::string to_hex(uint8_t i, HexString prefix = AsmPrefix); - std::string to_hex(uint16_t i, HexString prefix = StandardPrefix); + std::string to_hex(uint16_t i, HexString prefix = AsmPrefix); - std::string to_hex(uint24_t i, HexString prefix = StandardPrefix); + std::string to_hex(uint24_t i, HexString prefix = AsmPrefix); std::string to_binary(uint8_t i); diff --git a/sources/main.cpp b/sources/main.cpp index 99bbc08..a13903b 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -16,11 +16,12 @@ void usage(char *bin) std::cout << "ComSquare:" << std::endl << "\tUsage: " << bin << " rom_path [options]" << std::endl << "Options:" << std::endl - << "\t-c, --cpu: \tEnable the debugger of the CPU." << std::endl - << "\t-m, --memory: \tEnable the memory viewer panel." << std::endl - << "\t-h, --header: \tShow the header of the cartridge." << std::endl - << "\t-b, --bus: \tShow the memory bus's log." << std::endl - << "\t-g, --cgram: \tShow the palette viewer." << std::endl; + << "\t-c, --cpu: \tEnable the debugger of the CPU." << std::endl + << "\t-m, --memory: \tEnable the memory viewer panel." << std::endl + << "\t-h, --header: \tShow the header of the cartridge." << std::endl + << "\t-b, --bus: \tShow the memory bus's log." << std::endl + << "\t-g, --cgram: \tShow the palette viewer." << std::endl + << "\t-r, --registers: \tShow the registers viewer." << std::endl; } void parseArguments(int argc, char **argv, SNES &snes) @@ -28,16 +29,17 @@ void parseArguments(int argc, char **argv, SNES &snes) while (true) { int option_index = 0; static struct option long_options[] = { - {"cpu", no_argument, 0, 'c'}, - {"apu", no_argument, 0, 'a'}, - {"memory", no_argument, 0, 'm'}, - {"header", no_argument, 0, 'h'}, - {"bus", no_argument, 0, 'b'}, - {"cgram", no_argument, 0, 'g'}, - {0, 0, 0, 0} + {"cpu", no_argument, 0, 'c'}, + {"apu", no_argument, 0, 'a'}, + {"memory", no_argument, 0, 'm'}, + {"header", no_argument, 0, 'h'}, + {"bus", no_argument, 0, 'b'}, + {"cgram", no_argument, 0, 'g'}, + {"registers", no_argument, 0, 'r'}, + {0, 0, 0, 0} }; - int c = getopt_long(argc, argv, "camhbg", long_options, &option_index); + int c = getopt_long(argc, argv, "camhbgr", long_options, &option_index); if (c == -1) break; switch (c) { @@ -62,6 +64,9 @@ void parseArguments(int argc, char **argv, SNES &snes) case 'g': snes.enableCgramDebugging(); break; + case 'r': + snes.enableRegisterDebugging(); + break; default: break; } @@ -70,7 +75,7 @@ void parseArguments(int argc, char **argv, SNES &snes) int main(int argc, char **argv) { - if (argc < 2) { + if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { usage(argv[0]); return 1; } diff --git a/tests/CPU/testAddressingMode.cpp b/tests/CPU/testAddressingMode.cpp index f4ed3e4..1fd8371 100644 --- a/tests/CPU/testAddressingMode.cpp +++ b/tests/CPU/testAddressingMode.cpp @@ -13,7 +13,7 @@ using namespace ComSquare; Test(AddrModeInit, LegitBus) { Init() - cr_assert_eq(snes._bus.get(), snes.cpu->_bus.get(), "Warning, the CPU's bus is not the same the SNES's bus. Next tests of the CPU may fail."); + cr_assert_eq(snes.bus.get(), snes.cpu->_bus.get(), "Warning, the CPU's bus is not the same the SNES's bus. Next tests of the CPU may fail."); } Test(AddrMode, Immediate) diff --git a/tests/PPU/testPpuWrite.cpp b/tests/PPU/testPpuWrite.cpp index 036d214..3e63c36 100644 --- a/tests/PPU/testPpuWrite.cpp +++ b/tests/PPU/testPpuWrite.cpp @@ -14,7 +14,7 @@ using namespace ComSquare; Test(PPU_write, inidisp_data_full_ones) { Init() - snes._bus->write(0x2100, 0b11111111); + snes.bus->write(0x2100, 0b11111111); cr_assert_eq(snes.ppu->_registers._inidisp.fblank, true); cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0xF); } @@ -22,7 +22,7 @@ Test(PPU_write, inidisp_data_full_ones) Test(PPU_write, inidisp_data_full_zeros) { Init() - snes._bus->write(0x2100, 0b00000000); + snes.bus->write(0x2100, 0b00000000); cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x0); } @@ -30,7 +30,7 @@ Test(PPU_write, inidisp_data_full_zeros) Test(PPU_write, inidisp_data_fBlank_on_brghtness_off) { Init() - snes._bus->write(0x2100, 0b10000000); + snes.bus->write(0x2100, 0b10000000); cr_assert_eq(snes.ppu->_registers._inidisp.fblank, true); cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x0); } @@ -38,7 +38,7 @@ Test(PPU_write, inidisp_data_fBlank_on_brghtness_off) Test(PPU_write, inidisp_data_fBlank_off_brghtness_max) { Init() - snes._bus->write(0x2100, 0b00001111); + snes.bus->write(0x2100, 0b00001111); cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0xF); } @@ -46,7 +46,7 @@ Test(PPU_write, inidisp_data_fBlank_off_brghtness_max) Test(PPU_write, inidisp_data_fBlank_off_brghtness_half) { Init() - snes._bus->write(0x2100, 0b00000101); + snes.bus->write(0x2100, 0b00000101); cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x5); } @@ -54,7 +54,7 @@ Test(PPU_write, inidisp_data_fBlank_off_brghtness_half) Test(PPU_write, obsel_111_object_size_and_all_null) { Init() - snes._bus->write(0x2101, 0b11100000); + snes.bus->write(0x2101, 0b11100000); cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b111); cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b00); cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b000); @@ -63,7 +63,7 @@ Test(PPU_write, obsel_111_object_size_and_all_null) Test(PPU_write, obsel_data_full) { Init() - snes._bus->write(0x2101, 0b11111111); + snes.bus->write(0x2101, 0b11111111); cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b111); cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b11); cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b111); @@ -72,7 +72,7 @@ Test(PPU_write, obsel_data_full) Test(PPU_write, obsel_data_full_nameselect) { Init() - snes._bus->write(0x2101, 0b00011000); + snes.bus->write(0x2101, 0b00011000); cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b000); cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b11); cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b000); @@ -81,7 +81,7 @@ Test(PPU_write, obsel_data_full_nameselect) Test(PPU_write, obsel_data_full_baseselect) { Init() - snes._bus->write(0x2101, 0b00000111); + snes.bus->write(0x2101, 0b00000111); cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b000); cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b00); cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b111); @@ -90,14 +90,14 @@ Test(PPU_write, obsel_data_full_baseselect) Test(PPU_write, oamaddl_data_full) { Init() - snes._bus->write(0x2102, 0b11111111); + snes.bus->write(0x2102, 0b11111111); cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b011111111); } Test(PPU_write, oamaddh_data_full) { Init() - snes._bus->write(0x2103, 0b11111111); + snes.bus->write(0x2103, 0b11111111); cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b100000000); } @@ -105,8 +105,8 @@ Test(PPU_write, oamaddh_data_full) Test(PPU_write, oamaddlh_data_full) { Init() - snes._bus->write(0x2102, 0b11111111); - snes._bus->write(0x2103, 0b11111111); + snes.bus->write(0x2102, 0b11111111); + snes.bus->write(0x2103, 0b11111111); cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b111111111); } @@ -114,8 +114,8 @@ Test(PPU_write, oamaddlh_data_full) Test(PPU_write, oamaddlh_data_full_priorityBit_off) { Init() - snes._bus->write(0x2102, 0b11111111); - snes._bus->write(0x2103, 0b01111111); + snes.bus->write(0x2102, 0b11111111); + snes.bus->write(0x2103, 0b01111111); cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, false); cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b111111111); } @@ -123,8 +123,8 @@ Test(PPU_write, oamaddlh_data_full_priorityBit_off) Test(PPU_write, oamaddlh_oamAdress_11_priorityBit_on) { Init() - snes._bus->write(0x2102, 0b00001011); - snes._bus->write(0x2103, 0b10011100); + snes.bus->write(0x2102, 0b00001011); + snes.bus->write(0x2103, 0b10011100); cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 11); } @@ -132,7 +132,7 @@ Test(PPU_write, oamaddlh_oamAdress_11_priorityBit_on) Test(PPU_write, bgmode_data_full) { Init() - snes._bus->write(0x2105, 0b11111111); + snes.bus->write(0x2105, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgmode.bgMode, 7); cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg1, true); cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg2, true); @@ -144,7 +144,7 @@ Test(PPU_write, bgmode_data_full) Test(PPU_write, bgmode_bgmode_5_and_bg24_on) { Init() - snes._bus->write(0x2105, 0b10100101); + snes.bus->write(0x2105, 0b10100101); cr_assert_eq(snes.ppu->_registers._bgmode.bgMode, 5); cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg1, false); cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg2, true); @@ -156,7 +156,7 @@ Test(PPU_write, bgmode_bgmode_5_and_bg24_on) Test(PPU_write, mosaic_data_full) { Init() - snes._bus->write(0x2106, 0b11111111); + snes.bus->write(0x2106, 0b11111111); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, true); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, true); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, true); @@ -167,7 +167,7 @@ Test(PPU_write, mosaic_data_full) Test(PPU_write, mosaic_affectbg23_w_1x1_size) { Init() - snes._bus->write(0x2106, 0b00000110); + snes.bus->write(0x2106, 0b00000110); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, false); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, true); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, true); @@ -178,7 +178,7 @@ Test(PPU_write, mosaic_affectbg23_w_1x1_size) Test(PPU_write, mosaic_affectbg14_w_2x2_size) { Init() - snes._bus->write(0x2106, 0b00101001); + snes.bus->write(0x2106, 0b00101001); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, true); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, false); cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, false); @@ -189,7 +189,7 @@ Test(PPU_write, mosaic_affectbg14_w_2x2_size) Test(PPU_write, bg1sc_data_full) { Init() - snes._bus->write(0x2107, 0b11111111); + snes.bus->write(0x2107, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapAddress, 0b111111); cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapHorizontalMirroring, true); cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapVerticalMirroring, true); @@ -198,7 +198,7 @@ Test(PPU_write, bg1sc_data_full) Test(PPU_write, bg2sc_data_full) { Init() - snes._bus->write(0x2108, 0b11111111); + snes.bus->write(0x2108, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapAddress, 0b111111); cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapHorizontalMirroring, true); cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapVerticalMirroring, true); @@ -207,7 +207,7 @@ Test(PPU_write, bg2sc_data_full) Test(PPU_write, bg3sc_data_full) { Init() - snes._bus->write(0x2109, 0b11111111); + snes.bus->write(0x2109, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapAddress, 0b111111); cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapHorizontalMirroring, true); cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapVerticalMirroring, true); @@ -216,7 +216,7 @@ Test(PPU_write, bg3sc_data_full) Test(PPU_write, bg4sc_data_full) { Init() - snes._bus->write(0x210A, 0b11111111); + snes.bus->write(0x210A, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0b111111); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, true); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, true); @@ -225,7 +225,7 @@ Test(PPU_write, bg4sc_data_full) Test(PPU_write, bg4sc_data_null) { Init() - snes._bus->write(0x210A, 0b00000000); + snes.bus->write(0x210A, 0b00000000); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, false); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, false); @@ -234,7 +234,7 @@ Test(PPU_write, bg4sc_data_null) Test(PPU_write, bg4sc_horizontal_off_vertical_on_random_tilemapAdress) { Init() - snes._bus->write(0x210A, 0b11000110); + snes.bus->write(0x210A, 0b11000110); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0b110001); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, false); cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, true); @@ -243,7 +243,7 @@ Test(PPU_write, bg4sc_horizontal_off_vertical_on_random_tilemapAdress) Test(PPU_write, bg12nba_data_full) { Init() - snes._bus->write(0x210B, 0b11111111); + snes.bus->write(0x210B, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg1a3, 0b1111); cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg2a4, 0b1111); } @@ -251,7 +251,7 @@ Test(PPU_write, bg12nba_data_full) Test(PPU_write, bg34nba_data_full) { Init() - snes._bus->write(0x210C, 0b11111111); + snes.bus->write(0x210C, 0b11111111); cr_assert_eq(snes.ppu->_registers._bgnba[1].baseAddressBg1a3, 0b1111); cr_assert_eq(snes.ppu->_registers._bgnba[1].baseAddressBg2a4, 0b1111); } @@ -259,7 +259,7 @@ Test(PPU_write, bg34nba_data_full) Test(PPU_write, bg12nba_data_random_data) { Init() - snes._bus->write(0x210B, 0b10101010); + snes.bus->write(0x210B, 0b10101010); cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg1a3, 0b1010); cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg2a4, 0b1010); } \ No newline at end of file diff --git a/tests/PPU/testPpuWriteFromVmain.cpp b/tests/PPU/testPpuWriteFromVmain.cpp index df4f295..197aed0 100644 --- a/tests/PPU/testPpuWriteFromVmain.cpp +++ b/tests/PPU/testPpuWriteFromVmain.cpp @@ -14,7 +14,7 @@ using namespace ComSquare; Test(PPU_write_2, vmain_data_full) { Init() - snes._bus->write(0x2115, 0b11111111); + snes.bus->write(0x2115, 0b11111111); cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); @@ -23,7 +23,7 @@ Test(PPU_write_2, vmain_data_full) Test(PPU_write_2, vmain_incrementmode_off_false_else_full) { Init() - snes._bus->write(0x2115, 0b01111111); + snes.bus->write(0x2115, 0b01111111); cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, false); cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); @@ -32,7 +32,7 @@ Test(PPU_write_2, vmain_incrementmode_off_false_else_full) Test(PPU_write_2, vmain_addressremaping_null_else_full) { Init() - snes._bus->write(0x2115, 0b11110011); + snes.bus->write(0x2115, 0b11110011); cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b00); cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); @@ -41,7 +41,7 @@ Test(PPU_write_2, vmain_addressremaping_null_else_full) Test(PPU_write_2, vmain_incrementamount_null_else_full) { Init() - snes._bus->write(0x2115, 0b11111100); + snes.bus->write(0x2115, 0b11111100); cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b00); @@ -50,39 +50,39 @@ Test(PPU_write_2, vmain_incrementamount_null_else_full) Test(PPU_write_2, vmadd_full_data) { Init() - snes._bus->write(0x2116, 0b11111111); - snes._bus->write(0x2117, 0b11111111); + snes.bus->write(0x2116, 0b11111111); + snes.bus->write(0x2117, 0b11111111); cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0b1111111111111111); } Test(PPU_write_2, vmadd_full_high_byte_null) { Init() - snes._bus->write(0x2116, 0b11111111); - snes._bus->write(0x2117, 0b00000000); + snes.bus->write(0x2116, 0b11111111); + snes.bus->write(0x2117, 0b00000000); cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0b0000000011111111); } Test(PPU_write_2, vmdata_full_data) { Init() - snes._bus->write(0x2118, 0b11111111); - snes._bus->write(0x2119, 0b11111111); + snes.bus->write(0x2118, 0b11111111); + snes.bus->write(0x2119, 0b11111111); cr_assert_eq(snes.ppu->_registers._vmdata.vmdata, 0b1111111111111111); } Test(PPU_write_2, vmdata_full_high_byte_null) { Init() - snes._bus->write(0x2118, 0b11111111); - snes._bus->write(0x2119, 0b00000000); + snes.bus->write(0x2118, 0b11111111); + snes.bus->write(0x2119, 0b00000000); cr_assert_eq(snes.ppu->_registers._vmdata.vmdata, 0b0000000011111111); } Test(PPU_write_2, cgadd_full_high_byte_null) { Init() - snes._bus->write(0x2121, 0b11111111); + snes.bus->write(0x2121, 0b11111111); cr_assert_eq(snes.ppu->_registers._cgadd, 0b11111111); cr_assert_eq(snes.ppu->_registers._isLowByte, true); } @@ -90,12 +90,12 @@ Test(PPU_write_2, cgadd_full_high_byte_null) Test(PPU_write_2, cgdata_data_full) { Init() - snes._bus->write(0x2121, 0x0); - snes._bus->write(0x2122, 0b11111111); + snes.bus->write(0x2121, 0x0); + snes.bus->write(0x2122, 0b11111111); cr_assert_eq(snes.ppu->_registers._cgdata.cgdatal, 0b11111111); cr_assert_eq(snes.ppu->_registers._isLowByte, false); int address = snes.ppu->_registers._cgadd; - snes._bus->write(0x2122, 0b11111000); + snes.bus->write(0x2122, 0b11111000); cr_assert_eq(snes.ppu->_registers._cgdata.cgdatah, 0b11111000); cr_assert_eq(snes.ppu->_registers._isLowByte, true); cr_assert_eq(snes.ppu->_registers._cgadd, address + 2); @@ -104,7 +104,7 @@ Test(PPU_write_2, cgdata_data_full) Test(PPU_write_2, m7sel_data_full) { Init() - snes._bus->write(0x211A, 0b11111111); + snes.bus->write(0x211A, 0b11111111); cr_assert_eq(snes.ppu->_registers._m7sel.playingFieldSize, true); cr_assert_eq(snes.ppu->_registers._m7sel.emptySpaceFill, true); cr_assert_eq(snes.ppu->_registers._m7sel.horizontalMirroring, true); @@ -114,7 +114,7 @@ Test(PPU_write_2, m7sel_data_full) Test(PPU_write_2, m7sel_data_actual) { Init() - snes._bus->write(0x211A, 0b01111101); + snes.bus->write(0x211A, 0b01111101); cr_assert_eq(snes.ppu->_registers._m7sel.playingFieldSize, false); cr_assert_eq(snes.ppu->_registers._m7sel.emptySpaceFill, true); cr_assert_eq(snes.ppu->_registers._m7sel.horizontalMirroring, true); @@ -124,7 +124,7 @@ Test(PPU_write_2, m7sel_data_actual) Test(PPU_write_2, w12sel_data_full) { Init() - snes._bus->write(0x2123, 0b11111111); + snes.bus->write(0x2123, 0b11111111); cr_assert_eq(snes.ppu->_registers._wsel[0].window1InversionForBg1Bg2Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow1ForBg1Bg2Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[0].window2InversionForBg1Bg3Obj, true); @@ -138,7 +138,7 @@ Test(PPU_write_2, w12sel_data_full) Test(PPU_write_2, w34sel_data_full) { Init() - snes._bus->write(0x2124, 0b10101010); + snes.bus->write(0x2124, 0b10101010); cr_assert_eq(snes.ppu->_registers._wsel[1].window1InversionForBg1Bg2Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow1ForBg1Bg2Obj, false); cr_assert_eq(snes.ppu->_registers._wsel[1].window2InversionForBg1Bg3Obj, true); @@ -152,7 +152,7 @@ Test(PPU_write_2, w34sel_data_full) Test(PPU_write_2, wobjsel_data_full) { Init() - snes._bus->write(0x2125, 0b10110001); + snes.bus->write(0x2125, 0b10110001); cr_assert_eq(snes.ppu->_registers._wsel[2].window1InversionForBg1Bg2Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow1ForBg1Bg2Obj, false); cr_assert_eq(snes.ppu->_registers._wsel[2].window2InversionForBg1Bg3Obj, true); @@ -166,7 +166,7 @@ Test(PPU_write_2, wobjsel_data_full) Test(PPU_write_2, wbglog_data_full) { Init() - snes._bus->write(0x212A, 0b10110001); + snes.bus->write(0x212A, 0b10110001); cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg1, 0b10); cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg2, 0b11); cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg3, 0b00); @@ -176,7 +176,7 @@ Test(PPU_write_2, wbglog_data_full) Test(PPU_write_2, wobjlog_data_full) { Init() - snes._bus->write(0x212B, 0b10110001); + snes.bus->write(0x212B, 0b10110001); cr_assert_eq(snes.ppu->_registers._wobjlog.maskLogicObj, 0b01); cr_assert_eq(snes.ppu->_registers._wobjlog.maskLogicColor, 0b00); } @@ -184,7 +184,7 @@ Test(PPU_write_2, wobjlog_data_full) Test(PPU_write_2, tm_data_full) { Init() - snes._bus->write(0x212C, 0b10110001); + snes.bus->write(0x212C, 0b10110001); cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg1, true); cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg2, false); cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg3, false); @@ -195,7 +195,7 @@ Test(PPU_write_2, tm_data_full) Test(PPU_write_2, ts_data_full) { Init() - snes._bus->write(0x212D, 0b10101110); + snes.bus->write(0x212D, 0b10101110); cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg1, false); cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg2, true); cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg3, true); @@ -206,7 +206,7 @@ Test(PPU_write_2, ts_data_full) Test(PPU_write_2, tmw_data_full) { Init() - snes._bus->write(0x212E, 0b10101110); + snes.bus->write(0x212E, 0b10101110); cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg1, false); cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg2, true); cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg3, true); @@ -217,7 +217,7 @@ Test(PPU_write_2, tmw_data_full) Test(PPU_write_2, tsw_data_full) { Init() - snes._bus->write(0x212F, 0b10100011); + snes.bus->write(0x212F, 0b10100011); cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg1, true); cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg2, true); cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg3, false); @@ -228,7 +228,7 @@ Test(PPU_write_2, tsw_data_full) Test(PPU_write_2, cgwsel_data_full) { Init() - snes._bus->write(0x2130, 0b10111001); + snes.bus->write(0x2130, 0b10111001); cr_assert_eq(snes.ppu->_registers._cgwsel.clipColorToBlackBeforeMath, 0b10); cr_assert_eq(snes.ppu->_registers._cgwsel.preventColorMath, 0b11); cr_assert_eq(snes.ppu->_registers._cgwsel.addSubscreen, false); @@ -238,7 +238,7 @@ Test(PPU_write_2, cgwsel_data_full) Test(PPU_write_2, cgadsub_data_full) { Init() - snes._bus->write(0x2131, 0b10111001); + snes.bus->write(0x2131, 0b10111001); cr_assert_eq(snes.ppu->_registers._cgadsub.addSubtractSelect, true); cr_assert_eq(snes.ppu->_registers._cgadsub.halfColorMath, false); cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBackdrop, true); @@ -252,7 +252,7 @@ Test(PPU_write_2, cgadsub_data_full) Test(PPU_write_2, coldata_data_full) { Init() - snes._bus->write(0x2132, 0b10111001); + snes.bus->write(0x2132, 0b10111001); cr_assert_eq(snes.ppu->_registers._coldata.blue, true); cr_assert_eq(snes.ppu->_registers._coldata.green, false); cr_assert_eq(snes.ppu->_registers._coldata.red, true); @@ -262,7 +262,7 @@ Test(PPU_write_2, coldata_data_full) Test(PPU_write_2, setini_data_full) { Init() - snes._bus->write(0x2133, 0b10111001); + snes.bus->write(0x2133, 0b10111001); cr_assert_eq(snes.ppu->_registers._setini.externalSync, true); cr_assert_eq(snes.ppu->_registers._setini.mode7ExtBg, false); cr_assert_eq(snes.ppu->_registers._setini.enablePseudoHiresMode, true); @@ -274,14 +274,14 @@ Test(PPU_write_2, setini_data_full) Test(PPU_write_2, m7a_data_full) { Init() - snes._bus->write(0x211B, 0b10111001); + snes.bus->write(0x211B, 0b10111001); cr_assert_eq(snes.ppu->_registers._m7[0].m7l, 0b10111001); } Test(PPU_write_2, m7c_data_low_and_high_byte) { Init() - snes._bus->write(0x211D, 0b10111001); - snes._bus->write(0x211D, 0b11111111); + snes.bus->write(0x211D, 0b10111001); + snes.bus->write(0x211D, 0b11111111); cr_assert_eq(snes.ppu->_registers._m7[2].m7, 0b1011100111111111); } \ No newline at end of file diff --git a/tests/testMemoryBus.cpp b/tests/testMemoryBus.cpp index 81600be..d41788a 100644 --- a/tests/testMemoryBus.cpp +++ b/tests/testMemoryBus.cpp @@ -29,7 +29,7 @@ Test(BusAccessor, GetWramStart) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x7E0000); + accessor = snes.bus->getAccessor(0x7E0000); cr_assert_eq(accessor.get(), snes.wram.get()); } @@ -38,7 +38,7 @@ Test(BusAccessor, GetWramEnd) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x7FFFFF); + accessor = snes.bus->getAccessor(0x7FFFFF); cr_assert_eq(accessor.get(), snes.wram.get()); } @@ -47,7 +47,7 @@ Test(BusAccessor, GetWramMirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x2F11FF)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x2F11FF)); cr_assert_neq(accessor, nullptr); cr_assert_eq(accessor->_initial.get(), snes.wram.get()); } @@ -57,7 +57,7 @@ Test(BusAccessor, GetWramMirror2) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x100000)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x100000)); cr_assert_neq(accessor, nullptr); cr_assert_eq(accessor->_initial.get(), snes.wram.get()); } @@ -67,7 +67,7 @@ Test(BusAccessor, GetWramMirror3) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x1010)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x1010)); cr_assert_neq(accessor, nullptr); cr_assert_eq(accessor->_initial.get(), snes.wram.get()); } @@ -75,7 +75,7 @@ Test(BusAccessor, GetWramMirror3) Test(BusAccessor, GetOpenBus) { Init() - std::shared_ptr accessor = snes._bus->getAccessor(0x897654); + std::shared_ptr accessor = snes.bus->getAccessor(0x897654); cr_assert_eq(accessor.get(), nullptr); } @@ -84,7 +84,7 @@ Test(BusAccessor, GetSramStart) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x700000)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x700000)); cr_assert_eq(accessor->_initial.get(), snes.sram.get()); } @@ -93,7 +93,7 @@ Test(BusAccessor, GetSramEnd) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x7D7FFF)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x7D7FFF)); cr_assert_eq(accessor->_initial.get(), snes.sram.get()); } @@ -102,7 +102,7 @@ Test(BusAccessor, GetSramMirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0xF00123)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0xF00123)); cr_assert_eq(accessor.get(), snes.sram.get()); } @@ -111,7 +111,7 @@ Test(BusAccessor, GetAPUStart) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x002140); + accessor = snes.bus->getAccessor(0x002140); cr_assert_eq(accessor.get(), snes.apu.get()); } @@ -120,7 +120,7 @@ Test(BusAccessor, GetAPUEnd) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x002143); + accessor = snes.bus->getAccessor(0x002143); cr_assert_eq(accessor.get(), snes.apu.get()); } @@ -129,7 +129,7 @@ Test(BusAccessor, GetAPUMirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0xAB2143)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0xAB2143)); cr_assert_eq(accessor->_initial.get(), snes.apu.get()); } @@ -138,7 +138,7 @@ Test(BusAccessor, GetAPUMirrorFirstHalf) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x052143)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x052143)); cr_assert_eq(accessor->_initial.get(), snes.apu.get()); } @@ -147,7 +147,7 @@ Test(BusAccessor, GetCPUStart) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x004200); + accessor = snes.bus->getAccessor(0x004200); cr_assert_eq(accessor.get(), snes.cpu.get()); } @@ -156,7 +156,7 @@ Test(BusAccessor, GetCPUEnd) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x00421F); + accessor = snes.bus->getAccessor(0x00421F); cr_assert_eq(accessor.get(), snes.cpu.get()); } @@ -165,7 +165,7 @@ Test(BusAccessor, GetPPU1Start) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x00213E); + accessor = snes.bus->getAccessor(0x00213E); cr_assert_eq(accessor.get(), snes.ppu.get()); } @@ -174,7 +174,7 @@ Test(BusAccessor, GetPPU1End) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x00213F); + accessor = snes.bus->getAccessor(0x00213F); cr_assert_eq(accessor.get(), snes.ppu.get()); } @@ -183,7 +183,7 @@ Test(BusAccessor, GetCPU) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x004212); + accessor = snes.bus->getAccessor(0x004212); cr_assert_eq(accessor.get(), snes.cpu.get()); } @@ -192,7 +192,7 @@ Test(BusAccessor, GetPPU1Mirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x80213F)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x80213F)); cr_assert_eq(accessor->_initial.get(), snes.ppu.get()); } @@ -201,7 +201,7 @@ Test(BusAccessor, GetCPU2Mirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x804212)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x804212)); cr_assert_eq(accessor->_initial.get(), snes.cpu.get()); } @@ -210,7 +210,7 @@ Test(BusAccessor, GetRomStart) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0x808000); + accessor = snes.bus->getAccessor(0x808000); cr_assert_eq(accessor.get(), snes.cartridge.get()); } @@ -219,7 +219,7 @@ Test(BusAccessor, GetRomEnd) Init() std::shared_ptr accessor = nullptr; - accessor = snes._bus->getAccessor(0xFFFFFF); + accessor = snes.bus->getAccessor(0xFFFFFF); cr_assert_eq(accessor.get(), snes.cartridge.get()); } @@ -228,7 +228,7 @@ Test(BusAccessor, GetRomMirror) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x694200)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x694200)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); } @@ -237,7 +237,7 @@ Test(BusAccessor, GetRomMirror2) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x01FEDC)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x01FEDC)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); } @@ -246,7 +246,7 @@ Test(BusAccessor, GetRomMirror3) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0xDE1248)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0xDE1248)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); } @@ -255,7 +255,7 @@ Test(BusAccessor, Get0x0) Init() std::shared_ptr accessor = nullptr; - accessor = std::static_pointer_cast(snes._bus->getAccessor(0x0)); + accessor = std::static_pointer_cast(snes.bus->getAccessor(0x0)); cr_assert_eq(accessor->_initial.get(), snes.wram.get()); } @@ -271,7 +271,7 @@ Test(BusRead, Read0x0) uint8_t data; snes.wram->_data[0] = 123; - data = snes._bus->read(0x0); + data = snes.bus->read(0x0); cr_assert_eq(data, 123); } @@ -280,8 +280,8 @@ Test(BusRead, ReadOutside, .init = cr_redirect_stdout) Init() uint8_t data; - snes._bus->_openBus = 123; - data = snes._bus->read(0x002000); + snes.bus->_openBus = 123; + data = snes.bus->read(0x002000); cr_assert_eq(data, 123); } @@ -290,8 +290,8 @@ Test(BusRead, ReadOutside2, .init = cr_redirect_stdout) Init() uint8_t data; - snes._bus->_openBus = 123; - data = snes._bus->read(0xBF2FFF); + snes.bus->_openBus = 123; + data = snes.bus->read(0xBF2FFF); cr_assert_eq(data, 123); } @@ -300,8 +300,8 @@ Test(BusRead, ReadOutside3, .init = cr_redirect_stdout) Init() uint8_t data; - snes._bus->_openBus = 123; - data = snes._bus->read(0x127654); + snes.bus->_openBus = 123; + data = snes.bus->read(0x127654); cr_assert_eq(data, 123); } @@ -311,7 +311,7 @@ Test(BusRead, ReadAPU) uint8_t data; snes.apu->_registers.port0 = 123; - data = snes._bus->read(0x002140); + data = snes.bus->read(0x002140); cr_assert_eq(data, 123); } @@ -321,7 +321,7 @@ Test(BusRead, ReadROM) uint8_t data; snes.cartridge->_data[5] = 123; - data = snes._bus->read(0x808005); + data = snes.bus->read(0x808005); cr_assert_eq(data, 123); } @@ -331,7 +331,7 @@ Test(BusRead, ReadROMStart) uint8_t data; snes.cartridge->_data[0] = 123; - data = snes._bus->read(0x808000); + data = snes.bus->read(0x808000); cr_assert_eq(data, 123); } @@ -341,7 +341,7 @@ Test(BusRead, ReadCPU) uint8_t data; snes.cpu->_internalRegisters.wrio = 123; - data = snes._bus->read(0x004201); + data = snes.bus->read(0x004201); cr_assert_eq(data, 123); } @@ -351,7 +351,7 @@ Test(BusRead, ReadPPU) uint8_t data; snes.ppu->_registers._mpy.mpyl = 123; - data = snes._bus->read(0x002134); + data = snes.bus->read(0x002134); cr_assert_eq(data, 123); } @@ -361,7 +361,7 @@ Test(BusRead, ReadSRAM) uint8_t data; snes.sram->_data[7] = 123; - data = snes._bus->read(0x700007); + data = snes.bus->read(0x700007); cr_assert_eq(data, 123); } @@ -371,7 +371,7 @@ Test(BusRead, ReadWRAM) uint8_t data; snes.wram->_data[3] = 123; - data = snes._bus->read(0x7E0003); + data = snes.bus->read(0x7E0003); cr_assert_eq(data, 123); } @@ -381,7 +381,7 @@ Test(BusRead, ReadWRAM2) uint8_t data; snes.wram->_data[0x1010] = 123; - data = snes._bus->read(0x7E1010); + data = snes.bus->read(0x7E1010); cr_assert_eq(data, 123); } @@ -392,7 +392,7 @@ Test(BusRead, ReadWRAMMirror) uint8_t data; snes.wram->_data[0x1010] = 123; - data = snes._bus->read(0x1010); + data = snes.bus->read(0x1010); cr_assert_eq(data, 123); } @@ -407,7 +407,7 @@ Test(BusWrite, Write0x0) Init() try { - snes._bus->write(0x0, 123); + snes.bus->write(0x0, 123); } catch (std::exception &ex) { std::cout << ex.what() << std::endl; } @@ -419,7 +419,7 @@ Test(BusWrite, WriteAPU) { Init() - snes._bus->write(0x002143, 123); + snes.bus->write(0x002143, 123); cr_assert_eq(snes.apu->_registers.port3, 123); } @@ -427,7 +427,7 @@ Test(BusWrite, WritePPU) { Init() - snes._bus->write(0x002106, 123); + snes.bus->write(0x002106, 123); cr_assert_eq(snes.ppu->_registers._mosaic.raw, 123); } @@ -435,7 +435,7 @@ Test(BusWrite, WriteCPU) { Init() - snes._bus->write(0x00420D, 123); + snes.bus->write(0x00420D, 123); cr_assert_eq(snes.cpu->_internalRegisters.memsel, 123); } @@ -443,14 +443,14 @@ Test(BusWrite, WriteROM) { Init() - cr_assert_throw(snes._bus->write(0x808005, 123), InvalidAction); + cr_assert_throw(snes.bus->write(0x808005, 123), InvalidAction); } Test(BusWrite, WriteWRAM) { Init() - snes._bus->write(0x7E0002, 123); + snes.bus->write(0x7E0002, 123); cr_assert_eq(snes.wram->_data[2], 123); } @@ -458,6 +458,6 @@ Test(BusWrite, WriteSRAM) { Init() - snes._bus->write(0x700009, 123); + snes.bus->write(0x700009, 123); cr_assert_eq(snes.sram->_data[9], 123); } \ No newline at end of file diff --git a/ui/registersView.ui b/ui/registersView.ui index 44e26db..4f467e3 100644 --- a/ui/registersView.ui +++ b/ui/registersView.ui @@ -59,7 +59,91 @@ - + + + 0 + + + + 1 + + + + + + + + + + 2 + + + + + + + + + + 3 + + + + + + + + + + 4 + + + + + + + + + + 5 + + + + + + + + + + 6 + + + + + + + + + + 7 + + + + + + + + + + 8 + + + + + + + + From fdfa0fc0d67a9e8232a881b46789e2ef17aa04d9 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 29 May 2020 21:32:50 +0200 Subject: [PATCH 08/30] Adding the first dma channel to the register viewer --- sources/Debugger/RegisterViewer.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index d6ae10f..9f49c4c 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -26,9 +26,30 @@ namespace ComSquare::Debugger { for (int i = 0; i < 8; i++) { RegistersViewerModel *model = new RegistersViewerModel(this->_snes); - model->addRegister(Register(0x420B, "-0", "Enabled", [i](SNES &snes) { + model->addRegister(Register(0x420B, ":0", "Enabled", [i](SNES &snes) { return snes.cpu->_dmaChannels[i].enabled; }, nullptr, Boolean)); + model->addRegister(Register(0x4302, "-4", "A address", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._aAddress.raw; + }, nullptr, TwentyFourBits)); + model->addRegister(Register(0x4301, "", "B address", [i](SNES &snes) { + return 0x2100 | snes.cpu->_dmaChannels[i]._port; + }, nullptr, SixteenBits)); + model->addRegister(Register(0x4305, "-6", "Count", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._count.raw; + }, nullptr, SixteenBits)); + model->addRegister(Register(0x4300, ":7", "B To A", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._controlRegister.direction; + }, nullptr, Boolean)); + model->addRegister(Register(0x4300, ":3", "Fixed", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._controlRegister.fixed; + }, nullptr, Boolean)); + model->addRegister(Register(0x4300, ":4", "Increment", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._controlRegister.increment; + }, nullptr, Boolean)); + model->addRegister(Register(0x4300, ":0-2", "Mode", [i](SNES &snes) { + return snes.cpu->_dmaChannels[i]._controlRegister.increment; + }, nullptr, EightBits)); this->_ui.dmaChannel1->setModel(model); this->_models.push_back(model); } From ced42a3bf99edec14b21a3a985eed07defcdd6f4 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 1 Feb 2021 19:21:18 +0100 Subject: [PATCH 09/30] Fixing bugs with the DMA --- CMakeLists.txt | 2 +- Doxyfile | 2 +- sources/CPU/CPU.hpp | 1 - sources/CPU/DMA/DMA.cpp | 9 ++-- sources/CPU/DMA/DMA.hpp | 45 ++++++++++--------- sources/Debugger/RegisterViewer.cpp | 5 ++- sources/PPU/PPU.cpp | 4 +- sources/SNES.hpp | 10 ++--- tests/CPU/testDMA.cpp | 70 +++++++++++++++++++++++++++++ tests/CPU/testInternal.cpp | 65 +++++++++++++-------------- ui/ui_cpuView.h | 2 +- 11 files changed, 141 insertions(+), 74 deletions(-) create mode 100644 tests/CPU/testDMA.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 72fa0bd..d5e1027 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ add_executable(unit_tests sources/PPU/Background.hpp sources/CPU/DMA/DMA.cpp sources/CPU/DMA/DMA.hpp -) + tests/CPU/testDMA.cpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) diff --git a/Doxyfile b/Doxyfile index fe9687f..962fcf8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2431,7 +2431,7 @@ DIRECTORY_GRAPH = YES # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_IMAGE_FORMAT = png +DOT_IMAGE_FORMAT = svg # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 761684f..9db4b3f 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -12,7 +12,6 @@ #include "../Memory/AMemory.hpp" #include "Instruction.hpp" #include "DMA/DMA.hpp" -#include "../Debugger/RegisterViewer.hpp" namespace ComSquare::CPU { diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index 5815b67..e6491cf 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -72,13 +72,13 @@ namespace ComSquare::CPU if (this->_port == 0x80) { auto accessor = this->_bus->getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { - if (this->_controlRegister.direction == AToB) + if (this->_controlRegister.direction == AtoB) return 8; this->_bus->write(aAddress, 0xFF); return 4; } } - if (this->_controlRegister.direction == AToB) { + if (this->_controlRegister.direction == AtoB) { uint8_t data = this->_bus->read(aAddress); this->_bus->write(bAddress, data); } else { @@ -88,11 +88,10 @@ namespace ComSquare::CPU return 8; } - uint8_t DMA::run(unsigned int maxCycles) + unsigned DMA::run(unsigned int maxCycles) { unsigned cycles = 8; int i = 0; - std::cout << "Starting a DMA transfer" << std::endl; do { cycles += this->_writeOneByte(this->_aAddress.raw, 0x2100 | (this->_port + this->_getModeOffset(i))); @@ -100,7 +99,7 @@ namespace ComSquare::CPU this->_aAddress.page += this->_controlRegister.increment ? -1 : 1; this->_count.raw--; i++; - } while (this->_count.raw > 0); + } while (this->_count.raw > 0 && this->enabled); this->enabled = false; return cycles; } diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index 99fdbc3..3027dd5 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -9,31 +9,34 @@ #include #include "../../Models/Int24.hpp" #include "../../Memory/MemoryBus.hpp" -#include "../../Debugger/RegisterViewer.hpp" + +#ifdef DEBUGGER_ENABLED + #include "../../Debugger/RegisterViewer.hpp" +#endif namespace ComSquare::CPU { - //! @brief The first three bytes of the DMA's control register. Used to tell how many bytes/registers there is. - enum DMAMode { - //! @brief 1 byte is transferred to 1 register (write once) - OneToOne = 0b000, - //! @brief 2 byte is transferred to 2 register (write once) - TwoToTwo = 0b001, - //! @brief 2 byte is transferred to 1 register (write twice) - TwoToOne = 0b010, - //! @brief 4 byte is transferred to 2 register (write twice) - FourToTwo = 0b011, - //! @brief 4 byte is transferred to 4 register (write once) - FourToFour = 0b100 - }; - - enum Direction { - AToB, - BToA - }; - //! @brief Class handling all DMA/HDMA transfers (Direct Memory Access or H-Blank Direct Memory Access) class DMA { + public: + //! @brief The first three bytes of the DMA's control register. Used to tell how many bytes/registers there is. + enum DMAMode { + //! @brief 1 byte is transferred to 1 register (write once) + OneToOne = 0b000, + //! @brief 2 byte is transferred to 2 register (write once) + TwoToTwo = 0b001, + //! @brief 2 byte is transferred to 1 register (write twice) + TwoToOne = 0b010, + //! @brief 4 byte is transferred to 2 register (write twice) + FourToTwo = 0b011, + //! @brief 4 byte is transferred to 4 register (write once) + FourToFour = 0b100 + }; + + enum Direction { + AtoB, + BtoA + }; private: //! @brief Write one byte using the A address, the port and the _direction. Handle special cases where no write occurs. //! @return The number of cycles used. @@ -92,7 +95,7 @@ namespace ComSquare::CPU //! @brief Run the DMA for x cycles //! @param cycles The maximum number of cycles this DMA should run. //! @return the number of cycles taken - uint8_t run(unsigned cycles); + unsigned run(unsigned cycles); DMA() = default; DMA(std::shared_ptr bus); diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index 9f49c4c..1dfcc90 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -24,7 +24,8 @@ namespace ComSquare::Debugger void RegisterViewer::_setupUi() { - for (int i = 0; i < 8; i++) { + int i = 0; + // for (int i = 0; i < 8; i++) { RegistersViewerModel *model = new RegistersViewerModel(this->_snes); model->addRegister(Register(0x420B, ":0", "Enabled", [i](SNES &snes) { return snes.cpu->_dmaChannels[i].enabled; @@ -52,7 +53,7 @@ namespace ComSquare::Debugger }, nullptr, EightBits)); this->_ui.dmaChannel1->setModel(model); this->_models.push_back(model); - } +// } } void RegisterViewer::focus() diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 9075adc..0c5b98f 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -126,7 +126,7 @@ namespace ComSquare::PPU //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); + this->vram->write_internal(getVramAddress(), data); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -135,7 +135,7 @@ namespace ComSquare::PPU //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatah); + this->vram->write_internal(getVramAddress(), data); } if (this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; diff --git a/sources/SNES.hpp b/sources/SNES.hpp index c3d3ed5..7aa41ae 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -12,12 +12,12 @@ #include "PPU/PPU.hpp" #include "APU/APU.hpp" #include "Renderer/IRenderer.hpp" -#ifdef DEBUGGER_ENABLED -#include "Debugger/MemoryViewer.hpp" -#include "Debugger/HeaderViewer.hpp" -#include "Debugger/CGramDebug.hpp" -#include "Debugger/RegisterViewer.hpp" +#ifdef DEBUGGER_ENABLED + #include "Debugger/MemoryViewer.hpp" + #include "Debugger/HeaderViewer.hpp" + #include "Debugger/CGramDebug.hpp" + #include "Debugger/RegisterViewer.hpp" #endif namespace ComSquare diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp new file mode 100644 index 0000000..ce757e5 --- /dev/null +++ b/tests/CPU/testDMA.cpp @@ -0,0 +1,70 @@ +// +// Created by anonymus-raccoon on 2/1/21. +// + +#include +#include +#include "../tests.hpp" +using namespace ComSquare; + +//Test(DMA, RomToVRAM) +//{ +// Init() +// snes.cartridge->_size = 4000000; +// snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; +// for(unsigned i = 0xBE00, j = 0; i < 0xBE00 + 0x800; i++, j++) +// snes.cartridge->_data[i] = j; +// +// // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 +// +// // Setting VRam address (since this is an indirect write) +// snes.bus->write(0x2117, 0x20); +// snes.bus->write(0x2116, 0); +// +// snes.bus->write(0x4301, 0x18); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma's b port was $%x but it should have been $18.", snes.cpu->_dmaChannels[0]._port); +// snes.bus->write(0x4304, 0x13); +// snes.bus->write(0x4303, 0xBE); +// snes.bus->write(0x4302, 0x00); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13BE00, "The dma's a address was $%x but it should have been $13BE00.", snes.cpu->_dmaChannels[0]._aAddress.raw); +// snes.bus->write(0x4306, 0x08); +// snes.bus->write(0x4305, 0); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0x0800, "The dma's count was $%x but it should have been $0800.", snes.cpu->_dmaChannels[0]._count.raw); +// snes.bus->write(0x4300, 1); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.direction, CPU::DMA::AtoB, "Direction should have been 0 (A to B) but it was %x.", snes.cpu->_dmaChannels[0]._controlRegister.direction); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister._, 0, "The unused byte should be 0."); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.increment, 0, "The increment byte should be set to 0."); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.fixed, 0, "The increment byte should be set to 0."); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.mode, CPU::DMA::TwoToTwo, "The DMA mode should have been TwoToTwo (%%001) but it was) $%x", snes.cpu->_dmaChannels[0]._controlRegister.mode); +// cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); +// // Enabling DMA's channel 0 +// snes.bus->write(0x420B, 1); +// cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, true, "The DMA channel should be enabled."); +// // TODO There is an overhead of 12-24 cycles for the whole transfer. How should I know how many cycles there is? +// auto cycles = snes.cpu->_dmaChannels[0].run(1000000); +// cr_assert_eq(cycles, 8 + 8 * 0x800, "The dma should take $4008 cycles but it took $%x.", cycles); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0, "The dma count should be 0 but it was $%x.", snes.cpu->_dmaChannels[0]._count.raw); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13C600, "The dma count should be $13C600 but it was $%x.", snes.cpu->_dmaChannels[0]._aAddress.raw); +// cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma count should be $18 but it was $%x.", snes.cpu->_dmaChannels[0]._port); +// cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2400, "The vram address should be $2400 but it was %x.", snes.ppu->_registers._vmadd.vmadd); +// for(unsigned i = 0x2000, j = 0; i < 0x2000 + 0x800; i++, j++) +// std::cout << std::hex << i << ": " << (unsigned)snes.ppu->vram->_data[i] << std::endl; +//// cr_assert_eq(snes.ppu->vram->_data[i], j, "The memory at %x should be %x but it was %x", i, (uint16_t)j, snes.ppu->vram->_data[i]); +//} + +Test(DMA, VramWrite) +{ + Init() + snes.bus->write(0x2117, 0x20); + snes.bus->write(0x2116, 0x0); + for (unsigned i = 0; i < 0x400; i++) { + snes.bus->write(0x2119, i >> 8); + snes.bus->write(0x2118, i); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2001 + i, "The vram address was %x but it should have been %x", snes.ppu->_registers._vmadd.vmadd, 0x2001 + i); + } + for(unsigned i = 0; i < 0x400; i++) { + uint16_t value = snes.ppu->vram->_data[0x2000 + i * 2] | (snes.ppu->vram->_data[0x2000 + i * 2 + 1] << 8); + std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; +// cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); + } +} \ No newline at end of file diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp index 5b38be7..a85efbd 100644 --- a/tests/CPU/testInternal.cpp +++ b/tests/CPU/testInternal.cpp @@ -3,13 +3,8 @@ // #include -#include #include #include "../tests.hpp" -#include "../../sources/SNES.hpp" -#include "../../sources/Memory/MemoryBus.hpp" -#include "../../sources/CPU/CPU.hpp" - using namespace ComSquare; Test(SEP, setall) @@ -196,8 +191,8 @@ Test(PLA, basic) snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.a; cr_assert_eq(data, 0x7BCD, "The accumulator should be 0x7BCD but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -211,8 +206,8 @@ Test(PLA, zero) snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.a; cr_assert_eq(data, 0x0000, "The accumulator should be 0x0000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -226,8 +221,8 @@ Test(PLA, negative) snes.cpu->PLA(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.a; cr_assert_eq(data, 0xA000, "The accumulator should be 0xA000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -241,8 +236,8 @@ Test(PLX, basic) snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.x; cr_assert_eq(data, 0x7BCD, "The X register should be 0x7BCD but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -256,8 +251,8 @@ Test(PLX, zero) snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.x; cr_assert_eq(data, 0x0000, "The x register should be 0x0000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -271,8 +266,8 @@ Test(PLX, negative) snes.cpu->PLX(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.x; cr_assert_eq(data, 0xA000, "The x register should be 0xA000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -286,8 +281,8 @@ Test(PLY, basic) snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.y; cr_assert_eq(data, 0x7BCD, "The Y register should be 0x7BCD but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -301,8 +296,8 @@ Test(PLY, zero) snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.y; cr_assert_eq(data, 0x0000, "The y register should be 0x0000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -316,8 +311,8 @@ Test(PLY, negative) snes.cpu->PLY(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.y; cr_assert_eq(data, 0xA000, "The y register should be 0xA000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -330,8 +325,8 @@ Test(PLD, basic) snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.d; cr_assert_eq(data, 0x7BCD, "The D register should be 0x7BCD but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -344,8 +339,8 @@ Test(PLD, zero) snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.d; cr_assert_eq(data, 0x0000, "The d register should be 0x0000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -358,8 +353,8 @@ Test(PLD, negative) snes.cpu->PLD(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.d; cr_assert_eq(data, 0xA000, "The D register should be 0xA000 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.s, 0x2, "The Stack pointer should be equal to 0x2 but it was %x", snes.cpu->_registers.s); } @@ -371,8 +366,8 @@ Test(PLB, basic) snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.dbr; cr_assert_eq(data, 0x7D, "The DBR should be 0x7D but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s); } @@ -384,8 +379,8 @@ Test(PLB, zero) snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.dbr; cr_assert_eq(data, 0x00, "The dbr should be 0x00 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s); } @@ -397,8 +392,8 @@ Test(PLB, negative) snes.cpu->PLB(0x0, ComSquare::CPU::AddressingMode::Implied); auto data = snes.cpu->_registers.dbr; cr_assert_eq(data, 0xA0, "The D register should be 0xA0 but it was %x", data); - cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set.", snes.cpu->_registers.p.z); - cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.", snes.cpu->_registers.p.n); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag not should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.s, 0x1, "The Stack pointer should be equal to 0x1 but it was %x", snes.cpu->_registers.s); } diff --git a/ui/ui_cpuView.h b/ui/ui_cpuView.h index 00998e3..70433d5 100644 --- a/ui/ui_cpuView.h +++ b/ui/ui_cpuView.h @@ -1,7 +1,7 @@ /******************************************************************************** ** Form generated from reading UI file 'cpuView.ui' ** -** Created by: Qt User Interface Compiler version 5.14.2 +** Created by: Qt User Interface Compiler version 5.15.2 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ From 58f7fe6a2cf0588a04f4529e635e5265bf6715f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Tue, 2 Feb 2021 00:20:22 +0100 Subject: [PATCH 10/30] fixing ppu vram write --- sources/PPU/PPU.cpp | 6 +++--- tests/CPU/testDMA.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 0c5b98f..a8389ba 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -126,7 +126,7 @@ namespace ComSquare::PPU //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->vram->write_internal(getVramAddress(), data); + this->vram->write_internal(this->getVramAddress(), data); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -135,7 +135,7 @@ namespace ComSquare::PPU //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->vram->write_internal(getVramAddress(), data); + this->vram->write_internal(this->getVramAddress() + 1, data); } if (this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -221,7 +221,7 @@ namespace ComSquare::PPU uint16_t PPU::getVramAddress() { - uint16_t vanillaAddress = this->_registers._vmadd.vmadd; + uint16_t vanillaAddress = this->_registers._vmadd.vmadd * 2; switch (this->_registers._vmain.addressRemapping) { case 0b00: diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index ce757e5..bc86cde 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -55,6 +55,7 @@ using namespace ComSquare; Test(DMA, VramWrite) { Init() + //snes.bus->write(0x2115, 0b10000000); snes.bus->write(0x2117, 0x20); snes.bus->write(0x2116, 0x0); for (unsigned i = 0; i < 0x400; i++) { @@ -63,8 +64,8 @@ Test(DMA, VramWrite) cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2001 + i, "The vram address was %x but it should have been %x", snes.ppu->_registers._vmadd.vmadd, 0x2001 + i); } for(unsigned i = 0; i < 0x400; i++) { - uint16_t value = snes.ppu->vram->_data[0x2000 + i * 2] | (snes.ppu->vram->_data[0x2000 + i * 2 + 1] << 8); - std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; -// cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); + uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); + //std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; + cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); } } \ No newline at end of file From 71096ded7c40271991d0066b24550b7b79164703 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 00:32:06 +0100 Subject: [PATCH 11/30] Adding missings mode in the DMA & adding notes for weird behaviors --- sources/CPU/DMA/DMA.cpp | 13 ++++-- sources/CPU/DMA/DMA.hpp | 8 +++- tests/CPU/testDMA.cpp | 97 ++++++++++++++++++++++------------------- 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index e6491cf..306ed9b 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -72,8 +72,10 @@ namespace ComSquare::CPU if (this->_port == 0x80) { auto accessor = this->_bus->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); return 4; } @@ -108,13 +110,18 @@ namespace ComSquare::CPU { switch (this->_controlRegister.mode) { case OneToOne: - return 0; - case TwoToTwo: - return index % 2; case TwoToOne: + case TwoToOneBis: return 0; + + case TwoToTwo: + case TwoToTwoBis: + return index % 2; + case FourToTwo: + case FourToTwoBis: return (index & 0b11) > 1; + case FourToFour: return (index & 0b11); } diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index 3027dd5..de6d232 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -30,7 +30,13 @@ namespace ComSquare::CPU //! @brief 4 byte is transferred to 2 register (write twice) FourToTwo = 0b011, //! @brief 4 byte is transferred to 4 register (write once) - FourToFour = 0b100 + FourToFour = 0b100, + //! @brief Exactly the same as TwoToTwo (not implemented on the SNES so this fallbacks) + TwoToTwoBis = 0b101, + //! @brief Exactly the same as TwoToOne (not implemented on the SNES so this fallbacks) + TwoToOneBis = 0b110, + //! @brief Exactly the same as FourToTwo (not implemented on the SNES so this fallbacks) + FourToTwoBis = 0b111 }; enum Direction { diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index bc86cde..8f1baf9 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -7,55 +7,61 @@ #include "../tests.hpp" using namespace ComSquare; -//Test(DMA, RomToVRAM) -//{ -// Init() -// snes.cartridge->_size = 4000000; -// snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; -// for(unsigned i = 0xBE00, j = 0; i < 0xBE00 + 0x800; i++, j++) -// snes.cartridge->_data[i] = j; -// -// // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 -// -// // Setting VRam address (since this is an indirect write) -// snes.bus->write(0x2117, 0x20); -// snes.bus->write(0x2116, 0); -// -// snes.bus->write(0x4301, 0x18); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma's b port was $%x but it should have been $18.", snes.cpu->_dmaChannels[0]._port); -// snes.bus->write(0x4304, 0x13); -// snes.bus->write(0x4303, 0xBE); -// snes.bus->write(0x4302, 0x00); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13BE00, "The dma's a address was $%x but it should have been $13BE00.", snes.cpu->_dmaChannels[0]._aAddress.raw); -// snes.bus->write(0x4306, 0x08); -// snes.bus->write(0x4305, 0); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0x0800, "The dma's count was $%x but it should have been $0800.", snes.cpu->_dmaChannels[0]._count.raw); -// snes.bus->write(0x4300, 1); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.direction, CPU::DMA::AtoB, "Direction should have been 0 (A to B) but it was %x.", snes.cpu->_dmaChannels[0]._controlRegister.direction); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister._, 0, "The unused byte should be 0."); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.increment, 0, "The increment byte should be set to 0."); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.fixed, 0, "The increment byte should be set to 0."); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.mode, CPU::DMA::TwoToTwo, "The DMA mode should have been TwoToTwo (%%001) but it was) $%x", snes.cpu->_dmaChannels[0]._controlRegister.mode); -// cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); -// // Enabling DMA's channel 0 -// snes.bus->write(0x420B, 1); -// cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, true, "The DMA channel should be enabled."); -// // TODO There is an overhead of 12-24 cycles for the whole transfer. How should I know how many cycles there is? -// auto cycles = snes.cpu->_dmaChannels[0].run(1000000); -// cr_assert_eq(cycles, 8 + 8 * 0x800, "The dma should take $4008 cycles but it took $%x.", cycles); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0, "The dma count should be 0 but it was $%x.", snes.cpu->_dmaChannels[0]._count.raw); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13C600, "The dma count should be $13C600 but it was $%x.", snes.cpu->_dmaChannels[0]._aAddress.raw); -// cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma count should be $18 but it was $%x.", snes.cpu->_dmaChannels[0]._port); -// cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2400, "The vram address should be $2400 but it was %x.", snes.ppu->_registers._vmadd.vmadd); -// for(unsigned i = 0x2000, j = 0; i < 0x2000 + 0x800; i++, j++) -// std::cout << std::hex << i << ": " << (unsigned)snes.ppu->vram->_data[i] << std::endl; -//// cr_assert_eq(snes.ppu->vram->_data[i], j, "The memory at %x should be %x but it was %x", i, (uint16_t)j, snes.ppu->vram->_data[i]); -//} +Test(DMA, RomToVRAM) +{ + Init() + snes.cartridge->_size = 4000000; + snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; + for(unsigned i = 0; i < 0x400; i++) { + snes.cartridge->_data[0xBE00 + i * 2] = i >> 8; + snes.cartridge->_data[0xBE00 + i * 2 + 1] = i; + uint16_t value = snes.cartridge->_data[0xBE00 + i * 2] | (snes.cartridge->_data[0xBE00 + i * 2 + 1] << 8); + std::cout << std::hex << 0xBE00 + i << ": " << value << std::endl; + } + + // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 + + // Setting VRam address (since this is an indirect write) + snes.bus->write(0x2117, 0x20); + snes.bus->write(0x2116, 0); + + snes.bus->write(0x4301, 0x18); + cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma's b port was $%x but it should have been $18.", snes.cpu->_dmaChannels[0]._port); + snes.bus->write(0x4304, 0x13); + snes.bus->write(0x4303, 0xBE); + snes.bus->write(0x4302, 0x00); + cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13BE00, "The dma's a address was $%x but it should have been $13BE00.", snes.cpu->_dmaChannels[0]._aAddress.raw); + snes.bus->write(0x4306, 0x08); + snes.bus->write(0x4305, 0); + cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0x0800, "The dma's count was $%x but it should have been $0800.", snes.cpu->_dmaChannels[0]._count.raw); + snes.bus->write(0x4300, 1); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.direction, CPU::DMA::AtoB, "Direction should have been 0 (A to B) but it was %x.", snes.cpu->_dmaChannels[0]._controlRegister.direction); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister._, 0, "The unused byte should be 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.increment, 0, "The increment byte should be set to 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.fixed, 0, "The increment byte should be set to 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.mode, CPU::DMA::TwoToTwo, "The DMA mode should have been TwoToTwo (%%001) but it was) $%x", snes.cpu->_dmaChannels[0]._controlRegister.mode); + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); + // Enabling DMA's channel 0 + snes.bus->write(0x420B, 1); + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, true, "The DMA channel should be enabled."); + // TODO There is an overhead of 12-24 cycles for the whole transfer. How should I know how many cycles there is? + auto cycles = snes.cpu->_dmaChannels[0].run(1000000); + cr_assert_eq(cycles, 8 + 8 * 0x800, "The dma should take $4008 cycles but it took $%x.", cycles); + cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0, "The dma count should be 0 but it was $%x.", snes.cpu->_dmaChannels[0]._count.raw); + cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x13C600, "The dma count should be $13C600 but it was $%x.", snes.cpu->_dmaChannels[0]._aAddress.raw); + cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma count should be $18 but it was $%x.", snes.cpu->_dmaChannels[0]._port); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2400, "The vram address should be $2400 but it was %x.", snes.ppu->_registers._vmadd.vmadd); + for(unsigned i = 0; i < 0x400; i++) { + // TODO check endianess + uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); + std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; +// cr_assert_eq(value, i, "The memory at %x should be %x but it was %x", 0x2000 + i, i, snes.ppu->vram->_data[i]); + } +} Test(DMA, VramWrite) { Init() - //snes.bus->write(0x2115, 0b10000000); snes.bus->write(0x2117, 0x20); snes.bus->write(0x2116, 0x0); for (unsigned i = 0; i < 0x400; i++) { @@ -65,7 +71,6 @@ Test(DMA, VramWrite) } for(unsigned i = 0; i < 0x400; i++) { uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); - //std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); } } \ No newline at end of file From 2d83137b40a729a64ccebc57bd882e2ca4be98d8 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 17:44:02 +0100 Subject: [PATCH 12/30] Fixing the DMA test --- tests/CPU/testDMA.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index 8f1baf9..828f30a 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -12,16 +12,15 @@ Test(DMA, RomToVRAM) Init() snes.cartridge->_size = 4000000; snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; - for(unsigned i = 0; i < 0x400; i++) { - snes.cartridge->_data[0xBE00 + i * 2] = i >> 8; - snes.cartridge->_data[0xBE00 + i * 2 + 1] = i; - uint16_t value = snes.cartridge->_data[0xBE00 + i * 2] | (snes.cartridge->_data[0xBE00 + i * 2 + 1] << 8); - std::cout << std::hex << 0xBE00 + i << ": " << value << std::endl; + for (unsigned i = 0; i < 0x400; i++) { + snes.cartridge->_data[0xBDED + i * 2] = i; + snes.cartridge->_data[0xBDED + i * 2 + 1] = i >> 8; } // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 // Setting VRam address (since this is an indirect write) + snes.bus->write(0x2115, 0b10000000); snes.bus->write(0x2117, 0x20); snes.bus->write(0x2116, 0); @@ -52,10 +51,8 @@ Test(DMA, RomToVRAM) cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma count should be $18 but it was $%x.", snes.cpu->_dmaChannels[0]._port); cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2400, "The vram address should be $2400 but it was %x.", snes.ppu->_registers._vmadd.vmadd); for(unsigned i = 0; i < 0x400; i++) { - // TODO check endianess uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); - std::cout << std::hex << 0x2000 + i << ": " << value << std::endl; -// cr_assert_eq(value, i, "The memory at %x should be %x but it was %x", 0x2000 + i, i, snes.ppu->vram->_data[i]); + cr_assert_eq(value, i, "The memory at %x should be %x but it was %x", 0x2000 + i, i, snes.ppu->vram->_data[i]); } } @@ -73,4 +70,21 @@ Test(DMA, VramWrite) uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); } +} + +Test(DMA, VramWriteInvertedOrder) +{ + Init() + snes.bus->write(0x2115, 0b10000000); + snes.bus->write(0x2117, 0x20); + snes.bus->write(0x2116, 0x0); + for (unsigned i = 0; i < 0x400; i++) { + snes.bus->write(0x2118, i); + snes.bus->write(0x2119, i >> 8); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x2001 + i, "The vram address was %x but it should have been %x", snes.ppu->_registers._vmadd.vmadd, 0x2001 + i); + } + for(unsigned i = 0; i < 0x400; i++) { + uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); + cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); + } } \ No newline at end of file From 8ec3cad58bcd114ecd5faa9d308437eff529253f Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 18:18:49 +0100 Subject: [PATCH 13/30] Running dma inside the CPU's debugger --- sources/Debugger/CPU/CPUDebug.cpp | 4 ++++ tests/CPU/testDMA.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index d677158..ce5118d 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -79,6 +79,10 @@ namespace ComSquare::Debugger try { unsigned cycles = 0; + for (auto &channel : this->_dmaChannels) + if (channel.enabled) + cycles += channel.run(INT_MAX); + if (this->_isPaused) return 0xFF; if (this->_isStepping) { diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index 828f30a..412c295 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -54,6 +54,7 @@ Test(DMA, RomToVRAM) uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); cr_assert_eq(value, i, "The memory at %x should be %x but it was %x", 0x2000 + i, i, snes.ppu->vram->_data[i]); } + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); } Test(DMA, VramWrite) From 0b28719f41bd149de5b17e341606fa018ffc8a79 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 18:37:07 +0100 Subject: [PATCH 14/30] Adding more dma tests --- sources/Debugger/CPU/CPUDebug.cpp | 2 +- tests/CPU/testDMA.cpp | 48 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index ce5118d..c38be29 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -137,7 +137,7 @@ namespace ComSquare::Debugger { this->_isPaused = !this->_isPaused; if (this->_isPaused) - this->_ui.actionPause->setText("Resume"); + this->_ui.actionPause->setText("Continue"); else this->_ui.actionPause->setText("Pause"); this->_updateDisassembly(this->_registers.pac); diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index 412c295..25b87d3 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -88,4 +88,52 @@ Test(DMA, VramWriteInvertedOrder) uint16_t value = snes.ppu->vram->_data[0x2000 * 2 + i * 2] | (snes.ppu->vram->_data[0x2000 * 2 + i * 2 + 1] << 8); cr_assert_eq(value, (uint16_t)i, "The memory at %x should be %x but it was %x", 0x2000 + i, (uint16_t)i, value); } +} + +Test(DMA, WRamToVRAM) +{ + Init() + for (unsigned i = 0; i < 0x400; i++) { + snes.wram->_data[i * 2] = i; + snes.wram->_data[i * 2 + 1] = i >> 8; + } + + // Transferring $800 bytes from WRAM ($00) to VRam ($2000) via DMA channel 0 + + // Setting VRam address (since this is an indirect write) + snes.bus->write(0x2115, 0b10000000); + snes.bus->write(0x2117, 0); + snes.bus->write(0x2116, 0); + + snes.bus->write(0x4301, 0x18); + cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma's b port was $%x but it should have been $18.", snes.cpu->_dmaChannels[0]._port); + snes.bus->write(0x4304, 0x7E); + snes.bus->write(0x4303, 0x00); + snes.bus->write(0x4302, 0x00); + cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x7E0000, "The dma's a address was $%x but it should have been $7E0000.", snes.cpu->_dmaChannels[0]._aAddress.raw); + snes.bus->write(0x4306, 0x08); + snes.bus->write(0x4305, 0); + cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0x0800, "The dma's count was $%x but it should have been $0800.", snes.cpu->_dmaChannels[0]._count.raw); + snes.bus->write(0x4300, 1); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.direction, CPU::DMA::AtoB, "Direction should have been 0 (A to B) but it was %x.", snes.cpu->_dmaChannels[0]._controlRegister.direction); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister._, 0, "The unused byte should be 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.increment, 0, "The increment byte should be set to 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.fixed, 0, "The increment byte should be set to 0."); + cr_assert_eq(snes.cpu->_dmaChannels[0]._controlRegister.mode, CPU::DMA::TwoToTwo, "The DMA mode should have been TwoToTwo (%%001) but it was) $%x", snes.cpu->_dmaChannels[0]._controlRegister.mode); + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); + // Enabling DMA's channel 0 + snes.bus->write(0x420B, 1); + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, true, "The DMA channel should be enabled."); + // TODO There is an overhead of 12-24 cycles for the whole transfer. How should I know how many cycles there is? + auto cycles = snes.cpu->_dmaChannels[0].run(1000000); + cr_assert_eq(cycles, 8 + 8 * 0x800, "The dma should take $4008 cycles but it took $%x.", cycles); + cr_assert_eq(snes.cpu->_dmaChannels[0]._count.raw, 0, "The dma count should be 0 but it was $%x.", snes.cpu->_dmaChannels[0]._count.raw); + cr_assert_eq(snes.cpu->_dmaChannels[0]._aAddress.raw, 0x7E0800, "The dma count should be $7E0800 but it was $%x.", snes.cpu->_dmaChannels[0]._aAddress.raw); + cr_assert_eq(snes.cpu->_dmaChannels[0]._port, 0x18, "The dma count should be $18 but it was $%x.", snes.cpu->_dmaChannels[0]._port); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0x0400, "The vram address should be $400 but it was %x.", snes.ppu->_registers._vmadd.vmadd); + for(unsigned i = 0; i < 0x400; i++) { + uint16_t value = snes.ppu->vram->_data[i * 2] | (snes.ppu->vram->_data[i * 2 + 1] << 8); + cr_assert_eq(value, i, "The memory at %x should be %x but it was %x", i, i, snes.ppu->vram->_data[i]); + } + cr_assert_eq(snes.cpu->_dmaChannels[0].enabled, false, "The DMA channel should be disabled."); } \ No newline at end of file From 874c21b0fd85b6ee192cd97e79a52808c4d4e3a2 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 23:43:07 +0100 Subject: [PATCH 15/30] Reworking the memory management & fixing a bug in the memory viewer goto --- CMakeLists.txt | 4 +- sources/APU/APU.cpp | 13 +++---- sources/APU/IPL/IPL.hpp | 2 +- sources/CPU/CPU.cpp | 4 +- sources/Cartridge/Cartridge.cpp | 14 +++---- sources/Cartridge/Cartridge.hpp | 11 ++---- sources/Debugger/MemoryBusDebug.cpp | 12 +++--- sources/Debugger/MemoryBusDebug.hpp | 4 +- sources/Debugger/MemoryViewer.cpp | 26 ++++++------- sources/Debugger/RegisterViewer.cpp | 2 +- sources/Memory/AMemory.cpp | 13 +++---- sources/Memory/AMemory.hpp | 48 ++++++++---------------- sources/Memory/ARectangleMemory.cpp | 47 ++++++++++-------------- sources/Memory/ARectangleMemory.hpp | 52 ++++++++++---------------- sources/Memory/IMemory.hpp | 53 +++++++++++++++++++++++++++ sources/Memory/MemoryBus.cpp | 13 +++---- sources/Memory/MemoryBus.hpp | 4 +- sources/Memory/MemoryShadow.cpp | 4 +- sources/Memory/MemoryShadow.hpp | 13 +++---- sources/Memory/RectangleShadow.cpp | 26 ++++++++----- sources/Memory/RectangleShadow.hpp | 38 ++++++++++--------- sources/PPU/Backgrounds.cpp | 17 +++------ sources/PPU/PPU.cpp | 50 ++++++++++++------------- sources/PPU/PPU.hpp | 3 +- sources/Ram/Ram.cpp | 17 ++------- sources/Ram/Ram.hpp | 26 ++++++------- tests/CPU/testDMA.cpp | 3 +- tests/testMemoryBus.cpp | 57 +++++++++++++---------------- tests/testRectangleMemory.cpp | 26 ++++++------- 29 files changed, 295 insertions(+), 307 deletions(-) create mode 100644 sources/Memory/IMemory.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d5e1027..22d3311 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ add_executable(unit_tests sources/PPU/Background.hpp sources/CPU/DMA/DMA.cpp sources/CPU/DMA/DMA.hpp - tests/CPU/testDMA.cpp) + tests/CPU/testDMA.cpp sources/Memory/IMemory.hpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -226,7 +226,7 @@ add_executable(ComSquare ui/registersView.ui sources/Debugger/RegisterViewer.cpp sources/Debugger/RegisterViewer.hpp -) + sources/Memory/IMemory.hpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index dacb563..effc58d 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -7,7 +7,6 @@ #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" #include "../Exceptions/InvalidOpcode.hpp" -#include "../Utility/Utility.hpp" namespace ComSquare::APU { @@ -36,7 +35,7 @@ namespace ComSquare::APU uint8_t APU::_internalRead(uint24_t addr) { switch (addr) { case 0x0000 ... 0x00EF: - return this->_map->Page0.read_internal(addr); + return this->_map->Page0.read(addr); case 0xF0: return this->_registers.unknown; case 0xF2: @@ -62,9 +61,9 @@ namespace ComSquare::APU case 0xFF: return this->_registers.counter2; case 0x0100 ... 0x01FF: - return this->_map->Page1.read_internal(addr - 0x0100); + return this->_map->Page1.read(addr - 0x0100); case 0x0200 ... 0xFFBF: - return this->_map->Memory.read_internal(addr - 0x200); + return this->_map->Memory.read(addr - 0x200); case 0xFFC0 ... 0xFFFF: return this->_map->IPL.read(addr - 0xFFC0); default: @@ -75,7 +74,7 @@ namespace ComSquare::APU void APU::_internalWrite(uint24_t addr, uint8_t data) { switch (addr) { case 0x0000 ... 0x00EF: - this->_map->Page0.write_internal(addr, data); + this->_map->Page0.write(addr, data); break; case 0xF0: this->_registers.unknown = data; @@ -117,10 +116,10 @@ namespace ComSquare::APU this->_registers.timer2 = data; break; case 0x0100 ... 0x01FF: - this->_map->Page1.write_internal(addr - 0x0100, data); + this->_map->Page1.write(addr - 0x0100, data); break; case 0x0200 ... 0xFFBF: - this->_map->Memory.write_internal(addr - 0x200, data); + this->_map->Memory.write(addr - 0x200, data); break; case 0xFFC0 ... 0xFFFF: this->_map->IPL.write(addr - 0xFFC0, data); diff --git a/sources/APU/IPL/IPL.hpp b/sources/APU/IPL/IPL.hpp index 38c3437..54ba95d 100644 --- a/sources/APU/IPL/IPL.hpp +++ b/sources/APU/IPL/IPL.hpp @@ -5,7 +5,7 @@ #ifndef COMSQUARE_IPL_HPP #define COMSQUARE_IPL_HPP -#include "../../Memory/ARectangleMemory.hpp" +#include "../../Memory/AMemory.hpp" namespace ComSquare::APU::IPL { diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 5962413..107a6a9 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -101,7 +101,7 @@ namespace ComSquare::CPU case 0x100 ... 0x180: return this->_dmaChannels[(addr - 0x100) >> 8u].read(addr & 0xF); default: - throw InvalidAddress("CPU Internal Registers read", addr + this->getStart()); + throw InvalidAddress("CPU Internal Registers read", addr + this->_start); } } @@ -203,7 +203,7 @@ namespace ComSquare::CPU this->_dmaChannels[(addr - 0x100) >> 8u].write(addr & 0xF, data); break; default: - throw InvalidAddress("CPU Internal Registers write", addr + this->getStart()); + throw InvalidAddress("CPU Internal Registers write", addr + this->_start); } } diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 91a8036..8156c54 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -3,7 +3,6 @@ // #include -#include #include #include "Cartridge.hpp" #include "../Exceptions/InvalidAddress.hpp" @@ -39,17 +38,13 @@ namespace ComSquare::Cartridge } - uint8_t Cartridge::read_internal(uint24_t addr) + uint8_t Cartridge::read(uint24_t addr) { - if (addr >= this->_size) - throw InvalidAddress("Cartridge read", addr); - return this->_data[addr + this->_romStart]; + return Ram::read(addr + this->_romStart); } - void Cartridge::write_internal(uint24_t addr, uint8_t data) + void Cartridge::write(uint24_t, uint8_t) { - (void)addr; - (void)data; throw InvalidAction("Witting to the ROM is not allowed."); } @@ -123,7 +118,8 @@ namespace ComSquare::Cartridge if (info.checksum + info.checksumComplement == 0xFFFF && info.checksum != 0 && info.checksumComplement != 0) score += 8; - if (info.emulationInterrupts.reset < 0x8000u) // The reset vector is the first thing called by the SNES so It must execute the code inside the ROM (the rom starts at 0x8000). + // The reset vector is the first thing called by the SNES so It must execute the code inside the ROM (the rom starts at 0x8000). + if (info.emulationInterrupts.reset < 0x8000u) continue; uint8_t resetOpCode = this->_data[info.emulationInterrupts.reset - 0x8000u]; switch (resetOpCode) { diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index 9dc7c73..4b4ea0a 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -2,8 +2,7 @@ // Created by anonymus-raccoon on 1/27/20. // -#ifndef COMSQUARE_CARTRIDGE_HPP -#define COMSQUARE_CARTRIDGE_HPP +#pragma once #include #include "../Memory/AMemory.hpp" @@ -99,13 +98,11 @@ namespace ComSquare::Cartridge //! @param addr The address to read from. The address 0x0 should refer to the first byte of the rom's memory. //! @throw InvalidAddress will be thrown if the address is more than the size of the rom's memory. //! @return Return the data at the address. - uint8_t read_internal(uint24_t addr) override; + uint8_t read(uint24_t addr) override; //! @brief Write data to the rom. //! @param addr The address to write to. The address 0x0 should refer to the first byte of the rom's memory. //! @param data The data to write. //! @throw InvalidAddress will be thrown if the address is more than the size of the rom's memory. - void write_internal(uint24_t addr, uint8_t data) override; + void write(uint24_t addr, uint8_t data) override; }; -} - -#endif //COMSQUARE_CARTRIDGE_HPP +} \ No newline at end of file diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index 17d77fc..8ebe6c2 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -155,7 +155,7 @@ namespace ComSquare::Debugger if (!accessor) { this->_model.log(BusLog(true, addr, accessor, this->_openBus, this->_openBus)); } else { - uint8_t value = accessor->read(addr - accessor->getStart()); + uint8_t value = accessor->read(accessor->getRelativeAddress(addr)); this->_model.log(BusLog(false, addr, accessor, value, value)); } } @@ -168,7 +168,7 @@ namespace ComSquare::Debugger std::optional value = std::nullopt; try { if (accessor) - value = accessor->read(addr - accessor->getStart()); + value = accessor->read(accessor->getRelativeAddress(addr)); } catch (InvalidAddress &) { value = std::nullopt; } @@ -177,7 +177,7 @@ namespace ComSquare::Debugger MemoryBus::write(addr, data); } - BusLog::BusLog(bool _write, uint24_t _addr, std::shared_ptr &_accessor, std::optional _oldData, uint8_t _newData) : + 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) {} } @@ -206,8 +206,10 @@ QVariant BusLogModel::data(const QModelIndex &index, int role) const return QString(ComSquare::Utility::to_hex(log.addr).c_str()); case 2: return QString(log.accessor ? log.accessor->getName().c_str() : "Bus"); - case 3: - return QString(log.accessor ? log.accessor->getValueName(log.addr - log.accessor->getStart()).c_str() : "Open 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("???"); diff --git a/sources/Debugger/MemoryBusDebug.hpp b/sources/Debugger/MemoryBusDebug.hpp index c477d2d..1f19be1 100644 --- a/sources/Debugger/MemoryBusDebug.hpp +++ b/sources/Debugger/MemoryBusDebug.hpp @@ -17,13 +17,13 @@ namespace ComSquare::Debugger struct BusLog { BusLog(bool write, uint24_t addr, - std::shared_ptr &accessor, + std::shared_ptr &accessor, std::optional oldData, uint8_t newData); bool write; uint24_t addr; - std::shared_ptr accessor; + std::shared_ptr accessor; std::optional oldData; uint8_t newData; }; diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index 2e1b6b4..01b29ff 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -35,7 +35,7 @@ QVariant MemoryViewerModel::data(const QModelIndex &index, int role) const if (role != Qt::DisplayRole) return QVariant(); char buf[3]; - snprintf(buf, 3, "%02X", this->_memory->read_internal((index.row() << 4u) + index.column())); + snprintf(buf, 3, "%02X", this->_memory->read((index.row() << 4u) + index.column())); return QString(buf); } @@ -149,31 +149,31 @@ namespace ComSquare::Debugger value = this->switchToAddrTab(value); } catch (InvalidAddress &) {} } - QModelIndex index = this->_ui.tableView->model()->index(value >> 4, value & 0x0000000F); + QModelIndex index = this->_ui.tableView->model()->index(value >> 4, value & 0x0F); this->_ui.tableView->scrollTo(index); this->_ui.tableView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); } unsigned MemoryViewer::switchToAddrTab(uint24_t addr) { - std::shared_ptr accessor = this->_bus.getAccessor(addr); + std::shared_ptr accessor = this->_bus.getAccessor(addr); if (!accessor) throw InvalidAddress("Memory viewer switch to address", addr); - Memory::AMemory *ptr; - if (accessor->isMirror()) - ptr = accessor->getMirrored().get(); - else - ptr = accessor.get(); - if (ptr == this->_snes.wram.get()) + switch (accessor->getComponent()) { + case WRam: this->_ui.tabs->setCurrentIndex(0); - else if (ptr == this->_snes.sram.get()) + break; + case SRam: this->_ui.tabs->setCurrentIndex(1); - else if (ptr == this->_snes.cartridge.get()) + break; + case Rom: this->_ui.tabs->setCurrentIndex(2); - else + break; + default: throw InvalidAddress("Memory viewer switch to address", addr); - return addr - accessor->getStart(); + } + return accessor->getRelativeAddress(addr); } void MemoryViewer::focus() diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index 1dfcc90..dba6ee3 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -45,7 +45,7 @@ namespace ComSquare::Debugger model->addRegister(Register(0x4300, ":3", "Fixed", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.fixed; }, nullptr, Boolean)); - model->addRegister(Register(0x4300, ":4", "Increment", [i](SNES &snes) { + model->addRegister(Register(0x4300, ":4", "Decrement", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.increment; }, nullptr, Boolean)); model->addRegister(Register(0x4300, ":0-2", "Mode", [i](SNES &snes) { diff --git a/sources/Memory/AMemory.cpp b/sources/Memory/AMemory.cpp index ce51b16..3132424 100644 --- a/sources/Memory/AMemory.cpp +++ b/sources/Memory/AMemory.cpp @@ -3,10 +3,14 @@ // #include "AMemory.hpp" -#include namespace ComSquare::Memory { + uint24_t AMemory::getRelativeAddress(uint24_t addr) + { + return addr - this->_start; + } + void AMemory::setMemoryRegion(uint24_t start, uint24_t end) { this->_start = start; @@ -18,17 +22,12 @@ namespace ComSquare::Memory return this->_start <= addr && addr <= this->_end; } - uint32_t AMemory::getStart() - { - return this->_start; - } - bool AMemory::isMirror() { return false; } - std::shared_ptr AMemory::getMirrored() + std::shared_ptr AMemory::getMirrored() { return nullptr; } diff --git a/sources/Memory/AMemory.hpp b/sources/Memory/AMemory.hpp index 1450261..210aa49 100644 --- a/sources/Memory/AMemory.hpp +++ b/sources/Memory/AMemory.hpp @@ -2,9 +2,7 @@ // Created by anonymus-raccoon on 1/23/20. // -#ifndef COMSQUARE_AMEMORY_HPP -#define COMSQUARE_AMEMORY_HPP - +#pragma once #include #include @@ -12,27 +10,23 @@ #include #include "../Models/Int24.hpp" #include "../Models/Components.hpp" +#include "IMemory.hpp" namespace ComSquare::Memory { - //! @brief Common interface implemented by all components mapping memory. - class AMemory { - private: + //! @brief Abstract class representing a continuous block of memory. + class AMemory : public IMemory { + protected: //! @brief The starting address mapped to this component. uint24_t _start = 0; //! @brief The last continuous address mapped to this components. For shadows, see the MemoryShadow class. uint24_t _end = 0; 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). - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - //! @return Return the data at the address given as parameter. - virtual uint8_t read(uint24_t addr) = 0; - //! @brief Write data to this component. - //! @param addr The local address to write data (0x0 should refer to the first byte of this component). - //! @param data The new data to write. - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - virtual void write(uint24_t addr, uint8_t data) = 0; + //! @brief Translate an absolute address to a relative address + //! @param addr The absolute address (in the 24 bit bus) + //! @return The local address (0 refers to the first byte of this component). + //! @throw InvalidAddress is thrown if the address is not mapped by this component. + virtual uint24_t getRelativeAddress(uint24_t addr) override; //! @brief Change starting and ending points of this mapped memory. //! @param start The first address mapped to this component. //! @param end The last address mapped to this component. @@ -41,26 +35,16 @@ namespace ComSquare::Memory //! @brief Return true if this component has mapped the address. //! @param addr The address to check. //! @return True if this address is mapped to the component. False otherwise. - virtual bool hasMemoryAt(uint24_t addr); - //! @brief Get the first address mapped to this component. - //! @return the _start value. - virtual uint24_t getStart(); + virtual bool hasMemoryAt(uint24_t addr) override; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - virtual bool isMirror(); - //! @brief Get the name of this accessor (used for debug purpose) - virtual std::string getName() = 0; - //! @brief Get the component of this accessor (used for debug purpose) - virtual Component getComponent() = 0; + virtual bool isMirror() override; //! @brief Get the name of the data at the address //! @param addr The address (in local space) - virtual std::string getValueName(uint24_t addr); + virtual std::string getValueName(uint24_t addr) override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - virtual std::shared_ptr getMirrored(); - virtual ~AMemory() = default; + virtual std::shared_ptr getMirrored() override; + virtual ~AMemory() override = default; }; -}; - - -#endif //COMSQUARE_AMEMORY_HPP +} \ No newline at end of file diff --git a/sources/Memory/ARectangleMemory.cpp b/sources/Memory/ARectangleMemory.cpp index e7e9ff4..5c6b392 100644 --- a/sources/Memory/ARectangleMemory.cpp +++ b/sources/Memory/ARectangleMemory.cpp @@ -9,38 +9,19 @@ namespace ComSquare::Memory { - uint8_t ARectangleMemory::read(uint24_t addr) + uint24_t ARectangleMemory::getRelativeAddress(uint24_t addr) { - addr += this->getStart(); uint8_t bank = addr >> 16u; uint16_t page = addr; unsigned bankCount = bank - this->_startBank; unsigned pageCount = this->_endPage - this->_startPage; if (bank < this->_startBank || bank > this->_endBank) - throw InvalidAddress("Rectangle memory read Invalid Bank", addr); + throw InvalidAddress("Rectangle memory: Invalid Bank", addr); if (page < this->_startPage || page > this->_endPage) - throw InvalidAddress("Rectangle memory read Invalid Page", addr); + throw InvalidAddress("Rectangle memory: Invalid Page", addr); page -= this->_startPage; - page += pageCount * bankCount; - return this->read_internal(page); - } - - void ARectangleMemory::write(uint24_t addr, uint8_t data) - { - addr += this->getStart(); - uint8_t bank = addr >> 16u; - uint16_t page = addr; - unsigned bankCount = bank - this->_startBank; - unsigned pageCount = this->_endPage - this->_startPage; - - if (bank < this->_startBank || bank > this->_endBank) - throw InvalidRectangleAddress("Rectangle memory write Invalid Bank", addr, bank, this->_startBank, this->_endBank); - if (page < this->_startPage || page > this->_endPage) - throw InvalidRectangleAddress("Rectangle memory write Invalid Page", addr, page, this->_startPage, this->_endPage); - page -= this->_startPage; - page += pageCount * bankCount; - this->write_internal(page, data); + return pageCount * bankCount + page; } bool ARectangleMemory::hasMemoryAt(uint24_t addr) @@ -54,11 +35,6 @@ namespace ComSquare::Memory return false; } - uint24_t ARectangleMemory::getStart() - { - return (this->_startBank << 16u) + this->_startPage; - } - void ARectangleMemory::setMemoryRegion(uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage) { this->_startBank = startBank; @@ -66,4 +42,19 @@ namespace ComSquare::Memory this->_startPage = startPage; this->_endPage = endPage; } + + bool ARectangleMemory::isMirror() + { + return false; + } + + std::shared_ptr ARectangleMemory::getMirrored() + { + return nullptr; + } + + std::string ARectangleMemory::getValueName(uint24_t) + { + return "???"; + } } \ No newline at end of file diff --git a/sources/Memory/ARectangleMemory.hpp b/sources/Memory/ARectangleMemory.hpp index 0a8f028..e923bb3 100644 --- a/sources/Memory/ARectangleMemory.hpp +++ b/sources/Memory/ARectangleMemory.hpp @@ -2,16 +2,14 @@ // Created by anonymus-raccoon on 1/29/20. // -#ifndef COMSQUARE_ARECTANGLEMEMORY_HPP -#define COMSQUARE_ARECTANGLEMEMORY_HPP +#pragma once - -#include "AMemory.hpp" +#include "IMemory.hpp" namespace ComSquare::Memory { - //! @brief Superset of the AMemory to map non continuous rectangle to the memory. (A rectangle that spam across more than one bank but that does not start at 0000 or end at FFFF). - class ARectangleMemory : public AMemory { + //! @brief Base memory class to map non continuous rectangle to the memory. (A rectangle that spam across more than one bank but that does not start at $0000 or end at $FFFF). + class ARectangleMemory : public IMemory { protected: //! @brief The first bank to map to. uint8_t _startBank = 0; @@ -22,33 +20,15 @@ namespace ComSquare::Memory //! @brief The last address of each bank to map. uint16_t _endPage = 0; public: - //! @brief Read data from the component using the same method as the basic AMemory. - //! @param addr The global 24 bits address. This method is responsible of mapping to the component's read. - //! @throw InvalidAddress if the address is not mapped to the component. - //! @return Return the data at the address given as parameter. - uint8_t read(uint24_t addr) override; - //! @brief Write data to this component using the same method as the basic AMemory. - //! @param addr The global 24 bits address. This method is responsible of mapping to the component's write. - //! @param data The new data to write. - //! @throw InvalidAddress if the address is not mapped to the component. - void write(uint24_t addr, uint8_t data) override; - //! @brief Internal component read. Implement this as you would implement a basic AMemory's read. - //! @param addr The local address to read from. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - //! @return Return the data at the address given as parameter. - virtual uint8_t read_internal(uint24_t addr) = 0; - //! @brief Internal component write. Implement this as you would implement a basic AMemory's write. - //! @param addr The local address to write to. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous - //! @param data The new data to write. - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - virtual void write_internal(uint24_t addr, uint8_t data) = 0; + //! @brief Translate an absolute address to a relative address + //! @param addr The absolute address (in the 24 bit bus) + //! @return The local address (0 refers to the first byte of this component). + //! @throw InvalidAddress is thrown if the address is not mapped by this component. + virtual uint24_t getRelativeAddress(uint24_t addr) override; //! @brief Return true if this component has mapped the address. //! @param addr The address to check. //! @return True if this address is mapped to the component. False otherwise. bool hasMemoryAt(uint24_t addr) override; - //! @brief Get the first address mapped to this component. - //! @return the _start value. - uint24_t getStart() override; //! @brief Change starting and ending points of this mapped memory. //! @param startBank The first bank mapped to this component. //! @param endBank The last bank mapped to this component. @@ -56,7 +36,15 @@ namespace ComSquare::Memory //! @param endPage The end page mapped to this component (every mapped banks will have this pages lower than this mapped) //! @warning The start/end address should be a rectangle. To mirror memory, use the MemoryShadow class and not this one. void setMemoryRegion(uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); + //! @brief Check if this memory is a mirror or not. + //! @return True if this memory is a mirror. False otherwise. + virtual bool isMirror() override; + //! @brief Get the name of the data at the address + //! @param addr The address (in local space) + virtual std::string getValueName(uint24_t addr) override; + //! @brief Return the memory accessor this accessor mirror if any + //! @return nullptr if isMirror is false, the source otherwise. + virtual std::shared_ptr getMirrored() override; + virtual ~ARectangleMemory() override = default; }; -} - -#endif //COMSQUARE_ARECTANGLEMEMORY_HPP +} \ No newline at end of file diff --git a/sources/Memory/IMemory.hpp b/sources/Memory/IMemory.hpp new file mode 100644 index 0000000..14370af --- /dev/null +++ b/sources/Memory/IMemory.hpp @@ -0,0 +1,53 @@ +// +// Created by anonymus-raccoon on 1/23/20. +// + +#pragma once + +#include +#include +#include +#include +#include "../Models/Int24.hpp" +#include "../Models/Components.hpp" + +namespace ComSquare::Memory +{ + //! @brief Common interface implemented by all components mapping memory. + 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). + //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. + //! @return Return the data at the address given as parameter. + virtual uint8_t read(uint24_t addr) = 0; + //! @brief Write data to this component. + //! @param addr The local address to write data (0x0 should refer to the first byte of this component). + //! @param data The new data to write. + //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. + virtual void write(uint24_t addr, uint8_t data) = 0; + //! @brief Return true if this component has mapped the address. + //! @param addr The address to check. + //! @return True if this address is mapped to the component. False otherwise. + virtual bool hasMemoryAt(uint24_t addr) = 0; + //! @brief Translate an absolute address to a relative address + //! @param addr The absolute address (in the 24 bit bus) + //! @return The local address (0 refers to the first byte of this component). + //! @throw InvalidAddress is thrown if the address is not mapped by this component. + virtual uint24_t getRelativeAddress(uint24_t addr) = 0; + //! @brief Check if this memory is a mirror or not. + //! @return True if this memory is a mirror. False otherwise. + virtual bool isMirror() = 0; + //! @brief Get the name of this accessor (used for debug purpose) + virtual std::string getName() = 0; + //! @brief Get the component of this accessor (used for debug purpose) + virtual Component getComponent() = 0; + //! @brief Get the name of the data at the address + //! @param addr The address (in local space) + virtual std::string getValueName(uint24_t addr) = 0; + //! @brief Return the memory accessor this accessor mirror if any + //! @return nullptr if isMirror is false, the source otherwise. + virtual std::shared_ptr getMirrored() = 0; + virtual ~IMemory() = default; + }; +}; \ No newline at end of file diff --git a/sources/Memory/MemoryBus.cpp b/sources/Memory/MemoryBus.cpp index dca92ed..38d3ccc 100644 --- a/sources/Memory/MemoryBus.cpp +++ b/sources/Memory/MemoryBus.cpp @@ -11,9 +11,9 @@ namespace ComSquare::Memory { - std::shared_ptr MemoryBus::getAccessor(uint24_t addr) + std::shared_ptr MemoryBus::getAccessor(uint24_t addr) { - auto it = std::find_if(this->_memoryAccessors.begin(), this->_memoryAccessors.end(), [addr](std::shared_ptr &accessor) + auto it = std::find_if(this->_memoryAccessors.begin(), this->_memoryAccessors.end(), [addr](std::shared_ptr &accessor) { return accessor->hasMemoryAt(addr); }); @@ -24,27 +24,27 @@ namespace ComSquare::Memory uint8_t MemoryBus::read(uint24_t addr, bool silence) { - std::shared_ptr handler = this->getAccessor(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; return this->_openBus; } - uint8_t data = handler->read(addr - handler->getStart()); + uint8_t data = handler->read(handler->getRelativeAddress(addr)); this->_openBus = data; return data; } void MemoryBus::write(uint24_t addr, uint8_t data) { - std::shared_ptr handler = this->getAccessor(addr); + std::shared_ptr handler = this->getAccessor(addr); if (!handler) { std::cout << "Unknown memory accessor for address " << std::hex << addr << ". Warning, it was a write." << std::endl; return; } - handler->write(addr - handler->getStart(), data); + handler->write(handler->getRelativeAddress(addr), data); } void MemoryBus::_mirrorComponents(SNES &console, unsigned i) @@ -72,7 +72,6 @@ namespace ComSquare::Memory console.cpu->setMemoryRegion(0x4200, 0x44FF); this->_memoryAccessors.push_back(console.cpu); - // TODO implement DMA & HDMA (4220 to 4300) // TODO implement Joys. // Mirror to the quarter 1. diff --git a/sources/Memory/MemoryBus.hpp b/sources/Memory/MemoryBus.hpp index 044462d..301dcd4 100644 --- a/sources/Memory/MemoryBus.hpp +++ b/sources/Memory/MemoryBus.hpp @@ -20,7 +20,7 @@ namespace ComSquare class MemoryBus { 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. - std::vector> _memoryAccessors; + std::vector> _memoryAccessors; //! @brief WRam, CPU, PPU & APU registers are mirrored to all banks of Q1 & Q3. This function is used for the mirroring. //! @param console All the components. @@ -56,7 +56,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. - std::shared_ptr getAccessor(uint24_t addr); + std::shared_ptr getAccessor(uint24_t addr); //! @brief Return true if the Bus is overloaded with debugging features. virtual bool isDebugger(); diff --git a/sources/Memory/MemoryShadow.cpp b/sources/Memory/MemoryShadow.cpp index ecc4b4f..4912fc5 100644 --- a/sources/Memory/MemoryShadow.cpp +++ b/sources/Memory/MemoryShadow.cpp @@ -8,7 +8,7 @@ namespace ComSquare::Memory { - MemoryShadow::MemoryShadow(std::shared_ptr initial, uint24_t start, uint24_t end) + MemoryShadow::MemoryShadow(std::shared_ptr initial, uint24_t start, uint24_t end) : _initial(std::move(initial)) { this->setMemoryRegion(start, end); @@ -29,7 +29,7 @@ namespace ComSquare::Memory return true; } - std::shared_ptr MemoryShadow::getMirrored() + std::shared_ptr MemoryShadow::getMirrored() { return this->_initial; } diff --git a/sources/Memory/MemoryShadow.hpp b/sources/Memory/MemoryShadow.hpp index 7c33c43..519a4c6 100644 --- a/sources/Memory/MemoryShadow.hpp +++ b/sources/Memory/MemoryShadow.hpp @@ -2,8 +2,7 @@ // Created by anonymus-raccoon on 1/28/20. // -#ifndef COMSQUARE_MEMORYSHADOW_HPP -#define COMSQUARE_MEMORYSHADOW_HPP +#pragma once #include #include "AMemory.hpp" @@ -13,10 +12,10 @@ namespace ComSquare::Memory class MemoryShadow : public AMemory { private: //! @brief Memory to shadow from. - std::shared_ptr _initial; + std::shared_ptr _initial; public: //! @brief Create a shadow for the memory given as parameter. - explicit MemoryShadow(std::shared_ptr initial, uint24_t start, uint24_t end); + MemoryShadow(std::shared_ptr initial, uint24_t start, uint24_t end); MemoryShadow(const MemoryShadow &) = default; MemoryShadow &operator=(const MemoryShadow &) = default; ~MemoryShadow() = default; @@ -40,8 +39,6 @@ namespace ComSquare::Memory Component getComponent() override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - std::shared_ptr getMirrored() override; + std::shared_ptr getMirrored() override; }; -} - -#endif //COMSQUARE_MEMORYSHADOW_HPP +} \ No newline at end of file diff --git a/sources/Memory/RectangleShadow.cpp b/sources/Memory/RectangleShadow.cpp index 424724a..182a4fc 100644 --- a/sources/Memory/RectangleShadow.cpp +++ b/sources/Memory/RectangleShadow.cpp @@ -3,29 +3,35 @@ // #include "RectangleShadow.hpp" -#include "../Utility/Utility.hpp" - #include #include namespace ComSquare::Memory { - RectangleShadow::RectangleShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage) + RectangleShadow::RectangleShadow(std::shared_ptr initial, + uint8_t startBank, + uint8_t endBank, + uint16_t startPage, + uint16_t endPage) : _initial(std::move(initial)) { this->setMemoryRegion(startBank, endBank, startPage, endPage); } - uint8_t RectangleShadow::read_internal(uint24_t addr) + uint24_t RectangleShadow::getRelativeAddress(uint24_t addr) { - addr += this->_bankOffset * (this->_endPage - this->_startPage); - return this->_initial->read_internal(addr); + uint24_t base = ARectangleMemory::getRelativeAddress(addr); + return base + this->_bankOffset * (this->_endPage - this->_startPage); } - void RectangleShadow::write_internal(uint24_t addr, uint8_t data) + uint8_t RectangleShadow::read(uint24_t addr) { - addr += this->_bankOffset * (this->_endPage - this->_startPage); - this->_initial->write_internal(addr, data); + return this->_initial->read(addr); + } + + void RectangleShadow::write(uint24_t addr, uint8_t data) + { + return this->_initial->write(addr, data); } RectangleShadow *RectangleShadow::setBankOffset(uint8_t bankOffset) @@ -39,7 +45,7 @@ namespace ComSquare::Memory return true; } - std::shared_ptr RectangleShadow::getMirrored() + std::shared_ptr RectangleShadow::getMirrored() { return this->_initial; } diff --git a/sources/Memory/RectangleShadow.hpp b/sources/Memory/RectangleShadow.hpp index 365c85f..2c6cb24 100644 --- a/sources/Memory/RectangleShadow.hpp +++ b/sources/Memory/RectangleShadow.hpp @@ -2,8 +2,7 @@ // Created by anonymus-raccoon on 2/4/20. // -#ifndef COMSQUARE_RECTANGLESHADOW_HPP -#define COMSQUARE_RECTANGLESHADOW_HPP +#pragma once #include #include "ARectangleMemory.hpp" @@ -14,26 +13,31 @@ namespace ComSquare::Memory class RectangleShadow : public ARectangleMemory { private: //! @brief Memory to shadow from. - std::shared_ptr _initial; + std::shared_ptr _initial; //! @brief The number of banks to add to the memory before accessing it from the initial data. uint8_t _bankOffset = 0; public: //! @brief Create a shadow for the memory given as parameter. - explicit RectangleShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); + explicit RectangleShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); RectangleShadow(const RectangleShadow &) = default; RectangleShadow &operator=(const RectangleShadow &) = default; ~RectangleShadow() override = default; - //! @brief Internal component read. Implement this as you would implement a basic AMemory's read. - //! @param addr The local address to read from. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - //! @return Return the data at the address given as parameter. - uint8_t read_internal(uint24_t addr) override; - //! @brief Internal component write. Implement this as you would implement a basic AMemory's write. - //! @param addr The local address to write to. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous - //! @param data The new data to write. - //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. - void write_internal(uint24_t addr, uint8_t data) override; + //! @brief Read from the initial AMemory given. + //! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial AMemory. + //! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory. + //! @return Return the data at the address. + uint8_t read(uint24_t addr) override; + //! @brief Write data to the ram. + //! @param addr The address to write to. The address 0x0 should refer to the first byte of the initial AMemory. + //! @param data The data to write. + //! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory. + void write(uint24_t addr, uint8_t data) override; + //! @brief Translate an absolute address to a relative address + //! @param addr The absolute address (in the 24 bit bus) + //! @return The local address (0 refers to the first byte of this component). + //! @throw InvalidAddress is thrown if the address is not mapped by this component. + uint24_t getRelativeAddress(uint24_t addr) override; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. bool isMirror() override; @@ -43,10 +47,8 @@ namespace ComSquare::Memory Component getComponent() override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - std::shared_ptr getMirrored() override; + std::shared_ptr getMirrored() override; RectangleShadow *setBankOffset(uint8_t bankOffset); }; -} - -#endif //COMSQUARE_RECTANGLESHADOW_HPP +} \ No newline at end of file diff --git a/sources/PPU/Backgrounds.cpp b/sources/PPU/Backgrounds.cpp index c7d01dc..5919990 100644 --- a/sources/PPU/Backgrounds.cpp +++ b/sources/PPU/Backgrounds.cpp @@ -2,14 +2,9 @@ // Created by cbihan on 5/14/20. // -#include #include #include "PPU.hpp" #include "PPUUtils.hpp" -#include "../Exceptions/NotImplementedException.hpp" -#include "../Exceptions/InvalidAddress.hpp" -#include "../Ram/Ram.hpp" -#include "../Models/Vector2.hpp" namespace ComSquare::PPU { @@ -50,8 +45,8 @@ namespace ComSquare::PPU union TileMapData tileData; std::vector palette; int index = 0; - uint8_t reference = 0; - uint32_t color = 0; + uint8_t reference; + uint32_t color; tileData.raw = data; graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); @@ -106,7 +101,7 @@ namespace ComSquare::PPU uint8_t PPU::getTilePixelReference(uint16_t addr, int bpp, int nb) { - uint8_t reference = this->vram->read_internal(addr); + uint8_t reference = this->vram->read(addr); switch (bpp) { case 8: @@ -123,13 +118,13 @@ namespace ComSquare::PPU void PPU::drawBasicTileMap(uint16_t baseAddress, int bgNumber, int bpp, Vector2 characterSize, Vector2 offset) { - uint16_t tileMapValue = 0; + uint16_t tileMapValue; Vector2 pos(0,0); uint16_t vramAddress = baseAddress; while (vramAddress < 0x800 + baseAddress) { - tileMapValue = this->vram->read_internal(vramAddress); - tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; + tileMapValue = this->vram->read(vramAddress); + tileMapValue += this->vram->read(vramAddress + 1) << 8U; vramAddress += 2; drawBgTile(tileMapValue, {(pos.x * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.y}, bgNumber, bpp, characterSize); if (pos.x % 31 == 0 && pos.x) { diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index a8389ba..f931a8e 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -5,11 +5,8 @@ #include #include #include "PPU.hpp" -#include "PPUUtils.hpp" #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" -#include "../Ram/Ram.hpp" -#include "../Models/Vector2.hpp" namespace ComSquare::PPU { @@ -21,7 +18,7 @@ namespace ComSquare::PPU { this->_registers._isLowByte = true; for (int i = 0; i < 512; i++) { - this->cgram->write_internal(i, random() % 255); + this->cgram->write(i, random() % 255); } } @@ -45,7 +42,7 @@ namespace ComSquare::PPU case ppuRegisters::stat78: return 0; default: - throw InvalidAddress("PPU Internal Registers read ", addr + this->getStart()); + throw InvalidAddress("PPU Internal Registers read ", addr + this->_start); } } @@ -69,7 +66,7 @@ namespace ComSquare::PPU //throw InvalidAddress("oamdata", addr); std::cout << "oamdata" << std::endl; // the oamAddress have to be calculated if fblank or not (not implemented) - oamram->write_internal(this->_registers._oamadd.oamAddress, this->_registers._oamdata); + oamram->write(this->_registers._oamadd.oamAddress, this->_registers._oamdata); this->_registers._oamadd.oamAddress++; break; case ppuRegisters::bgmode: @@ -126,7 +123,7 @@ namespace ComSquare::PPU //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->vram->write_internal(this->getVramAddress(), data); + this->vram->write(this->getVramAddress(), data); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -135,7 +132,7 @@ namespace ComSquare::PPU //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->vram->write_internal(this->getVramAddress() + 1, data); + this->vram->write(this->getVramAddress() + 1, data); } if (this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -163,9 +160,9 @@ namespace ComSquare::PPU } else { this->_registers._cgdata.cgdatah = data; - this->cgram->write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatal); + this->cgram->write(this->_registers._cgadd, this->_registers._cgdata.cgdatal); this->_registers._cgadd++; - this->cgram->write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatah); + this->cgram->write(this->_registers._cgadd, this->_registers._cgdata.cgdatah); this->_registers._cgadd++; } this->_registers._isLowByte = !this->_registers._isLowByte; @@ -215,7 +212,7 @@ namespace ComSquare::PPU break; //TODO adding the rest of the registers. oaf ! default: - throw InvalidAddress("PPU Internal Registers write", addr + this->getStart()); + throw InvalidAddress("PPU Internal Registers write", addr + this->_start); } } @@ -233,6 +230,7 @@ namespace ComSquare::PPU case 0b11: return (vanillaAddress & 0xFC00U) | (vanillaAddress & 0x0380U) >> 7U | (vanillaAddress & 0x7FU) << 3U; } + throw InvalidAddress("Invalid vram address", vanillaAddress); } void PPU::update(unsigned cycles) @@ -242,23 +240,23 @@ namespace ComSquare::PPU uint8_t red; uint8_t green; uint8_t blue; - uint32_t pixelTmp = 0x0; + uint32_t pixelTmp; if (!this->_registers._inidisp.fblank) { - for (int y = 0; y <= 255; y += 2) { - tmp = this->cgram->read_internal(y); - tmp += this->cgram->read_internal(y + 1) << 8; - blue = (tmp & 0x7D00U) >> 10U; - green = (tmp & 0x03E0U) >> 5U; - red = (tmp & 0x001FU); + for (int y = 0; y <= 255; y += 2) { + tmp = this->cgram->read(y); + tmp += this->cgram->read(y + 1) << 8; + blue = (tmp & 0x7D00U) >> 10U; + green = (tmp & 0x03E0U) >> 5U; + red = (tmp & 0x001FU); - pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; - pixelTmp += (red * 255U / 31U) << 24U; - pixelTmp += (green * 255U / 31U) << 16U; - pixelTmp += (blue * 255U / 31U) << 8U; + pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; + pixelTmp += (red * 255U / 31U) << 24U; + pixelTmp += (green * 255U / 31U) << 16U; + pixelTmp += (blue * 255U / 31U) << 8U; - for (int x = 0; x < 100; x++) - this->_renderer.putPixel(x, y, pixelTmp); - } + for (int x = 0; x < 100; x++) + this->_renderer.putPixel(x, y, pixelTmp); + } } this->renderBackground(1, {8, 8}, 4, false); this->_renderer.drawScreen(); @@ -417,6 +415,6 @@ namespace ComSquare::PPU uint16_t PPU::cgramRead(uint16_t addr) { - return this->cgram->read_internal(addr); + return this->cgram->read(addr); } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 38aceaf..c8cdf30 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -5,11 +5,10 @@ #ifndef COMSQUARE_PPU_HPP #define COMSQUARE_PPU_HPP -#include +#include #include "../Memory/AMemory.hpp" #include "../Memory/MemoryBus.hpp" #include "../Renderer/IRenderer.hpp" -//#include "../Ram/ExtendedRam.hpp" #include "../Ram/Ram.hpp" #include "../Models/Vector2.hpp" diff --git a/sources/Ram/Ram.cpp b/sources/Ram/Ram.cpp index 100901d..da6ab26 100644 --- a/sources/Ram/Ram.cpp +++ b/sources/Ram/Ram.cpp @@ -27,29 +27,20 @@ namespace ComSquare::Ram delete[] this->_data; } - uint8_t Ram::read_internal(uint24_t addr) + uint8_t Ram::read(uint24_t addr) { if (addr >= this->_size) - throw InvalidAddress("Ram read", addr); + throw InvalidAddress(this->getName() + " read", addr); return this->_data[addr]; } - void Ram::write_internal(uint24_t addr, uint8_t data) + void Ram::write(uint24_t addr, uint8_t data) { if (addr >= this->_size) - throw InvalidAddress("Ram write", addr); + throw InvalidAddress(this->getName() + " write", addr); this->_data[addr] = data; } - void Ram::memset(uint24_t start, uint24_t end, uint8_t value) - { - if (end >= this->_size) - throw InvalidAddress("Ram memset end", end); - if (start >= end) - throw InvalidAddress("Ram memset start", start); - std::memset(&this->_data[start], value, sizeof(uint8_t) * (end - start)); - } - size_t Ram::getSize() { return this->_size; diff --git a/sources/Ram/Ram.hpp b/sources/Ram/Ram.hpp index 2a68e36..4fe2a41 100644 --- a/sources/Ram/Ram.hpp +++ b/sources/Ram/Ram.hpp @@ -29,22 +29,18 @@ namespace ComSquare::Ram Ram &operator=(Ram &) = delete; //! @brief Destructor that free the ram. ~Ram() override; - //! @brief Read from the ram. - //! @param addr The address to read from. The address 0x0 should refer to the first byte of this ram. - //! @throw InvalidAddress will be thrown if the address is more than the size of the ram. - //! @return Return the data at the address. - uint8_t read_internal(uint24_t addr) override; - //! @brief Write data to the ram. - //! @param addr The address to write to. The address 0x0 should refer to the first byte of this ram. - //! @param data The data to write. - //! @throw InvalidAddress will be thrown if the address is more than the size of the ram. - void write_internal(uint24_t addr, uint8_t data) override; - //! @brief replace values between two addresses with a value - //! @param start start address to replace - //! @param end end address to replace - //! @param value replace value - void memset(uint24_t start, uint24_t end, uint8_t value); + //! @brief Read data from the component. + //! @param addr The local address to read from (0x0 should refer to the first byte of this component). + //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. + //! @return Return the data at the address given as parameter. + uint8_t read(uint24_t addr) override; + //! @brief Write data to this component. + //! @param addr The local address to write data (0x0 should refer to the first byte of this component). + //! @param data The new data to write. + //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. + void write(uint24_t addr, uint8_t data) override; + //! @brief Get the name of this accessor (used for debug purpose) std::string getName() override; diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index 25b87d3..d35b02f 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -7,7 +7,8 @@ #include "../tests.hpp" using namespace ComSquare; -Test(DMA, RomToVRAM) +//Test(DMA, RomToVRAM) +int main() { Init() snes.cartridge->_size = 4000000; diff --git a/tests/testMemoryBus.cpp b/tests/testMemoryBus.cpp index d41788a..cb8c9dc 100644 --- a/tests/testMemoryBus.cpp +++ b/tests/testMemoryBus.cpp @@ -6,13 +6,8 @@ #include #include #include "tests.hpp" -#include "../sources/Memory/MemoryBus.hpp" -#include "../sources/Memory/AMemory.hpp" -#include "../sources/SNES.hpp" -#include "../sources/Renderer/NoRenderer.hpp" #include "../sources/Memory/MemoryShadow.hpp" #include "../sources/Memory/RectangleShadow.hpp" -#include "../sources/PPU/PPU.hpp" #include "../sources/Exceptions/InvalidAction.hpp" @@ -27,7 +22,7 @@ using namespace ComSquare; Test(BusAccessor, GetWramStart) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x7E0000); cr_assert_eq(accessor.get(), snes.wram.get()); @@ -36,7 +31,7 @@ Test(BusAccessor, GetWramStart) Test(BusAccessor, GetWramEnd) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x7FFFFF); cr_assert_eq(accessor.get(), snes.wram.get()); @@ -45,7 +40,7 @@ Test(BusAccessor, GetWramEnd) Test(BusAccessor, GetWramMirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x2F11FF)); cr_assert_neq(accessor, nullptr); @@ -55,7 +50,7 @@ Test(BusAccessor, GetWramMirror) Test(BusAccessor, GetWramMirror2) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x100000)); cr_assert_neq(accessor, nullptr); @@ -65,7 +60,7 @@ Test(BusAccessor, GetWramMirror2) Test(BusAccessor, GetWramMirror3) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x1010)); cr_assert_neq(accessor, nullptr); @@ -75,14 +70,14 @@ Test(BusAccessor, GetWramMirror3) Test(BusAccessor, GetOpenBus) { Init() - std::shared_ptr accessor = snes.bus->getAccessor(0x897654); + std::shared_ptr accessor = snes.bus->getAccessor(0x897654); cr_assert_eq(accessor.get(), nullptr); } Test(BusAccessor, GetSramStart) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x700000)); cr_assert_eq(accessor->_initial.get(), snes.sram.get()); @@ -91,7 +86,7 @@ Test(BusAccessor, GetSramStart) Test(BusAccessor, GetSramEnd) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x7D7FFF)); cr_assert_eq(accessor->_initial.get(), snes.sram.get()); @@ -100,7 +95,7 @@ Test(BusAccessor, GetSramEnd) Test(BusAccessor, GetSramMirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0xF00123)); cr_assert_eq(accessor.get(), snes.sram.get()); @@ -109,7 +104,7 @@ Test(BusAccessor, GetSramMirror) Test(BusAccessor, GetAPUStart) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x002140); cr_assert_eq(accessor.get(), snes.apu.get()); @@ -118,7 +113,7 @@ Test(BusAccessor, GetAPUStart) Test(BusAccessor, GetAPUEnd) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x002143); cr_assert_eq(accessor.get(), snes.apu.get()); @@ -127,7 +122,7 @@ Test(BusAccessor, GetAPUEnd) Test(BusAccessor, GetAPUMirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0xAB2143)); cr_assert_eq(accessor->_initial.get(), snes.apu.get()); @@ -136,7 +131,7 @@ Test(BusAccessor, GetAPUMirror) Test(BusAccessor, GetAPUMirrorFirstHalf) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x052143)); cr_assert_eq(accessor->_initial.get(), snes.apu.get()); @@ -145,7 +140,7 @@ Test(BusAccessor, GetAPUMirrorFirstHalf) Test(BusAccessor, GetCPUStart) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x004200); cr_assert_eq(accessor.get(), snes.cpu.get()); @@ -154,7 +149,7 @@ Test(BusAccessor, GetCPUStart) Test(BusAccessor, GetCPUEnd) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x00421F); cr_assert_eq(accessor.get(), snes.cpu.get()); @@ -163,7 +158,7 @@ Test(BusAccessor, GetCPUEnd) Test(BusAccessor, GetPPU1Start) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x00213E); cr_assert_eq(accessor.get(), snes.ppu.get()); @@ -172,7 +167,7 @@ Test(BusAccessor, GetPPU1Start) Test(BusAccessor, GetPPU1End) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x00213F); cr_assert_eq(accessor.get(), snes.ppu.get()); @@ -181,7 +176,7 @@ Test(BusAccessor, GetPPU1End) Test(BusAccessor, GetCPU) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x004212); cr_assert_eq(accessor.get(), snes.cpu.get()); @@ -190,7 +185,7 @@ Test(BusAccessor, GetCPU) Test(BusAccessor, GetPPU1Mirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x80213F)); cr_assert_eq(accessor->_initial.get(), snes.ppu.get()); @@ -199,7 +194,7 @@ Test(BusAccessor, GetPPU1Mirror) Test(BusAccessor, GetCPU2Mirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x804212)); cr_assert_eq(accessor->_initial.get(), snes.cpu.get()); @@ -208,7 +203,7 @@ Test(BusAccessor, GetCPU2Mirror) Test(BusAccessor, GetRomStart) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0x808000); cr_assert_eq(accessor.get(), snes.cartridge.get()); @@ -217,7 +212,7 @@ Test(BusAccessor, GetRomStart) Test(BusAccessor, GetRomEnd) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = snes.bus->getAccessor(0xFFFFFF); cr_assert_eq(accessor.get(), snes.cartridge.get()); @@ -226,7 +221,7 @@ Test(BusAccessor, GetRomEnd) Test(BusAccessor, GetRomMirror) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x694200)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); @@ -235,7 +230,7 @@ Test(BusAccessor, GetRomMirror) Test(BusAccessor, GetRomMirror2) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x01FEDC)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); @@ -244,7 +239,7 @@ Test(BusAccessor, GetRomMirror2) Test(BusAccessor, GetRomMirror3) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0xDE1248)); cr_assert_eq(accessor->_initial.get(), snes.cartridge.get()); @@ -253,7 +248,7 @@ Test(BusAccessor, GetRomMirror3) Test(BusAccessor, Get0x0) { Init() - std::shared_ptr accessor = nullptr; + std::shared_ptr accessor; accessor = std::static_pointer_cast(snes.bus->getAccessor(0x0)); cr_assert_eq(accessor->_initial.get(), snes.wram.get()); diff --git a/tests/testRectangleMemory.cpp b/tests/testRectangleMemory.cpp index 71edf33..c0b8376 100644 --- a/tests/testRectangleMemory.cpp +++ b/tests/testRectangleMemory.cpp @@ -5,11 +5,7 @@ #include #include #include "tests.hpp" -#include "../sources/SNES.hpp" -#include "../sources/Renderer/NoRenderer.hpp" -#include "../sources/PPU/PPU.hpp" #include "../sources/Memory/RectangleShadow.hpp" -#include "../sources/Utility/Utility.hpp" using namespace ComSquare; @@ -19,8 +15,10 @@ Test(RectangleMemory, HorizontalRamRead) ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); for (int i = 0x00; i < 0xFF; i++) ram._data[i] = i; - for (uint24_t i = 0x000000; i < 0xFF0000; i += 0x010000) - cr_assert_eq(ram.read(i), i >> 16u, "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", ram.read(i), i >> 16, i); + for (uint24_t i = 0x000000; i < 0xFF0000; i += 0x010000) { + uint8_t value = ram.read(ram.getRelativeAddress(i)); + cr_assert_eq(value, i >> 16u, "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", value, i >> 16, i); + } } Test(RectangleMemory, HorizontalRamWrite) @@ -28,7 +26,7 @@ Test(RectangleMemory, HorizontalRamWrite) Ram::Ram ram(0xFF, Component::Rom, "Rom"); ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); for (uint24_t i = 0x000000; i < 0xFF0000; i += 0x010000) - ram.write(i, i >> 16u); + ram.write(ram.getRelativeAddress(i), i >> 16u); for (int i = 0x00; i < 0xFF; i++) cr_assert_eq(ram._data[i], i, "The ram's write put 0x%x but it should had put: 0x%x (addr: 0x%06x)", ram._data[i], i, i << 16u); } @@ -40,8 +38,10 @@ Test(RectangleMemory, DualLineRamRead) for (int i = 0x00; i < 0xFF * 2; i++) ram._data[i] = i; for (uint24_t i = 0x000000, v = 0; v < 0xFF * 2; i += 0x010000, v += 2) { - cr_assert_eq(ram.read(i), (uint8_t)(v), "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", ram.read(i), (uint8_t)(v), i); - cr_assert_eq(ram.read(i + 1), (uint8_t)(v + 1), "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", ram.read(i + 1), (uint8_t)(v + 1), i + 1); + uint8_t value = ram.read(ram.getRelativeAddress(i)); + cr_assert_eq(value, (uint8_t)(v), "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", value, (uint8_t)(v), i); + value = ram.read(ram.getRelativeAddress(i + 1)); + cr_assert_eq(value, (uint8_t)(v + 1), "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", value, (uint8_t)(v + 1), i + 1); } } @@ -53,7 +53,7 @@ Test(RectangleMemory, HorizontalRamShadowRead) for (int i = 0x00; i < 0xFF; i++) ram->_data[i] = i; for (uint24_t i = 0x008000; i < 0xFF8000; i += 0x010000) { - uint8_t v = shadow.read(i - shadow.getStart()); + uint8_t v = shadow.read(shadow.getRelativeAddress(i)); cr_assert_eq(v, i >> 16u, "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", v, i >> 16, i); }} @@ -66,7 +66,7 @@ Test(RectangleMemory, HorizontalRamShadowReadWithBankOffset) ram->_data[i] = i; shadow.setBankOffset(0x80); for (uint24_t i = 0x808000; i < 0xFF8000; i += 0x010000) { - uint8_t v = shadow.read(i - shadow.getStart()); + uint8_t v = shadow.read(shadow.getRelativeAddress(i)); cr_assert_eq(v, i >> 16u, "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", v, i >> 16, i); } } @@ -82,8 +82,8 @@ Test(RectangleMemory, ShadowOffsetCartridge) for (uint24_t i = 0xC00000; i < 0xEF7FFF; i += 0x1) { if ((uint16_t)i > 0x7FFFu) i += 0x010000 - 0x8000; - uint8_t v = shadow.read(i - shadow.getStart()); - uint8_t r = ram->read(i + 0x8000 - ram->getStart()); + uint8_t v = shadow.read(shadow.getRelativeAddress(i)); + uint8_t r = ram->read(ram->getRelativeAddress(i + 0x8000)); cr_assert_eq(v, r, "The ram's read returned 0x%x but the internal ram value was: 0x%x (addr: 0x%06x)", v, r, i); } } \ No newline at end of file From 33bb057ee67f582c91001138bc4fdda02b768973 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Feb 2021 23:43:23 +0100 Subject: [PATCH 16/30] Oups --- tests/CPU/testDMA.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index d35b02f..25b87d3 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -7,8 +7,7 @@ #include "../tests.hpp" using namespace ComSquare; -//Test(DMA, RomToVRAM) -int main() +Test(DMA, RomToVRAM) { Init() snes.cartridge->_size = 4000000; From 2e4e39a69649bd58a8d493a13ff262f6deca1ded Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 09:27:04 +0100 Subject: [PATCH 17/30] Fixing the DMA test --- sources/Debugger/MemoryViewer.cpp | 2 +- tests/CPU/testDMA.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index 01b29ff..5cbd6bc 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -147,7 +147,7 @@ namespace ComSquare::Debugger if (dialogUI.checkBox->isChecked()) { try { value = this->switchToAddrTab(value); - } catch (InvalidAddress &) {} + } catch (const InvalidAddress &) {} } QModelIndex index = this->_ui.tableView->model()->index(value >> 4, value & 0x0F); this->_ui.tableView->scrollTo(index); diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index 25b87d3..ee5243f 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -13,8 +13,8 @@ Test(DMA, RomToVRAM) snes.cartridge->_size = 4000000; snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; for (unsigned i = 0; i < 0x400; i++) { - snes.cartridge->_data[0xBDED + i * 2] = i; - snes.cartridge->_data[0xBDED + i * 2 + 1] = i >> 8; + snes.cartridge->_data[0x9bded + i * 2] = i; + snes.cartridge->_data[0x9bded + i * 2 + 1] = i >> 8; } // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 From c9eed502893e9456113393f15b1df17545b19b0a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 10:22:30 +0100 Subject: [PATCH 18/30] Adding const qualifiers to the IMemory and adding error messages in the memory viewer --- sources/APU/APU.cpp | 19 +++++++++----- sources/APU/APU.hpp | 39 +++++++++++++++++------------ sources/APU/DSP/DSP.cpp | 11 +++++--- sources/APU/DSP/DSP.hpp | 10 +++++--- sources/APU/IPL/IPL.cpp | 11 +++++--- sources/APU/IPL/IPL.hpp | 10 +++++--- sources/CPU/CPU.cpp | 13 +++++++--- sources/CPU/CPU.hpp | 12 ++++++--- sources/CPU/DMA/DMA.cpp | 2 +- sources/CPU/DMA/DMA.hpp | 2 +- sources/Cartridge/Cartridge.cpp | 2 +- sources/Cartridge/Cartridge.hpp | 2 +- sources/Debugger/APUDebug.cpp | 2 +- sources/Debugger/APUDebug.hpp | 2 +- sources/Debugger/CPU/CPUDebug.cpp | 7 ++++-- sources/Debugger/CPU/CPUDebug.hpp | 2 +- sources/Debugger/MemoryViewer.cpp | 18 +++++++++++-- sources/Memory/AMemory.cpp | 10 ++++---- sources/Memory/AMemory.hpp | 10 ++++---- sources/Memory/ARectangleMemory.cpp | 11 ++++---- sources/Memory/ARectangleMemory.hpp | 10 ++++---- sources/Memory/IMemory.hpp | 19 ++++++++------ sources/Memory/MemoryShadow.cpp | 15 +++++++---- sources/Memory/MemoryShadow.hpp | 13 ++++++---- sources/Memory/RectangleShadow.cpp | 17 ++++++++----- sources/Memory/RectangleShadow.hpp | 15 ++++++----- sources/PPU/PPU.cpp | 15 +++++++---- sources/PPU/PPU.hpp | 13 ++++++---- sources/Ram/Ram.cpp | 9 ++++--- sources/Ram/Ram.hpp | 10 ++++---- 30 files changed, 208 insertions(+), 123 deletions(-) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index effc58d..ee93fba 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -17,22 +17,23 @@ namespace ComSquare::APU this->reset(); } - bool APU::isDebugger() + bool APU::isDebugger() const { return false; } - std::string APU::getName() + std::string APU::getName() const { return "APU"; } - Component APU::getComponent() + Component APU::getComponent() const { return Apu; } - uint8_t APU::_internalRead(uint24_t addr) { + uint8_t APU::_internalRead(uint24_t addr) const + { switch (addr) { case 0x0000 ... 0x00EF: return this->_map->Page0.read(addr); @@ -71,7 +72,8 @@ namespace ComSquare::APU } } - void APU::_internalWrite(uint24_t addr, uint8_t data) { + void APU::_internalWrite(uint24_t addr, uint8_t data) + { switch (addr) { case 0x0000 ... 0x00EF: this->_map->Page0.write(addr, data); @@ -129,7 +131,7 @@ namespace ComSquare::APU } } - uint8_t APU::read(uint24_t addr) + uint8_t APU::read(uint24_t addr) const { switch (addr) { case 0x00: @@ -165,6 +167,11 @@ namespace ComSquare::APU } } + uint24_t APU::getSize() const + { + return 0x3; + } + void APU::reset() { this->_registers.port0 = 0x00; diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index 6503207..1725859 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -149,19 +149,14 @@ namespace ComSquare::APU //! @param addr The address to read from. The address 0x0000 should refer to the first byte of the register. //! @throw InvalidAddress will be thrown if the address is more than $FFFF (the number of register). //! @return Return the data. - uint8_t _internalRead(uint24_t addr); + uint8_t _internalRead(uint24_t addr) const; + //! @brief Write data to the APU ram. //! @param addr The address to write to. The address 0x0000 should refer to the first byte of register. //! @param data The new value of the register. //! @throw InvalidAddress will be thrown if the address is more than $FFFF (the number of register). void _internalWrite(uint24_t addr, uint8_t data); - //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; - - //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; - //! @brief Current state of APU CPU StateMode _state = Running; @@ -372,16 +367,28 @@ namespace ComSquare::APU APU &operator=(const APU &) = default; ~APU() override = default; - //! @brief Read from the internal APU register. - //! @param addr The address to read from. The address 0x00 should refer to the first byte of the register. - //! @throw InvalidAddress will be thrown if the address is more than $0F (the number of register). - //! @return Return the value of the register. - uint8_t read(uint24_t addr) override; - //! @brief Write data to the internal APU register. - //! @param addr The address to write to. The address 0x00 should refer to the first byte of register. + //! @brief Read from the APU ram. + //! @param addr The address to read from. The address 0x0000 should refer to the first byte of the register. + //! @throw InvalidAddress will be thrown if the address is more than $FFFF (the number of register). + //! @return Return the data. + uint8_t read(uint24_t addr) const override; + + //! @brief Write data to the APU ram. + //! @param addr The address to write to. The address 0x0000 should refer to the first byte of register. //! @param data The new value of the register. - //! @throw InvalidAddress will be thrown if the address is more than $0F (the number of register). + //! @throw InvalidAddress will be thrown if the address is more than $FFFF (the number of register). void write(uint24_t addr, uint8_t data) override; + + //! @brief Get the name of this accessor (used for debug purpose) + std::string getName() const override; + + //! @brief Get the component of this accessor (used for debug purpose) + Component getComponent() const override; + + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + uint24_t getSize() const override; + //! @brief This function execute the instructions received until the maximum number of cycles is reached. //! @return The number of cycles that elapsed. virtual void update(unsigned cycles); @@ -390,7 +397,7 @@ namespace ComSquare::APU void reset(); //! @brief Return true if the CPU is overloaded with debugging features. - virtual bool isDebugger(); + virtual bool isDebugger() const; }; } diff --git a/sources/APU/DSP/DSP.cpp b/sources/APU/DSP/DSP.cpp index 421826e..59dfad5 100644 --- a/sources/APU/DSP/DSP.cpp +++ b/sources/APU/DSP/DSP.cpp @@ -7,7 +7,7 @@ namespace ComSquare::APU::DSP { - uint8_t DSP::read(uint24_t addr) + uint8_t DSP::read(uint24_t addr) const { switch (addr) { case 0x00: @@ -579,6 +579,11 @@ namespace ComSquare::APU::DSP } } + uint24_t DSP::getSize() const + { + return 0x7F; + } + Registers DSP::getRegisters() { return this->_registers; @@ -589,12 +594,12 @@ namespace ComSquare::APU::DSP return this->_channels; } - std::string DSP::getName() + std::string DSP::getName() const { return "DSP"; } - Component DSP::getComponent() + Component DSP::getComponent() const { return Apu; } diff --git a/sources/APU/DSP/DSP.hpp b/sources/APU/DSP/DSP.hpp index 1676cd5..04d6265 100644 --- a/sources/APU/DSP/DSP.hpp +++ b/sources/APU/DSP/DSP.hpp @@ -134,7 +134,7 @@ namespace ComSquare::APU::DSP //! @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 $7F (the number of register). //! @return Return the value of the register. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to the internal DSP register. //! @param addr The address to write to. The address 0x0 should refer to the first byte of register. //! @param data The new value of the register. @@ -142,10 +142,14 @@ namespace ComSquare::APU::DSP void write(uint24_t addr, uint8_t data) override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; + + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + uint24_t getSize() const override; }; } diff --git a/sources/APU/IPL/IPL.cpp b/sources/APU/IPL/IPL.cpp index 4bbf989..0b90e6a 100644 --- a/sources/APU/IPL/IPL.cpp +++ b/sources/APU/IPL/IPL.cpp @@ -17,7 +17,7 @@ namespace ComSquare::APU::IPL IPL::~IPL() { } - uint8_t IPL::read(uint24_t addr) + uint8_t IPL::read(uint24_t addr) const { if (addr >= this->_size) throw InvalidAddress("IPL read", addr); @@ -31,12 +31,17 @@ namespace ComSquare::APU::IPL this->_data[addr] = data; } - std::string IPL::getName() + uint24_t IPL::getSize() const + { + return this->_size; + } + + std::string IPL::getName() const { return this->_iplName; } - Component IPL::getComponent() + Component IPL::getComponent() const { return this->_iplType; } diff --git a/sources/APU/IPL/IPL.hpp b/sources/APU/IPL/IPL.hpp index 54ba95d..0c0c5a3 100644 --- a/sources/APU/IPL/IPL.hpp +++ b/sources/APU/IPL/IPL.hpp @@ -45,7 +45,7 @@ namespace ComSquare::APU::IPL //! @param addr The global 24 bits address. This method is responsible of mapping to the component's read. //! @throw InvalidAddress if the address is not mapped to the component. //! @return Return the data at the address given as parameter. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to this component using the same method as the basic IMemory. //! @param addr The global 24 bits address. This method is responsible of mapping to the component's write. @@ -53,11 +53,15 @@ namespace ComSquare::APU::IPL //! @throw InvalidAddress if the address is not mapped to the component. void write(uint24_t addr, uint8_t data) override; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + uint24_t getSize() const override; + //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; }; } diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 107a6a9..6ccfc60 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -20,7 +20,7 @@ namespace ComSquare::CPU channel.setBus(_bus); } - bool CPU::isDebugger() + bool CPU::isDebugger() const { return false; } @@ -31,7 +31,7 @@ namespace ComSquare::CPU } //! @bref The CPU's internal registers starts at $4200 and finish at $421F. - uint8_t CPU::read(uint24_t addr) + uint8_t CPU::read(uint24_t addr) const { uint8_t tmp = 0; @@ -207,6 +207,11 @@ namespace ComSquare::CPU } } + uint24_t CPU::getSize() const + { + return 0x180; + } + uint8_t CPU::readPC() { uint8_t ret = this->_bus->read(this->_registers.pac); @@ -349,12 +354,12 @@ namespace ComSquare::CPU return value; } - std::string CPU::getName() + std::string CPU::getName() const { return "CPU"; } - Component CPU::getComponent() + Component CPU::getComponent() const { return Cpu; } diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 9db4b3f..7872bbf 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -741,18 +741,22 @@ namespace ComSquare::CPU //! @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). //! @return Return the value of the register. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to the internal CPU register. //! @param addr The address to write to. The address 0x0 should refer to the first byte of register. //! @param data The new value of the register. //! @throw InvalidAddress will be thrown if the address is more than $1F (the number of register). void write(uint24_t addr, uint8_t data) override; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + uint24_t getSize() const override; + //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; //! @brief Reset interrupt - Called on boot and when the reset button is pressed. virtual int RESB(); @@ -765,7 +769,7 @@ namespace ComSquare::CPU bool IsAbortRequested = false; //! @brief Return true if the CPU is overloaded with debugging features. - virtual bool isDebugger(); + virtual bool isDebugger() const; //! @brief Change the memory bus used by the CPU. virtual void setMemoryBus(std::shared_ptr bus); diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index 306ed9b..9c049ca 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -15,7 +15,7 @@ namespace ComSquare::CPU this->_bus = std::move(bus); } - uint8_t DMA::read(uint8_t addr) + uint8_t DMA::read(uint8_t addr) const { switch (addr) { case 0x0: diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index de6d232..eef46dc 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -94,7 +94,7 @@ namespace ComSquare::CPU void setBus(std::shared_ptr bus); //! @brief Bus helper to read from this channel. - uint8_t read(uint8_t addr); + uint8_t read(uint8_t addr) const; //! @brief Bus helper to write to this channel. void write(uint8_t addr, uint8_t data); diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 8156c54..ead9363 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -38,7 +38,7 @@ namespace ComSquare::Cartridge } - uint8_t Cartridge::read(uint24_t addr) + uint8_t Cartridge::read(uint24_t addr) const { return Ram::read(addr + this->_romStart); } diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index 4b4ea0a..90562e8 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -98,7 +98,7 @@ namespace ComSquare::Cartridge //! @param addr The address to read from. The address 0x0 should refer to the first byte of the rom's memory. //! @throw InvalidAddress will be thrown if the address is more than the size of the rom's memory. //! @return Return the data at the address. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to the rom. //! @param addr The address to write to. The address 0x0 should refer to the first byte of the rom's memory. //! @param data The data to write. diff --git a/sources/Debugger/APUDebug.cpp b/sources/Debugger/APUDebug.cpp index 6e11913..62e2519 100644 --- a/sources/Debugger/APUDebug.cpp +++ b/sources/Debugger/APUDebug.cpp @@ -522,7 +522,7 @@ namespace ComSquare::Debugger this->_snes.disableAPUDebugging(); } - bool APUDebug::isDebugger() + bool APUDebug::isDebugger() const { return true; } diff --git a/sources/Debugger/APUDebug.hpp b/sources/Debugger/APUDebug.hpp index db7628f..f907208 100644 --- a/sources/Debugger/APUDebug.hpp +++ b/sources/Debugger/APUDebug.hpp @@ -57,7 +57,7 @@ namespace ComSquare::Debugger //! @brief Return true if the CPU is overloaded with debugging features. - bool isDebugger() override; + bool isDebugger() const override; //! @brief Focus the debugger's window. void focus(); diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index c38be29..fda754d 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace ComSquare::CPU; @@ -58,7 +59,7 @@ namespace ComSquare::Debugger this->_updateDisassembly(this->_registers.pac, 0); } - bool CPUDebug::isDebugger() + bool CPUDebug::isDebugger() const { return true; } @@ -387,7 +388,9 @@ QSize RowPainter::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) co return QSize(); } -StackModel::StackModel(std::shared_ptr bus, ComSquare::Debugger::CPUDebug &cpu) : _bus(bus), _cpu(cpu) { } +StackModel::StackModel(std::shared_ptr bus, ComSquare::Debugger::CPUDebug &cpu) + : _bus(std::move(bus)), _cpu(cpu) +{ } void StackModel::setMemoryBus(std::shared_ptr bus) { diff --git a/sources/Debugger/CPU/CPUDebug.hpp b/sources/Debugger/CPU/CPUDebug.hpp index 69d3e0e..57f403b 100644 --- a/sources/Debugger/CPU/CPUDebug.hpp +++ b/sources/Debugger/CPU/CPUDebug.hpp @@ -281,7 +281,7 @@ namespace ComSquare::Debugger ~CPUDebug() override = default; //! @brief Return true if the CPU is overloaded with debugging features. - bool isDebugger() override; + bool isDebugger() const override; //! @brief Focus the debugger's window. void focus(); diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index 5cbd6bc..fa6e760 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "MemoryViewer.hpp" #include "../SNES.hpp" #include "../Memory/MemoryShadow.hpp" @@ -147,11 +148,17 @@ namespace ComSquare::Debugger if (dialogUI.checkBox->isChecked()) { try { value = this->switchToAddrTab(value); - } catch (const InvalidAddress &) {} + } catch (const InvalidAddress &) { + QMessageBox msgBox; + msgBox.setText("This address is not mapped. Reading it will result in OpenBus."); + msgBox.exec(); + return; + } } QModelIndex index = this->_ui.tableView->model()->index(value >> 4, value & 0x0F); this->_ui.tableView->scrollTo(index); this->_ui.tableView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); + this->_ui.tableView->setCurrentIndex(index); } unsigned MemoryViewer::switchToAddrTab(uint24_t addr) @@ -173,7 +180,14 @@ namespace ComSquare::Debugger default: throw InvalidAddress("Memory viewer switch to address", addr); } - return accessor->getRelativeAddress(addr); + addr = accessor->getRelativeAddress(addr); + if (addr > accessor->getSize()) { + QMessageBox msgBox; + msgBox.setText((std::string("The ") + accessor->getName() + " is too small to contain this address.").c_str()); + msgBox.exec(); + return 0; + } + return addr; } void MemoryViewer::focus() diff --git a/sources/Memory/AMemory.cpp b/sources/Memory/AMemory.cpp index 3132424..70ea7b5 100644 --- a/sources/Memory/AMemory.cpp +++ b/sources/Memory/AMemory.cpp @@ -6,7 +6,7 @@ namespace ComSquare::Memory { - uint24_t AMemory::getRelativeAddress(uint24_t addr) + uint24_t AMemory::getRelativeAddress(uint24_t addr) const { return addr - this->_start; } @@ -17,22 +17,22 @@ namespace ComSquare::Memory this->_end = end; } - bool AMemory::hasMemoryAt(uint24_t addr) + bool AMemory::hasMemoryAt(uint24_t addr) const { return this->_start <= addr && addr <= this->_end; } - bool AMemory::isMirror() + bool AMemory::isMirror() const { return false; } - std::shared_ptr AMemory::getMirrored() + std::shared_ptr AMemory::getMirrored() const { return nullptr; } - std::string AMemory::getValueName(uint24_t) + std::string AMemory::getValueName(uint24_t) const { return "???"; } diff --git a/sources/Memory/AMemory.hpp b/sources/Memory/AMemory.hpp index 210aa49..575226a 100644 --- a/sources/Memory/AMemory.hpp +++ b/sources/Memory/AMemory.hpp @@ -26,7 +26,7 @@ namespace ComSquare::Memory //! @param addr The absolute address (in the 24 bit bus) //! @return The local address (0 refers to the first byte of this component). //! @throw InvalidAddress is thrown if the address is not mapped by this component. - virtual uint24_t getRelativeAddress(uint24_t addr) override; + virtual uint24_t getRelativeAddress(uint24_t addr) const override; //! @brief Change starting and ending points of this mapped memory. //! @param start The first address mapped to this component. //! @param end The last address mapped to this component. @@ -35,16 +35,16 @@ namespace ComSquare::Memory //! @brief Return true if this component has mapped the address. //! @param addr The address to check. //! @return True if this address is mapped to the component. False otherwise. - virtual bool hasMemoryAt(uint24_t addr) override; + virtual bool hasMemoryAt(uint24_t addr) const override; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - virtual bool isMirror() override; + virtual bool isMirror() const override; //! @brief Get the name of the data at the address //! @param addr The address (in local space) - virtual std::string getValueName(uint24_t addr) override; + virtual std::string getValueName(uint24_t addr) const override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - virtual std::shared_ptr getMirrored() override; + virtual std::shared_ptr getMirrored() const override; virtual ~AMemory() override = default; }; } \ No newline at end of file diff --git a/sources/Memory/ARectangleMemory.cpp b/sources/Memory/ARectangleMemory.cpp index 5c6b392..e1be35b 100644 --- a/sources/Memory/ARectangleMemory.cpp +++ b/sources/Memory/ARectangleMemory.cpp @@ -5,11 +5,10 @@ #include #include "ARectangleMemory.hpp" #include "../Exceptions/InvalidAddress.hpp" -#include "../Utility/Utility.hpp" namespace ComSquare::Memory { - uint24_t ARectangleMemory::getRelativeAddress(uint24_t addr) + uint24_t ARectangleMemory::getRelativeAddress(uint24_t addr) const { uint8_t bank = addr >> 16u; uint16_t page = addr; @@ -24,7 +23,7 @@ namespace ComSquare::Memory return pageCount * bankCount + page; } - bool ARectangleMemory::hasMemoryAt(uint24_t addr) + bool ARectangleMemory::hasMemoryAt(uint24_t addr) const { uint8_t bank = addr >> 16u; uint16_t page = addr; @@ -43,17 +42,17 @@ namespace ComSquare::Memory this->_endPage = endPage; } - bool ARectangleMemory::isMirror() + bool ARectangleMemory::isMirror() const { return false; } - std::shared_ptr ARectangleMemory::getMirrored() + std::shared_ptr ARectangleMemory::getMirrored() const { return nullptr; } - std::string ARectangleMemory::getValueName(uint24_t) + std::string ARectangleMemory::getValueName(uint24_t) const { return "???"; } diff --git a/sources/Memory/ARectangleMemory.hpp b/sources/Memory/ARectangleMemory.hpp index e923bb3..347db58 100644 --- a/sources/Memory/ARectangleMemory.hpp +++ b/sources/Memory/ARectangleMemory.hpp @@ -24,11 +24,11 @@ namespace ComSquare::Memory //! @param addr The absolute address (in the 24 bit bus) //! @return The local address (0 refers to the first byte of this component). //! @throw InvalidAddress is thrown if the address is not mapped by this component. - virtual uint24_t getRelativeAddress(uint24_t addr) override; + virtual uint24_t getRelativeAddress(uint24_t addr) const override; //! @brief Return true if this component has mapped the address. //! @param addr The address to check. //! @return True if this address is mapped to the component. False otherwise. - bool hasMemoryAt(uint24_t addr) override; + bool hasMemoryAt(uint24_t addr) const override; //! @brief Change starting and ending points of this mapped memory. //! @param startBank The first bank mapped to this component. //! @param endBank The last bank mapped to this component. @@ -38,13 +38,13 @@ namespace ComSquare::Memory void setMemoryRegion(uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - virtual bool isMirror() override; + virtual bool isMirror() const override; //! @brief Get the name of the data at the address //! @param addr The address (in local space) - virtual std::string getValueName(uint24_t addr) override; + virtual std::string getValueName(uint24_t addr) const override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - virtual std::shared_ptr getMirrored() override; + virtual std::shared_ptr getMirrored() const override; virtual ~ARectangleMemory() override = default; }; } \ No newline at end of file diff --git a/sources/Memory/IMemory.hpp b/sources/Memory/IMemory.hpp index 14370af..fb36045 100644 --- a/sources/Memory/IMemory.hpp +++ b/sources/Memory/IMemory.hpp @@ -20,7 +20,7 @@ namespace ComSquare::Memory //! @param addr The local address to read from (0x0 should refer to the first byte of this component). //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. //! @return Return the data at the address given as parameter. - virtual uint8_t read(uint24_t addr) = 0; + virtual uint8_t read(uint24_t addr) const = 0; //! @brief Write data to this component. //! @param addr The local address to write data (0x0 should refer to the first byte of this component). //! @param data The new data to write. @@ -29,25 +29,28 @@ namespace ComSquare::Memory //! @brief Return true if this component has mapped the address. //! @param addr The address to check. //! @return True if this address is mapped to the component. False otherwise. - virtual bool hasMemoryAt(uint24_t addr) = 0; + virtual bool hasMemoryAt(uint24_t addr) const = 0; //! @brief Translate an absolute address to a relative address //! @param addr The absolute address (in the 24 bit bus) //! @return The local address (0 refers to the first byte of this component). //! @throw InvalidAddress is thrown if the address is not mapped by this component. - virtual uint24_t getRelativeAddress(uint24_t addr) = 0; + virtual uint24_t getRelativeAddress(uint24_t addr) const = 0; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + virtual uint24_t getSize() const = 0; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - virtual bool isMirror() = 0; + virtual bool isMirror() const = 0; //! @brief Get the name of this accessor (used for debug purpose) - virtual std::string getName() = 0; + virtual std::string getName() const = 0; //! @brief Get the component of this accessor (used for debug purpose) - virtual Component getComponent() = 0; + virtual Component getComponent() const = 0; //! @brief Get the name of the data at the address //! @param addr The address (in local space) - virtual std::string getValueName(uint24_t addr) = 0; + virtual std::string getValueName(uint24_t addr) const = 0; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - virtual std::shared_ptr getMirrored() = 0; + virtual std::shared_ptr getMirrored() const = 0; virtual ~IMemory() = default; }; }; \ No newline at end of file diff --git a/sources/Memory/MemoryShadow.cpp b/sources/Memory/MemoryShadow.cpp index 4912fc5..40434db 100644 --- a/sources/Memory/MemoryShadow.cpp +++ b/sources/Memory/MemoryShadow.cpp @@ -14,7 +14,7 @@ namespace ComSquare::Memory this->setMemoryRegion(start, end); } - uint8_t MemoryShadow::read(uint24_t addr) + uint8_t MemoryShadow::read(uint24_t addr) const { return this->_initial->read(addr); } @@ -24,22 +24,27 @@ namespace ComSquare::Memory return this->_initial->write(addr, data); } - bool MemoryShadow::isMirror() + uint24_t MemoryShadow::getSize() const + { + return this->_initial->getSize(); + } + + bool MemoryShadow::isMirror() const { return true; } - std::shared_ptr MemoryShadow::getMirrored() + std::shared_ptr MemoryShadow::getMirrored() const { return this->_initial; } - std::string MemoryShadow::getName() + std::string MemoryShadow::getName() const { return this->_initial->getName(); } - Component MemoryShadow::getComponent() + Component MemoryShadow::getComponent() const { return this->_initial->getComponent(); } diff --git a/sources/Memory/MemoryShadow.hpp b/sources/Memory/MemoryShadow.hpp index 519a4c6..8b2c037 100644 --- a/sources/Memory/MemoryShadow.hpp +++ b/sources/Memory/MemoryShadow.hpp @@ -24,21 +24,24 @@ namespace ComSquare::Memory //! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial AMemory. //! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory. //! @return Return the data at the address. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to the ram. //! @param addr The address to write to. The address 0x0 should refer to the first byte of the initial AMemory. //! @param data The data to write. //! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory. void write(uint24_t addr, uint8_t data) override; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + virtual uint24_t getSize() const override; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - bool isMirror() override; + bool isMirror() const override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - std::shared_ptr getMirrored() override; + std::shared_ptr getMirrored() const override; }; } \ No newline at end of file diff --git a/sources/Memory/RectangleShadow.cpp b/sources/Memory/RectangleShadow.cpp index 182a4fc..8a7ad5e 100644 --- a/sources/Memory/RectangleShadow.cpp +++ b/sources/Memory/RectangleShadow.cpp @@ -18,13 +18,13 @@ namespace ComSquare::Memory this->setMemoryRegion(startBank, endBank, startPage, endPage); } - uint24_t RectangleShadow::getRelativeAddress(uint24_t addr) + uint24_t RectangleShadow::getRelativeAddress(uint24_t addr) const { uint24_t base = ARectangleMemory::getRelativeAddress(addr); return base + this->_bankOffset * (this->_endPage - this->_startPage); } - uint8_t RectangleShadow::read(uint24_t addr) + uint8_t RectangleShadow::read(uint24_t addr) const { return this->_initial->read(addr); } @@ -40,22 +40,27 @@ namespace ComSquare::Memory return this; } - bool RectangleShadow::isMirror() + uint24_t RectangleShadow::getSize() const + { + return this->_initial->getSize(); + } + + bool RectangleShadow::isMirror() const { return true; } - std::shared_ptr RectangleShadow::getMirrored() + std::shared_ptr RectangleShadow::getMirrored() const { return this->_initial; } - std::string RectangleShadow::getName() + std::string RectangleShadow::getName() const { return this->_initial->getName(); } - Component RectangleShadow::getComponent() + Component RectangleShadow::getComponent() const { return this->_initial->getComponent(); } diff --git a/sources/Memory/RectangleShadow.hpp b/sources/Memory/RectangleShadow.hpp index 2c6cb24..2365550 100644 --- a/sources/Memory/RectangleShadow.hpp +++ b/sources/Memory/RectangleShadow.hpp @@ -27,7 +27,7 @@ namespace ComSquare::Memory //! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial AMemory. //! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory. //! @return Return the data at the address. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to the ram. //! @param addr The address to write to. The address 0x0 should refer to the first byte of the initial AMemory. //! @param data The data to write. @@ -37,17 +37,20 @@ namespace ComSquare::Memory //! @param addr The absolute address (in the 24 bit bus) //! @return The local address (0 refers to the first byte of this component). //! @throw InvalidAddress is thrown if the address is not mapped by this component. - uint24_t getRelativeAddress(uint24_t addr) override; + uint24_t getRelativeAddress(uint24_t addr) const override; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + virtual uint24_t getSize() const override; //! @brief Check if this memory is a mirror or not. //! @return True if this memory is a mirror. False otherwise. - bool isMirror() override; + bool isMirror() const override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; //! @brief Return the memory accessor this accessor mirror if any //! @return nullptr if isMirror is false, the source otherwise. - std::shared_ptr getMirrored() override; + std::shared_ptr getMirrored() const override; RectangleShadow *setBankOffset(uint8_t bankOffset); }; diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index f931a8e..8844a24 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -22,7 +22,7 @@ namespace ComSquare::PPU } } - uint8_t PPU::read(uint24_t addr) + uint8_t PPU::read(uint24_t addr) const { switch (addr) { case ppuRegisters::mpyl: @@ -216,6 +216,11 @@ namespace ComSquare::PPU } } + uint24_t PPU::getSize() const + { + return 0x3F; + } + uint16_t PPU::getVramAddress() { uint16_t vanillaAddress = this->_registers._vmadd.vmadd * 2; @@ -262,12 +267,12 @@ namespace ComSquare::PPU this->_renderer.drawScreen(); } - std::string PPU::getName() + std::string PPU::getName() const { return "PPU"; } - std::string PPU::getValueName(uint24_t addr) + std::string PPU::getValueName(uint24_t addr) const { switch (addr) { case ppuRegisters::inidisp: @@ -403,12 +408,12 @@ namespace ComSquare::PPU } } - Component PPU::getComponent() + Component PPU::getComponent() const { return Ppu; } - bool PPU::isDebugger() + bool PPU::isDebugger() const { return false; } diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index c8cdf30..6436f74 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -562,16 +562,19 @@ namespace ComSquare::PPU //! @param addr The local address to read from (0x0 should refer to the first byte of this component). //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. //! @return Return the data at the address given as parameter. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to this component. //! @param addr The local address to write data (0x0 should refer to the first byte of this component). //! @param data The new data to write. //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. void write(uint24_t addr, uint8_t data) override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; + //! @brief Get the size of the data. This size can be lower than the mapped data. + //! @return The number of bytes inside this memory. + uint24_t getSize() const override; //! @brief Update the PPU of n cycles. //! @param The number of cycles to update. @@ -579,9 +582,9 @@ namespace ComSquare::PPU //! @brief Give the Vram Address with the right Address remapping uint16_t getVramAddress(); //! @brief Give the name of the Address register (used for debug) - std::string getValueName(uint24_t addr); + std::string getValueName(uint24_t addr) const; //! @brief Return true if the CPU is overloaded with debugging features. - virtual bool isDebugger(); + virtual bool isDebugger() const; //! @brief Allow others components to read the CGRAM (Debuggers) uint16_t cgramRead(uint16_t addr); //! @brief Render a background on the screen diff --git a/sources/Ram/Ram.cpp b/sources/Ram/Ram.cpp index da6ab26..de8dc98 100644 --- a/sources/Ram/Ram.cpp +++ b/sources/Ram/Ram.cpp @@ -27,8 +27,9 @@ namespace ComSquare::Ram delete[] this->_data; } - uint8_t Ram::read(uint24_t addr) + uint8_t Ram::read(uint24_t addr) const { + // TODO read/write after the size of the rom should noop or behave like a mirror. I don't really know. if (addr >= this->_size) throw InvalidAddress(this->getName() + " read", addr); return this->_data[addr]; @@ -41,17 +42,17 @@ namespace ComSquare::Ram this->_data[addr] = data; } - size_t Ram::getSize() + uint24_t Ram::getSize() const { return this->_size; } - std::string Ram::getName() + std::string Ram::getName() const { return this->_ramName; } - Component Ram::getComponent() + Component Ram::getComponent() const { return this->_ramType; } diff --git a/sources/Ram/Ram.hpp b/sources/Ram/Ram.hpp index 4fe2a41..d3e4916 100644 --- a/sources/Ram/Ram.hpp +++ b/sources/Ram/Ram.hpp @@ -15,7 +15,7 @@ namespace ComSquare::Ram //! @brief The ram. (Can be used for WRam, SRam, VRam etc) uint8_t *_data; //! @brief The size of the ram (in bytes). - size_t _size; + uint24_t _size; //! @brief An id identifying the type of memory this is (for the debugger) Component _ramType; //! @brief The name of this ram. @@ -34,7 +34,7 @@ namespace ComSquare::Ram //! @param addr The local address to read from (0x0 should refer to the first byte of this component). //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. //! @return Return the data at the address given as parameter. - uint8_t read(uint24_t addr) override; + uint8_t read(uint24_t addr) const override; //! @brief Write data to this component. //! @param addr The local address to write data (0x0 should refer to the first byte of this component). //! @param data The new data to write. @@ -43,13 +43,13 @@ namespace ComSquare::Ram //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() override; + std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() override; + Component getComponent() const override; //! @brief Get the size of the ram in bytes. - size_t getSize(); + uint24_t getSize() const override; }; } From 2e1ede5016987ec04e558e20cb72b8f45d70686b Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 10:24:45 +0100 Subject: [PATCH 19/30] Adding error icons in the memory viewer's messages --- sources/Debugger/MemoryViewer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index fa6e760..4273c47 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -150,6 +150,7 @@ namespace ComSquare::Debugger value = this->switchToAddrTab(value); } catch (const InvalidAddress &) { QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); msgBox.setText("This address is not mapped. Reading it will result in OpenBus."); msgBox.exec(); return; @@ -183,6 +184,7 @@ namespace ComSquare::Debugger addr = accessor->getRelativeAddress(addr); if (addr > accessor->getSize()) { QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); msgBox.setText((std::string("The ") + accessor->getName() + " is too small to contain this address.").c_str()); msgBox.exec(); return 0; From 04f9b9a8fcc0294155646da241d05e9361207bcc Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 11:13:04 +0100 Subject: [PATCH 20/30] Fixing rectangle memory endPage inclusivness --- sources/Memory/ARectangleMemory.cpp | 2 +- sources/Memory/RectangleShadow.cpp | 4 ++-- sources/Memory/RectangleShadow.hpp | 5 +++-- tests/CPU/testDMA.cpp | 4 ++-- tests/testRectangleMemory.cpp | 16 ++++++++-------- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/sources/Memory/ARectangleMemory.cpp b/sources/Memory/ARectangleMemory.cpp index e1be35b..4252f74 100644 --- a/sources/Memory/ARectangleMemory.cpp +++ b/sources/Memory/ARectangleMemory.cpp @@ -13,7 +13,7 @@ namespace ComSquare::Memory uint8_t bank = addr >> 16u; uint16_t page = addr; unsigned bankCount = bank - this->_startBank; - unsigned pageCount = this->_endPage - this->_startPage; + unsigned pageCount = this->_endPage + 1 - this->_startPage; if (bank < this->_startBank || bank > this->_endBank) throw InvalidAddress("Rectangle memory: Invalid Bank", addr); diff --git a/sources/Memory/RectangleShadow.cpp b/sources/Memory/RectangleShadow.cpp index 8a7ad5e..325645d 100644 --- a/sources/Memory/RectangleShadow.cpp +++ b/sources/Memory/RectangleShadow.cpp @@ -21,7 +21,7 @@ namespace ComSquare::Memory uint24_t RectangleShadow::getRelativeAddress(uint24_t addr) const { uint24_t base = ARectangleMemory::getRelativeAddress(addr); - return base + this->_bankOffset * (this->_endPage - this->_startPage); + return base + this->_bankOffset * (1 + this->_endPage - this->_startPage); } uint8_t RectangleShadow::read(uint24_t addr) const @@ -34,7 +34,7 @@ namespace ComSquare::Memory return this->_initial->write(addr, data); } - RectangleShadow *RectangleShadow::setBankOffset(uint8_t bankOffset) + RectangleShadow *RectangleShadow::setBankOffset(int bankOffset) { this->_bankOffset = bankOffset; return this; diff --git a/sources/Memory/RectangleShadow.hpp b/sources/Memory/RectangleShadow.hpp index 2365550..8873f97 100644 --- a/sources/Memory/RectangleShadow.hpp +++ b/sources/Memory/RectangleShadow.hpp @@ -15,7 +15,7 @@ namespace ComSquare::Memory //! @brief Memory to shadow from. std::shared_ptr _initial; //! @brief The number of banks to add to the memory before accessing it from the initial data. - uint8_t _bankOffset = 0; + int _bankOffset = 0; public: //! @brief Create a shadow for the memory given as parameter. explicit RectangleShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); @@ -52,6 +52,7 @@ namespace ComSquare::Memory //! @return nullptr if isMirror is false, the source otherwise. std::shared_ptr getMirrored() const override; - RectangleShadow *setBankOffset(uint8_t bankOffset); + //! @brief Set the number of bank this component do not shadow. Referring to the first byte of this component will refer to the first byte of the bank at (bankOffset + start of initial memory). + RectangleShadow *setBankOffset(int bankOffset); }; } \ No newline at end of file diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index ee5243f..e661701 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -13,8 +13,8 @@ Test(DMA, RomToVRAM) snes.cartridge->_size = 4000000; snes.cartridge->_data = new uint8_t[snes.cartridge->_size]; for (unsigned i = 0; i < 0x400; i++) { - snes.cartridge->_data[0x9bded + i * 2] = i; - snes.cartridge->_data[0x9bded + i * 2 + 1] = i >> 8; + snes.cartridge->_data[0x9be00 + i * 2] = i; + snes.cartridge->_data[0x9be00 + i * 2 + 1] = i >> 8; } // Transferring $800 bytes from ROM ($13BE00) to VRam ($2000) via DMA channel 0 diff --git a/tests/testRectangleMemory.cpp b/tests/testRectangleMemory.cpp index c0b8376..69baaab 100644 --- a/tests/testRectangleMemory.cpp +++ b/tests/testRectangleMemory.cpp @@ -12,7 +12,7 @@ using namespace ComSquare; Test(RectangleMemory, HorizontalRamRead) { Ram::Ram ram(0xFF, Component::Rom, "Rom"); - ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); + ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0000); for (int i = 0x00; i < 0xFF; i++) ram._data[i] = i; for (uint24_t i = 0x000000; i < 0xFF0000; i += 0x010000) { @@ -24,7 +24,7 @@ Test(RectangleMemory, HorizontalRamRead) Test(RectangleMemory, HorizontalRamWrite) { Ram::Ram ram(0xFF, Component::Rom, "Rom"); - ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); + ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0000); for (uint24_t i = 0x000000; i < 0xFF0000; i += 0x010000) ram.write(ram.getRelativeAddress(i), i >> 16u); for (int i = 0x00; i < 0xFF; i++) @@ -34,7 +34,7 @@ Test(RectangleMemory, HorizontalRamWrite) Test(RectangleMemory, DualLineRamRead) { Ram::Ram ram(0xFF * 2, Component::Rom, "Rom"); - ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0002); + ram.setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); for (int i = 0x00; i < 0xFF * 2; i++) ram._data[i] = i; for (uint24_t i = 0x000000, v = 0; v < 0xFF * 2; i += 0x010000, v += 2) { @@ -48,8 +48,8 @@ Test(RectangleMemory, DualLineRamRead) Test(RectangleMemory, HorizontalRamShadowRead) { std::shared_ptr ram = std::make_shared(0xFF, Component::Rom, "Rom"); - ram->setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); - Memory::RectangleShadow shadow(ram, 0x00, 0xFF, 0x8000, 0x8001); + ram->setMemoryRegion(0x00, 0xFF, 0x0000, 0x0000); + Memory::RectangleShadow shadow(ram, 0x00, 0xFF, 0x8000, 0x8000); for (int i = 0x00; i < 0xFF; i++) ram->_data[i] = i; for (uint24_t i = 0x008000; i < 0xFF8000; i += 0x010000) { @@ -60,8 +60,8 @@ Test(RectangleMemory, HorizontalRamShadowRead) Test(RectangleMemory, HorizontalRamShadowReadWithBankOffset) { std::shared_ptr ram = std::make_shared(0xFF, Component::Rom, "Rom"); - ram->setMemoryRegion(0x00, 0xFF, 0x0000, 0x0001); - Memory::RectangleShadow shadow(ram, 0x80, 0xFF, 0x8000, 0x8001); + ram->setMemoryRegion(0x00, 0xFF, 0x0000, 0x0000); + Memory::RectangleShadow shadow(ram, 0x80, 0xFF, 0x8000, 0x8000); for (int i = 0x00; i < 0xFF; i++) ram->_data[i] = i; shadow.setBankOffset(0x80); @@ -79,7 +79,7 @@ Test(RectangleMemory, ShadowOffsetCartridge) for (int i = 0x00; i < 0x3fff80; i++) ram->_data[i] = i; shadow.setBankOffset(0x40); - for (uint24_t i = 0xC00000; i < 0xEF7FFF; i += 0x1) { + for (uint24_t i = 0xC00000; i <= 0xEF7FFF; i += 0x1) { if ((uint16_t)i > 0x7FFFu) i += 0x010000 - 0x8000; uint8_t v = shadow.read(shadow.getRelativeAddress(i)); From 845a8c26f0ec782ffc0bef721bca7b56361e2a51 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 12:07:26 +0100 Subject: [PATCH 21/30] Adding an error message on invalid instructions --- sources/Debugger/CPU/CPUDebug.cpp | 14 +++++++++++++- sources/Debugger/CPU/CPUDebug.hpp | 4 +++- sources/Debugger/CPU/Disassembly.cpp | 4 ++-- sources/Debugger/MemoryBusDebug.cpp | 9 ++++++++- sources/Debugger/MemoryBusDebug.hpp | 7 ++++++- sources/Memory/MemoryBus.cpp | 23 +++++++++++++++++++---- sources/Memory/MemoryBus.hpp | 9 +++++++-- sources/PPU/PPU.cpp | 2 ++ sources/Renderer/QtRenderer/QtSFML.cpp | 7 +++---- sources/SNES.cpp | 11 ++++++++++- sources/SNES.hpp | 5 +++++ 11 files changed, 78 insertions(+), 17 deletions(-) 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. From caa547b80ed981ea724f93c6ce319b0f9cd31c28 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 14:22:39 +0100 Subject: [PATCH 22/30] Fixing tests compilation --- sources/Exceptions/DebuggableError.hpp | 5 +---- sources/SNES.hpp | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sources/Exceptions/DebuggableError.hpp b/sources/Exceptions/DebuggableError.hpp index fcc9180..08c8d8e 100644 --- a/sources/Exceptions/DebuggableError.hpp +++ b/sources/Exceptions/DebuggableError.hpp @@ -2,8 +2,7 @@ // Created by anonymus-raccoon on 3/26/20. // -#ifndef COMSQUARE_DEBUGGABLEERROR_HPP -#define COMSQUARE_DEBUGGABLEERROR_HPP +#pragma once #include @@ -11,5 +10,3 @@ namespace ComSquare { class DebuggableError : public std::exception {}; } - -#endif //COMSQUARE_DEBUGGABLEERROR_HPP diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 48b45ce..5f604df 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -12,14 +12,13 @@ #include "PPU/PPU.hpp" #include "APU/APU.hpp" #include "Renderer/IRenderer.hpp" +#include "Exceptions/DebuggableError.hpp" #ifdef DEBUGGER_ENABLED #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" #include "Debugger/CGramDebug.hpp" #include "Debugger/RegisterViewer.hpp" -#include "Exceptions/DebuggableError.hpp" - #endif namespace ComSquare From ecc611748cb084b12ba330255452c7547df2c526 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 14:25:48 +0100 Subject: [PATCH 23/30] Fixing a warning when debuggers are disabled --- sources/SNES.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 004dc1e..2ea7edb 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -40,6 +40,8 @@ namespace ComSquare #ifdef DEBUGGER_ENABLED auto cpuDebug = std::static_pointer_cast(this->cpu); cpuDebug->showError(exception); + #else + (void)exception; #endif } From 77232268bc30ddd45044dd382d614baa1eeb7dd7 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 14:51:03 +0100 Subject: [PATCH 24/30] Adding all DMA channels in the register viewer --- .gitignore | 3 +- sources/Debugger/RegisterViewer.cpp | 35 ++- sources/Debugger/RegisterViewer.hpp | 2 +- ui/registersView.ui | 20 +- ui/ui_cpuView.h | 457 ---------------------------- 5 files changed, 36 insertions(+), 481 deletions(-) delete mode 100644 ui/ui_cpuView.h diff --git a/.gitignore b/.gitignore index 568de19..5468f3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/* -cmake-build-debug/* \ No newline at end of file +cmake-build-debug/* +ui/*.h \ No newline at end of file diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index dba6ee3..5797773 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -24,36 +24,47 @@ namespace ComSquare::Debugger void RegisterViewer::_setupUi() { - int i = 0; - // for (int i = 0; i < 8; i++) { + this->_models.clear(); + + std::array channels = { + this->_ui.dmaChannel1, + this->_ui.dmaChannel2, + this->_ui.dmaChannel3, + this->_ui.dmaChannel4, + this->_ui.dmaChannel5, + this->_ui.dmaChannel6, + this->_ui.dmaChannel7, + this->_ui.dmaChannel8 + }; + for (int i = 0; i < 8; i++) { RegistersViewerModel *model = new RegistersViewerModel(this->_snes); - model->addRegister(Register(0x420B, ":0", "Enabled", [i](SNES &snes) { + model->addRegister(Register(0x420B, std::string(":") + std::to_string(i), "Enabled", [i](SNES &snes) { return snes.cpu->_dmaChannels[i].enabled; }, nullptr, Boolean)); - model->addRegister(Register(0x4302, "-4", "A address", [i](SNES &snes) { + model->addRegister(Register(0x4302 + (i << 4u), "-4", "A address", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._aAddress.raw; }, nullptr, TwentyFourBits)); - model->addRegister(Register(0x4301, "", "B address", [i](SNES &snes) { + model->addRegister(Register(0x4301 + (i << 4u), "", "B address", [i](SNES &snes) { return 0x2100 | snes.cpu->_dmaChannels[i]._port; }, nullptr, SixteenBits)); - model->addRegister(Register(0x4305, "-6", "Count", [i](SNES &snes) { + model->addRegister(Register(0x4305 + (i << 4u), "-6", "Count", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._count.raw; }, nullptr, SixteenBits)); - model->addRegister(Register(0x4300, ":7", "B To A", [i](SNES &snes) { + model->addRegister(Register(0x4300 + (i << 4u), ":7", "B To A", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.direction; }, nullptr, Boolean)); - model->addRegister(Register(0x4300, ":3", "Fixed", [i](SNES &snes) { + model->addRegister(Register(0x4300 + (i << 4u), ":3", "Fixed", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.fixed; }, nullptr, Boolean)); - model->addRegister(Register(0x4300, ":4", "Decrement", [i](SNES &snes) { + model->addRegister(Register(0x4300 + (i << 4u), ":4", "Decrement", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.increment; }, nullptr, Boolean)); - model->addRegister(Register(0x4300, ":0-2", "Mode", [i](SNES &snes) { + model->addRegister(Register(0x4300 + (i << 4u), ":0-2", "Mode", [i](SNES &snes) { return snes.cpu->_dmaChannels[i]._controlRegister.increment; }, nullptr, EightBits)); - this->_ui.dmaChannel1->setModel(model); + channels[i]->setModel(model); this->_models.push_back(model); -// } + } } void RegisterViewer::focus() diff --git a/sources/Debugger/RegisterViewer.hpp b/sources/Debugger/RegisterViewer.hpp index e98390e..b232c10 100644 --- a/sources/Debugger/RegisterViewer.hpp +++ b/sources/Debugger/RegisterViewer.hpp @@ -59,7 +59,7 @@ namespace ComSquare //! @brief The list of models used by different panels. std::vector _models; - //! @brief The snes instance to read/write to DMA channels. + //! @brief The snes instance to read/write to. SNES &_snes; //! @brief Set models to the different tables and initialize them. diff --git a/ui/registersView.ui b/ui/registersView.ui index 4f467e3..4dd129a 100644 --- a/ui/registersView.ui +++ b/ui/registersView.ui @@ -43,16 +43,6 @@ - - - PPU - - - - - - - DMA @@ -147,6 +137,16 @@ + + + PPU + + + + + + + diff --git a/ui/ui_cpuView.h b/ui/ui_cpuView.h deleted file mode 100644 index 70433d5..0000000 --- a/ui/ui_cpuView.h +++ /dev/null @@ -1,457 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'cpuView.ui' -** -** Created by: Qt User Interface Compiler version 5.15.2 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_CPUVIEW_H -#define UI_CPUVIEW_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_3; - QTableView *disassembly; - QGridLayout *gridLayout_2; - QTableView *stackView; - QLabel *label; - 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 *emulationModeLabel; - QCheckBox *emulationModeCheckBox; - QGridLayout *gridLayout; - QLabel *loggerLabel; - QPushButton *clear; - QTableView *history; - QGroupBox *formGroupBox; - QFormLayout *formLayout_2; - QLabel *negativeLabel; - QCheckBox *mCheckbox; - QLabel *zeroLabel; - QCheckBox *xCheckbox; - QLabel *carryLabel; - QCheckBox *iCheckbox; - QLabel *Overflow; - QCheckBox *vCheckbox; - QLabel *decimalLabel; - QCheckBox *dCheckbox; - QLabel *memoryAccumulatorSelectLabel; - QCheckBox *cCheckbox; - QLabel *indeXSelectLabel; - QLabel *irqDisableLabel; - QCheckBox *nCheckbox; - QCheckBox *zCheckbox; - QLabel *breakBLabel; - QCheckBox *bCheckbox; - QToolBar *toolBar; - - void setupUi(QMainWindow *CPUView) - { - if (CPUView->objectName().isEmpty()) - CPUView->setObjectName(QString::fromUtf8("CPUView")); - CPUView->resize(1058, 673); - 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_3 = new QGridLayout(centralwidget); - gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3")); - 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_3->addWidget(disassembly, 0, 0, 3, 1); - - gridLayout_2 = new QGridLayout(); - gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2")); - stackView = new QTableView(centralwidget); - stackView->setObjectName(QString::fromUtf8("stackView")); - stackView->horizontalHeader()->setVisible(false); - - gridLayout_2->addWidget(stackView, 1, 0, 1, 1); - - label = new QLabel(centralwidget); - label->setObjectName(QString::fromUtf8("label")); - label->setAlignment(Qt::AlignCenter); - - gridLayout_2->addWidget(label, 0, 0, 1, 1); - - - gridLayout_3->addLayout(gridLayout_2, 0, 1, 1, 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); - - emulationModeLabel = new QLabel(centralwidget); - emulationModeLabel->setObjectName(QString::fromUtf8("emulationModeLabel")); - - formLayout->setWidget(8, QFormLayout::LabelRole, emulationModeLabel); - - emulationModeCheckBox = new QCheckBox(centralwidget); - emulationModeCheckBox->setObjectName(QString::fromUtf8("emulationModeCheckBox")); - emulationModeCheckBox->setLayoutDirection(Qt::RightToLeft); - emulationModeCheckBox->setCheckable(true); - - formLayout->setWidget(8, QFormLayout::FieldRole, emulationModeCheckBox); - - - gridLayout_3->addLayout(formLayout, 0, 2, 2, 1); - - gridLayout = new QGridLayout(); - gridLayout->setObjectName(QString::fromUtf8("gridLayout")); - loggerLabel = new QLabel(centralwidget); - loggerLabel->setObjectName(QString::fromUtf8("loggerLabel")); - loggerLabel->setAlignment(Qt::AlignCenter); - - gridLayout->addWidget(loggerLabel, 0, 0, 1, 1); - - clear = new QPushButton(centralwidget); - clear->setObjectName(QString::fromUtf8("clear")); - - gridLayout->addWidget(clear, 2, 0, 1, 1); - - history = new QTableView(centralwidget); - history->setObjectName(QString::fromUtf8("history")); - - gridLayout->addWidget(history, 1, 0, 1, 1); - - - gridLayout_3->addLayout(gridLayout, 1, 1, 2, 1); - - formGroupBox = new QGroupBox(centralwidget); - formGroupBox->setObjectName(QString::fromUtf8("formGroupBox")); - formGroupBox->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - formGroupBox->setFlat(false); - formGroupBox->setCheckable(false); - formLayout_2 = new QFormLayout(formGroupBox); - formLayout_2->setObjectName(QString::fromUtf8("formLayout_2")); - formLayout_2->setSizeConstraint(QLayout::SetDefaultConstraint); - formLayout_2->setLabelAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - formLayout_2->setFormAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - formLayout_2->setContentsMargins(26, 7, 0, -1); - negativeLabel = new QLabel(formGroupBox); - negativeLabel->setObjectName(QString::fromUtf8("negativeLabel")); - - formLayout_2->setWidget(0, QFormLayout::LabelRole, negativeLabel); - - mCheckbox = new QCheckBox(formGroupBox); - mCheckbox->setObjectName(QString::fromUtf8("mCheckbox")); - mCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(0, QFormLayout::FieldRole, mCheckbox); - - zeroLabel = new QLabel(formGroupBox); - zeroLabel->setObjectName(QString::fromUtf8("zeroLabel")); - - formLayout_2->setWidget(1, QFormLayout::LabelRole, zeroLabel); - - xCheckbox = new QCheckBox(formGroupBox); - xCheckbox->setObjectName(QString::fromUtf8("xCheckbox")); - xCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(1, QFormLayout::FieldRole, xCheckbox); - - carryLabel = new QLabel(formGroupBox); - carryLabel->setObjectName(QString::fromUtf8("carryLabel")); - - formLayout_2->setWidget(3, QFormLayout::LabelRole, carryLabel); - - iCheckbox = new QCheckBox(formGroupBox); - iCheckbox->setObjectName(QString::fromUtf8("iCheckbox")); - iCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(3, QFormLayout::FieldRole, iCheckbox); - - Overflow = new QLabel(formGroupBox); - Overflow->setObjectName(QString::fromUtf8("Overflow")); - - formLayout_2->setWidget(4, QFormLayout::LabelRole, Overflow); - - vCheckbox = new QCheckBox(formGroupBox); - vCheckbox->setObjectName(QString::fromUtf8("vCheckbox")); - vCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(4, QFormLayout::FieldRole, vCheckbox); - - decimalLabel = new QLabel(formGroupBox); - decimalLabel->setObjectName(QString::fromUtf8("decimalLabel")); - - formLayout_2->setWidget(5, QFormLayout::LabelRole, decimalLabel); - - dCheckbox = new QCheckBox(formGroupBox); - dCheckbox->setObjectName(QString::fromUtf8("dCheckbox")); - dCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(5, QFormLayout::FieldRole, dCheckbox); - - memoryAccumulatorSelectLabel = new QLabel(formGroupBox); - memoryAccumulatorSelectLabel->setObjectName(QString::fromUtf8("memoryAccumulatorSelectLabel")); - - formLayout_2->setWidget(6, QFormLayout::LabelRole, memoryAccumulatorSelectLabel); - - cCheckbox = new QCheckBox(formGroupBox); - cCheckbox->setObjectName(QString::fromUtf8("cCheckbox")); - cCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(6, QFormLayout::FieldRole, cCheckbox); - - indeXSelectLabel = new QLabel(formGroupBox); - indeXSelectLabel->setObjectName(QString::fromUtf8("indeXSelectLabel")); - - formLayout_2->setWidget(7, QFormLayout::LabelRole, indeXSelectLabel); - - irqDisableLabel = new QLabel(formGroupBox); - irqDisableLabel->setObjectName(QString::fromUtf8("irqDisableLabel")); - - formLayout_2->setWidget(8, QFormLayout::LabelRole, irqDisableLabel); - - nCheckbox = new QCheckBox(formGroupBox); - nCheckbox->setObjectName(QString::fromUtf8("nCheckbox")); - nCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(8, QFormLayout::FieldRole, nCheckbox); - - zCheckbox = new QCheckBox(formGroupBox); - zCheckbox->setObjectName(QString::fromUtf8("zCheckbox")); - zCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(7, QFormLayout::FieldRole, zCheckbox); - - breakBLabel = new QLabel(formGroupBox); - breakBLabel->setObjectName(QString::fromUtf8("breakBLabel")); - - formLayout_2->setWidget(2, QFormLayout::LabelRole, breakBLabel); - - bCheckbox = new QCheckBox(formGroupBox); - bCheckbox->setObjectName(QString::fromUtf8("bCheckbox")); - bCheckbox->setLayoutDirection(Qt::RightToLeft); - - formLayout_2->setWidget(2, QFormLayout::FieldRole, bCheckbox); - - - gridLayout_3->addWidget(formGroupBox, 2, 2, 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) - label->setText(QCoreApplication::translate("CPUView", "Stack Viewer", nullptr)); - 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)); - emulationModeLabel->setText(QCoreApplication::translate("CPUView", "Emulation mode", nullptr)); - loggerLabel->setText(QCoreApplication::translate("CPUView", "Instructions History", nullptr)); - clear->setText(QCoreApplication::translate("CPUView", "Clear History", nullptr)); - formGroupBox->setTitle(QCoreApplication::translate("CPUView", "Flags", nullptr)); - negativeLabel->setText(QCoreApplication::translate("CPUView", "Memory Select (M)", nullptr)); - zeroLabel->setText(QCoreApplication::translate("CPUView", "Index Select (X)", nullptr)); - carryLabel->setText(QCoreApplication::translate("CPUView", "Interupt Request Disable (I)", nullptr)); - Overflow->setText(QCoreApplication::translate("CPUView", "Overflow (V)", nullptr)); - decimalLabel->setText(QCoreApplication::translate("CPUView", "Decimal (D)", nullptr)); - memoryAccumulatorSelectLabel->setText(QCoreApplication::translate("CPUView", "Carry (C)", nullptr)); - indeXSelectLabel->setText(QCoreApplication::translate("CPUView", "Zero (Z)", nullptr)); - irqDisableLabel->setText(QCoreApplication::translate("CPUView", "Negative (N)", nullptr)); - breakBLabel->setText(QCoreApplication::translate("CPUView", "Break (B)", nullptr)); - toolBar->setWindowTitle(QCoreApplication::translate("CPUView", "toolBar", nullptr)); - } // retranslateUi - -}; - -namespace Ui { - class CPUView: public Ui_CPUView {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_CPUVIEW_H From 6b18bb1257ef61e8686eabb5de50d24e4e8a4e3b Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 15:55:08 +0100 Subject: [PATCH 25/30] Fixing the CI --- .github/workflows/build.yml | 2 +- .github/workflows/buildwin.yml | 4 ++-- .github/workflows/doc.yml | 5 +++-- .github/workflows/test.yml | 3 --- codecov.yml | 6 ++++++ 5 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 codecov.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aefff04..7c8dd2a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: run: sudo apt-get update && sudo apt-get install --yes libfreetype6-dev libxrandr-dev libudev-dev libogg-dev libflac-dev libvorbis-dev libopenal-dev freeglut3-dev - name: Install Qt - uses: ouuan/install-qt-action@v2.3.1 + uses: jurplel/install-qt-action@v2 - name: Install the SFML. run: | git clone https://github.com/SFML/SFML -b 2.5.x /tmp/sfml diff --git a/.github/workflows/buildwin.yml b/.github/workflows/buildwin.yml index 25632da..73fe8ab 100644 --- a/.github/workflows/buildwin.yml +++ b/.github/workflows/buildwin.yml @@ -3,10 +3,10 @@ name: Build for windows on: push: branches: - - master + - CI-TEST pull_request: branches: - - master + - CI-TEST jobs: Building: diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 9da660d..007a36e 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -21,10 +21,11 @@ jobs: cd docs git config --global user.email "${GITHUB_ACTOR}@github.com"; git config --global user.name "${GITHUB_ACTOR}"; + git init git add -A; git commit -m "Deploying the doc"; - git remote set-url --push origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${GITHUB_REPO}; - git push origin gh-pages; + git remote add origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${GITHUB_REPO}; + git push --force origin gh-pages; env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPO: "github.com/AnonymusRaccoon/ComSquare" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5de8a5e..7272337 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,9 +21,6 @@ jobs: uses: actions/setup-python@v1 with: python-version: '3.x' - - name: Install the SFML. - run: sudo apt-get update && - sudo apt-get install --yes libsfml-dev qt5-default - name: Install Criterion run: sudo add-apt-repository ppa:snaipewastaken/ppa && sudo apt-get update && diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..9a7531b --- /dev/null +++ b/codecov.yml @@ -0,0 +1,6 @@ +coverage: + status: + project: + default: + target: auto + threshold: 5% \ No newline at end of file From 71e675457dbaff1e08287fac6a4b0785a6686b0f Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 15:59:05 +0100 Subject: [PATCH 26/30] The test CI now only run cmake on the unit_tests tartget --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7272337..8f487d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - name: Install Gcovr run: python -m pip install --upgrade pip gcovr - name: Build Makefile with CMake - run: mkdir -p build && cd build && cmake .. + run: mkdir -p build && cd build && cmake .. --target unit_tests - name: Build with Makefile run: make -C build unit_tests - name: Execute tests From 1a8d58264653fa69df28388d6dc79180d37fc20c Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 16:15:40 +0100 Subject: [PATCH 27/30] Installing SFML & QT5 for tests, I'm tired --- .github/workflows/test.yml | 5 ++++- CMakeLists.txt | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8f487d0..5de8a5e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,9 @@ jobs: uses: actions/setup-python@v1 with: python-version: '3.x' + - name: Install the SFML. + run: sudo apt-get update && + sudo apt-get install --yes libsfml-dev qt5-default - name: Install Criterion run: sudo add-apt-repository ppa:snaipewastaken/ppa && sudo apt-get update && @@ -28,7 +31,7 @@ jobs: - name: Install Gcovr run: python -m pip install --upgrade pip gcovr - name: Build Makefile with CMake - run: mkdir -p build && cd build && cmake .. --target unit_tests + run: mkdir -p build && cd build && cmake .. - name: Build with Makefile run: make -C build unit_tests - name: Execute tests diff --git a/CMakeLists.txt b/CMakeLists.txt index 22d3311..9db1d4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,12 +109,6 @@ add_executable(unit_tests target_link_libraries(unit_tests criterion -lgcov) target_compile_options(unit_tests PUBLIC -fprofile-arcs -ftest-coverage) -if ("${GITBUILD}" STREQUAL true) - include_directories(ComSquare build/include) - link_directories(ComSquare build/lib) - message("Git build is true") -endif () - set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) From a147f69ac6753ba5354b5733ad61552496d4f437 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 16:22:34 +0100 Subject: [PATCH 28/30] Oups --- .github/workflows/doc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 007a36e..4f7e3e2 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -15,7 +15,6 @@ jobs: run: sudo apt-get install --yes doxygen graphviz - name: Update the docs run: | - git clone -b gh-pages https://${GITHUB_REPO} docs rm -rf docs/* doxygen Doxyfile cd docs From efd333204c6b1629e581f699fa7931c2654f6231 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 16:34:56 +0100 Subject: [PATCH 29/30] Renaming the doc branch --- .github/workflows/doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 4f7e3e2..0af3bfb 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -24,7 +24,7 @@ jobs: git add -A; git commit -m "Deploying the doc"; git remote add origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${GITHUB_REPO}; - git push --force origin gh-pages; + git push --force origin Documentation; env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPO: "github.com/AnonymusRaccoon/ComSquare" \ No newline at end of file From 9edd0304ced42eb3d94254fed9b1977bc4e09cfa Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Thu, 4 Feb 2021 17:53:05 +0100 Subject: [PATCH 30/30] Adding a checkout to the Documentation branch in the CI --- .github/workflows/doc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 0af3bfb..4da3ce2 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -24,6 +24,7 @@ jobs: git add -A; git commit -m "Deploying the doc"; git remote add origin https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${GITHUB_REPO}; + git checkout -b Documentation git push --force origin Documentation; env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}