Debugger: Breakpoint support

This commit is contained in:
Sour 2019-03-01 20:27:49 -05:00
parent 72c17966b9
commit 8502581a1d
30 changed files with 2271 additions and 43 deletions

88
Core/Breakpoint.cpp Normal file
View file

@ -0,0 +1,88 @@
#include "stdafx.h"
#include "Breakpoint.h"
#include "DebugTypes.h"
bool Breakpoint::Matches(uint32_t memoryAddr, AddressInfo &info)
{
if(_memoryType == SnesMemoryType::CpuMemory) {
if(_startAddr == -1) {
return true;
} else if(_endAddr == -1) {
return (int32_t)memoryAddr == _startAddr;
} else {
return (int32_t)memoryAddr >= _startAddr && (int32_t)memoryAddr <= _endAddr;
}
} else if(_memoryType == info.Type) {
if(_startAddr == -1) {
return true;
} else if(_endAddr == -1) {
return info.Address == _startAddr;
} else {
return info.Address >= _startAddr && info.Address <= _endAddr;
}
}
return false;
}
bool Breakpoint::HasBreakpointType(BreakpointType type)
{
switch(type) {
default:
case BreakpointType::Execute: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Execute) != 0;
case BreakpointType::Read: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Read) != 0;
case BreakpointType::Write: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Write) != 0;
}
}
string Breakpoint::GetCondition()
{
return _condition;
}
bool Breakpoint::HasCondition()
{
return _condition[0] != 0;
}
uint32_t Breakpoint::GetId()
{
return _id;
}
BreakpointCategory Breakpoint::GetBreakpointCategory()
{
return GetBreakpointCategory(_memoryType);
}
BreakpointCategory Breakpoint::GetBreakpointCategory(SnesMemoryType memoryType)
{
switch(memoryType) {
case SnesMemoryType::CpuMemory:
case SnesMemoryType::PrgRom:
case SnesMemoryType::WorkRam:
case SnesMemoryType::SaveRam:
return BreakpointCategory::Cpu;
case SnesMemoryType::VideoRam:
return BreakpointCategory::VideoRam;
case SnesMemoryType::SpriteRam:
return BreakpointCategory::Oam;
case SnesMemoryType::CGRam:
return BreakpointCategory::CgRam;
default: throw std::runtime_error("invalid memory type");
}
}
bool Breakpoint::IsEnabled()
{
return _enabled;
}
bool Breakpoint::IsMarked()
{
return _markEvent;
}

34
Core/Breakpoint.h Normal file
View file

@ -0,0 +1,34 @@
#pragma once
#include "stdafx.h"
enum class SnesMemoryType;
struct AddressInfo;
enum class BreakpointType;
enum class BreakpointTypeFlags;
enum class BreakpointCategory;
class Breakpoint
{
public:
bool Matches(uint32_t memoryAddr, AddressInfo &info);
bool HasBreakpointType(BreakpointType type);
string GetCondition();
bool HasCondition();
uint32_t GetId();
bool IsEnabled();
bool IsMarked();
BreakpointCategory GetBreakpointCategory();
static BreakpointCategory GetBreakpointCategory(SnesMemoryType memoryType);
private:
uint32_t _id;
SnesMemoryType _memoryType;
BreakpointTypeFlags _type;
int32_t _startAddr;
int32_t _endAddr;
bool _enabled;
bool _markEvent;
char _condition[1000];
};

View file

@ -0,0 +1,86 @@
#include "stdafx.h"
#include "BreakpointManager.h"
#include "DebugTypes.h"
#include "Debugger.h"
#include "Breakpoint.h"
#include "ExpressionEvaluator.h"
BreakpointManager::BreakpointManager(Debugger *debugger)
{
_debugger = debugger;
}
void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
{
for(int j = 0; j < BreakpointManager::CategoryCount; j++) {
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
_breakpoints[j][i].clear();
_rpnList[j][i].clear();
_hasBreakpoint[j][i] = false;
}
}
_bpExpEval.reset(new ExpressionEvaluator(_debugger));
for(uint32_t j = 0; j < count; j++) {
Breakpoint &bp = breakpoints[j];
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
BreakpointType bpType = (BreakpointType)i;
bool isEnabled = bp.IsEnabled(); //TODO && _console->GetSettings()->CheckFlag(EmulationFlags::DebuggerWindowEnabled);
if((bp.IsMarked() || isEnabled) && bp.HasBreakpointType(bpType)) {
BreakpointCategory category = bp.GetBreakpointCategory();
_breakpoints[(int)category][i].push_back(bp);
if(bp.HasCondition()) {
bool success = true;
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
_rpnList[(int)category][i].push_back(success ? data : ExpressionData());
} else {
_rpnList[(int)category][i].push_back(ExpressionData());
}
_hasBreakpoint[(int)category][i] = true;
}
}
}
}
BreakpointType BreakpointManager::GetBreakpointType(MemoryOperationType type)
{
switch(type) {
default:
case MemoryOperationType::ExecOperand:
case MemoryOperationType::ExecOpCode:
return BreakpointType::Execute;
case MemoryOperationType::DmaRead:
case MemoryOperationType::Read: return BreakpointType::Read;
case MemoryOperationType::DmaWrite:
case MemoryOperationType::Write: return BreakpointType::Write;
}
}
bool BreakpointManager::CheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address)
{
BreakpointCategory category = Breakpoint::GetBreakpointCategory(address.Type);
BreakpointType type = GetBreakpointType(operationInfo.Type);
if(!_hasBreakpoint[(int)category][(int)type]) {
return false;
}
DebugState state;
_debugger->GetState(state);
EvalResultType resultType;
vector<Breakpoint> &breakpoints = _breakpoints[(int)category][(int)type];
for(size_t i = 0; i < breakpoints.size(); i++) {
Breakpoint bp = breakpoints[i];
if(bp.Matches(operationInfo.Address, address)) {
if(!bp.HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)category][(int)type][i], state, resultType, operationInfo)) {
return true;
}
}
}
return false;
}

33
Core/BreakpointManager.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "stdafx.h"
#include "Breakpoint.h"
class ExpressionEvaluator;
class Debugger;
struct MemoryOperationInfo;
struct ExpressionData;
struct AddressInfo;
enum class MemoryOperationType;
class BreakpointManager
{
private:
static constexpr int BreakpointTypeCount = 3; //Read, Write, Exec
static constexpr int CategoryCount = 4; //CPU, VRAM, OAM, CGRAM
Debugger *_debugger;
vector<Breakpoint> _breakpoints[CategoryCount][BreakpointTypeCount];
vector<ExpressionData> _rpnList[CategoryCount][BreakpointTypeCount];
bool _hasBreakpoint[CategoryCount][BreakpointTypeCount] = {};
unique_ptr<ExpressionEvaluator> _bpExpEval;
BreakpointType GetBreakpointType(MemoryOperationType type);
public:
BreakpointManager(Debugger *debugger);
void SetBreakpoints(Breakpoint breakpoints[], uint32_t count);
bool CheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address);
};

View file

@ -10,6 +10,7 @@
#include "BaseCartridge.h"
#include "RamHandler.h"
#include "Debugger.h"
#include "DebugTypes.h"
#include "NotificationManager.h"
#include "SoundMixer.h"
#include "VideoDecoder.h"
@ -247,3 +248,30 @@ void Console::ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType
_debugger->ProcessCpuWrite(addr, value, type);
}
}
void Console::ProcessPpuRead(uint32_t addr, uint8_t value, SnesMemoryType memoryType)
{
if(_debugger) {
_debugger->ProcessPpuRead(addr, value, memoryType);
}
}
void Console::ProcessPpuWrite(uint32_t addr, uint8_t value, SnesMemoryType memoryType)
{
if(_debugger) {
_debugger->ProcessPpuWrite(addr, value, memoryType);
}
}
void Console::ProcessWorkRamRead(uint32_t addr, uint8_t value)
{
if(_debugger) {
_debugger->ProcessWorkRamRead(addr, value);
}
}
void Console::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
{
if(_debugger) {
_debugger->ProcessWorkRamWrite(addr, value);
}
}

View file

@ -18,6 +18,7 @@ class VideoRenderer;
class VideoDecoder;
class NotificationManager;
enum class MemoryOperationType;
enum class SnesMemoryType;
class Console : public std::enable_shared_from_this<Console>
{
@ -75,4 +76,8 @@ public:
void ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType type);
void ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType type);
void ProcessPpuRead(uint32_t addr, uint8_t value, SnesMemoryType memoryType);
void ProcessPpuWrite(uint32_t addr, uint8_t value, SnesMemoryType memoryType);
void ProcessWorkRamRead(uint32_t addr, uint8_t value);
void ProcessWorkRamWrite(uint32_t addr, uint8_t value);
};

View file

@ -52,6 +52,8 @@
<ClInclude Include="blargg_config.h" />
<ClInclude Include="blargg_endian.h" />
<ClInclude Include="blargg_source.h" />
<ClInclude Include="Breakpoint.h" />
<ClInclude Include="BreakpointManager.h" />
<ClInclude Include="CodeDataLogger.h" />
<ClInclude Include="Console.h" />
<ClInclude Include="ControlDeviceState.h" />
@ -114,6 +116,8 @@
<ClCompile Include="BaseRenderer.cpp" />
<ClCompile Include="BaseSoundManager.cpp" />
<ClCompile Include="BaseVideoFilter.cpp" />
<ClCompile Include="Breakpoint.cpp" />
<ClCompile Include="BreakpointManager.cpp" />
<ClCompile Include="CodeDataLogger.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="ControlManager.cpp" />

View file

