Debugger: Added Event Viewer

This commit is contained in:
Sour 2019-03-07 20:12:32 -05:00
parent b6f1f54888
commit 0ada7f9d2f
43 changed files with 2309 additions and 38 deletions

View file

@ -19,6 +19,7 @@
#include "FrameLimiter.h"
#include "MessageManager.h"
#include "KeyManager.h"
#include "EventType.h"
#include "../Utilities/Timer.h"
#include "../Utilities/VirtualFile.h"
#include "../Utilities/PlatformUtilities.h"
@ -68,6 +69,8 @@ void Console::Run()
uint32_t keyCode = KeyManager::GetKeyCode("Tab");
_emulationThreadId = std::this_thread::get_id();
auto lock = _runLock.AcquireSafe();
while(!_stopFlag) {
_cpu->Exec();
@ -81,6 +84,8 @@ void Console::Run()
}
}
_emulationThreadId = thread::id();
PlatformUtilities::RestoreTimerResolution();
}
@ -136,7 +141,7 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
_memoryManager->Initialize(shared_from_this());
_cpu.reset(new Cpu(_memoryManager.get()));
_cpu.reset(new Cpu(this));
_memoryManager->IncrementMasterClockValue<162>();
//if(_debugger) {
@ -228,6 +233,11 @@ shared_ptr<Debugger> Console::GetDebugger(bool autoStart)
return debugger;
}
thread::id Console::GetEmulationThreadId()
{
return _emulationThreadId;
}
bool Console::IsRunning()
{
return _cpu != nullptr;
@ -280,4 +290,11 @@ void Console::ProcessPpuCycle()
if(_debugger) {
_debugger->ProcessPpuCycle();
}
}
void Console::ProcessEvent(EventType type)
{
if(_debugger) {
_debugger->ProcessEvent(type);
}
}

View file

@ -19,6 +19,7 @@ class VideoDecoder;
class NotificationManager;
enum class MemoryOperationType;
enum class SnesMemoryType;
enum class EventType;
class Console : public std::enable_shared_from_this<Console>
{
@ -40,6 +41,8 @@ private:
shared_ptr<VideoDecoder> _videoDecoder;
shared_ptr<DebugHud> _debugHud;
thread::id _emulationThreadId;
SimpleLock _runLock;
SimpleLock _debuggerLock;
atomic<bool> _stopFlag;
@ -71,6 +74,8 @@ public:
shared_ptr<ControlManager> GetControlManager();
shared_ptr<DmaController> GetDmaController();
shared_ptr<Debugger> GetDebugger(bool autoStart = true);
thread::id GetEmulationThreadId();
bool IsRunning();
@ -81,4 +86,5 @@ public:
void ProcessWorkRamRead(uint32_t addr, uint8_t value);
void ProcessWorkRamWrite(uint32_t addr, uint8_t value);
void ProcessPpuCycle();
void ProcessEvent(EventType type);
};

View file

@ -59,7 +59,10 @@
<ClInclude Include="ControlDeviceState.h" />
<ClInclude Include="ControlManager.h" />
<ClInclude Include="Cpu.h" />
<ClInclude Include="DebugBreakHelper.h" />
<ClInclude Include="DummyCpu.h" />
<ClInclude Include="EventManager.h" />
<ClInclude Include="EventType.h" />
<ClInclude Include="ExpressionEvaluator.h" />
<ClInclude Include="PpuTools.h" />
<ClInclude Include="RegisterHandlerB.h" />
@ -130,6 +133,7 @@
<ClCompile Include="Disassembler.cpp" />
<ClCompile Include="DisassemblyInfo.cpp" />
<ClCompile Include="DmaController.cpp" />
<ClCompile Include="EventManager.cpp" />
<ClCompile Include="ExpressionEvaluator.cpp" />
<ClCompile Include="InternalRegisters.cpp" />
<ClCompile Include="KeyManager.cpp" />

View file

@ -200,6 +200,15 @@
<ClInclude Include="PpuTools.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="EventManager.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="EventType.h">
<Filter>Misc</Filter>
</ClInclude>
<ClInclude Include="DebugBreakHelper.h">
<Filter>Debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
@ -308,8 +317,15 @@
<ClCompile Include="Breakpoint.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="BreakpointManager.cpp" />
<ClCompile Include="PpuTools.cpp" />
<ClCompile Include="BreakpointManager.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="EventManager.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="PpuTools.cpp">
<Filter>Debugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="SNES">

View file

@ -1,11 +1,14 @@
#include "stdafx.h"
#include "CpuTypes.h"
#include "Cpu.h"
#include "Console.h"
#include "MemoryManager.h"
#include "EventType.h"
Cpu::Cpu(MemoryManager* memoryManager)
Cpu::Cpu(Console *console)
{
_memoryManager = memoryManager;
_console = console;
_memoryManager = console->GetMemoryManager().get();
_state = {};
_state.PC = ReadDataWord(Cpu::ResetVector);
_state.SP = 0x1FF;
@ -292,9 +295,11 @@ void Cpu::Exec()
//Use the state of the IRQ/NMI flags on the previous cycle to determine if an IRQ is processed or not
if(_prevNmiFlag) {
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector);
_console->ProcessEvent(EventType::Nmi);
_nmiFlag = false;
} else if(_prevIrqSource && !CheckFlag(ProcFlags::IrqDisable)) {
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector);
_console->ProcessEvent(EventType::Irq);
}
}

View file

@ -9,6 +9,7 @@
#include "CpuTypes.h"
class MemoryManager;
class Console;
class Cpu
{
@ -31,7 +32,8 @@ private:
typedef void(Cpu::*Func)();
MemoryManager* _memoryManager;
MemoryManager *_memoryManager;
Console *_console;
bool _immediateMode = false;
@ -292,7 +294,7 @@ private:
void AddrMode_StkRelIndIdxY();
public:
Cpu(MemoryManager* memoryManager);
Cpu(Console *console);
~Cpu();
void Reset();

36
Core/DebugBreakHelper.h Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include "stdafx.h"
#include "Debugger.h"
#include "Console.h"
class DebugBreakHelper
{
private:
Debugger * _debugger;
bool _needResume = false;
bool _isEmulationThread = false;
public:
DebugBreakHelper(Debugger* debugger)
{
_debugger = debugger;
_isEmulationThread = debugger->GetConsole()->GetEmulationThreadId() == std::this_thread::get_id();
if(!_isEmulationThread) {
//Only attempt to break if this is done in a thread other than the main emulation thread
debugger->BreakRequest(true);
if(!debugger->IsExecutionStopped()) {
while(!debugger->IsExecutionStopped()) {}
_needResume = true;
}
}
}
~DebugBreakHelper()
{
if(!_isEmulationThread) {
_debugger->BreakRequest(false);
}
}
};

View file

@ -6,6 +6,7 @@
#include "Ppu.h"
#include "BaseCartridge.h"
#include "MemoryManager.h"
#include "SoundMixer.h"
#include "NotificationManager.h"
#include "CpuTypes.h"
#include "DisassemblyInfo.h"
@ -15,6 +16,8 @@
#include "Disassembler.h"
#include "BreakpointManager.h"
#include "PpuTools.h"
#include "EventManager.h"
#include "EventType.h"
#include "ExpressionEvaluator.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/FolderUtilities.h"
@ -29,11 +32,15 @@ Debugger::Debugger(shared_ptr<Console> console)
_watchExpEval.reset(new ExpressionEvaluator(this));
_codeDataLogger.reset(new CodeDataLogger(console->GetCartridge()->DebugGetPrgRomSize()));
_disassembler.reset(new Disassembler(console, _codeDataLogger));
_traceLogger.reset(new TraceLogger(this, _memoryManager));
_traceLogger.reset(new TraceLogger(this, _console));
_memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, console->GetCartridge()));
_breakpointManager.reset(new BreakpointManager(this));
_ppuTools.reset(new PpuTools(_console.get(), _ppu.get()));
_eventManager.reset(new EventManager(this, _cpu.get(), _ppu.get()));
_cpuStepCount = 0;
_executionStopped = false;
_breakRequestCount = 0;
string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_console->GetCartridge()->GetRomInfo().RomPath, false) + ".cdl");
_codeDataLogger->LoadCdlFile(cdlFile);
@ -100,6 +107,10 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
}
}
if(_memoryManager->IsRegister(addr)) {
_eventManager->AddEvent(DebugEventType::Register, operation);
}
ProcessBreakConditions(operation, addressInfo);
}
@ -111,6 +122,10 @@ void Debugger::ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType
_disassembler->InvalidateCache(addressInfo);
}
if(_memoryManager->IsRegister(addr)) {
_eventManager->AddEvent(DebugEventType::Register, operation);
}
ProcessBreakConditions(operation, addressInfo);
}
@ -157,12 +172,25 @@ void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInf
_cpuStepCount = 0;
}
if(_cpuStepCount == 0) {
if(_cpuStepCount == 0 || _breakRequestCount) {
_console->GetSoundMixer()->StopAudio();
_disassembler->Disassemble();
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak);
while(_cpuStepCount == 0) {
_executionStopped = true;
while(_cpuStepCount == 0 || _breakRequestCount) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
}
_executionStopped = false;
}
}
void Debugger::ProcessEvent(EventType type)
{
switch(type) {
case EventType::Nmi: _eventManager->AddEvent(DebugEventType::Nmi); break;
case EventType::Irq: _eventManager->AddEvent(DebugEventType::Irq); break;
case EventType::StartFrame: _eventManager->ClearFrameEvents(); break;
}
}
@ -191,8 +219,16 @@ void Debugger::Step(int32_t stepCount)
bool Debugger::IsExecutionStopped()
{
//TODO
return false;
return _executionStopped;
}
void Debugger::BreakRequest(bool release)
{
if(release) {
_breakRequestCount--;
} else {
_breakRequestCount++;
}
}
void Debugger::GetState(DebugState &state)
@ -225,3 +261,13 @@ shared_ptr<PpuTools> Debugger::GetPpuTools()
{
return _ppuTools;
}
shared_ptr<EventManager> Debugger::GetEventManager()
{
return _eventManager;
}
shared_ptr<Console> Debugger::GetConsole()
{
return _console;
}

View file

