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