@ -191,6 +191,12 @@
<ClInclude Include="DummyCpu.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="BreakpointManager.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="Breakpoint.h">
<Filter>Debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
@ -296,6 +302,10 @@
<ClCompile Include="ExpressionEvaluator.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="Breakpoint.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="BreakpointManager.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="SNES">

View file

@ -92,10 +92,8 @@ enum class MemoryOperationType
Write = 1,
ExecOpCode = 2,
ExecOperand = 3,
DummyRead = 5,
DummyWrite = 6,
DmaRead = 7,
DmaWrite = 8
DmaRead = 4,
DmaWrite = 5
};
enum class IrqSource

View file

@ -24,13 +24,53 @@ struct AddressInfo
{
int32_t Address;
SnesMemoryType Type;
AddressInfo() { }
AddressInfo(int32_t address, SnesMemoryType type)
{
Address = address;
Type = type;
}
};
struct MemoryOperationInfo
{
uint32_t Address;
int32_t Value;
MemoryOperationType OperationType;
MemoryOperationType Type;
MemoryOperationInfo() { }
MemoryOperationInfo(uint32_t address, int32_t value, MemoryOperationType type)
{
Address = address;
Value = value;
Type = type;
}
};
enum class BreakpointTypeFlags
{
None = 0,
Execute = 1,
Read = 2,
Write = 4,
};
enum class BreakpointType
{
Execute = 0,
Read = 1,
Write = 2,
};
enum class BreakpointCategory
{
Cpu = 0,
VideoRam = 1,
Oam = 2,
CgRam = 3
};
namespace CdlFlags

View file

@ -13,6 +13,7 @@
#include "MemoryDumper.h"
#include "CodeDataLogger.h"
#include "Disassembler.h"
#include "BreakpointManager.h"
#include "ExpressionEvaluator.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/FolderUtilities.h"
@ -29,6 +30,7 @@ Debugger::Debugger(shared_ptr<Console> console)
_disassembler.reset(new Disassembler(console, _codeDataLogger));
_traceLogger.reset(new TraceLogger(this, _memoryManager));
_memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, console->GetCartridge()));
_breakpointManager.reset(new BreakpointManager(this));
_cpuStepCount = 0;
string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_console->GetCartridge()->GetRomInfo().RomPath, false) + ".cdl");
@ -55,6 +57,7 @@ Debugger::~Debugger()
void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(addr);
MemoryOperationInfo operation = { addr, value, type };
CpuState state = _cpu->GetState();
if(type == MemoryOperationType::ExecOpCode) {
@ -70,27 +73,20 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
}
DebugState debugState;
GetState(&debugState);
GetState(debugState);
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(debugState, disInfo);
_prevOpCode = value;
if(value == 0x00 || value == 0xCB) {
//break on BRK/WAI
_cpuStepCount = 1;
}
if(_cpuStepCount > 0) {
_cpuStepCount--;
if(_cpuStepCount == 0) {
_disassembler->Disassemble();
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak);
while(_cpuStepCount == 0) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
}
}
}
if(value == 0x00 || value == 0xCB) {
//Break on BRK/WAI
_cpuStepCount = 0;
}
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Type == SnesMemoryType::PrgRom && addressInfo.Address >= 0) {
@ -101,21 +97,71 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Data | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8)));
}
}
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(addr);
MemoryOperationInfo operation = { addr, value, type };
if(addressInfo.Address >= 0 && (addressInfo.Type == SnesMemoryType::WorkRam || addressInfo.Type == SnesMemoryType::SaveRam)) {
_disassembler->InvalidateCache(addressInfo);
}
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessWorkRamRead(uint32_t addr, uint8_t value)
{
AddressInfo addressInfo(addr, SnesMemoryType::WorkRam);
//TODO Make this more flexible/accurate
MemoryOperationInfo operation(0x7E0000 | addr, value, MemoryOperationType::Read);
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessWorkRamWrite(uint32_t addr, uint8_t value)
{
AddressInfo addressInfo(addr, SnesMemoryType::WorkRam);
//TODO Make this more flexible/accurate
MemoryOperationInfo operation(0x7E0000 | addr, value, MemoryOperationType::Write);
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessPpuRead(uint16_t addr, uint8_t value, SnesMemoryType memoryType)
{
AddressInfo addressInfo(addr, memoryType);
MemoryOperationInfo operation(addr, value, MemoryOperationType::Read);
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType)
{
AddressInfo addressInfo(addr, memoryType);
MemoryOperationInfo operation(addr, value, MemoryOperationType::Write);
ProcessBreakConditions(operation, addressInfo);
}
void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo)
{
if(_breakpointManager->CheckBreakpoint(operation, addressInfo)) {
_cpuStepCount = 0;
}
if(_cpuStepCount == 0) {
_disassembler->Disassemble();
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak);
while(_cpuStepCount == 0) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
}
}
}
int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultType, bool useCache)
{
MemoryOperationInfo operationInfo { 0, 0, MemoryOperationType::Read };
DebugState state;
MemoryOperationInfo operationInfo { 0, 0, MemoryOperationType::DummyRead };
GetState(&state);
GetState(state);
if(useCache) {
return _watchExpEval->Evaluate(expression, state, resultType, operationInfo);
} else {
@ -140,10 +186,10 @@ bool Debugger::IsExecutionStopped()
return false;
}
void Debugger::GetState(DebugState *state)
void Debugger::GetState(DebugState &state)
{
state->Cpu = _cpu->GetState();
state->Ppu = _ppu->GetState();
state.Cpu = _cpu->GetState();
state.Ppu = _ppu->GetState();
}
shared_ptr<TraceLogger> Debugger::GetTraceLogger()
@ -160,3 +206,8 @@ shared_ptr<Disassembler> Debugger::GetDisassembler()
{
return _disassembler;
}
shared_ptr<BreakpointManager> Debugger::GetBreakpointManager()
{
return _breakpointManager;
}

View file

@ -10,13 +10,18 @@ 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;
struct DebugState;
struct MemoryOperationInfo;
struct AddressInfo;
class Debugger
{
@ -31,6 +36,7 @@ private:
shared_ptr<MemoryDumper> _memoryDumper;
shared_ptr<CodeDataLogger> _codeDataLogger;
shared_ptr<Disassembler> _disassembler;
shared_ptr<BreakpointManager> _breakpointManager;
unique_ptr<ExpressionEvaluator> _watchExpEval;
@ -44,15 +50,24 @@ public:
void ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType type);
void ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType type);
void ProcessWorkRamRead(uint32_t addr, uint8_t value);
void ProcessWorkRamWrite(uint32_t addr, uint8_t value);
void ProcessPpuRead(uint16_t addr, uint8_t value, SnesMemoryType memoryType);
void ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType);
void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo);
int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache);
void Run();
void Step(int32_t stepCount);
bool IsExecutionStopped();
void GetState(DebugState *state);
void GetState(DebugState &state);
shared_ptr<TraceLogger> GetTraceLogger();
shared_ptr<MemoryDumper> GetMemoryDumper();
shared_ptr<Disassembler> GetDisassembler();
shared_ptr<BreakpointManager> GetBreakpointManager();
};

View file