@ -8,18 +8,22 @@ class Cpu;
class Ppu;
class BaseCartridge;
class MemoryManager;
class CodeDataLogger;
enum class SnesMemoryType;
enum class MemoryOperationType;
enum class BreakpointCategory;
enum class EvalResultType : int32_t;
class TraceLogger;
class ExpressionEvaluator;
class MemoryDumper;
class Disassembler;
class BreakpointManager;
class PpuTools;
class CodeDataLogger;
class EventManager;
enum class EventType;
enum class SnesMemoryType;
enum class MemoryOperationType;
enum class BreakpointCategory;
enum class EvalResultType : int32_t;
struct DebugState;
struct MemoryOperationInfo;
struct AddressInfo;
@ -39,9 +43,13 @@ private:
shared_ptr<Disassembler> _disassembler;
shared_ptr<BreakpointManager> _breakpointManager;
shared_ptr<PpuTools> _ppuTools;
shared_ptr<EventManager> _eventManager;
unique_ptr<ExpressionEvaluator> _watchExpEval;
atomic<bool> _executionStopped;
atomic<uint32_t> _breakRequestCount;
atomic<int32_t> _cpuStepCount;
uint8_t _prevOpCode = 0;
@ -60,6 +68,7 @@ public:
void ProcessPpuCycle();
void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo);
void ProcessEvent(EventType type);
int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache);
@ -67,6 +76,8 @@ public:
void Step(int32_t stepCount);
bool IsExecutionStopped();
void BreakRequest(bool release);
void GetState(DebugState &state);
shared_ptr<TraceLogger> GetTraceLogger();
@ -74,4 +85,6 @@ public:
shared_ptr<Disassembler> GetDisassembler();
shared_ptr<BreakpointManager> GetBreakpointManager();
shared_ptr<PpuTools> GetPpuTools();
shared_ptr<EventManager> GetEventManager();
shared_ptr<Console> GetConsole();
};

View file

@ -252,10 +252,9 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
data.OpSize = disInfo->GetOperandSize() + 1;
MemoryManager *memoryManager = _console->GetMemoryManager().get();
data.EffectiveAddress = disInfo->GetEffectiveAddress(state, memoryManager);
data.EffectiveAddress = disInfo->GetEffectiveAddress(state, _console);
if(data.EffectiveAddress >= 0) {
data.Value = disInfo->GetMemoryValue(data.EffectiveAddress, memoryManager, data.ValueSize);
data.Value = disInfo->GetMemoryValue(data.EffectiveAddress, _console->GetMemoryManager().get(), data.ValueSize);
} else {
data.ValueSize = 0;
}

View file

