mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
208 lines
6.6 KiB
C++
208 lines
6.6 KiB
C++
#include "pch.h"
|
|
#include "SNES/Debugger/SnesEventManager.h"
|
|
#include "SNES/SnesCpu.h"
|
|
#include "SNES/SnesPpu.h"
|
|
#include "SNES/SnesDmaController.h"
|
|
#include "SNES/SnesMemoryManager.h"
|
|
#include "Debugger/DebugTypes.h"
|
|
#include "Debugger/Debugger.h"
|
|
#include "Debugger/DebugBreakHelper.h"
|
|
#include "Debugger/BaseEventManager.h"
|
|
#include "Shared/ColorUtilities.h"
|
|
|
|
SnesEventManager::SnesEventManager(Debugger *debugger, SnesCpu *cpu, SnesPpu *ppu, SnesMemoryManager *memoryManager, SnesDmaController *dmaController)
|
|
{
|
|
_debugger = debugger;
|
|
_cpu = cpu;
|
|
_ppu = ppu;
|
|
_memoryManager = memoryManager;
|
|
_dmaController = dmaController;
|
|
|
|
_ppuBuffer = new uint16_t[512 * 478];
|
|
memset(_ppuBuffer, 0, 512 * 478 * sizeof(uint16_t));
|
|
}
|
|
|
|
SnesEventManager::~SnesEventManager()
|
|
{
|
|
delete[] _ppuBuffer;
|
|
}
|
|
|
|
void SnesEventManager::AddEvent(DebugEventType type, MemoryOperationInfo &operation, int32_t breakpointId)
|
|
{
|
|
DebugEventInfo evt = {};
|
|
evt.Type = type;
|
|
evt.Flags = (uint32_t)EventFlags::ReadWriteOp;
|
|
evt.Operation = operation;
|
|
evt.Scanline = (int16_t)_ppu->GetScanline();
|
|
evt.Cycle = _memoryManager->GetHClock();
|
|
evt.BreakpointId = breakpointId;
|
|
|
|
if(operation.Type == MemoryOperationType::DmaRead || operation.Type == MemoryOperationType::DmaWrite) {
|
|
evt.DmaChannel = _dmaController->GetActiveChannel();
|
|
evt.DmaChannelInfo = _dmaController->GetChannelConfig(evt.DmaChannel & 0x07);
|
|
} else {
|
|
evt.DmaChannel = -1;
|
|
}
|
|
|
|
evt.ProgramCounter = _debugger->GetProgramCounter(CpuType::Snes, true);
|
|
|
|
_debugEvents.push_back(evt);
|
|
}
|
|
|
|
void SnesEventManager::AddEvent(DebugEventType type)
|
|
{
|
|
DebugEventInfo evt = {};
|
|
evt.Type = type;
|
|
evt.Scanline = _ppu->GetScanline();
|
|
evt.Cycle = _memoryManager->GetHClock();
|
|
evt.BreakpointId = -1;
|
|
evt.DmaChannel = -1;
|
|
|
|
evt.ProgramCounter = (_cpu->GetState().K << 16) | _cpu->GetState().PC;
|
|
|
|
_debugEvents.push_back(evt);
|
|
}
|
|
|
|
DebugEventInfo SnesEventManager::GetEvent(uint16_t y, uint16_t x)
|
|
{
|
|
auto lock = _lock.AcquireSafe();
|
|
|
|
x *= 2; //convert to hclock value
|
|
y /= 2; //convert to scanline value
|
|
|
|
//Search without including larger background color first
|
|
for(int i = (int)_sentEvents.size() - 1; i >= 0; i--) {
|
|
DebugEventInfo& evt = _sentEvents[i];
|
|
if((x >= evt.Cycle && x <= evt.Cycle + 2) && evt.Scanline == y) {
|
|
return evt;
|
|
}
|
|
}
|
|
|
|
//If no exact match, extend to the background color
|
|
for(int i = (int)_sentEvents.size() - 1; i >= 0; i--) {
|
|
DebugEventInfo& evt = _sentEvents[i];
|
|
if((x >= evt.Cycle - 4 && x <= evt.Cycle + 6) && std::abs((int)evt.Scanline - (int)y) <= 1) {
|
|
return evt;
|
|
}
|
|
}
|
|
|
|
DebugEventInfo empty = {};
|
|
empty.ProgramCounter = 0xFFFFFFFF;
|
|
return empty;
|
|
}
|
|
|
|
bool SnesEventManager::ShowPreviousFrameEvents()
|
|
{
|
|
return _config.ShowPreviousFrameEvents;
|
|
}
|
|
|
|
void SnesEventManager::SetConfiguration(BaseEventViewerConfig& config)
|
|
{
|
|
_config = (SnesEventViewerConfig&)config;
|
|
}
|
|
|
|
EventViewerCategoryCfg SnesEventManager::GetEventConfig(DebugEventInfo& evt)
|
|
{
|
|
bool isDma = evt.Operation.Type == MemoryOperationType::DmaWrite || evt.Operation.Type == MemoryOperationType::DmaRead;
|
|
if(evt.Type == DebugEventType::Register && isDma && !_config.ShowDmaChannels[evt.DmaChannel & 0x07]) {
|
|
return {};
|
|
}
|
|
|
|
switch(evt.Type) {
|
|
default: return {};
|
|
case DebugEventType::Breakpoint: return _config.MarkedBreakpoints;
|
|
case DebugEventType::Irq: return _config.Irq;
|
|
case DebugEventType::Nmi: return _config.Nmi;
|
|
case DebugEventType::Register:
|
|
uint16_t reg = evt.Operation.Address & 0xFFFF;
|
|
bool isWrite = evt.Operation.Type == MemoryOperationType::Write || evt.Operation.Type == MemoryOperationType::DmaWrite;
|
|
if(reg <= 0x213F) {
|
|
if(isWrite) {
|
|
if(reg >= 0x2101 && reg <= 0x2104) {
|
|
return _config.PpuRegisterOamWrites;
|
|
} else if(reg >= 0x2105 && reg <= 0x210C) {
|
|
return _config.PpuRegisterBgOptionWrites;
|
|
} else if(reg >= 0x210D && reg <= 0x2114) {
|
|
return _config.PpuRegisterBgScrollWrites;
|
|
} else if(reg >= 0x2115 && reg <= 0x2119) {
|
|
return _config.PpuRegisterVramWrites;
|
|
} else if(reg >= 0x211A && reg <= 0x2120) {
|
|
return _config.PpuRegisterMode7Writes;
|
|
} else if(reg >= 0x2121 && reg <= 0x2122) {
|
|
return _config.PpuRegisterCgramWrites;
|
|
} else if(reg >= 0x2123 && reg <= 0x212B) {
|
|
return _config.PpuRegisterWindowWrites;
|
|
} else {
|
|
return _config.PpuRegisterOtherWrites;
|
|
}
|
|
} else {
|
|
return _config.PpuRegisterReads;
|
|
}
|
|
} else if(reg <= 0x217F) {
|
|
return isWrite ? _config.ApuRegisterWrites : _config.ApuRegisterReads;
|
|
} else if(reg <= 0x2183) {
|
|
return isWrite ? _config.WorkRamRegisterWrites : _config.WorkRamRegisterReads;
|
|
} else if(reg >= 0x4000) {
|
|
return isWrite ? _config.CpuRegisterWrites : _config.CpuRegisterReads;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
void SnesEventManager::ConvertScanlineCycleToRowColumn(int32_t& x, int32_t& y)
|
|
{
|
|
y *= 2;
|
|
x /= 2;
|
|
}
|
|
|
|
uint32_t SnesEventManager::TakeEventSnapshot(bool forAutoRefresh)
|
|
{
|
|
DebugBreakHelper breakHelper(_debugger);
|
|
auto lock = _lock.AcquireSafe();
|
|
|
|
uint16_t cycle = _memoryManager->GetHClock();
|
|
uint16_t scanline = _ppu->GetScanline();
|
|
|
|
_overscanMode = _ppu->GetState().OverscanMode;
|
|
_useHighResOutput = _ppu->IsHighResOutput();
|
|
|
|
if(scanline >= _ppu->GetNmiScanline() || scanline == 0) {
|
|
memcpy(_ppuBuffer, _ppu->GetScreenBuffer(), (_useHighResOutput ? (512 * 478) : (256*239)) * sizeof(uint16_t));
|
|
} else {
|
|
uint16_t adjustedScanline = scanline + (_overscanMode ? 0 : 7);
|
|
uint32_t size = _useHighResOutput ? (512 * 478) : (256 * 239);
|
|
uint32_t offset = _useHighResOutput ? (512 * adjustedScanline * 2) : (256 * adjustedScanline);
|
|
memcpy(_ppuBuffer, _ppu->GetScreenBuffer(), offset * sizeof(uint16_t));
|
|
memcpy(_ppuBuffer+offset, _ppu->GetPreviousScreenBuffer()+offset, (size - offset) * sizeof(uint16_t));
|
|
}
|
|
|
|
_snapshotCurrentFrame = _debugEvents;
|
|
_snapshotPrevFrame = _prevDebugEvents;
|
|
_snapshotScanline = scanline;
|
|
_snapshotCycle = cycle;
|
|
_forAutoRefresh = forAutoRefresh;
|
|
_scanlineCount = _ppu->GetVblankEndScanline() + 1;
|
|
return _scanlineCount;
|
|
}
|
|
|
|
FrameInfo SnesEventManager::GetDisplayBufferSize()
|
|
{
|
|
FrameInfo size;
|
|
size.Width = SnesEventManager::ScanlineWidth;
|
|
size.Height = _scanlineCount * 2;
|
|
return size;
|
|
}
|
|
|
|
void SnesEventManager::DrawScreen(uint32_t *buffer)
|
|
{
|
|
//Skip the first 7 blank lines in the buffer when overscan mode is off
|
|
uint16_t *src = _ppuBuffer + (_overscanMode ? 0 : (_useHighResOutput ? (512 * 14) : (256 * 7)));
|
|
|
|
for(uint32_t y = 0, len = _overscanMode ? 239*2 : 224*2; y < len; y++) {
|
|
for(uint32_t x = 0; x < 512; x++) {
|
|
int srcOffset = _useHighResOutput ? ((y << 9) | x) : (((y >> 1) << 8) | (x >> 1));
|
|
buffer[(y + 2)*SnesEventManager::ScanlineWidth + x + 22*2] = ColorUtilities::Rgb555ToArgb(src[srcOffset]);
|
|
}
|
|
}
|
|
}
|