@ -553,7 +553,7 @@ void ExpressionEvaluator::RunTests()
//Some basic unit tests to run in debug mode
auto test = [=](string expr, EvalResultType expectedType, int expectedResult) {
DebugState state = { 0 };
OperationInfo opInfo = { 0 };
MemoryOperationInfo opInfo(0, 0, MemoryOperationType::Read);
EvalResultType type;
int32_t result = Evaluate(expr, state, type, opInfo);

View file

@ -29,6 +29,7 @@ void MemoryManager::Initialize(shared_ptr<Console> console)
));
_registerHandlerB.reset(new RegisterHandlerB(
_console.get(),
_ppu.get(),
console->GetSpc().get(),
_workRam

View file

@ -1065,8 +1065,10 @@ uint8_t Ppu::Read(uint16_t addr)
uint8_t value;
if(_internalOamAddress < 512) {
value = _oamRam[_internalOamAddress];
_console->ProcessPpuRead(_internalOamAddress, value, SnesMemoryType::SpriteRam);
} else {
value = _oamRam[0x200 | (_internalOamAddress & 0x1F)];
_console->ProcessPpuRead(0x200 | (_internalOamAddress & 0x1F), value, SnesMemoryType::SpriteRam);
}
_internalOamAddress = (_internalOamAddress + 1) & 0x3FF;
return value;
@ -1075,6 +1077,7 @@ uint8_t Ppu::Read(uint16_t addr)
case 0x2139: {
//VMDATALREAD - VRAM Data Read low byte
uint8_t returnValue = (uint8_t)_vramReadBuffer;
_console->ProcessPpuRead(_vramAddress, returnValue, SnesMemoryType::VideoRam);
if(!_vramAddrIncrementOnSecondReg) {
UpdateVramReadBuffer();
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
@ -1085,6 +1088,7 @@ uint8_t Ppu::Read(uint16_t addr)
case 0x213A: {
//VMDATAHREAD - VRAM Data Read high byte
uint8_t returnValue = (uint8_t)(_vramReadBuffer >> 8);
_console->ProcessPpuRead(_vramAddress + 1, returnValue, SnesMemoryType::VideoRam);
if(_vramAddrIncrementOnSecondReg) {
UpdateVramReadBuffer();
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
@ -1095,6 +1099,7 @@ uint8_t Ppu::Read(uint16_t addr)
case 0x213B: {
//CGDATAREAD - CGRAM Data read
uint8_t value = _cgram[_cgramAddress];
_console->ProcessPpuRead(_cgramAddress, value, SnesMemoryType::CGRam);
_cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1);
return value;
}
@ -1195,7 +1200,10 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x2104:
if(_internalOamAddress < 512) {
if(_internalOamAddress & 0x01) {
_console->ProcessPpuWrite(_internalOamAddress - 1, _oamWriteBuffer, SnesMemoryType::SpriteRam);
_oamRam[_internalOamAddress - 1] = _oamWriteBuffer;
_console->ProcessPpuWrite(_internalOamAddress, value, SnesMemoryType::SpriteRam);
_oamRam[_internalOamAddress] = value;
} else {
_oamWriteBuffer = value;
@ -1205,6 +1213,7 @@ void Ppu::Write(uint32_t addr, uint8_t value)
if((_internalOamAddress & 0x01) == 0) {
_oamWriteBuffer = value;
}
_console->ProcessPpuWrite(address, value, SnesMemoryType::SpriteRam);
_oamRam[address] = value;
}
_internalOamAddress = (_internalOamAddress + 1) & 0x3FF;
@ -1303,6 +1312,8 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x2118:
//VMDATAL - VRAM Data Write low byte
_console->ProcessPpuWrite(_vramAddress << 1, value, SnesMemoryType::VideoRam);
_vram[_vramAddress << 1] = value;
if(!_vramAddrIncrementOnSecondReg) {
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
@ -1311,6 +1322,8 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x2119:
//VMDATAH - VRAM Data Write high byte
_console->ProcessPpuWrite((_vramAddress << 1) + 1, value, SnesMemoryType::VideoRam);
_vram[(_vramAddress << 1) + 1] = value;
if(_vramAddrIncrementOnSecondReg) {
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
@ -1350,6 +1363,8 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 0x2122:
//CGRAM Data write (CGDATA)
_console->ProcessPpuWrite(_cgramAddress, value, SnesMemoryType::CGRam);
_cgram[_cgramAddress] = value;
_cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1);
break;

View file

@ -1,20 +1,23 @@
#pragma once
#include "stdafx.h"
#include "IMemoryHandler.h"
#include "Console.h"
#include "Ppu.h"
#include "Spc.h"
class RegisterHandlerB : public IMemoryHandler
{
private:
Ppu * _ppu;
Console *_console;
Ppu *_ppu;
Spc *_spc;
uint8_t *_workRam;
uint32_t _wramPosition;
public:
RegisterHandlerB(Ppu *ppu, Spc *spc, uint8_t *workRam)
RegisterHandlerB(Console *console, Ppu *ppu, Spc *spc, uint8_t *workRam)
{
_console = console;
_ppu = ppu;
_spc = spc;
_workRam = workRam;
@ -28,6 +31,7 @@ public:
return _spc->Read(addr & 0x03);
} else if(addr == 0x2180) {
uint8_t value = _workRam[_wramPosition];
_console->ProcessWorkRamRead(_wramPosition, value);
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
return value;
} else {
@ -49,8 +53,9 @@ public:
} if(addr >= 0x2180 && addr <= 0x2183) {
switch(addr & 0xFFFF) {
case 0x2180:
_console->ProcessWorkRamWrite(_wramPosition, value);
_workRam[_wramPosition] = value;
_wramPosition = (_wramPosition + 1) & (0x1FFFF);
_wramPosition = (_wramPosition + 1) & 0x1FFFF;
break;
case 0x2181: _wramPosition = (_wramPosition & 0x1FF00) | value; break;

View file

@ -5,6 +5,8 @@
#include "../Core/MemoryDumper.h"
#include "../Core/Disassembler.h"
#include "../Core/DebugTypes.h"
#include "../Core/Breakpoint.h"
#include "../Core/BreakpointManager.h"
extern shared_ptr<Console> _console;
@ -33,7 +35,7 @@ extern "C"
}
DllExport bool __stdcall IsExecutionStopped() { return GetDebugger()->IsExecutionStopped(); }
DllExport void __stdcall ResumeExecution() { GetDebugger()->Run(); }
DllExport void __stdcall ResumeExecution() { if(IsDebuggerRunning()) GetDebugger()->Run(); }
DllExport void __stdcall Step(uint32_t count) { GetDebugger()->Step(count); }
DllExport void __stdcall GetDisassemblyLineData(uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(lineIndex, data); }
@ -46,9 +48,10 @@ extern "C"
DllExport void __stdcall StopTraceLogger() { GetDebugger()->GetTraceLogger()->StopLogging(); }
DllExport const char* GetExecutionTrace(uint32_t lineCount) { return GetDebugger()->GetTraceLogger()->GetExecutionTrace(lineCount); }
DllExport void __stdcall SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->GetBreakpointManager()->SetBreakpoints(breakpoints, length); }
DllExport int32_t __stdcall EvaluateExpression(char* expression, EvalResultType *resultType, bool useCache) { return GetDebugger()->EvaluateExpression(expression, *resultType, useCache); }
DllExport void __stdcall GetState(DebugState *state) { GetDebugger()->GetState(state); }
DllExport void __stdcall GetState(DebugState &state) { GetDebugger()->GetState(state); }
DllExport void __stdcall SetMemoryState(SnesMemoryType type, uint8_t *buffer, int32_t length) { GetDebugger()->GetMemoryDumper()->SetMemoryState(type, buffer, length); }
DllExport uint32_t __stdcall GetMemorySize(SnesMemoryType type) { return GetDebugger()->GetMemoryDumper()->GetMemorySize(type); }

View file

@ -0,0 +1,221 @@
using System;
using System.Text;
namespace Mesen.GUI.Debugger
{
public class Breakpoint
{
private SnesMemoryType _memoryType = SnesMemoryType.CpuMemory;
private bool _isCpuBreakpoint = true;
public bool BreakOnRead = false;
public bool BreakOnWrite = false;
public bool BreakOnExec = true;
public bool Enabled = true;
public bool MarkEvent = false;
public UInt32 Address = UInt32.MaxValue;
public UInt32 StartAddress;
public UInt32 EndAddress;
public BreakpointAddressType AddressType = BreakpointAddressType.SingleAddress;
public string Condition = "";
public SnesMemoryType MemoryType
{
get { return _memoryType; }
set
{
_memoryType = value;
_isCpuBreakpoint = IsTypeCpuBreakpoint(value);
}
}
public string GetAddressString(bool showLabel)
{
string addr = "";
switch(AddressType) {
case BreakpointAddressType.AnyAddress:
return "<any>";
case BreakpointAddressType.SingleAddress:
if(IsAbsoluteAddress) {
addr += $"[${Address.ToString("X6")}]";
} else {
addr = $"${Address.ToString("X6")}";
}
break;
case BreakpointAddressType.AddressRange:
if(IsAbsoluteAddress) {
addr = $"[${StartAddress.ToString("X6")}] - [${EndAddress.ToString("X6")}]";
} else {
addr = $"${StartAddress.ToString("X6")} - ${EndAddress.ToString("X6")}";
}
break;
}
//TODO LABELS
/*string label = GetAddressLabel();
if(showLabel && !string.IsNullOrWhiteSpace(label)) {
addr = label + $", {addr}";
}*/
return addr;
}
public static bool IsTypeCpuBreakpoint(SnesMemoryType type)
{
return (
type == SnesMemoryType.CpuMemory ||
type == SnesMemoryType.WorkRam ||
type == SnesMemoryType.SaveRam ||
type == SnesMemoryType.PrgRom
);
}
public void SetEnabled(bool enabled)
{
Enabled = enabled;
BreakpointManager.RefreshBreakpoints(this);
}
public void SetMarked(bool marked)
{
MarkEvent = marked;
BreakpointManager.RefreshBreakpoints(this);
}
public bool IsAbsoluteAddress { get { return MemoryType != SnesMemoryType.CpuMemory; } }
public bool IsCpuBreakpoint { get { return this._isCpuBreakpoint; } }
private BreakpointTypeFlags Type
{
get
{
BreakpointTypeFlags type = BreakpointTypeFlags.None;
if(BreakOnRead) {
type |= BreakpointTypeFlags.Read;
}
if(BreakOnWrite) {
type |= BreakpointTypeFlags.Write;
}
if(BreakOnExec && IsCpuBreakpoint) {
type |= BreakpointTypeFlags.Execute;
}
return type;
}
}
public string ToReadableType()
{
string type;
switch(MemoryType) {
default: throw new Exception("invalid type");
case SnesMemoryType.CpuMemory: type = "CPU"; break;
case SnesMemoryType.PrgRom: type = "PRG"; break;
case SnesMemoryType.WorkRam: type = "WRAM"; break;
case SnesMemoryType.SaveRam: type = "SRAM"; break;
case SnesMemoryType.VideoRam: type = "VRAM"; break;
case SnesMemoryType.SpriteRam: type = "OAM"; break;
case SnesMemoryType.CGRam: type = "CG"; break;
}
type += ":";
type += BreakOnRead ? "R" : "";
type += BreakOnWrite ? "W" : "";
if(IsCpuBreakpoint) {
type += BreakOnExec ? "X" : "";
}
return type;
}
public int GetRelativeAddress()
{
UInt32 address = AddressType == BreakpointAddressType.SingleAddress ? this.Address : this.StartAddress;
if(IsCpuBreakpoint && this.IsAbsoluteAddress) {
//TODO
//return InteropEmu.DebugGetRelativeAddress(address, this.MemoryType.ToAddressType());
return -1;
} else {
return (int)address;
}
}
private int GetRelativeAddressEnd()
{
if(this.AddressType == BreakpointAddressType.AddressRange){
if(IsCpuBreakpoint && this.IsAbsoluteAddress) {
//TODO
//return InteropEmu.DebugGetRelativeAddress(this.EndAddress, this.MemoryType.ToAddressType());
} else {
return (int)this.EndAddress;
}
}
return -1;
}
public bool Matches(UInt32 address, SnesMemoryType type)
{
if(IsTypeCpuBreakpoint(type) != this.IsCpuBreakpoint) {
return false;
}
bool isRelativeMemory = type == SnesMemoryType.CpuMemory;
if(this.AddressType == BreakpointAddressType.SingleAddress) {
return address == this.Address && type == this.MemoryType;
} else if(this.AddressType == BreakpointAddressType.AddressRange) {
return address >= this.StartAddress && address <= this.EndAddress && type == this.MemoryType;
}
return false;
}
public InteropBreakpoint ToInteropBreakpoint(int breakpointId)
{
InteropBreakpoint bp = new InteropBreakpoint() {
Id = breakpointId,
MemoryType = MemoryType,
Type = Type,
MarkEvent = MarkEvent,
Enabled = Enabled
};
switch(AddressType) {
case BreakpointAddressType.AnyAddress:
bp.StartAddress = -1;
bp.EndAddress = -1;
break;
case BreakpointAddressType.SingleAddress:
bp.StartAddress = (Int32)Address;
bp.EndAddress = -1;
break;
case BreakpointAddressType.AddressRange:
bp.StartAddress = (Int32)StartAddress;
bp.EndAddress = (Int32)EndAddress;
break;
}
bp.Condition = new byte[1000];
byte[] condition = Encoding.UTF8.GetBytes(Condition.Replace(Environment.NewLine, " "));
Array.Copy(condition, bp.Condition, condition.Length);
return bp;
}
}
public enum BreakpointAddressType
{
AnyAddress,
SingleAddress,
AddressRange,
}
[Flags]
public enum BreakpointTypeFlags
{
None = 0,
Execute = 1,
Read = 2,
Write = 4,
}
}

View file

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public class BreakpointManager
{
public static event EventHandler BreakpointsChanged;
private static List<Breakpoint> _breakpoints = new List<Breakpoint>();
public static ReadOnlyCollection<Breakpoint> Breakpoints
{
get { return _breakpoints.ToList().AsReadOnly(); }
}
public static void RefreshBreakpoints(Breakpoint bp = null)
{
if(BreakpointsChanged != null) {
BreakpointsChanged(bp, null);
}
SetBreakpoints();
}
public static void SetBreakpoints(List<Breakpoint> breakpoints)
{
_breakpoints = breakpoints.ToList();
RefreshBreakpoints();
}
public static void EditBreakpoint(Breakpoint bp)
{
if(new frmBreakpoint(bp).ShowDialog() == DialogResult.OK) {
if(!_breakpoints.Contains(bp)) {
_breakpoints.Add(bp);
}
RefreshBreakpoints(bp);
}
}
public static void RemoveBreakpoint(Breakpoint bp)
{
_breakpoints.Remove(bp);
RefreshBreakpoints(bp);
}
public static void AddBreakpoint(Breakpoint bp)
{
_breakpoints.Add(bp);
RefreshBreakpoints(bp);
}
public static Breakpoint GetMatchingBreakpoint(AddressInfo info)
{
return Breakpoints.Where((bp) => bp.Matches((UInt32)info.Address, info.Type)).FirstOrDefault();
}
public static Breakpoint GetMatchingBreakpoint(UInt32 startAddress, UInt32 endAddress, SnesMemoryType memoryType)
{
bool isAddressRange = startAddress != endAddress;
return Breakpoints.Where((bp) =>
bp.MemoryType == memoryType &&
((!isAddressRange && bp.Address == startAddress) || (isAddressRange && bp.StartAddress == startAddress && bp.EndAddress == endAddress))
).FirstOrDefault();
}
public static void EnableDisableBreakpoint(AddressInfo info)
{
Breakpoint breakpoint = BreakpointManager.GetMatchingBreakpoint(info);
if(breakpoint != null) {
breakpoint.SetEnabled(!breakpoint.Enabled);
}
}
public static void ToggleBreakpoint(AddressInfo info)
{
if(info.Address < 0) {
return;
}
Breakpoint breakpoint = BreakpointManager.GetMatchingBreakpoint(info);
if(breakpoint != null) {
BreakpointManager.RemoveBreakpoint(breakpoint);
} else {
breakpoint = new Breakpoint() {
Enabled = true,
BreakOnExec = true,
Address = (UInt32)info.Address
};
if(info.Type != SnesMemoryType.PrgRom) {
breakpoint.BreakOnRead = true;
breakpoint.BreakOnWrite = true;
}
breakpoint.MemoryType = info.Type;
BreakpointManager.AddBreakpoint(breakpoint);
}
}
public static void SetBreakpoints()
{
List<InteropBreakpoint> breakpoints = new List<InteropBreakpoint>();
for(int i = 0; i < Breakpoints.Count; i++) {
breakpoints.Add(Breakpoints[i].ToInteropBreakpoint(i));
}
DebugApi.SetBreakpoints(breakpoints.ToArray(), (UInt32)breakpoints.Count);
}
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Runtime.InteropServices;
namespace Mesen.GUI.Debugger
{
public struct InteropBreakpoint
{
public Int32 Id;
public SnesMemoryType MemoryType;
public BreakpointTypeFlags Type;
public Int32 StartAddress;
public Int32 EndAddress;
[MarshalAs(UnmanagedType.I1)]
public bool Enabled;
[MarshalAs(UnmanagedType.I1)]
public bool MarkEvent;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
public byte[] Condition;
}
}

View file

@ -0,0 +1,176 @@
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 Mesen.GUI.Controls;
using System.Collections.ObjectModel;
using Mesen.GUI.Config;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlBreakpoints : BaseControl
{
public event EventHandler BreakpointNavigation;
private Font _markedColumnFont;
public ctrlBreakpoints()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!IsDesignMode) {
_markedColumnFont = new Font(this.Font.FontFamily, 13f);
//TODO Labels
//mnuShowLabels.Checked = ConfigManager.Config.Debug.ShowBreakpointLabels;
mnuShowLabels.CheckedChanged += mnuShowLabels_CheckedChanged;
BreakpointManager.BreakpointsChanged += BreakpointManager_OnBreakpointChanged;
mnuRemoveBreakpoint.Enabled = false;
mnuEditBreakpoint.Enabled = false;
mnuGoToLocation.Enabled = false;
InitShortcuts();
}
}
private void InitShortcuts()
{
mnuAddBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Add));
mnuEditBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Edit));
mnuRemoveBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_Delete));
mnuGoToLocation.InitShortcut(this, nameof(DebuggerShortcutsConfig.BreakpointList_GoToLocation));
}
private void BreakpointManager_OnBreakpointChanged(object sender, EventArgs e)
{
RefreshList();
}
public void RefreshListAddresses()
{
lstBreakpoints.BeginUpdate();
ReadOnlyCollection<Breakpoint> breakpoints = BreakpointManager.Breakpoints;
for(int i = 0; i < breakpoints.Count; i++) {
lstBreakpoints.Items[i].SubItems[3].Text = breakpoints[i].GetAddressString(mnuShowLabels.Checked);
}
lstBreakpoints.EndUpdate();
}
public void RefreshList()
{
lstBreakpoints.ItemChecked -= new ItemCheckedEventHandler(lstBreakpoints_ItemChecked);
int topIndex = lstBreakpoints.TopItem != null ? lstBreakpoints.TopItem.Index : 0;
lstBreakpoints.BeginUpdate();
lstBreakpoints.Items.Clear();
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
ListViewItem item = new ListViewItem();
item.Tag = breakpoint;
item.Checked = breakpoint.Enabled;
item.UseItemStyleForSubItems = false;
item.SubItems.Add(breakpoint.MarkEvent ? "☑" : "☐").Font = _markedColumnFont;
item.SubItems.Add(breakpoint.ToReadableType());
item.SubItems.Add(breakpoint.GetAddressString(mnuShowLabels.Checked));
item.SubItems.Add(breakpoint.Condition);
lstBreakpoints.Items.Add(item);
}
lstBreakpoints.EndUpdate();
if(lstBreakpoints.Items.Count > 0) {
lstBreakpoints.TopItem = lstBreakpoints.Items[lstBreakpoints.Items.Count > topIndex ? topIndex : lstBreakpoints.Items.Count - 1];
}
lstBreakpoints.ItemChecked += new ItemCheckedEventHandler(lstBreakpoints_ItemChecked);
}
private void lstBreakpoints_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if(((Breakpoint)e.Item.Tag).Enabled != e.Item.Checked) {
((Breakpoint)e.Item.Tag).SetEnabled(e.Item.Checked);
}
}
private void lstBreakpoints_DoubleClick(object sender, EventArgs e)
{
if(lstBreakpoints.SelectedItems.Count > 0) {
BreakpointManager.EditBreakpoint(((Breakpoint)lstBreakpoints.SelectedItems[0].Tag));
}
}
private void mnuRemoveBreakpoint_Click(object sender, EventArgs e)
{
foreach(ListViewItem item in lstBreakpoints.SelectedItems) {
BreakpointManager.RemoveBreakpoint((Breakpoint)item.Tag);
}
}
private void mnuAddBreakpoint_Click(object sender, EventArgs e)
{
Breakpoint breakpoint = new Breakpoint();
if(new frmBreakpoint(breakpoint).ShowDialog() == DialogResult.OK) {
BreakpointManager.AddBreakpoint(breakpoint);
}
}
private void mnuGoToLocation_Click(object sender, EventArgs e)
{
if(BreakpointNavigation != null) {
Breakpoint bp = lstBreakpoints.SelectedItems[0].Tag as Breakpoint;
if(bp.IsCpuBreakpoint && bp.GetRelativeAddress() >= 0) {
BreakpointNavigation(bp, null);
}
}
}
private void mnuEditBreakpoint_Click(object sender, EventArgs e)
{
if(lstBreakpoints.SelectedItems.Count > 0) {
BreakpointManager.EditBreakpoint(((Breakpoint)lstBreakpoints.SelectedItems[0].Tag));
}
}
private void lstBreakpoints_SelectedIndexChanged(object sender, EventArgs e)
{
mnuRemoveBreakpoint.Enabled = (lstBreakpoints.SelectedItems.Count > 0);
mnuEditBreakpoint.Enabled = (lstBreakpoints.SelectedItems.Count == 1);
if(lstBreakpoints.SelectedItems.Count == 1) {
Breakpoint bp = lstBreakpoints.SelectedItems[0].Tag as Breakpoint;
mnuGoToLocation.Enabled = bp.IsCpuBreakpoint && bp.GetRelativeAddress() >= 0;
}
}
private void mnuShowLabels_CheckedChanged(object sender, EventArgs e)
{
//TODO
/*ConfigManager.Config.Debug.ShowBreakpointLabels = mnuShowLabels.Checked;
ConfigManager.ApplyChanges();
*/
this.RefreshListAddresses();
}
private void lstBreakpoints_MouseDown(object sender, MouseEventArgs e)
{
ListViewHitTestInfo info = lstBreakpoints.HitTest(e.X, e.Y);
if(info != null && info.Item != null) {
int row = info.Item.Index;
int col = info.Item.SubItems.IndexOf(info.SubItem);
if(col == 1 && row < lstBreakpoints.Items.Count) {
this.BeginInvoke((Action)(() => {
Breakpoint bp = lstBreakpoints.Items[row].Tag as Breakpoint;
bp?.SetMarked(!bp.MarkEvent);
}));
}
}
}
}
}

