mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
246 lines
7.4 KiB
C++
246 lines
7.4 KiB
C++
#include "pch.h"
|
|
#include "PCE/Debugger/PceEventManager.h"
|
|
#include "PCE/PceConsole.h"
|
|
#include "PCE/PceCpu.h"
|
|
#include "PCE/PceVdc.h"
|
|
#include "PCE/PceVce.h"
|
|
#include "PCE/PceVpc.h"
|
|
#include "PCE/PceMemoryManager.h"
|
|
#include "PCE/PceConstants.h"
|
|
#include "Debugger/DebugTypes.h"
|
|
#include "Debugger/Debugger.h"
|
|
#include "Debugger/DebugBreakHelper.h"
|
|
#include "Debugger/BaseEventManager.h"
|
|
#include "Shared/Emulator.h"
|
|
#include "Shared/EmuSettings.h"
|
|
|
|
PceEventManager::PceEventManager(Debugger *debugger, PceConsole *console)
|
|
{
|
|
_debugger = debugger;
|
|
_emu = debugger->GetEmulator();
|
|
_console = console;
|
|
_cpu = console->GetCpu();
|
|
_vdc = console->GetVdc();
|
|
_vpc = console->GetVpc();
|
|
_vce = console->GetVce();
|
|
_memoryManager = console->GetMemoryManager();
|
|
|
|
_ppuBuffer = new uint16_t[PceConstants::MaxScreenWidth * PceConstants::ScreenHeight];
|
|
memset(_ppuBuffer, 0, PceConstants::MaxScreenWidth * PceConstants::ScreenHeight * sizeof(uint16_t));
|
|
}
|
|
|
|
PceEventManager::~PceEventManager()
|
|
{
|
|
delete[] _ppuBuffer;
|
|
}
|
|
|
|
void PceEventManager::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)_vdc->GetScanline();
|
|
evt.Cycle = _vdc->GetHClock();
|
|
evt.BreakpointId = breakpointId;
|
|
evt.DmaChannel = -1;
|
|
evt.ProgramCounter = _debugger->GetProgramCounter(CpuType::Pce, true);
|
|
|
|
if(operation.Type == MemoryOperationType::Write && (operation.Address & 0x1FFF) < 0x400) {
|
|
if(_console->IsSuperGrafx()) {
|
|
if((operation.Address & 0x1A) == 2) {
|
|
evt.RegisterId = _vdc->GetState().CurrentReg; //VDC reg
|
|
} else {
|
|
//TODOv2 - supergrafx VPC writes, not VDC
|
|
}
|
|
} else {
|
|
if((operation.Address & 0x03) >= 2) {
|
|
evt.RegisterId = _vdc->GetState().CurrentReg; //VDC reg
|
|
}
|
|
}
|
|
}
|
|
|
|
_debugEvents.push_back(evt);
|
|
}
|
|
|
|
void PceEventManager::AddEvent(DebugEventType type)
|
|
{
|
|
DebugEventInfo evt = {};
|
|
evt.Type = type;
|
|
evt.Scanline = _vdc->GetScanline();
|
|
evt.Cycle = _vdc->GetHClock();
|
|
evt.BreakpointId = -1;
|
|
evt.DmaChannel = -1;
|
|
evt.ProgramCounter = _cpu->GetState().PC;
|
|
_debugEvents.push_back(evt);
|
|
}
|
|
|
|
DebugEventInfo PceEventManager::GetEvent(uint16_t y, uint16_t x)
|
|
{
|
|
auto lock = _lock.AcquireSafe();
|
|
|
|
uint16_t cycle = x; //convert to hclock value
|
|
uint16_t scanline = 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((evt.Cycle == cycle || evt.Cycle == cycle + 1) && evt.Scanline == scanline) {
|
|
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(cycle >= evt.Cycle - 2 && cycle <= evt.Cycle + 3 && std::abs((int)evt.Scanline - scanline) <= 1) {
|
|
return evt;
|
|
}
|
|
}
|
|
|
|
DebugEventInfo empty = {};
|
|
empty.ProgramCounter = 0xFFFFFFFF;
|
|
return empty;
|
|
}
|
|
|
|
bool PceEventManager::ShowPreviousFrameEvents()
|
|
{
|
|
return _config.ShowPreviousFrameEvents;
|
|
}
|
|
|
|
void PceEventManager::SetConfiguration(BaseEventViewerConfig& config)
|
|
{
|
|
_config = (PceEventViewerConfig&)config;
|
|
}
|
|
|
|
EventViewerCategoryCfg PceEventManager::GetEventConfig(DebugEventInfo& evt)
|
|
{
|
|
switch(evt.Type) {
|
|
default: return {};
|
|
case DebugEventType::Breakpoint: return _config.MarkedBreakpoints;
|
|
case DebugEventType::Irq: return _config.Irq;
|
|
case DebugEventType::Register:
|
|
uint16_t reg = evt.Operation.Address & 0x1FFF;
|
|
bool isWrite = evt.Operation.Type == MemoryOperationType::Write;
|
|
|
|
if(reg <= 0x3FF) {
|
|
if(isWrite) {
|
|
switch(evt.RegisterId) {
|
|
case -1: return _config.VdcRegSelectWrites;
|
|
case 0: return _config.VdcVramWrites;
|
|
case 1: return _config.VdcVramReads;
|
|
case 2: return _config.VdcVramWrites;
|
|
case 5: return _config.VdcControlWrites;
|
|
case 6: return _config.VdcRcrWrites;
|
|
|
|
case 7: case 8:
|
|
return _config.VdcScrollWrites;
|
|
|
|
case 9: return _config.VdcMemoryWidthWrites;
|
|
|
|
case 0xA: case 0xB: case 0xC: case 0xD: case 0xE:
|
|
return _config.VdcHvConfigWrites;
|
|
|
|
case 0xF: case 0x10: case 0x11: case 0x12: case 0x13:
|
|
return _config.VdcDmaWrites;
|
|
}
|
|
} else {
|
|
if((reg & 0x03) == 0) {
|
|
return _config.VdcStatusReads;
|
|
} else if((reg & 0x03) >= 2) {
|
|
return _config.VdcVramReads;
|
|
}
|
|
}
|
|
} else if(reg <= 0x7FF) {
|
|
return isWrite ? _config.VceWrites : _config.VceReads;
|
|
} else if(reg <= 0xBFF) {
|
|
return isWrite ? _config.PsgWrites : _config.PsgReads;
|
|
} else if(reg <= 0xFFF) {
|
|
return isWrite ? _config.TimerWrites : _config.TimerReads;
|
|
} else if(reg <= 0x13FF) {
|
|
return isWrite ? _config.IoWrites : _config.IoReads;
|
|
} else if(reg <= 0x17FF) {
|
|
return isWrite ? _config.IrqControlWrites : _config.IrqControlReads;
|
|
} else if(reg <= 0x1BFF) {
|
|
if(reg & 0x200) {
|
|
return isWrite ? _config.ArcadeCardWrites : _config.ArcadeCardReads;
|
|
} else {
|
|
switch(reg & 0x0F) {
|
|
case 8:
|
|
return isWrite ? _config.AdpcmWrites : _config.CdRomReads;
|
|
|
|
case 9: case 0xA: case 0xB: case 0xC: case 0xD: case 0xE:
|
|
return isWrite ? _config.AdpcmWrites : _config.AdpcmReads;
|
|
|
|
default:
|
|
return isWrite ? _config.CdRomWrites : _config.CdRomReads;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
void PceEventManager::ConvertScanlineCycleToRowColumn(int32_t& x, int32_t& y)
|
|
{
|
|
y *= 2;
|
|
}
|
|
|
|
uint32_t PceEventManager::TakeEventSnapshot(bool forAutoRefresh)
|
|
{
|
|
DebugBreakHelper breakHelper(_debugger);
|
|
auto lock = _lock.AcquireSafe();
|
|
|
|
uint16_t cycle = _vdc->GetHClock();
|
|
uint16_t scanline = _vdc->GetScanline();
|
|
|
|
constexpr uint32_t size = PceConstants::MaxScreenWidth * PceConstants::ScreenHeight;
|
|
if(scanline < 14 || scanline >= 256) {
|
|
memcpy(_ppuBuffer, _vpc->GetScreenBuffer(), size * sizeof(uint16_t));
|
|
memcpy(_rowClockDividers, _vpc->GetScreenBuffer()+size, PceConstants::ScreenHeight * sizeof(uint16_t));
|
|
} else {
|
|
uint32_t scanlineOffset = (scanline - 14);
|
|
uint32_t offset = PceConstants::MaxScreenWidth * scanlineOffset;
|
|
memcpy(_ppuBuffer, _vpc->GetScreenBuffer(), offset * sizeof(uint16_t));
|
|
memcpy(_ppuBuffer + offset, _vpc->GetPreviousScreenBuffer() + offset, (size - offset) * sizeof(uint16_t));
|
|
|
|
memcpy(_rowClockDividers, _vpc->GetScreenBuffer()+size, scanlineOffset * sizeof(uint16_t));
|
|
memcpy(_rowClockDividers + scanlineOffset, _vpc->GetPreviousScreenBuffer() + size + scanlineOffset, (PceConstants::ScreenHeight - scanlineOffset) * sizeof(uint16_t));
|
|
}
|
|
|
|
_snapshotCurrentFrame = _debugEvents;
|
|
_snapshotPrevFrame = _prevDebugEvents;
|
|
_snapshotScanline = scanline;
|
|
_snapshotCycle = cycle;
|
|
_forAutoRefresh = forAutoRefresh;
|
|
_scanlineCount = _vce->GetScanlineCount();
|
|
return _scanlineCount;
|
|
}
|
|
|
|
FrameInfo PceEventManager::GetDisplayBufferSize()
|
|
{
|
|
FrameInfo size;
|
|
size.Width = PceConstants::ClockPerScanline;
|
|
size.Height = _scanlineCount * 2;
|
|
return size;
|
|
}
|
|
|
|
void PceEventManager::DrawScreen(uint32_t *buffer)
|
|
{
|
|
uint16_t *src = _ppuBuffer;
|
|
uint32_t* palette = _emu->GetSettings()->GetPcEngineConfig().Palette;
|
|
|
|
for(uint32_t y = 0, len = PceConstants::ScreenHeight * 2; y < len; y++) {
|
|
uint16_t scanline = y >> 1;
|
|
uint32_t divider = _rowClockDividers[scanline];
|
|
if(divider == 0) {
|
|
break;
|
|
}
|
|
|
|
for(uint32_t x = 0; x < PceConstants::ClockPerScanline; x++) {
|
|
int srcOffset = (scanline * PceConstants::MaxScreenWidth) + (x / divider);
|
|
buffer[(y + 14*2) * PceConstants::ClockPerScanline + x] = palette[src[srcOffset] & 0x3FF];
|
|
}
|
|
}
|
|
}
|