@ -185,18 +185,18 @@ void DisassemblyInfo::GetByteCode(string &out)
out += str.ToString();
}
void DisassemblyInfo::GetEffectiveAddressString(string &out, CpuState &state, MemoryManager* memoryManager)
void DisassemblyInfo::GetEffectiveAddressString(string &out, CpuState &state, Console* console)
{
int32_t effectiveAddress = GetEffectiveAddress(state, memoryManager);
int32_t effectiveAddress = GetEffectiveAddress(state, console);
if(effectiveAddress >= 0) {
out += " [" + HexUtilities::ToHex24(effectiveAddress) + "]";
}
}
int32_t DisassemblyInfo::GetEffectiveAddress(CpuState &state, MemoryManager *memoryManager)
int32_t DisassemblyInfo::GetEffectiveAddress(CpuState &state, Console *console)
{
if(_addrMode > AddrMode::ImmM && _addrMode != AddrMode::Acc && _addrMode != AddrMode::Imp && _addrMode != AddrMode::Stk && _addrMode != AddrMode::Rel && _addrMode != AddrMode::RelLng && _addrMode != AddrMode::BlkMov) {
DummyCpu cpu(memoryManager);
DummyCpu cpu(console);
state.PS &= ~(ProcFlags::IndexMode8 | ProcFlags::MemoryMode8);
state.PS |= _flags;
cpu.SetDummyState(state);

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include <unordered_map>
class Console;
class MemoryManager;
struct CpuState;
@ -36,8 +37,8 @@ public:
void GetByteCode(uint8_t copyBuffer[4]);
void GetByteCode(string &out);
void GetEffectiveAddressString(string &out, CpuState &state, MemoryManager* memoryManager);
int32_t GetEffectiveAddress(CpuState &state, MemoryManager *memoryManager);
void GetEffectiveAddressString(string &out, CpuState &state, Console* console);
int32_t GetEffectiveAddress(CpuState &state, Console *console);
uint16_t GetMemoryValue(uint32_t effectiveAddress, MemoryManager *memoryManager, uint8_t &valueSize);
};

192
Core/EventManager.cpp Normal file
View file

@ -0,0 +1,192 @@
#include "stdafx.h"
#include "EventManager.h"
#include "DebugTypes.h"
#include "Cpu.h"
#include "Ppu.h"
#include "Debugger.h"
#include "DebugBreakHelper.h"
EventManager::EventManager(Debugger *debugger, Cpu *cpu, Ppu *ppu)
{
_debugger = debugger;
_cpu = cpu;
_ppu = ppu;
}
void EventManager::AddEvent(DebugEventType type, MemoryOperationInfo &operation, int32_t breakpointId)
{
DebugEventInfo evt;
evt.Type = type;
evt.Operation = operation;
evt.Scanline = _ppu->GetScanline();
evt.Cycle = _ppu->GetCycle();
evt.BreakpointId = breakpointId;
evt.ProgramCounter = _cpu->GetState().PC;
_debugEvents.push_back(evt);
}
void EventManager::AddEvent(DebugEventType type)
{
DebugEventInfo evt = {};
evt.Type = type;
evt.Scanline = _ppu->GetScanline();
evt.Cycle = _ppu->GetCycle();
evt.ProgramCounter = _cpu->GetState().PC;
_debugEvents.push_back(evt);
}
void EventManager::GetEvents(DebugEventInfo *eventArray, uint32_t &maxEventCount, bool getPreviousFrameData)
{
DebugBreakHelper breakHelper(_debugger);
vector<DebugEventInfo> &events = getPreviousFrameData ? _prevDebugEvents : _debugEvents;
uint32_t eventCount = std::min(maxEventCount, (uint32_t)events.size());
memcpy(eventArray, events.data(), eventCount * sizeof(DebugEventInfo));
maxEventCount = eventCount;
}
DebugEventInfo EventManager::GetEvent(uint16_t scanline, uint16_t cycle, EventViewerDisplayOptions &options)
{
auto lock = _lock.AcquireSafe();
for(DebugEventInfo &evt : _sentEvents) {
if(evt.Cycle == cycle && evt.Scanline == scanline) {
return evt;
}
}
DebugEventInfo empty = {};
empty.ProgramCounter = 0xFFFFFFFF;
return empty;
}
uint32_t EventManager::GetEventCount(bool getPreviousFrameData)
{
DebugBreakHelper breakHelper(_debugger);
return (uint32_t)(getPreviousFrameData ? _prevDebugEvents.size() : _debugEvents.size());
}
void EventManager::ClearFrameEvents()
{
_prevDebugEvents = _debugEvents;
_debugEvents.clear();
}
void EventManager::DrawEvent(DebugEventInfo &evt, bool drawBackground, uint32_t *buffer, EventViewerDisplayOptions &options)
{
bool isWrite = evt.Operation.Type == MemoryOperationType::Write || evt.Operation.Type == MemoryOperationType::DmaWrite;
bool showEvent = false;
uint32_t color = 0;
switch(evt.Type) {
case DebugEventType::Breakpoint: showEvent = options.ShowMarkedBreakpoints; color = options.BreakpointColor; break;
case DebugEventType::Irq: showEvent = options.ShowIrq; color = options.IrqColor; break;
case DebugEventType::Nmi: showEvent = options.ShowNmi; color = options.NmiColor; break;
case DebugEventType::Register:
uint16_t reg = evt.Operation.Address & 0xFFFF;
if(reg <= 0x213F) {
showEvent = isWrite ? options.ShowPpuRegisterWrites : options.ShowPpuRegisterReads;
color = isWrite ? options.PpuRegisterWriteColor : options.PpuRegisterReadColor;
} else if(reg <= 0x217F) {
showEvent = isWrite ? options.ShowApuRegisterWrites : options.ShowApuRegisterReads;
color = isWrite ? options.ApuRegisterWriteColor : options.ApuRegisterReadColor;
} else if(reg <= 0x2183) {
showEvent = isWrite ? options.ShowWorkRamRegisterWrites : options.ShowWorkRamRegisterReads;
color = isWrite ? options.WorkRamRegisterWriteColor : options.WorkRamRegisterReadColor;
} else if(reg >= 0x4000) {
showEvent = isWrite ? options.ShowCpuRegisterWrites : options.ShowCpuRegisterReads;
color = isWrite ? options.CpuRegisterWriteColor : options.CpuRegisterReadColor;
}
break;
}
if(!showEvent) {
return;
}
if(drawBackground){
color = 0xFF000000 | ((color >> 1) & 0x7F7F7F);
} else {
_sentEvents.push_back(evt);
color |= 0xFF000000;
}
int iMin = drawBackground ? -2 : 0;
int iMax = drawBackground ? 3 : 1;
int jMin = drawBackground ? -2 : 0;
int jMax = drawBackground ? 3 : 1;
uint32_t y = evt.Scanline * 2;
uint32_t x = evt.Cycle * 2;
for(int i = iMin; i <= iMax; i++) {
for(int j = jMin; j <= jMax; j++) {
int32_t pos = (y + i) * 340 * 2 + x + j;
if(pos < 0 || pos > 340 * 2 * 262 * 2) {
continue;
}
buffer[pos] = color;
}
}
}
void EventManager::TakeEventSnapshot(EventViewerDisplayOptions options)
{
DebugBreakHelper breakHelper(_debugger);
auto lock = _lock.AcquireSafe();
_snapshot.clear();
uint16_t cycle = _ppu->GetState().Cycle;
uint16_t scanline = _ppu->GetState().Scanline;
uint32_t key = (scanline << 9) + cycle;
_snapshot = _debugEvents;
_snapshotScanline = scanline;
if(options.ShowPreviousFrameEvents) {
for(DebugEventInfo &evt : _prevDebugEvents) {
uint32_t evtKey = (evt.Scanline << 9) + evt.Cycle;
if(evtKey > key) {
_snapshot.push_back(evt);
}
}
}
}
void EventManager::GetDisplayBuffer(uint32_t *buffer, EventViewerDisplayOptions options)
{
auto lock = _lock.AcquireSafe();
_sentEvents.clear();
for(int i = 0; i < 340 * 2 * 262 * 2; i++) {
buffer[i] = 0xFF555555;
}
bool overscanMode = _ppu->GetState().OverscanMode;
uint16_t *ppuBuffer = _ppu->GetScreenBuffer();
uint32_t pixelCount = 256*2*239*2;
for(uint32_t y = 0, len = overscanMode ? 239*2 : 224*2; y < len; y++) {
for(uint32_t x = 0; x < 512; x++) {
uint16_t rgb555 = ppuBuffer[(y << 9) | x];
uint8_t b = (rgb555 >> 10) * 256 / 32;
uint8_t g = ((rgb555 >> 5) & 0x1F) * 256 / 32;
uint8_t r = (rgb555 & 0x1F) * 256 / 32;
buffer[(y + 2)*340*2 + x + 22*2] = 0xFF000000 | (r << 16) | (g << 8) | b;
}
}
constexpr uint32_t nmiColor = 0xFF55FFFF;
int nmiScanline = (overscanMode ? 240 : 225) * 2 * 340 * 2;
uint32_t scanlineOffset = _snapshotScanline * 2 * 340 * 2;
for(int i = 0; i < 340 * 2; i++) {
buffer[nmiScanline + i] = nmiColor;
buffer[nmiScanline + 340 * 2 + i] = nmiColor;
buffer[scanlineOffset + i] = nmiColor;
buffer[scanlineOffset + 340 * 2 + i] = nmiColor;
}
for(DebugEventInfo &evt : _snapshot) {
DrawEvent(evt, true, buffer, options);
}
for(DebugEventInfo &evt : _snapshot) {
DrawEvent(evt, false, buffer, options);
}
}

94
Core/EventManager.h Normal file
View file

@ -0,0 +1,94 @@
#pragma once
#include "stdafx.h"
#include "DmaController.h"
#include "DebugTypes.h"
#include "../Utilities/SimpleLock.h"
enum class DebugEventType;
struct DebugEventInfo;
struct EventViewerDisplayOptions;
class Cpu;
class Ppu;
class Debugger;
class EventManager
{
private:
Cpu * _cpu;
Ppu *_ppu;
Debugger *_debugger;
vector<DebugEventInfo> _debugEvents;
vector<DebugEventInfo> _prevDebugEvents;
vector<DebugEventInfo> _sentEvents;
vector<DebugEventInfo> _snapshot;
uint16_t _snapshotScanline;
SimpleLock _lock;
void DrawEvent(DebugEventInfo &evt, bool drawBackground, uint32_t *buffer, EventViewerDisplayOptions &options);
public:
EventManager(Debugger *debugger, Cpu *cpu, Ppu *ppu);
void AddEvent(DebugEventType type, MemoryOperationInfo &operation, int32_t breakpointId = -1);
void AddEvent(DebugEventType type);
void GetEvents(DebugEventInfo *eventArray, uint32_t &maxEventCount, bool getPreviousFrameData);
uint32_t GetEventCount(bool getPreviousFrameData);
void ClearFrameEvents();
void TakeEventSnapshot(EventViewerDisplayOptions options);
void GetDisplayBuffer(uint32_t *buffer, EventViewerDisplayOptions options);
DebugEventInfo GetEvent(uint16_t scanline, uint16_t cycle, EventViewerDisplayOptions &options);
};
enum class DebugEventType
{
Register,
Nmi,
Irq,
Breakpoint
};
struct DebugEventInfo
{
MemoryOperationInfo Operation;
DebugEventType Type;
uint32_t ProgramCounter;
uint16_t Scanline;
uint16_t Cycle;
int16_t BreakpointId;
//DmaChannelConfig DmaChannelInfo;
//uint8_t DmaChannel;
};
struct EventViewerDisplayOptions
{
bool ShowPpuRegisterWrites;
bool ShowPpuRegisterReads;
bool ShowCpuRegisterWrites;
bool ShowCpuRegisterReads;
bool ShowApuRegisterWrites;
bool ShowApuRegisterReads;
bool ShowWorkRamRegisterWrites;
bool ShowWorkRamRegisterReads;
bool ShowNmi;
bool ShowIrq;
bool ShowMarkedBreakpoints;
bool ShowPreviousFrameEvents;
uint32_t IrqColor;
uint32_t NmiColor;
uint32_t BreakpointColor;
uint32_t PpuRegisterReadColor;
uint32_t PpuRegisterWriteColor;
uint32_t ApuRegisterReadColor;
uint32_t ApuRegisterWriteColor;
uint32_t CpuRegisterReadColor;
uint32_t CpuRegisterWriteColor;
uint32_t WorkRamRegisterReadColor;
uint32_t WorkRamRegisterWriteColor;
};

9
Core/EventType.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
enum class EventType
{
Nmi = 0,
Irq = 1,
StartFrame = 2,
EndFrame = 3
};

View file

@ -233,6 +233,11 @@ uint8_t * MemoryManager::DebugGetWorkRam()
return _workRam;
}
bool MemoryManager::IsRegister(uint32_t cpuAddress)
{
return _handlers[cpuAddress >> 12] == _registerHandlerA.get() || _handlers[cpuAddress >> 12] == _registerHandlerB.get();
}
AddressInfo MemoryManager::GetAbsoluteAddress(uint32_t addr)
{
if(_handlers[addr >> 12]) {

View file

@ -58,6 +58,7 @@ public:
uint64_t GetMasterClock();
uint8_t* DebugGetWorkRam();
bool IsRegister(uint32_t cpuAddress);
AddressInfo GetAbsoluteAddress(uint32_t addr);
int GetRelativeAddress(AddressInfo &address, int32_t cpuAddress = -1);
};

View file

@ -10,6 +10,7 @@
#include "NotificationManager.h"
#include "DmaController.h"
#include "MessageManager.h"
#include "EventType.h"
#include "../Utilities/HexUtilities.h"
Ppu::Ppu(shared_ptr<Console> console)
@ -54,6 +55,16 @@ uint32_t Ppu::GetFrameCount()
return _frameCount;
}
uint16_t Ppu::GetScanline()
{
return _scanline;
}
uint16_t Ppu::GetCycle()
{
return _cycle;
}
PpuState Ppu::GetState()
{
PpuState state;
@ -110,6 +121,7 @@ void Ppu::Exec()
_scanline = 0;
_rangeOver = false;
_timeOver = false;
_console->ProcessEvent(EventType::StartFrame);
if(_mosaicEnabled) {
_mosaicStartScanline = 0;
@ -1066,6 +1078,11 @@ void Ppu::SendFrame()
}
}
uint16_t* Ppu::GetScreenBuffer()
{
return _currentBuffer;
}
uint8_t* Ppu::GetVideoRam()
{
return _vram;

View file

@ -224,10 +224,13 @@ public:
~Ppu();
uint32_t GetFrameCount();
uint16_t GetScanline();
uint16_t GetCycle();
PpuState GetState();
void Exec();
uint16_t* GetScreenBuffer();
uint8_t* GetVideoRam();
uint8_t* GetCgRam();
uint8_t* GetSpriteRam();

View file

@ -10,9 +10,9 @@
string TraceLogger::_executionTrace = "";
TraceLogger::TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager)
TraceLogger::TraceLogger(Debugger* debugger, shared_ptr<Console> console)
{
_memoryManager = memoryManager;
_console = console;
_currentPos = 0;
_logCount = 0;
_logToFile = false;
@ -218,17 +218,17 @@ void TraceLogger::GetTraceRow(string &output, CpuState &cpuState, PpuState &ppuS
case RowDataType::EffectiveAddress:
{
string effectiveAddress;
disassemblyInfo.GetEffectiveAddressString(effectiveAddress, cpuState, _memoryManager.get());
disassemblyInfo.GetEffectiveAddressString(effectiveAddress, cpuState, _console.get());
WriteValue(output, effectiveAddress, rowPart);
break;
}
case RowDataType::MemoryValue:
{
int32_t address = disassemblyInfo.GetEffectiveAddress(cpuState, _memoryManager.get());
int32_t address = disassemblyInfo.GetEffectiveAddress(cpuState, _console.get());
if(address >= 0) {
uint8_t valueSize;
uint16_t value = disassemblyInfo.GetMemoryValue(address, _memoryManager.get(), valueSize);
uint16_t value = disassemblyInfo.GetMemoryValue(address, _console->GetMemoryManager().get(), valueSize);
if(rowPart.DisplayInHex) {
output += "= $";
if(valueSize == 2) {

View file

@ -5,7 +5,7 @@
#include "DisassemblyInfo.h"
#include "../Utilities/SimpleLock.h"
class MemoryManager;
class Console;
class Debugger;
struct DebugState;
@ -63,7 +63,7 @@ private:
string _outputFilepath;
string _outputBuffer;
ofstream _outputFile;
shared_ptr<MemoryManager> _memoryManager;
shared_ptr<Console> _console;
//shared_ptr<LabelManager> _labelManager;
vector<RowPart> _rowParts;
@ -94,7 +94,7 @@ private:
template<typename T> void WriteValue(string &output, T value, RowPart& rowPart);
public:
TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager);
TraceLogger(Debugger* debugger, shared_ptr<Console> console);
~TraceLogger();
void Log(DebugState &state, DisassemblyInfo &disassemblyInfo);

View file

@ -8,6 +8,7 @@
#include "../Core/Breakpoint.h"
#include "../Core/BreakpointManager.h"
#include "../Core/PpuTools.h"
#include "../Core/EventManager.h"
extern shared_ptr<Console> _console;
@ -63,4 +64,10 @@ extern "C"
DllExport void __stdcall GetTilemap(GetTilemapOptions options, uint32_t *buffer) { GetDebugger()->GetPpuTools()->GetTilemap(options, buffer); }
DllExport void __stdcall SetViewerUpdateTiming(uint32_t viewerId, uint16_t scanline, uint16_t cycle) { GetDebugger()->GetPpuTools()->SetViewerUpdateTiming(viewerId, scanline, cycle); }
DllExport void __stdcall GetDebugEvents(DebugEventInfo *infoArray, uint32_t &maxEventCount, bool getPreviousFrameData) { GetDebugger()->GetEventManager()->GetEvents(infoArray, maxEventCount, getPreviousFrameData); }
DllExport uint32_t __stdcall GetDebugEventCount(bool getPreviousFrameData) { return GetDebugger()->GetEventManager()->GetEventCount(getPreviousFrameData); }
DllExport void __stdcall GetEventViewerOutput(uint32_t *buffer, EventViewerDisplayOptions options) { GetDebugger()->GetEventManager()->GetDisplayBuffer(buffer, options); }
DllExport DebugEventInfo __stdcall GetEventViewerEvent(uint16_t scanline, uint16_t cycle, EventViewerDisplayOptions options) { return GetDebugger()->GetEventManager()->GetEvent(scanline, cycle, options); }
DllExport void __stdcall TakeEventSnapshot(EventViewerDisplayOptions options) { GetDebugger()->GetEventManager()->TakeEventSnapshot(options); }
};

View file

@ -19,10 +19,10 @@ namespace Mesen.GUI.Config
public DebuggerShortcutsConfig Shortcuts = new DebuggerShortcutsConfig();
public TraceLoggerInfo TraceLogger = new TraceLoggerInfo();
public HexEditorInfo HexEditor = new HexEditorInfo();
public EventViewerInfo EventViewer = new EventViewerInfo();
public bool ShowSelectionLength = false;
public XmlColor EventViewerBreakpointColor = ColorTranslator.FromHtml("#1898E4");
public XmlColor CodeOpcodeColor = Color.FromArgb(22, 37, 37);
public XmlColor CodeLabelDefinitionColor = Color.Blue;
public XmlColor CodeImmediateColor = Color.Chocolate;

View file

@ -0,0 +1,70 @@
using Mesen.GUI.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Config
{
public class EventViewerInfo
{
public bool ShowPpuRegisterWrites = true;
public bool ShowPpuRegisterReads = true;
public bool ShowCpuRegisterWrites = true;
public bool ShowCpuRegisterReads = true;
public bool ShowApuRegisterWrites = false;
public bool ShowApuRegisterReads = false;
public bool ShowWorkRamRegisterWrites = false;
public bool ShowWorkRamRegisterReads = false;
public bool ShowNmi = true;
public bool ShowIrq = true;
public bool ShowMarkedBreakpoints = true;
public bool ShowPreviousFrameEvents = true;
public XmlColor IrqColor = ColorTranslator.FromHtml("#FFADAC");
public XmlColor NmiColor = ColorTranslator.FromHtml("#FFADAC");
public XmlColor BreakpointColor = ColorTranslator.FromHtml("#FFADAC");
public XmlColor PpuRegisterReadColor = ColorTranslator.FromHtml("#007597");
public XmlColor PpuRegisterWriteColor = ColorTranslator.FromHtml("#C92929");
public XmlColor ApuRegisterReadColor = ColorTranslator.FromHtml("#F9FEAC");
public XmlColor ApuRegisterWriteColor = ColorTranslator.FromHtml("#9F93C6");
public XmlColor CpuRegisterReadColor = ColorTranslator.FromHtml("#1898E4");
public XmlColor CpuRegisterWriteColor = ColorTranslator.FromHtml("#FF5E5E");
public XmlColor WorkRamRegisterReadColor = ColorTranslator.FromHtml("#8E33FF");
public XmlColor WorkRamRegisterWriteColor = ColorTranslator.FromHtml("#2EFF28");
public EventViewerDisplayOptions GetInteropOptions()
{
return new EventViewerDisplayOptions() {
ShowPpuRegisterWrites = this.ShowPpuRegisterWrites,
ShowPpuRegisterReads = this.ShowPpuRegisterReads,
ShowCpuRegisterWrites = this.ShowCpuRegisterWrites,
ShowCpuRegisterReads = this.ShowCpuRegisterReads,
ShowApuRegisterWrites = this.ShowApuRegisterWrites,
ShowApuRegisterReads = this.ShowApuRegisterReads,
ShowWorkRamRegisterWrites = this.ShowWorkRamRegisterWrites,
ShowWorkRamRegisterReads = this.ShowWorkRamRegisterReads,
ShowNmi = this.ShowNmi,
ShowIrq = this.ShowIrq,
ShowMarkedBreakpoints = this.ShowMarkedBreakpoints,
ShowPreviousFrameEvents = this.ShowPreviousFrameEvents,
IrqColor = (uint)this.IrqColor.Color.ToArgb(),
NmiColor = (uint)this.NmiColor.Color.ToArgb(),
BreakpointColor = (uint)this.BreakpointColor.Color.ToArgb(),
PpuRegisterReadColor = (uint)this.PpuRegisterReadColor.Color.ToArgb(),
PpuRegisterWriteColor = (uint)this.PpuRegisterWriteColor.Color.ToArgb(),
ApuRegisterReadColor = (uint)this.ApuRegisterReadColor.Color.ToArgb(),
ApuRegisterWriteColor = (uint)this.ApuRegisterWriteColor.Color.ToArgb(),
CpuRegisterReadColor = (uint)this.CpuRegisterReadColor.Color.ToArgb(),
CpuRegisterWriteColor = (uint)this.CpuRegisterWriteColor.Color.ToArgb(),
WorkRamRegisterReadColor = (uint)this.WorkRamRegisterReadColor.Color.ToArgb(),
WorkRamRegisterWriteColor = (uint)this.WorkRamRegisterWriteColor.Color.ToArgb()
};
}
}
}

View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public class ctrlColorPicker : PictureBox
{
public ctrlColorPicker() : base()
{
this.BorderStyle = BorderStyle.FixedSingle;
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
using(ColorDialog cd = new ColorDialog()) {
cd.SolidColorOnly = true;
cd.AllowFullOpen = true;
cd.FullOpen = true;
cd.Color = this.BackColor;
if(cd.ShowDialog() == DialogResult.OK) {
this.BackColor = cd.Color;
}
}
}
}
}

View file

@ -1052,7 +1052,7 @@ namespace Mesen.GUI.Debugger.Controls
}
if(lineProperties.Symbol.HasFlag(LineSymbol.Mark)) {
using(Brush b = new SolidBrush(ConfigManager.Config.Debug.EventViewerBreakpointColor)) {
using(Brush b = new SolidBrush(ConfigManager.Config.Debug.EventViewer.BreakpointColor)) {
g.FillEllipse(b, circleOffsetX + circleSize * 3 / 4, positionY + 1, lineHeight / 2.0f, lineHeight / 2.0f);
}
g.DrawEllipse(Pens.Black, circleOffsetX + circleSize * 3 / 4, positionY + 1, lineHeight / 2.0f, lineHeight / 2.0f);

View file

@ -35,6 +35,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.TraceLogger: frm = new frmTraceLogger(); frm.Icon = Properties.Resources.LogWindow; break;
case DebugWindow.MemoryTools: frm = new frmMemoryTools(); frm.Icon = Properties.Resources.CheatCode; break;
case DebugWindow.TilemapViewer: frm = new frmTilemapViewer(); frm.Icon = Properties.Resources.VideoOptions; break;
case DebugWindow.EventViewer: frm = new frmEventViewer(); frm.Icon = Properties.Resources.NesEventViewer; break;
}
_openedWindows.Add(frm);
frm.FormClosed += Debugger_FormClosed;
@ -117,6 +118,7 @@ namespace Mesen.GUI.Debugger
Debugger,
MemoryTools,
TraceLogger,
TilemapViewer
TilemapViewer,
EventViewer
}
}

View file

@ -0,0 +1,280 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Mesen.GUI.Controls;
using Mesen.GUI.Forms;
using Mesen.GUI.Config;
namespace Mesen.GUI.Debugger
{
public partial class ctrlEventViewerPpuView : BaseControl
{
private int _baseWidth = 340 * 2;
private int _baseHeight = 262 * 2;
private EntityBinder _entityBinder = new EntityBinder();
private frmInfoTooltip _tooltip = null;
private Point _lastPos = new Point(-1, -1);
private bool _needUpdate = false;
private Bitmap _screenBitmap = null;
private Bitmap _overlayBitmap = null;
private Bitmap _displayBitmap = null;
private byte[] _pictureData = null;
private Font _overlayFont;
private bool _zoomed = false;
public ctrlEventViewerPpuView()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!IsDesignMode) {
tmrOverlay.Start();
_overlayFont = new Font(BaseControl.MonospaceFontFamily, 10);
_entityBinder.Entity = ConfigManager.Config.Debug.EventViewer;
_entityBinder.AddBinding(nameof(EventViewerInfo.ApuRegisterReadColor), picApuReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.ApuRegisterWriteColor), picApuWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.CpuRegisterReadColor), picCpuReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.CpuRegisterWriteColor), picCpuWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.IrqColor), picIrq);
_entityBinder.AddBinding(nameof(EventViewerInfo.BreakpointColor), picMarkedBreakpoints);
_entityBinder.AddBinding(nameof(EventViewerInfo.NmiColor), picNmi);
_entityBinder.AddBinding(nameof(EventViewerInfo.PpuRegisterReadColor), picPpuReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.PpuRegisterWriteColor), picPpuWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.WorkRamRegisterReadColor), picWramReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.WorkRamRegisterWriteColor), picWramWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowApuRegisterReads), chkShowApuRegisterReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowApuRegisterWrites), chkShowApuRegisterWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowCpuRegisterReads), chkShowCpuRegisterReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowCpuRegisterWrites), chkShowCpuRegisterWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowIrq), chkShowIrq);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowMarkedBreakpoints), chkShowMarkedBreakpoints);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowNmi), chkShowNmi);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowPpuRegisterReads), chkShowPpuRegisterReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowPpuRegisterWrites), chkShowPpuRegisterWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowWorkRamRegisterReads), chkShowWorkRamRegisterReads);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowWorkRamRegisterWrites), chkShowWorkRamRegisterWrites);
_entityBinder.AddBinding(nameof(EventViewerInfo.ShowPreviousFrameEvents), chkShowPreviousFrameEvents);
_entityBinder.UpdateUI();
RefreshData();
RefreshViewer();
}
}
protected override void OnHandleDestroyed(EventArgs e)
{
if(!IsDesignMode) {
_entityBinder.UpdateObject();
ConfigManager.ApplyChanges();
}
base.OnHandleDestroyed(e);
}
public void RefreshData()
{
this.BeginInvoke((Action)(() => {
_entityBinder.UpdateObject();
}));
EventViewerDisplayOptions options = ConfigManager.Config.Debug.EventViewer.GetInteropOptions();
DebugApi.TakeEventSnapshot(options);
}
public void RefreshViewer()
{
_entityBinder.UpdateObject();
EventViewerDisplayOptions options = ConfigManager.Config.Debug.EventViewer.GetInteropOptions();
_pictureData = DebugApi.GetEventViewerOutput(options);
int picHeight = _baseHeight;
if(_screenBitmap == null || _screenBitmap.Height != picHeight) {
_screenBitmap = new Bitmap(_baseWidth, picHeight);
_overlayBitmap = new Bitmap(_baseWidth, picHeight);
_displayBitmap = new Bitmap(_baseWidth, picHeight);
}
GCHandle handle = GCHandle.Alloc(this._pictureData, GCHandleType.Pinned);
try {
Bitmap source = new Bitmap(_baseWidth, _baseHeight, _baseWidth*4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
using(Graphics g = Graphics.FromImage(_screenBitmap)) {
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
g.DrawImageUnscaled(source, 0, 0);
}
} finally {
handle.Free();
}
UpdateDisplay(true);
}
private void UpdateDisplay(bool forceUpdate)
{
if(!_needUpdate && !forceUpdate) {
return;
}
using(Graphics g = Graphics.FromImage(_displayBitmap)) {
g.DrawImage(_screenBitmap, 0, 0);
g.DrawImage(_overlayBitmap, 0, 0);
if(_lastPos.X >= 0) {
string location = _lastPos.X / 2 + ", " + (_lastPos.Y / 2);
SizeF size = g.MeasureString(location, _overlayFont);
int x = _lastPos.X + 15;
int y = _lastPos.Y - (int)size.Height - 5;
if(x + size.Width > _displayBitmap.Width - 5) {
x -= (int)size.Width + 20;
}
if(y < size.Height + 5) {
y = _lastPos.Y + 5;
}
g.DrawOutlinedString(location, _overlayFont, Brushes.Black, Brushes.White, x, y);
}
}
picViewer.Image = _displayBitmap;
_needUpdate = false;
}
private void UpdateOverlay(Point p)
{
int x = ((p.X & ~0x01) / (_zoomed ? 2 : 1)) & ~0x01;
int y = ((p.Y & ~0x01) / (_zoomed ? 2 : 1)) & ~0x01;
if(_lastPos.X == x && _lastPos.Y == y) {
//Same x,y location, no need to update
return;
}
using(Graphics g = Graphics.FromImage(_overlayBitmap)) {
g.Clear(Color.Transparent);
using(Pen bg = new Pen(Color.FromArgb(128, Color.LightGray))) {
g.DrawRectangle(bg, x - 1, 0, 3, _overlayBitmap.Height);
g.DrawRectangle(bg, 0, y - 1, _overlayBitmap.Width, 3);
}
}
_needUpdate = true;
_lastPos = new Point(x, y);
}
private void ClearOverlay()
{
using(Graphics g = Graphics.FromImage(_overlayBitmap)) {
g.Clear(Color.Transparent);
}
UpdateDisplay(false);
_lastPos = new Point(-1, -1);
}
private void picPicture_MouseMove(object sender, MouseEventArgs e)
{
int cycle = ((e.X & ~0x01) / (_zoomed ? 2 : 1)) / 2;
int scanline = ((e.Y & ~0x01) / (_zoomed ? 2 : 1)) / 2;
EventViewerDisplayOptions options = ConfigManager.Config.Debug.EventViewer.GetInteropOptions();
DebugEventInfo evt = DebugApi.GetEventViewerEvent((UInt16)scanline, (UInt16)cycle, options);
if(evt.ProgramCounter == 0xFFFFFFFF) {
ResetTooltip();
UpdateOverlay(e.Location);
return;
}
Dictionary<string, string> values = new Dictionary<string, string>() {
{ "Type", ResourceHelper.GetEnumText(evt.Type) },
{ "Scanline", evt.Scanline.ToString() },
{ "Cycle", evt.Cycle.ToString() },
{ "PC", "$" + evt.ProgramCounter.ToString("X6") },
};
switch(evt.Type) {
case DebugEventType.Register:
bool isWrite = evt.Operation.Type == MemoryOperationType.Write || evt.Operation.Type == MemoryOperationType.DmaWrite;
bool isDma = evt.Operation.Type == MemoryOperationType.DmaWrite|| evt.Operation.Type == MemoryOperationType.DmaRead;
values["Register"] = "$" + evt.Operation.Address.ToString("X4") + (isWrite ? " (Write)" : " (Read)") + (isDma ? " (DMA)" : "");
values["Value"] = "$" + evt.Operation.Value.ToString("X2");
break;
case DebugEventType.Breakpoint:
//TODO
/*ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
if(debugEvent.BreakpointId >= 0 && debugEvent.BreakpointId < breakpoints.Count) {
Breakpoint bp = breakpoints[debugEvent.BreakpointId];
values["BP Type"] = bp.ToReadableType();
values["BP Addresses"] = bp.GetAddressString(true);
if(bp.Condition.Length > 0) {
values["BP Condition"] = bp.Condition;
}
}*/
break;
}
double scale = _zoomed ? 2 : 1;
UpdateOverlay(new Point((int)(evt.Cycle * 2 * scale), (int)(evt.Scanline * 2 * scale)));
ResetTooltip();
Form parentForm = this.FindForm();
_tooltip = new frmInfoTooltip(parentForm, values, 10);
_tooltip.FormClosed += (s, ev) => { _tooltip = null; };
Point location = picViewer.PointToScreen(e.Location);
location.Offset(10, 10);
_tooltip.SetFormLocation(location, this);
}
private void ResetTooltip()
{
if(_tooltip != null) {
_tooltip.Close();
_tooltip = null;
}
}
private void picPicture_MouseLeave(object sender, EventArgs e)
{
ResetTooltip();
ClearOverlay();
}
private void tmrOverlay_Tick(object sender, EventArgs e)
{
UpdateDisplay(false);
}
private void picPicture_DoubleClick(object sender, EventArgs e)
{
_zoomed = !_zoomed;
UpdateViewerSize();
}
private void UpdateViewerSize()
{
picViewer.Width = (_zoomed ? _baseWidth * 2 : _baseWidth) + 2;
picViewer.Height = (_zoomed ? _baseHeight * 2 : _baseHeight) + 2;
}
private void chkOption_Click(object sender, EventArgs e)
{
RefreshViewer();
}
}
}