View file

@ -0,0 +1,188 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlBreakpoints
{
/// <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();
}
BreakpointManager.BreakpointsChanged -= BreakpointManager_OnBreakpointChanged;
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.mnuBreakpoints = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuAddBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuShowLabels = new System.Windows.Forms.ToolStripMenuItem();
this.lstBreakpoints = new Mesen.GUI.Controls.MyListView();
this.colEnabled = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colMarker = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colCondition = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.mnuBreakpoints.SuspendLayout();
this.SuspendLayout();
//
// mnuBreakpoints
//
this.mnuBreakpoints.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuAddBreakpoint,
this.mnuEditBreakpoint,
this.mnuRemoveBreakpoint,
this.toolStripMenuItem1,
this.mnuGoToLocation,
this.toolStripMenuItem2,
this.mnuShowLabels});
this.mnuBreakpoints.Name = "mnuBreakpoints";
this.mnuBreakpoints.Size = new System.Drawing.Size(150, 126);
//
// mnuAddBreakpoint
//
this.mnuAddBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddBreakpoint.Name = "mnuAddBreakpoint";
this.mnuAddBreakpoint.Size = new System.Drawing.Size(149, 22);
this.mnuAddBreakpoint.Text = "Add...";
this.mnuAddBreakpoint.Click += new System.EventHandler(this.mnuAddBreakpoint_Click);
//
// mnuEditBreakpoint
//
this.mnuEditBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditBreakpoint.Name = "mnuEditBreakpoint";
this.mnuEditBreakpoint.Size = new System.Drawing.Size(149, 22);
this.mnuEditBreakpoint.Text = "Edit";
this.mnuEditBreakpoint.Click += new System.EventHandler(this.mnuEditBreakpoint_Click);
//
// mnuRemoveBreakpoint
//
this.mnuRemoveBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Close;
this.mnuRemoveBreakpoint.Name = "mnuRemoveBreakpoint";
this.mnuRemoveBreakpoint.Size = new System.Drawing.Size(149, 22);
this.mnuRemoveBreakpoint.Text = "Remove";
this.mnuRemoveBreakpoint.Click += new System.EventHandler(this.mnuRemoveBreakpoint_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(146, 6);
//
// mnuGoToLocation
//
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.Size = new System.Drawing.Size(149, 22);
this.mnuGoToLocation.Text = "Go to location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(146, 6);
//
// mnuShowLabels
//
this.mnuShowLabels.CheckOnClick = true;
this.mnuShowLabels.Name = "mnuShowLabels";
this.mnuShowLabels.Size = new System.Drawing.Size(149, 22);
this.mnuShowLabels.Text = "Show Labels";
//
// lstBreakpoints
//
this.lstBreakpoints.CheckBoxes = true;
this.lstBreakpoints.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colEnabled,
this.colMarker,
this.colType,
this.colAddress,
this.colCondition});
this.lstBreakpoints.ContextMenuStrip = this.mnuBreakpoints;
this.lstBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstBreakpoints.FullRowSelect = true;
this.lstBreakpoints.GridLines = true;
this.lstBreakpoints.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.lstBreakpoints.Location = new System.Drawing.Point(0, 0);
this.lstBreakpoints.Name = "lstBreakpoints";
this.lstBreakpoints.Size = new System.Drawing.Size(393, 101);
this.lstBreakpoints.TabIndex = 7;
this.lstBreakpoints.UseCompatibleStateImageBehavior = false;
this.lstBreakpoints.View = System.Windows.Forms.View.Details;
this.lstBreakpoints.SelectedIndexChanged += new System.EventHandler(this.lstBreakpoints_SelectedIndexChanged);
this.lstBreakpoints.DoubleClick += new System.EventHandler(this.lstBreakpoints_DoubleClick);
this.lstBreakpoints.MouseDown += new System.Windows.Forms.MouseEventHandler(this.lstBreakpoints_MouseDown);
//
// colEnabled
//
this.colEnabled.Text = "";
this.colEnabled.Width = 21;
//
// colMarker
//
this.colMarker.Text = "M";
this.colMarker.Width = 25;
//
// colType
//
this.colType.Text = "Type";
this.colType.Width = 87;
//
// colAddress
//
this.colAddress.Text = "Address";
this.colAddress.Width = 108;
//
// colCondition
//
this.colCondition.Text = "Condition";
this.colCondition.Width = 142;
//
// ctrlBreakpoints
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.lstBreakpoints);
this.Name = "ctrlBreakpoints";
this.Size = new System.Drawing.Size(393, 101);
this.mnuBreakpoints.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private Mesen.GUI.Controls.MyListView lstBreakpoints;
private System.Windows.Forms.ColumnHeader colType;
private System.Windows.Forms.ColumnHeader colAddress;
private System.Windows.Forms.ContextMenuStrip mnuBreakpoints;
private System.Windows.Forms.ToolStripMenuItem mnuAddBreakpoint;
private System.Windows.Forms.ToolStripMenuItem mnuRemoveBreakpoint;
private System.Windows.Forms.ColumnHeader colEnabled;
private System.Windows.Forms.ColumnHeader colCondition;
private System.Windows.Forms.ToolStripMenuItem mnuGoToLocation;
private System.Windows.Forms.ToolStripMenuItem mnuEditBreakpoint;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuShowLabels;
private System.Windows.Forms.ColumnHeader colMarker;
}
}

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="mnuBreakpoints.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,219 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
using Mesen.GUI.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmBreakpoint : BaseConfigForm
{
public frmBreakpoint(Breakpoint breakpoint)
{
InitializeComponent();
Entity = breakpoint;
switch(breakpoint.AddressType) {
case BreakpointAddressType.AnyAddress: radAnyAddress.Checked = true; break;
case BreakpointAddressType.SingleAddress: radSpecificAddress.Checked = true; break;
case BreakpointAddressType.AddressRange: radRange.Checked = true; break;
}
AddBinding("MemoryType", cboBreakpointType);
AddBinding("Enabled", chkEnabled);
AddBinding("MarkEvent", chkMarkOnEventViewer);
AddBinding("Address", txtAddress);
AddBinding("StartAddress", txtFrom);
AddBinding("EndAddress", txtTo);
AddBinding("BreakOnRead", chkRead);
AddBinding("BreakOnWrite", chkWrite);
AddBinding("BreakOnExec", chkExec);
AddBinding("Condition", txtCondition);
cboBreakpointType.Items.Clear();
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CpuMemory));
cboBreakpointType.Items.Add("-");
//TODO - Might not be useful on the SNES?
/*if(DebugApi.GetMemorySize(SnesMemoryType.PrgRom) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.PrgRom));
}
if(DebugApi.GetMemorySize(SnesMemoryType.WorkRam) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.WorkRam));
}
if(DebugApi.GetMemorySize(SnesMemoryType.SaveRam) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SaveRam));
}
if(cboBreakpointType.Items.Count > 2) {
cboBreakpointType.Items.Add("-");
}*/
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.VideoRam));
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.SpriteRam));
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.CGRam));
this.toolTip.SetToolTip(this.picExpressionWarning, "Condition contains invalid syntax or symbols.");
this.toolTip.SetToolTip(this.picHelp, frmBreakpoint.GetConditionTooltip(false));
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
Breakpoint bp = (Breakpoint)this.Entity;
if(!BreakpointManager.Breakpoints.Contains(bp)) {
//This is a new breakpoint, make sure address fields are empty instead of 0
if(bp.Address == UInt32.MaxValue) {
txtAddress.Text = "";
}
if(txtFrom.Text == "0") {
txtFrom.Text = "";
}
if(txtTo.Text == "0") {
txtTo.Text = "";
}
}
if(bp.Address == 0 && bp.AddressType != BreakpointAddressType.SingleAddress) {
txtAddress.Text = "";
}
if(bp.StartAddress == 0 && bp.EndAddress == 0 && bp.AddressType != BreakpointAddressType.AddressRange) {
txtFrom.Text = "";
txtTo.Text = "";
}
if(bp.AddressType == BreakpointAddressType.AddressRange) {
txtFrom.Focus();
txtFrom.SelectionStart = 0;
txtFrom.SelectionLength = 0;
} else if(bp.AddressType == BreakpointAddressType.SingleAddress) {
txtAddress.Focus();
txtAddress.SelectionStart = 0;
txtAddress.SelectionLength = 0;
}
}
public static string GetConditionTooltip(bool forWatch)
{
string tooltip =
"Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine +
"Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine +
"Note 2: Labels assigned to the code can be used (their value will match the label's address in CPU memory)." + Environment.NewLine + Environment.NewLine +
"A/X/Y/PS/SP: Value of registers" + Environment.NewLine +
"PC: Program Counter" + Environment.NewLine +
"OpPC: Address of the current instruction's first byte" + Environment.NewLine +
"PreviousOpPC: Address of the previous instruction's first byte" + Environment.NewLine +
"Irq/Nmi/Sprite0Hit/SpriteOverflow/VerticalBlank: True if the corresponding flags are set" + Environment.NewLine +
"Branched: True if the current instruction was reached by jumping or branching" + Environment.NewLine +
"Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 260) of the PPU" + Environment.NewLine +
"Frame: PPU frame number (since power on/reset)" + Environment.NewLine +
"Value: Current value being read/written from/to memory" + Environment.NewLine +
"IsRead: True if the CPU is reading from a memory address" + Environment.NewLine +
"IsWrite: True if the CPU is writing to a memory address" + Environment.NewLine;
if(!forWatch) {
tooltip +=
"Address: Current CPU memory address being read/written" + Environment.NewLine +
"RomAddress: Current ROM address being read/written" + Environment.NewLine;
}
tooltip +=
"[<address>]: (Byte) Memory value at <address> (CPU)" + Environment.NewLine +
"{<address>}: (Word) Memory value at <address> (CPU)" + Environment.NewLine + Environment.NewLine +
"Examples:" + Environment.NewLine +
"a == 10 || x == $23" + Environment.NewLine +
"scanline == 10 && (cycle >= 55 && cycle <= 100)" + Environment.NewLine +
"x == [$150] || y == [10]" + Environment.NewLine +
"[[$15] + y] -> Reads the value at address $15, adds Y to it and reads the value at the resulting address." + Environment.NewLine +
"{$FFFA} -> Returns the NMI handler's address.";
return tooltip;
}
protected override void UpdateConfig()
{
base.UpdateConfig();
if(radAnyAddress.Checked) {
((Breakpoint)Entity).AddressType = BreakpointAddressType.AnyAddress;
} else if(radSpecificAddress.Checked) {
((Breakpoint)Entity).AddressType = BreakpointAddressType.SingleAddress;
} else if(radRange.Checked) {
((Breakpoint)Entity).AddressType = BreakpointAddressType.AddressRange;
}
}
protected override bool ValidateInput()
{
if(txtCondition.Text.Trim().Length > 0) {
EvalResultType resultType;
DebugApi.EvaluateExpression(txtCondition.Text.Replace(Environment.NewLine, " "), out resultType, false);
if(resultType == EvalResultType.Invalid) {
picExpressionWarning.Visible = true;
return false;
}
}
picExpressionWarning.Visible = false;
SnesMemoryType type = cboBreakpointType.GetEnumValue<SnesMemoryType>();
int maxValue = DebugApi.GetMemorySize(type) - 1;
if(radSpecificAddress.Checked) {
if(ValidateAddress(txtAddress, maxValue) < 0) {
return false;
}
} else if(radRange.Checked) {
int start = ValidateAddress(txtFrom, maxValue);
int end = ValidateAddress(txtTo, maxValue);
if(start < 0 || end < 0 || end < start) {
return false;
}
}
return chkRead.Checked || chkWrite.Checked || (chkExec.Checked && Breakpoint.IsTypeCpuBreakpoint(type)) || txtCondition.Text.Length > 0;
}
private int ValidateAddress(TextBox field, int maxValue)
{
int value = -1;
if(!int.TryParse(field.Text, NumberStyles.HexNumber, null, out value) || value > maxValue) {
field.ForeColor = Color.Red;
value = -1;
} else {
field.ForeColor = SystemColors.ControlText;
}
return value;
}
private void txtAddress_Enter(object sender, EventArgs e)
{
radSpecificAddress.Checked = true;
}
private void txtFrom_Enter(object sender, EventArgs e)
{
radRange.Checked = true;
}
private void txtTo_Enter(object sender, EventArgs e)
{
radRange.Checked = true;
}
private void cboBreakpointType_SelectedIndexChanged(object sender, EventArgs e)
{
SnesMemoryType type = cboBreakpointType.GetEnumValue<SnesMemoryType>();
chkExec.Visible = Breakpoint.IsTypeCpuBreakpoint(type);
string maxValue = (DebugApi.GetMemorySize(type) - 1).ToString("X2");
string minValue = "".PadLeft(maxValue.Length, '0');
lblRange.Text = $"(range: ${minValue}-${maxValue})";
}
}
}

