Enabling the memory bus debugger

This commit is contained in:
Zoe Roux
2021-07-05 00:23:48 +02:00
parent f16815c36f
commit cb6fb8a240
20 changed files with 475 additions and 418 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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--;

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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).

View 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;
};
}
}

View File

@@ -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;
}
}

View File

@@ -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;
};
}
}

View File

@@ -95,7 +95,7 @@ namespace ComSquare::Renderer
void QtFullSFML::enableDebugBus()
{
// this->_snes.enableMemoryBusDebugging();
this->_snes.enableMemoryBusDebugging();
}
void QtFullSFML::enableCgramViewer()

View File

@@ -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()
{

View File

@@ -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.