View file

@ -0,0 +1,524 @@
using Mesen.GUI.Controls;
namespace Mesen.GUI.Debugger
{
partial class ctrlEventViewerPpuView
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.picViewer = new Mesen.GUI.Controls.ctrlMesenPictureBox();
this.tmrOverlay = new System.Windows.Forms.Timer(this.components);
this.pnlPicture = new System.Windows.Forms.Panel();
this.grpOptions = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.picNmi = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowNmi = new System.Windows.Forms.CheckBox();
this.picIrq = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowIrq = new System.Windows.Forms.CheckBox();
this.label4 = new System.Windows.Forms.Label();
this.picWramWrites = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowWorkRamRegisterWrites = new System.Windows.Forms.CheckBox();
this.picWramReads = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowWorkRamRegisterReads = new System.Windows.Forms.CheckBox();
this.label3 = new System.Windows.Forms.Label();
this.picCpuWrites = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowCpuRegisterWrites = new System.Windows.Forms.CheckBox();
this.picCpuReads = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowCpuRegisterReads = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label();
this.picApuWrites = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowApuRegisterWrites = new System.Windows.Forms.CheckBox();
this.picApuReads = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowApuRegisterReads = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.picPpuWrites = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowPpuRegisterWrites = new System.Windows.Forms.CheckBox();
this.chkShowPpuRegisterReads = new System.Windows.Forms.CheckBox();
this.lblPpuRegisters = new System.Windows.Forms.Label();
this.picPpuReads = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowMarkedBreakpoints = new System.Windows.Forms.CheckBox();
this.picMarkedBreakpoints = new Mesen.GUI.Debugger.ctrlColorPicker();
this.chkShowPreviousFrameEvents = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.picViewer)).BeginInit();
this.pnlPicture.SuspendLayout();
this.grpOptions.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picNmi)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picIrq)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picWramWrites)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picWramReads)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picCpuWrites)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picCpuReads)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picApuWrites)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picApuReads)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picPpuWrites)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picPpuReads)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picMarkedBreakpoints)).BeginInit();
this.SuspendLayout();
//
// picViewer
//
this.picViewer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picViewer.Cursor = System.Windows.Forms.Cursors.Default;
this.picViewer.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.picViewer.Location = new System.Drawing.Point(0, 0);
this.picViewer.Margin = new System.Windows.Forms.Padding(0);
this.picViewer.Name = "picViewer";
this.picViewer.Size = new System.Drawing.Size(682, 526);
this.picViewer.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.picViewer.TabIndex = 0;
this.picViewer.TabStop = false;
this.picViewer.DoubleClick += new System.EventHandler(this.picPicture_DoubleClick);
this.picViewer.MouseLeave += new System.EventHandler(this.picPicture_MouseLeave);
this.picViewer.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picPicture_MouseMove);
//
// tmrOverlay
//
this.tmrOverlay.Interval = 50;
this.tmrOverlay.Tick += new System.EventHandler(this.tmrOverlay_Tick);
//
// pnlPicture
//
this.pnlPicture.AutoScroll = true;
this.pnlPicture.Controls.Add(this.picViewer);
this.pnlPicture.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlPicture.Location = new System.Drawing.Point(0, 0);
this.pnlPicture.Name = "pnlPicture";
this.pnlPicture.Size = new System.Drawing.Size(686, 529);
this.pnlPicture.TabIndex = 1;
//
// grpOptions
//
this.grpOptions.Controls.Add(this.tableLayoutPanel1);
this.grpOptions.Dock = System.Windows.Forms.DockStyle.Right;
this.grpOptions.Location = new System.Drawing.Point(686, 0);
this.grpOptions.Name = "grpOptions";
this.grpOptions.Size = new System.Drawing.Size(261, 529);
this.grpOptions.TabIndex = 2;
this.grpOptions.TabStop = false;
this.grpOptions.Text = "Show...";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 6;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 15F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.chkShowPreviousFrameEvents, 0, 6);
this.tableLayoutPanel1.Controls.Add(this.picNmi, 5, 4);
this.tableLayoutPanel1.Controls.Add(this.chkShowNmi, 4, 4);
this.tableLayoutPanel1.Controls.Add(this.picIrq, 2, 4);
this.tableLayoutPanel1.Controls.Add(this.chkShowIrq, 1, 4);
this.tableLayoutPanel1.Controls.Add(this.label4, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.picWramWrites, 5, 3);
this.tableLayoutPanel1.Controls.Add(this.chkShowWorkRamRegisterWrites, 4, 3);
this.tableLayoutPanel1.Controls.Add(this.picWramReads, 2, 3);
this.tableLayoutPanel1.Controls.Add(this.chkShowWorkRamRegisterReads, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.label3, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.picCpuWrites, 5, 2);
this.tableLayoutPanel1.Controls.Add(this.chkShowCpuRegisterWrites, 4, 2);
this.tableLayoutPanel1.Controls.Add(this.picCpuReads, 2, 2);
this.tableLayoutPanel1.Controls.Add(this.chkShowCpuRegisterReads, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.picApuWrites, 5, 1);
this.tableLayoutPanel1.Controls.Add(this.chkShowApuRegisterWrites, 4, 1);
this.tableLayoutPanel1.Controls.Add(this.picApuReads, 2, 1);
this.tableLayoutPanel1.Controls.Add(this.chkShowApuRegisterReads, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.picPpuWrites, 5, 0);
this.tableLayoutPanel1.Controls.Add(this.chkShowPpuRegisterWrites, 4, 0);
this.tableLayoutPanel1.Controls.Add(this.chkShowPpuRegisterReads, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.lblPpuRegisters, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.picPpuReads, 2, 0);
this.tableLayoutPanel1.Controls.Add(this.chkShowMarkedBreakpoints, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.picMarkedBreakpoints, 2, 5);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 7;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(255, 510);
this.tableLayoutPanel1.TabIndex = 0;
//
// picNmi
//
this.picNmi.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picNmi.Location = new System.Drawing.Point(238, 95);
this.picNmi.Name = "picNmi";
this.picNmi.Size = new System.Drawing.Size(14, 14);
this.picNmi.TabIndex = 25;
this.picNmi.TabStop = false;
//
// chkShowNmi
//
this.chkShowNmi.AutoSize = true;
this.chkShowNmi.Location = new System.Drawing.Point(181, 95);
this.chkShowNmi.Name = "chkShowNmi";
this.chkShowNmi.Size = new System.Drawing.Size(46, 17);
this.chkShowNmi.TabIndex = 24;
this.chkShowNmi.Text = "NMI";
this.chkShowNmi.UseVisualStyleBackColor = true;
this.chkShowNmi.Click += new System.EventHandler(this.chkOption_Click);
//
// picIrq
//
this.picIrq.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picIrq.Location = new System.Drawing.Point(146, 95);
this.picIrq.Name = "picIrq";
this.picIrq.Size = new System.Drawing.Size(14, 14);
this.picIrq.TabIndex = 23;
this.picIrq.TabStop = false;
//
// chkShowIrq
//
this.chkShowIrq.AutoSize = true;
this.chkShowIrq.Location = new System.Drawing.Point(88, 95);
this.chkShowIrq.Name = "chkShowIrq";
this.chkShowIrq.Size = new System.Drawing.Size(45, 17);
this.chkShowIrq.TabIndex = 22;
this.chkShowIrq.Text = "IRQ";
this.chkShowIrq.UseVisualStyleBackColor = true;
this.chkShowIrq.Click += new System.EventHandler(this.chkOption_Click);
//
// label4
//
this.label4.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(3, 97);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(51, 13);
this.label4.TabIndex = 21;
this.label4.Text = "Interrupts";
//
// picWramWrites
//
this.picWramWrites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picWramWrites.Location = new System.Drawing.Point(238, 72);
this.picWramWrites.Name = "picWramWrites";
this.picWramWrites.Size = new System.Drawing.Size(14, 14);
this.picWramWrites.TabIndex = 20;
this.picWramWrites.TabStop = false;
//
// chkShowWorkRamRegisterWrites
//
this.chkShowWorkRamRegisterWrites.AutoSize = true;
this.chkShowWorkRamRegisterWrites.Location = new System.Drawing.Point(181, 72);
this.chkShowWorkRamRegisterWrites.Name = "chkShowWorkRamRegisterWrites";
this.chkShowWorkRamRegisterWrites.Size = new System.Drawing.Size(51, 17);
this.chkShowWorkRamRegisterWrites.TabIndex = 19;
this.chkShowWorkRamRegisterWrites.Text = "Write";
this.chkShowWorkRamRegisterWrites.UseVisualStyleBackColor = true;
this.chkShowWorkRamRegisterWrites.Click += new System.EventHandler(this.chkOption_Click);
//
// picWramReads
//
this.picWramReads.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picWramReads.Location = new System.Drawing.Point(146, 72);
this.picWramReads.Name = "picWramReads";
this.picWramReads.Size = new System.Drawing.Size(14, 14);
this.picWramReads.TabIndex = 18;
this.picWramReads.TabStop = false;
//
// chkShowWorkRamRegisterReads
//
this.chkShowWorkRamRegisterReads.AutoSize = true;
this.chkShowWorkRamRegisterReads.Location = new System.Drawing.Point(88, 72);
this.chkShowWorkRamRegisterReads.Name = "chkShowWorkRamRegisterReads";
this.chkShowWorkRamRegisterReads.Size = new System.Drawing.Size(52, 17);
this.chkShowWorkRamRegisterReads.TabIndex = 17;
this.chkShowWorkRamRegisterReads.Text = "Read";
this.chkShowWorkRamRegisterReads.UseVisualStyleBackColor = true;
this.chkShowWorkRamRegisterReads.Click += new System.EventHandler(this.chkOption_Click);
//
// label3
//
this.label3.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(3, 74);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(73, 13);
this.label3.TabIndex = 16;
this.label3.Text = "WRAM Regs:";
//
// picCpuWrites
//
this.picCpuWrites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picCpuWrites.Location = new System.Drawing.Point(238, 49);
this.picCpuWrites.Name = "picCpuWrites";
this.picCpuWrites.Size = new System.Drawing.Size(14, 14);
this.picCpuWrites.TabIndex = 15;
this.picCpuWrites.TabStop = false;
//
// chkShowCpuRegisterWrites
//
this.chkShowCpuRegisterWrites.AutoSize = true;
this.chkShowCpuRegisterWrites.Location = new System.Drawing.Point(181, 49);
this.chkShowCpuRegisterWrites.Name = "chkShowCpuRegisterWrites";
this.chkShowCpuRegisterWrites.Size = new System.Drawing.Size(51, 17);
this.chkShowCpuRegisterWrites.TabIndex = 14;
this.chkShowCpuRegisterWrites.Text = "Write";
this.chkShowCpuRegisterWrites.UseVisualStyleBackColor = true;
this.chkShowCpuRegisterWrites.Click += new System.EventHandler(this.chkOption_Click);
//
// picCpuReads
//
this.picCpuReads.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picCpuReads.Location = new System.Drawing.Point(146, 49);
this.picCpuReads.Name = "picCpuReads";
this.picCpuReads.Size = new System.Drawing.Size(14, 14);
this.picCpuReads.TabIndex = 13;
this.picCpuReads.TabStop = false;
//
// chkShowCpuRegisterReads
//
this.chkShowCpuRegisterReads.AutoSize = true;
this.chkShowCpuRegisterReads.Location = new System.Drawing.Point(88, 49);
this.chkShowCpuRegisterReads.Name = "chkShowCpuRegisterReads";
this.chkShowCpuRegisterReads.Size = new System.Drawing.Size(52, 17);
this.chkShowCpuRegisterReads.TabIndex = 12;
this.chkShowCpuRegisterReads.Text = "Read";
this.chkShowCpuRegisterReads.UseVisualStyleBackColor = true;
this.chkShowCpuRegisterReads.Click += new System.EventHandler(this.chkOption_Click);
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 51);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(79, 13);
this.label2.TabIndex = 11;
this.label2.Text = "CPU Registers:";
//
// picApuWrites
//
this.picApuWrites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picApuWrites.Location = new System.Drawing.Point(238, 26);
this.picApuWrites.Name = "picApuWrites";
this.picApuWrites.Size = new System.Drawing.Size(14, 14);
this.picApuWrites.TabIndex = 10;
this.picApuWrites.TabStop = false;
//
// chkShowApuRegisterWrites
//
this.chkShowApuRegisterWrites.AutoSize = true;
this.chkShowApuRegisterWrites.Location = new System.Drawing.Point(181, 26);
this.chkShowApuRegisterWrites.Name = "chkShowApuRegisterWrites";
this.chkShowApuRegisterWrites.Size = new System.Drawing.Size(51, 17);
this.chkShowApuRegisterWrites.TabIndex = 9;
this.chkShowApuRegisterWrites.Text = "Write";
this.chkShowApuRegisterWrites.UseVisualStyleBackColor = true;
this.chkShowApuRegisterWrites.Click += new System.EventHandler(this.chkOption_Click);
//
// picApuReads
//
this.picApuReads.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picApuReads.Location = new System.Drawing.Point(146, 26);
this.picApuReads.Name = "picApuReads";
this.picApuReads.Size = new System.Drawing.Size(14, 14);
this.picApuReads.TabIndex = 8;
this.picApuReads.TabStop = false;
//
// chkShowApuRegisterReads
//
this.chkShowApuRegisterReads.AutoSize = true;
this.chkShowApuRegisterReads.Location = new System.Drawing.Point(88, 26);
this.chkShowApuRegisterReads.Name = "chkShowApuRegisterReads";
this.chkShowApuRegisterReads.Size = new System.Drawing.Size(52, 17);
this.chkShowApuRegisterReads.TabIndex = 7;
this.chkShowApuRegisterReads.Text = "Read";
this.chkShowApuRegisterReads.UseVisualStyleBackColor = true;
this.chkShowApuRegisterReads.Click += new System.EventHandler(this.chkOption_Click);
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 28);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(79, 13);
this.label1.TabIndex = 6;
this.label1.Text = "APU Registers:";
//
// picPpuWrites
//
this.picPpuWrites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picPpuWrites.Location = new System.Drawing.Point(238, 3);
this.picPpuWrites.Name = "picPpuWrites";
this.picPpuWrites.Size = new System.Drawing.Size(14, 14);
this.picPpuWrites.TabIndex = 5;
this.picPpuWrites.TabStop = false;
//
// chkShowPpuRegisterWrites
//
this.chkShowPpuRegisterWrites.AutoSize = true;
this.chkShowPpuRegisterWrites.Location = new System.Drawing.Point(181, 3);
this.chkShowPpuRegisterWrites.Name = "chkShowPpuRegisterWrites";
this.chkShowPpuRegisterWrites.Size = new System.Drawing.Size(51, 17);
this.chkShowPpuRegisterWrites.TabIndex = 2;
this.chkShowPpuRegisterWrites.Text = "Write";
this.chkShowPpuRegisterWrites.UseVisualStyleBackColor = true;
this.chkShowPpuRegisterWrites.Click += new System.EventHandler(this.chkOption_Click);
//
// chkShowPpuRegisterReads
//
this.chkShowPpuRegisterReads.AutoSize = true;
this.chkShowPpuRegisterReads.Location = new System.Drawing.Point(88, 3);
this.chkShowPpuRegisterReads.Name = "chkShowPpuRegisterReads";
this.chkShowPpuRegisterReads.Size = new System.Drawing.Size(52, 17);
this.chkShowPpuRegisterReads.TabIndex = 0;
this.chkShowPpuRegisterReads.Text = "Read";
this.chkShowPpuRegisterReads.UseVisualStyleBackColor = true;
this.chkShowPpuRegisterReads.Click += new System.EventHandler(this.chkOption_Click);
//
// lblPpuRegisters
//
this.lblPpuRegisters.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblPpuRegisters.AutoSize = true;
this.lblPpuRegisters.Location = new System.Drawing.Point(3, 5);
this.lblPpuRegisters.Name = "lblPpuRegisters";
this.lblPpuRegisters.Size = new System.Drawing.Size(79, 13);
this.lblPpuRegisters.TabIndex = 3;
this.lblPpuRegisters.Text = "PPU Registers:";
//
// picPpuReads
//
this.picPpuReads.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picPpuReads.Location = new System.Drawing.Point(146, 3);
this.picPpuReads.Name = "picPpuReads";
this.picPpuReads.Size = new System.Drawing.Size(14, 14);
this.picPpuReads.TabIndex = 4;
this.picPpuReads.TabStop = false;
//
// chkShowMarkedBreakpoints
//
this.chkShowMarkedBreakpoints.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.chkShowMarkedBreakpoints, 2);
this.chkShowMarkedBreakpoints.Location = new System.Drawing.Point(3, 118);
this.chkShowMarkedBreakpoints.Name = "chkShowMarkedBreakpoints";
this.chkShowMarkedBreakpoints.Size = new System.Drawing.Size(121, 17);
this.chkShowMarkedBreakpoints.TabIndex = 26;
this.chkShowMarkedBreakpoints.Text = "Marked Breakpoints";
this.chkShowMarkedBreakpoints.UseVisualStyleBackColor = true;
this.chkShowMarkedBreakpoints.Click += new System.EventHandler(this.chkOption_Click);
//
// picMarkedBreakpoints
//
this.picMarkedBreakpoints.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picMarkedBreakpoints.Location = new System.Drawing.Point(146, 118);
this.picMarkedBreakpoints.Name = "picMarkedBreakpoints";
this.picMarkedBreakpoints.Size = new System.Drawing.Size(14, 14);
this.picMarkedBreakpoints.TabIndex = 27;
this.picMarkedBreakpoints.TabStop = false;
//
// chkShowPreviousFrameEvents
//
this.chkShowPreviousFrameEvents.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.chkShowPreviousFrameEvents, 6);
this.chkShowPreviousFrameEvents.Location = new System.Drawing.Point(3, 148);
this.chkShowPreviousFrameEvents.Margin = new System.Windows.Forms.Padding(3, 10, 3, 3);
this.chkShowPreviousFrameEvents.Name = "chkShowPreviousFrameEvents";
this.chkShowPreviousFrameEvents.Size = new System.Drawing.Size(167, 17);
this.chkShowPreviousFrameEvents.TabIndex = 28;
this.chkShowPreviousFrameEvents.Text = "Show previous frame\'s events";
this.chkShowPreviousFrameEvents.UseVisualStyleBackColor = true;
this.chkShowPreviousFrameEvents.Click += new System.EventHandler(this.chkOption_Click);
//
// ctrlEventViewerPpuView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.pnlPicture);
this.Controls.Add(this.grpOptions);
this.Name = "ctrlEventViewerPpuView";
this.Size = new System.Drawing.Size(947, 529);
((System.ComponentModel.ISupportInitialize)(this.picViewer)).EndInit();
this.pnlPicture.ResumeLayout(false);
this.grpOptions.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picNmi)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picIrq)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picWramWrites)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picWramReads)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picCpuWrites)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picCpuReads)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picApuWrites)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picApuReads)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picPpuWrites)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picPpuReads)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picMarkedBreakpoints)).EndInit();
this.ResumeLayout(false);
}
#endregion
private ctrlMesenPictureBox picViewer;
private System.Windows.Forms.Timer tmrOverlay;
private System.Windows.Forms.Panel pnlPicture;
private System.Windows.Forms.GroupBox grpOptions;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private ctrlColorPicker picNmi;
private System.Windows.Forms.CheckBox chkShowNmi;
private ctrlColorPicker picIrq;
private System.Windows.Forms.CheckBox chkShowIrq;
private System.Windows.Forms.Label label4;
private ctrlColorPicker picWramWrites;
private System.Windows.Forms.CheckBox chkShowWorkRamRegisterWrites;
private ctrlColorPicker picWramReads;
private System.Windows.Forms.CheckBox chkShowWorkRamRegisterReads;
private System.Windows.Forms.Label label3;
private ctrlColorPicker picCpuWrites;
private System.Windows.Forms.CheckBox chkShowCpuRegisterWrites;
private ctrlColorPicker picCpuReads;
private System.Windows.Forms.CheckBox chkShowCpuRegisterReads;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox chkShowApuRegisterWrites;
private ctrlColorPicker picApuReads;
private System.Windows.Forms.CheckBox chkShowApuRegisterReads;
private System.Windows.Forms.Label label1;
private ctrlColorPicker picPpuWrites;
private System.Windows.Forms.CheckBox chkShowPpuRegisterWrites;
private System.Windows.Forms.CheckBox chkShowPpuRegisterReads;
private System.Windows.Forms.Label lblPpuRegisters;
private ctrlColorPicker picPpuReads;
private ctrlColorPicker picApuWrites;
private System.Windows.Forms.CheckBox chkShowMarkedBreakpoints;
private ctrlColorPicker picMarkedBreakpoints;
private System.Windows.Forms.CheckBox chkShowPreviousFrameEvents;
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="tmrOverlay.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -0,0 +1,57 @@
namespace Mesen.GUI.Debugger
{
partial class frmEventViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.ctrlPpuView = new Mesen.GUI.Debugger.ctrlEventViewerPpuView();
this.SuspendLayout();
//
// ctrlPpuView
//
this.ctrlPpuView.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPpuView.Location = new System.Drawing.Point(0, 0);
this.ctrlPpuView.Name = "ctrlPpuView";
this.ctrlPpuView.Size = new System.Drawing.Size(945, 531);
this.ctrlPpuView.TabIndex = 0;
//
// frmEventViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(945, 531);
this.Controls.Add(this.ctrlPpuView);
this.Name = "frmEventViewer";
this.Text = "Event Viewer";
this.ResumeLayout(false);
}
#endregion
private ctrlEventViewerPpuView ctrlPpuView;
}
}