View file

@ -0,0 +1,562 @@
namespace Mesen.GUI.Debugger
{
partial class frmBreakpoint
{
/// <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.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.lblBreakpointType = new System.Windows.Forms.Label();
this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
this.chkRead = new System.Windows.Forms.CheckBox();
this.chkWrite = new System.Windows.Forms.CheckBox();
this.chkExec = new System.Windows.Forms.CheckBox();
this.lblBreakOn = new System.Windows.Forms.Label();
this.lblAddress = new System.Windows.Forms.Label();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.picHelp = new System.Windows.Forms.PictureBox();
this.txtCondition = new System.Windows.Forms.TextBox();
this.picExpressionWarning = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.txtAddress = new System.Windows.Forms.TextBox();
this.radSpecificAddress = new System.Windows.Forms.RadioButton();
this.radAnyAddress = new System.Windows.Forms.RadioButton();
this.lblAddressSign = new System.Windows.Forms.Label();
this.radRange = new System.Windows.Forms.RadioButton();
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
this.txtTo = new System.Windows.Forms.TextBox();
this.lblTo = new System.Windows.Forms.Label();
this.txtFrom = new System.Windows.Forms.TextBox();
this.lblFrom = new System.Windows.Forms.Label();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.cboBreakpointType = new Mesen.GUI.Debugger.Controls.ComboBoxWithSeparator();
this.lblRange = new System.Windows.Forms.Label();
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
this.label1 = new System.Windows.Forms.Label();
this.lblCondition = new System.Windows.Forms.Label();
this.chkMarkOnEventViewer = new System.Windows.Forms.CheckBox();
this.chkEnabled = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel7 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel1.SuspendLayout();
this.flowLayoutPanel2.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).BeginInit();
this.tableLayoutPanel3.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.tableLayoutPanel6.SuspendLayout();
this.tableLayoutPanel7.SuspendLayout();
this.SuspendLayout();
//
// baseConfigPanel
//
this.baseConfigPanel.Location = new System.Drawing.Point(0, 197);
this.baseConfigPanel.Size = new System.Drawing.Size(426, 29);
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.lblBreakpointType, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.lblBreakOn, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.lblAddress, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel6, 0, 3);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 6;
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.Absolute, 20F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(426, 226);
this.tableLayoutPanel1.TabIndex = 2;
//
// lblBreakpointType
//
this.lblBreakpointType.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblBreakpointType.AutoSize = true;
this.lblBreakpointType.Location = new System.Drawing.Point(3, 8);
this.lblBreakpointType.Margin = new System.Windows.Forms.Padding(3, 4, 3, 0);
this.lblBreakpointType.Name = "lblBreakpointType";
this.lblBreakpointType.Size = new System.Drawing.Size(88, 13);
this.lblBreakpointType.TabIndex = 12;
this.lblBreakpointType.Text = "Breakpoint Type:";
//
// flowLayoutPanel2
//
this.flowLayoutPanel2.Controls.Add(this.chkRead);
this.flowLayoutPanel2.Controls.Add(this.chkWrite);
this.flowLayoutPanel2.Controls.Add(this.chkExec);
this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutPanel2.Location = new System.Drawing.Point(94, 25);
this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel2.Name = "flowLayoutPanel2";
this.flowLayoutPanel2.Size = new System.Drawing.Size(332, 23);
this.flowLayoutPanel2.TabIndex = 4;
//
// chkRead
//
this.chkRead.AutoSize = true;
this.chkRead.Location = new System.Drawing.Point(3, 3);
this.chkRead.Name = "chkRead";
this.chkRead.Size = new System.Drawing.Size(52, 17);
this.chkRead.TabIndex = 4;
this.chkRead.Text = "Read";
this.chkRead.UseVisualStyleBackColor = true;
//
// chkWrite
//
this.chkWrite.AutoSize = true;
this.chkWrite.Location = new System.Drawing.Point(61, 3);
this.chkWrite.Name = "chkWrite";
this.chkWrite.Size = new System.Drawing.Size(51, 17);
this.chkWrite.TabIndex = 5;
this.chkWrite.Text = "Write";
this.chkWrite.UseVisualStyleBackColor = true;
//
// chkExec
//
this.chkExec.AutoSize = true;
this.chkExec.Location = new System.Drawing.Point(118, 3);
this.chkExec.Name = "chkExec";
this.chkExec.Size = new System.Drawing.Size(73, 17);
this.chkExec.TabIndex = 3;
this.chkExec.Text = "Execution";
this.chkExec.UseVisualStyleBackColor = true;
//
// lblBreakOn
//
this.lblBreakOn.AutoSize = true;
this.lblBreakOn.Location = new System.Drawing.Point(3, 29);
this.lblBreakOn.Margin = new System.Windows.Forms.Padding(3, 4, 3, 0);
this.lblBreakOn.Name = "lblBreakOn";
this.lblBreakOn.Size = new System.Drawing.Size(53, 13);
this.lblBreakOn.TabIndex = 0;
this.lblBreakOn.Text = "Break on:";
//
// lblAddress
//
this.lblAddress.AutoSize = true;
this.lblAddress.Location = new System.Drawing.Point(3, 53);
this.lblAddress.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0);
this.lblAddress.Name = "lblAddress";
this.lblAddress.Size = new System.Drawing.Size(48, 13);
this.lblAddress.TabIndex = 3;
this.lblAddress.Text = "Address:";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 3;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel2.Controls.Add(this.picHelp, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.txtCondition, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.picExpressionWarning, 1, 0);
this.tableLayoutPanel2.Location = new System.Drawing.Point(94, 123);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(329, 65);
this.tableLayoutPanel2.TabIndex = 10;
//
// picHelp
//
this.picHelp.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHelp.Location = new System.Drawing.Point(308, 24);
this.picHelp.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picHelp.Name = "picHelp";
this.picHelp.Size = new System.Drawing.Size(18, 18);
this.picHelp.TabIndex = 8;
this.picHelp.TabStop = false;
//
// txtCondition
//
this.txtCondition.AcceptsReturn = true;
this.txtCondition.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtCondition.Location = new System.Drawing.Point(3, 3);
this.txtCondition.MaxLength = 900;
this.txtCondition.Multiline = true;
this.txtCondition.Name = "txtCondition";
this.txtCondition.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtCondition.Size = new System.Drawing.Size(275, 59);
this.txtCondition.TabIndex = 6;
//
// picExpressionWarning
//
this.picExpressionWarning.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picExpressionWarning.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picExpressionWarning.Location = new System.Drawing.Point(284, 24);
this.picExpressionWarning.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picExpressionWarning.Name = "picExpressionWarning";
this.picExpressionWarning.Size = new System.Drawing.Size(18, 18);
this.picExpressionWarning.TabIndex = 9;
this.picExpressionWarning.TabStop = false;
this.picExpressionWarning.Visible = false;
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 4;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.Controls.Add(this.txtAddress, 2, 0);
this.tableLayoutPanel3.Controls.Add(this.radSpecificAddress, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.radAnyAddress, 0, 2);
this.tableLayoutPanel3.Controls.Add(this.lblAddressSign, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.radRange, 0, 1);
this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel5, 1, 1);
this.tableLayoutPanel3.Location = new System.Drawing.Point(94, 48);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 4;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(271, 75);
this.tableLayoutPanel3.TabIndex = 11;
//
// txtAddress
//
this.txtAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtAddress.Location = new System.Drawing.Point(85, 3);
this.txtAddress.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtAddress.Name = "txtAddress";
this.txtAddress.Size = new System.Drawing.Size(64, 20);
this.txtAddress.TabIndex = 5;
this.txtAddress.Enter += new System.EventHandler(this.txtAddress_Enter);
//
// radSpecificAddress
//
this.radSpecificAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.radSpecificAddress.AutoSize = true;
this.radSpecificAddress.Location = new System.Drawing.Point(3, 4);
this.radSpecificAddress.Name = "radSpecificAddress";
this.radSpecificAddress.Size = new System.Drawing.Size(66, 17);
this.radSpecificAddress.TabIndex = 7;
this.radSpecificAddress.TabStop = true;
this.radSpecificAddress.Text = "Specific:";
this.radSpecificAddress.UseVisualStyleBackColor = true;
//
// radAnyAddress
//
this.radAnyAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.radAnyAddress.AutoSize = true;
this.radAnyAddress.Location = new System.Drawing.Point(3, 52);
this.radAnyAddress.Name = "radAnyAddress";
this.radAnyAddress.Size = new System.Drawing.Size(43, 17);
this.radAnyAddress.TabIndex = 8;
this.radAnyAddress.TabStop = true;
this.radAnyAddress.Text = "Any";
this.radAnyAddress.UseVisualStyleBackColor = true;
//
// lblAddressSign
//
this.lblAddressSign.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblAddressSign.AutoSize = true;
this.lblAddressSign.Location = new System.Drawing.Point(72, 6);
this.lblAddressSign.Margin = new System.Windows.Forms.Padding(0);
this.lblAddressSign.Name = "lblAddressSign";
this.lblAddressSign.Size = new System.Drawing.Size(13, 13);
this.lblAddressSign.TabIndex = 9;
this.lblAddressSign.Text = "$";
//
// radRange
//
this.radRange.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.radRange.AutoSize = true;
this.radRange.Location = new System.Drawing.Point(3, 29);
this.radRange.Name = "radRange";
this.radRange.Size = new System.Drawing.Size(60, 17);
this.radRange.TabIndex = 10;
this.radRange.TabStop = true;
this.radRange.Text = "Range:";
this.radRange.UseVisualStyleBackColor = true;
//
// tableLayoutPanel5
//
this.tableLayoutPanel5.ColumnCount = 4;
this.tableLayoutPanel3.SetColumnSpan(this.tableLayoutPanel5, 2);
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel5.Controls.Add(this.txtTo, 3, 0);
this.tableLayoutPanel5.Controls.Add(this.lblTo, 2, 0);
this.tableLayoutPanel5.Controls.Add(this.txtFrom, 1, 0);
this.tableLayoutPanel5.Controls.Add(this.lblFrom, 0, 0);
this.tableLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel5.Location = new System.Drawing.Point(72, 26);
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel5.Name = "tableLayoutPanel5";
this.tableLayoutPanel5.RowCount = 1;
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel5.Size = new System.Drawing.Size(199, 23);
this.tableLayoutPanel5.TabIndex = 12;
//
// txtTo
//
this.txtTo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtTo.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtTo.Location = new System.Drawing.Point(131, 3);
this.txtTo.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtTo.Name = "txtTo";
this.txtTo.Size = new System.Drawing.Size(65, 20);
this.txtTo.TabIndex = 13;
this.txtTo.Enter += new System.EventHandler(this.txtTo_Enter);
//
// lblTo
//
this.lblTo.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTo.AutoSize = true;
this.lblTo.Location = new System.Drawing.Point(106, 5);
this.lblTo.Margin = new System.Windows.Forms.Padding(0);
this.lblTo.Name = "lblTo";
this.lblTo.Size = new System.Drawing.Size(25, 13);
this.lblTo.TabIndex = 11;
this.lblTo.Text = "to $";
//
// txtFrom
//
this.txtFrom.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtFrom.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtFrom.Location = new System.Drawing.Point(39, 3);
this.txtFrom.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtFrom.Name = "txtFrom";
this.txtFrom.Size = new System.Drawing.Size(64, 20);
this.txtFrom.TabIndex = 12;
this.txtFrom.Enter += new System.EventHandler(this.txtFrom_Enter);
//
// lblFrom
//
this.lblFrom.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblFrom.AutoSize = true;
this.lblFrom.Location = new System.Drawing.Point(0, 5);
this.lblFrom.Margin = new System.Windows.Forms.Padding(0);
this.lblFrom.Name = "lblFrom";
this.lblFrom.Size = new System.Drawing.Size(39, 13);
this.lblFrom.TabIndex = 10;
this.lblFrom.Text = "From $";
//
// tableLayoutPanel4
//
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.cboBreakpointType, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.lblRange, 1, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(94, 0);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 1;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(332, 25);
this.tableLayoutPanel4.TabIndex = 13;
//
// cboBreakpointType
//
this.cboBreakpointType.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.cboBreakpointType.FormattingEnabled = true;
this.cboBreakpointType.Location = new System.Drawing.Point(3, 3);
this.cboBreakpointType.Name = "cboBreakpointType";
this.cboBreakpointType.Size = new System.Drawing.Size(121, 21);
this.cboBreakpointType.TabIndex = 13;
this.cboBreakpointType.SelectedIndexChanged += new System.EventHandler(this.cboBreakpointType_SelectedIndexChanged);
//
// lblRange
//
this.lblRange.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblRange.AutoSize = true;
this.lblRange.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
this.lblRange.Location = new System.Drawing.Point(130, 6);
this.lblRange.Name = "lblRange";
this.lblRange.Size = new System.Drawing.Size(40, 13);
this.lblRange.TabIndex = 6;
this.lblRange.Text = "(range)";
//
// tableLayoutPanel6
//
this.tableLayoutPanel6.ColumnCount = 1;
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel6.Controls.Add(this.label1, 0, 1);
this.tableLayoutPanel6.Controls.Add(this.lblCondition, 0, 0);
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 123);
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
this.tableLayoutPanel6.RowCount = 2;
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel6.Size = new System.Drawing.Size(94, 65);
this.tableLayoutPanel6.TabIndex = 14;
//
// label1
//
this.label1.AutoSize = true;
this.label1.ForeColor = System.Drawing.SystemColors.GrayText;
this.label1.Location = new System.Drawing.Point(3, 32);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(50, 13);
this.label1.TabIndex = 8;
this.label1.Text = "(optional)";
//
// lblCondition
//
this.lblCondition.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lblCondition.AutoSize = true;
this.lblCondition.Location = new System.Drawing.Point(3, 19);
this.lblCondition.Name = "lblCondition";
this.lblCondition.Size = new System.Drawing.Size(54, 13);
this.lblCondition.TabIndex = 7;
this.lblCondition.Text = "Condition:";
//
// chkMarkOnEventViewer
//
this.chkMarkOnEventViewer.AutoSize = true;
this.chkMarkOnEventViewer.Location = new System.Drawing.Point(3, 3);
this.chkMarkOnEventViewer.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.chkMarkOnEventViewer.Name = "chkMarkOnEventViewer";
this.chkMarkOnEventViewer.Size = new System.Drawing.Size(131, 17);
this.chkMarkOnEventViewer.TabIndex = 15;
this.chkMarkOnEventViewer.Text = "Mark on Event Viewer";
this.chkMarkOnEventViewer.UseVisualStyleBackColor = true;
//
// chkEnabled
//
this.chkEnabled.AutoSize = true;
this.chkEnabled.Location = new System.Drawing.Point(3, 20);
this.chkEnabled.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.chkEnabled.Name = "chkEnabled";
this.chkEnabled.Size = new System.Drawing.Size(104, 17);
this.chkEnabled.TabIndex = 2;
this.chkEnabled.Text = "Break Execution";
this.chkEnabled.UseVisualStyleBackColor = true;
//
// tableLayoutPanel7
//
this.tableLayoutPanel7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.tableLayoutPanel7.ColumnCount = 1;
this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel7.Controls.Add(this.chkEnabled, 0, 3);
this.tableLayoutPanel7.Controls.Add(this.chkMarkOnEventViewer, 0, 2);
this.tableLayoutPanel7.Location = new System.Drawing.Point(0, 188);
this.tableLayoutPanel7.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel7.Name = "tableLayoutPanel7";
this.tableLayoutPanel7.RowCount = 4;
this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel7.Size = new System.Drawing.Size(243, 37);
this.tableLayoutPanel7.TabIndex = 3;
//
// frmBreakpoint
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(426, 226);
this.Controls.Add(this.tableLayoutPanel7);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "frmBreakpoint";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Breakpoint";
this.Controls.SetChildIndex(this.tableLayoutPanel1, 0);
this.Controls.SetChildIndex(this.baseConfigPanel, 0);
this.Controls.SetChildIndex(this.tableLayoutPanel7, 0);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.flowLayoutPanel2.ResumeLayout(false);
this.flowLayoutPanel2.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).EndInit();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
this.tableLayoutPanel5.ResumeLayout(false);
this.tableLayoutPanel5.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
this.tableLayoutPanel6.ResumeLayout(false);
this.tableLayoutPanel6.PerformLayout();
this.tableLayoutPanel7.ResumeLayout(false);
this.tableLayoutPanel7.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label lblBreakOn;
private System.Windows.Forms.Label lblAddress;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
private System.Windows.Forms.TextBox txtAddress;
private System.Windows.Forms.CheckBox chkEnabled;
private System.Windows.Forms.TextBox txtCondition;
private System.Windows.Forms.Label lblCondition;
private System.Windows.Forms.PictureBox picHelp;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.CheckBox chkExec;
private System.Windows.Forms.CheckBox chkRead;
private System.Windows.Forms.CheckBox chkWrite;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.RadioButton radSpecificAddress;
private System.Windows.Forms.RadioButton radAnyAddress;
private System.Windows.Forms.Label lblAddressSign;
private System.Windows.Forms.PictureBox picExpressionWarning;
private System.Windows.Forms.RadioButton radRange;
private System.Windows.Forms.Label lblFrom;
private System.Windows.Forms.TextBox txtFrom;
private System.Windows.Forms.Label lblTo;
private System.Windows.Forms.TextBox txtTo;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
private System.Windows.Forms.Label lblBreakpointType;
private Mesen.GUI.Debugger.Controls.ComboBoxWithSeparator cboBreakpointType;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.Label lblRange;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckBox chkMarkOnEventViewer;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel7;
}
}

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

@ -116,13 +116,14 @@ namespace Mesen.GUI.Debugger.Controls
props.Symbol |= LineSymbol.Arrow;
}
public LineProperties GetLineStyle(CodeLineData lineData, int lineNumber)
public LineProperties GetLineStyle(CodeLineData lineData, int lineIndex)
{
DebugInfo info = ConfigManager.Config.Debug;
LineProperties props = new LineProperties();
//TODO
//AddressInfo addressInfo = _code.GetAddressInfo(lineNumber);
//GetBreakpointLineProperties(props, cpuAddress, addressInfo);
if(lineData.Address >= 0) {
GetBreakpointLineProperties(props, lineData.Address);
}
bool isActiveStatement = ActiveAddress.HasValue && ActiveAddress.Value == lineData.Address;
if(isActiveStatement) {
@ -151,13 +152,11 @@ namespace Mesen.GUI.Debugger.Controls
return props;
}
public static void GetBreakpointLineProperties(LineProperties props, int cpuAddress, AddressInfo addressInfo)
public static void GetBreakpointLineProperties(LineProperties props, int cpuAddress)
{
//TODO
/*DebugInfo config = ConfigManager.Config.Debug;
DebugInfo config = ConfigManager.Config.Debug;
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
if(breakpoint.Matches(cpuAddress, addressInfo)) {
if(breakpoint.Matches((uint)cpuAddress, SnesMemoryType.CpuMemory)) {
Color fgColor = Color.White;
Color? bgColor = null;
Color bpColor = breakpoint.BreakOnExec ? config.CodeExecBreakpointColor : (breakpoint.BreakOnWrite ? config.CodeWriteBreakpointColor : config.CodeReadBreakpointColor);
@ -185,7 +184,7 @@ namespace Mesen.GUI.Debugger.Controls
props.Symbol = symbol;
return;
}
}*/
}
}
}
}