View file

@ -0,0 +1,52 @@
using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmEventViewer : BaseForm
{
private NotificationListener _notifListener;
public frmEventViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!this.DesignMode) {
_notifListener = new NotificationListener();
_notifListener.OnNotification += OnNotificationReceived;
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
_notifListener?.Dispose();
}
private void OnNotificationReceived(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.CodeBreak:
case ConsoleNotificationType.PpuFrameDone:
ctrlPpuView.RefreshData();
this.BeginInvoke((Action)(() => {
ctrlPpuView.RefreshViewer();
}));
break;
}
}
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public static class GraphicsExtensions
{
public static void DrawOutlinedString(this Graphics g, string text, Font font, Brush foreColor, Brush backColor, int x, int y)
{
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
g.DrawString(text, font, backColor, x+j, y+i);
}
}
g.DrawString(text, font, foreColor, x, y);
}
}
}

View file

@ -0,0 +1,60 @@
using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public class TooltipForm : BaseForm
{
protected Form _parentForm;
private Point _requestedLocation;
private bool _parentContainedFocus = false;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!DesignMode) {
UpdateLocation();
}
}
private void UpdateLocation()
{
Point p = _requestedLocation;
if(p.Y + this.Height > _parentForm.ClientSize.Height) {
this.Location = new Point(p.X, _parentForm.ClientSize.Height - this.Height);
} else {
this.Location = p;
}
}
public bool NeedRestoreFocus
{
get { return _parentContainedFocus; }
}
public void SetFormLocation(Point screenLocation, Control focusTarget)
{
_requestedLocation = _parentForm.PointToClient(screenLocation);
if(!this.Visible) {
this._parentContainedFocus = focusTarget.ContainsFocus;
UpdateLocation();
this.Show();
} else {
UpdateLocation();
}
if(Program.IsMono) {
focusTarget.Focus();
}
}
}
}