View file

@ -58,12 +58,17 @@
this.ctrlSplitContainer = new Mesen.GUI.Controls.ctrlSplitContainer();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
this.grpWatch = new System.Windows.Forms.GroupBox();
this.grpBreakpoints = new System.Windows.Forms.GroupBox();
this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints();
this.ctrlMesenMenuStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.ctrlSplitContainer)).BeginInit();
this.ctrlSplitContainer.Panel1.SuspendLayout();
this.ctrlSplitContainer.Panel2.SuspendLayout();
this.ctrlSplitContainer.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.grpWatch.SuspendLayout();
this.grpBreakpoints.SuspendLayout();
this.SuspendLayout();
//
// ctrlDisassemblyView
@ -275,7 +280,8 @@
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.ctrlWatch, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.grpWatch, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.grpBreakpoints, 1, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
@ -287,11 +293,41 @@
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 3);
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(420, 171);
this.ctrlWatch.Size = new System.Drawing.Size(414, 152);
this.ctrlWatch.TabIndex = 0;
//
// grpWatch
//
this.grpWatch.Controls.Add(this.ctrlWatch);
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(420, 171);
this.grpWatch.TabIndex = 1;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
//
// grpBreakpoints
//
this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints);
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(429, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(420, 171);
this.grpBreakpoints.TabIndex = 2;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
//
// ctrlBreakpoints
//
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(414, 152);
this.ctrlBreakpoints.TabIndex = 0;
//
// frmDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -308,6 +344,8 @@
((System.ComponentModel.ISupportInitialize)(this.ctrlSplitContainer)).EndInit();
this.ctrlSplitContainer.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.grpWatch.ResumeLayout(false);
this.grpBreakpoints.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@ -342,5 +380,8 @@
private GUI.Controls.ctrlSplitContainer ctrlSplitContainer;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private ctrlWatch ctrlWatch;
private System.Windows.Forms.GroupBox grpWatch;
private System.Windows.Forms.GroupBox grpBreakpoints;
private Controls.ctrlBreakpoints ctrlBreakpoints;
}
}