View file

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
namespace Mesen.GUI.Debugger
{
public partial class frmInfoTooltip : TooltipForm
{
private Dictionary<string, string> _values;
private int _showOnLeftOffset;
protected override bool ShowWithoutActivation
{
get { return true; }
}
public frmInfoTooltip(Form parent, Dictionary<string, string> values, int showOnLeftOffset = 0)
{
_showOnLeftOffset = showOnLeftOffset;
_parentForm = parent;
_values = values;
InitializeComponent();
this.TopLevel = false;
this.Parent = _parentForm;
_parentForm.Controls.Add(this);
}
protected override void OnLoad(EventArgs e)
{
tlpMain.SuspendLayout();
TableLayoutPanel tlpLabels = new TableLayoutPanel();
tlpLabels.SuspendLayout();
tlpLabels.AutoSize = true;
tlpMain.Controls.Add(tlpLabels, 0, 0);
int i = 0;
int maxLabelWidth = (_parentForm.ClientSize.Width - this.Location.X - 150);
foreach(KeyValuePair<string, string> kvp in _values) {
tlpLabels.RowStyles.Add(new RowStyle());
Label lbl = new Label();
lbl.Margin = new Padding(2, 3, 2, 2);
lbl.Text = kvp.Key + ":";
lbl.Font = new Font(lbl.Font, FontStyle.Bold);
lbl.AutoSize = true;
tlpLabels.Controls.Add(lbl, 0, i);
lbl = new ctrlAutoGrowLabel();
lbl.Font = new Font(BaseControl.MonospaceFontFamily, 10);
lbl.Margin = new Padding(2);
lbl.Text = kvp.Value;
if(_showOnLeftOffset == 0) {
lbl.Size = new Size(maxLabelWidth, 10);
} else {
lbl.Size = new Size(500, 10);
}
tlpLabels.Controls.Add(lbl, 1, i);
i++;
}
tlpLabels.ResumeLayout();
tlpMain.ResumeLayout();
base.OnLoad(e);
this.Width = this.tlpMain.Width;
if(this.Location.X + this.Width > _parentForm.ClientSize.Width) {
if(_showOnLeftOffset > 0) {
this.Left -= this.Width + _showOnLeftOffset * 2;
} else {
int maxWidth = Math.Max(10, _parentForm.ClientSize.Width - this.Location.X - 10);
this.tlpMain.MaximumSize = new Size(maxWidth, _parentForm.ClientSize.Height - 10);
this.MaximumSize = new Size(maxWidth, _parentForm.ClientSize.Height - 10);
}
}
this.Height = this.tlpMain.Height;
this.BringToFront();
panel.BackColor = SystemColors.Info;
}
}
}