View file

@ -61,6 +61,8 @@ namespace Mesen.GUI
[DllImport(DllPath)] public static extern void SetMemoryValues(SnesMemoryType type, UInt32 address, [In] byte[] data, Int32 length);
[DllImport(DllPath)] public static extern void SetMemoryState(SnesMemoryType type, [In] byte[] buffer, Int32 length);
[DllImport(DllPath)] public static extern void SetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropBreakpoint[] breakpoints, UInt32 length);
[DllImport(DllPath, EntryPoint = "GetMemoryState")] private static extern void GetMemoryStateWrapper(SnesMemoryType type, [In, Out] byte[] buffer);
public static byte[] GetMemoryState(SnesMemoryType type)
{

View file

@ -212,6 +212,21 @@
<Compile Include="Config\ConfigAttributes.cs" />
<Compile Include="Config\Configuration.cs" />
<Compile Include="Config\ConfigManager.cs" />
<Compile Include="Debugger\Breakpoints\Breakpoint.cs" />
<Compile Include="Debugger\Breakpoints\BreakpointManager.cs" />
<Compile Include="Debugger\Breakpoints\ctrlBreakpoints.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Breakpoints\ctrlBreakpoints.designer.cs">
<DependentUpon>ctrlBreakpoints.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Breakpoints\frmBreakpoint.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\Breakpoints\frmBreakpoint.designer.cs">
<DependentUpon>frmBreakpoint.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Breakpoints\InteropBreakpoint.cs" />
<Compile Include="Debugger\Config\DebuggerShortcutsConfig.cs" />
<Compile Include="Debugger\Config\HexEditorInfo.cs" />
<Compile Include="Debugger\Config\TraceLoggerInfo.cs" />
@ -454,6 +469,12 @@
<EmbeddedResource Include="Controls\ctrlRenderer.resx">
<DependentUpon>ctrlRenderer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Breakpoints\ctrlBreakpoints.resx">
<DependentUpon>ctrlBreakpoints.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Breakpoints\frmBreakpoint.resx">
<DependentUpon>frmBreakpoint.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlDbgShortcuts.resx">
<DependentUpon>ctrlDbgShortcuts.cs</DependentUpon>
</EmbeddedResource>