View file

@ -0,0 +1,93 @@
namespace Mesen.GUI.Debugger
{
partial class frmInfoTooltip
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel = new System.Windows.Forms.Panel();
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
this.panel.SuspendLayout();
this.SuspendLayout();
//
// panel
//
this.panel.AutoSize = true;
this.panel.BackColor = System.Drawing.SystemColors.Info;
this.panel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel.Controls.Add(this.tlpMain);
this.panel.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel.Location = new System.Drawing.Point(0, 0);
this.panel.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
this.panel.Name = "panel";
this.panel.Size = new System.Drawing.Size(10, 10);
this.panel.TabIndex = 0;
//
// tlpMain
//
this.tlpMain.AutoSize = true;
this.tlpMain.ColumnCount = 1;
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpMain.Location = new System.Drawing.Point(0, 0);
this.tlpMain.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
this.tlpMain.Name = "tlpMain";
this.tlpMain.RowCount = 1;
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tlpMain.Size = new System.Drawing.Size(8, 8);
this.tlpMain.TabIndex = 0;
//
// frmCodeTooltip
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(10, 10);
this.ControlBox = false;
this.Controls.Add(this.panel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmCodeTooltip";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "frmCodeTooltip";
this.panel.ResumeLayout(false);
this.panel.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel;
private System.Windows.Forms.TableLayoutPanel tlpMain;
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Forms.Config;
using Mesen.GUI.Utilities;
namespace Mesen.GUI.Forms
{
@ -85,6 +86,8 @@ namespace Mesen.GUI.Forms
((ctrlRiskyOption)kvp.Value).Checked = Convert.ToBoolean(value);
} else if(kvp.Value is RadioButton) {
((RadioButton)kvp.Value).Checked = (bool)value;
} else if(kvp.Value is PictureBox) {
((PictureBox)kvp.Value).BackColor = (XmlColor)value;
} else if(kvp.Value is Panel) {
RadioButton radio = ((Panel)kvp.Value).Controls.OfType<RadioButton>().FirstOrDefault(r => r.Tag.Equals(value));
if(radio != null) {
@ -222,6 +225,8 @@ namespace Mesen.GUI.Forms
}
} else if(kvp.Value is RadioButton) {
field.SetValue(Entity, ((RadioButton)kvp.Value).Checked);
} else if(kvp.Value is PictureBox) {
field.SetValue(Entity, (XmlColor)((PictureBox)kvp.Value).BackColor);
} else if(kvp.Value is Panel) {
field.SetValue(Entity, ((Panel)kvp.Value).Controls.OfType<RadioButton>().FirstOrDefault(r => r.Checked).Tag);
} else if(kvp.Value is ctrlTrackbar) {

View file

@ -40,6 +40,7 @@
this.mnuMemoryTools = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTilemapViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEventViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMain.SuspendLayout();
this.SuspendLayout();
//
@ -88,7 +89,8 @@
this.mnuDebugger,
this.mnuMemoryTools,
this.mnuTraceLogger,
this.mnuTilemapViewer});
this.mnuTilemapViewer,
this.mnuEventViewer});
this.debugToolStripMenuItem.Name = "debugToolStripMenuItem";
this.debugToolStripMenuItem.Size = new System.Drawing.Size(54, 20);
this.debugToolStripMenuItem.Text = "Debug";
@ -154,6 +156,14 @@
this.mnuTilemapViewer.Text = "Tilemap Viewer";
this.mnuTilemapViewer.Click += new System.EventHandler(this.mnuTilemapViewer_Click);
//
// mnuEventViewer
//
this.mnuEventViewer.Image = global::Mesen.GUI.Properties.Resources.NesEventViewer;
this.mnuEventViewer.Name = "mnuEventViewer";
this.mnuEventViewer.Size = new System.Drawing.Size(163, 22);
this.mnuEventViewer.Text = "Event Viewer";
this.mnuEventViewer.Click += new System.EventHandler(this.mnuEventViewer_Click);
//
// frmMain
//
this.AllowDrop = true;
@ -187,5 +197,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuRun100Instructions;
private System.Windows.Forms.ToolStripMenuItem mnuMemoryTools;
private System.Windows.Forms.ToolStripMenuItem mnuTilemapViewer;
private System.Windows.Forms.ToolStripMenuItem mnuEventViewer;
}
}

View file

@ -78,6 +78,11 @@ namespace Mesen.GUI.Forms
DebugWindowManager.OpenDebugWindow(DebugWindow.TilemapViewer);
}
private void mnuEventViewer_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.EventViewer);
}
private void mnuStep_Click(object sender, EventArgs e)
{
DebugApi.Step(1);

View file

@ -80,6 +80,33 @@ namespace Mesen.GUI
}
[DllImport(DllPath)] public static extern void SetViewerUpdateTiming(Int32 viewerId, Int32 scanline, Int32 cycle);
[DllImport(DllPath)] private static extern UInt32 GetDebugEventCount([MarshalAs(UnmanagedType.I1)]bool getPreviousFrameData);
[DllImport(DllPath, EntryPoint = "GetDebugEvents")] private static extern void GetDebugEventsWrapper([In, Out]DebugEventInfo[] eventArray, ref UInt32 maxEventCount, [MarshalAs(UnmanagedType.I1)]bool getPreviousFrameData);
public static DebugEventInfo[] GetDebugEvents(bool getPreviousFrameData)
{
UInt32 maxEventCount = GetDebugEventCount(getPreviousFrameData);
DebugEventInfo[] debugEvents = new DebugEventInfo[maxEventCount];
DebugApi.GetDebugEventsWrapper(debugEvents, ref maxEventCount, getPreviousFrameData);
if(maxEventCount < debugEvents.Length) {
//Remove the excess from the array if needed
Array.Resize(ref debugEvents, (int)maxEventCount);
}
return debugEvents;
}
[DllImport(DllPath)] public static extern DebugEventInfo GetEventViewerEvent(UInt16 scanline, UInt16 cycle, EventViewerDisplayOptions options);
[DllImport(DllPath)] public static extern void TakeEventSnapshot(EventViewerDisplayOptions options);
[DllImport(DllPath, EntryPoint = "GetEventViewerOutput")] private static extern void GetEventViewerOutputWrapper([In, Out]byte[] buffer, EventViewerDisplayOptions options);
public static byte[] GetEventViewerOutput(EventViewerDisplayOptions options)
{
byte[] buffer = new byte[340*2 * 262*2 * 4];
DebugApi.GetEventViewerOutputWrapper(buffer, options);
return buffer;
}
}
public enum SnesMemoryType
@ -150,6 +177,74 @@ namespace Mesen.GUI
public PpuState Ppu;
}
public enum MemoryOperationType
{
Read = 0,
Write = 1,
ExecOpCode = 2,
ExecOperand = 3,
DmaRead = 4,
DmaWrite = 5
}
public struct MemoryOperationInfo
{
public UInt32 Address;
public Int32 Value;
public MemoryOperationType Type;
}
public enum DebugEventType
{
Register,
Nmi,
Irq,
Breakpoint
}
public struct DebugEventInfo
{
//public DmaChannelConfig DmaChannelInfo;
public MemoryOperationInfo Operation;
public DebugEventType Type;
public UInt32 ProgramCounter;
public UInt16 Scanline;
public UInt16 Cycle;
public UInt16 BreakpointId;
//public byte DmaChannel;
};
public struct EventViewerDisplayOptions
{
[MarshalAs(UnmanagedType.I1)] public bool ShowPpuRegisterWrites;
[MarshalAs(UnmanagedType.I1)] public bool ShowPpuRegisterReads;
[MarshalAs(UnmanagedType.I1)] public bool ShowCpuRegisterWrites;
[MarshalAs(UnmanagedType.I1)] public bool ShowCpuRegisterReads;
[MarshalAs(UnmanagedType.I1)] public bool ShowApuRegisterWrites;
[MarshalAs(UnmanagedType.I1)] public bool ShowApuRegisterReads;
[MarshalAs(UnmanagedType.I1)] public bool ShowWorkRamRegisterWrites;
[MarshalAs(UnmanagedType.I1)] public bool ShowWorkRamRegisterReads;
[MarshalAs(UnmanagedType.I1)] public bool ShowNmi;
[MarshalAs(UnmanagedType.I1)] public bool ShowIrq;
[MarshalAs(UnmanagedType.I1)] public bool ShowMarkedBreakpoints;
[MarshalAs(UnmanagedType.I1)] public bool ShowPreviousFrameEvents;
public UInt32 IrqColor;
public UInt32 NmiColor;
public UInt32 BreakpointColor;
public UInt32 PpuRegisterReadColor;
public UInt32 PpuRegisterWriteColor;
public UInt32 ApuRegisterReadColor;
public UInt32 ApuRegisterWriteColor;
public UInt32 CpuRegisterReadColor;
public UInt32 CpuRegisterWriteColor;
public UInt32 WorkRamRegisterReadColor;
public UInt32 WorkRamRegisterWriteColor;
}
public struct GetTilemapOptions
{
public byte BgMode;

View file

@ -228,6 +228,7 @@
</Compile>
<Compile Include="Debugger\Breakpoints\InteropBreakpoint.cs" />
<Compile Include="Debugger\Config\DebuggerShortcutsConfig.cs" />
<Compile Include="Debugger\Config\EventViewerInfo.cs" />
<Compile Include="Debugger\Config\HexEditorInfo.cs" />
<Compile Include="Debugger\Config\TraceLoggerInfo.cs" />
<Compile Include="Debugger\Config\DebugInfo.cs" />
@ -298,6 +299,9 @@
<Compile Include="Debugger\Controls\ComboBoxWithSeparator.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlColorPicker.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlDbgShortcuts.cs">
<SubType>UserControl</SubType>
</Compile>
@ -322,6 +326,18 @@
<Compile Include="Debugger\Controls\ctrlWatch.designer.cs">
<DependentUpon>ctrlWatch.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\EventViewer\ctrlEventViewerPpuView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\EventViewer\ctrlEventViewerPpuView.designer.cs">
<DependentUpon>ctrlEventViewerPpuView.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\EventViewer\frmEventViewer.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\EventViewer\frmEventViewer.Designer.cs">
<DependentUpon>frmEventViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\frmDbgPreferences.cs">
<SubType>Form</SubType>
</Compile>
@ -374,6 +390,7 @@
<Compile Include="Debugger\frmMemoryTools.designer.cs">
<DependentUpon>frmMemoryTools.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\GraphicsExtensions.cs" />
<Compile Include="Debugger\PpuViewer\ctrlScanlineCycleSelect.cs">
<SubType>UserControl</SubType>
</Compile>
@ -417,6 +434,15 @@
<Compile Include="Debugger\HexBox\Util.cs" />
<Compile Include="Debugger\TblLoader.cs" />
<Compile Include="Debugger\DebugWindowManager.cs" />
<Compile Include="Debugger\Tooltips\frmInfoTooltip.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\Tooltips\frmInfoTooltip.designer.cs">
<DependentUpon>frmInfoTooltip.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Tooltips\TooltipForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\WatchManager.cs" />
<Compile Include="Forms\BaseConfigForm.Designer.cs">
<DependentUpon>BaseConfigForm.cs</DependentUpon>
@ -499,6 +525,12 @@
<EmbeddedResource Include="Debugger\Controls\ctrlWatch.resx">
<DependentUpon>ctrlWatch.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\EventViewer\ctrlEventViewerPpuView.resx">
<DependentUpon>ctrlEventViewerPpuView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\EventViewer\frmEventViewer.resx">
<DependentUpon>frmEventViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\frmDbgPreferences.resx">
<DependentUpon>frmDbgPreferences.cs</DependentUpon>
</EmbeddedResource>
@ -532,6 +564,9 @@
<EmbeddedResource Include="Debugger\HexBox\HexBox.resx">
<DependentUpon>HexBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Tooltips\frmInfoTooltip.resx">
<DependentUpon>frmInfoTooltip.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\BaseConfigForm.resx">
<DependentUpon>BaseConfigForm.cs</DependentUpon>
</EmbeddedResource>