Debugger: Added conditional logging to trace logger

This commit is contained in:
Souryo 2017-08-05 12:13:53 -04:00
parent 3fe9faaf57
commit 2753273206
13 changed files with 371 additions and 201 deletions

View file

@ -41,7 +41,7 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger, this, _disassembler));
_memoryAccessCounter.reset(new MemoryAccessCounter(this));
_profiler.reset(new Profiler(this));
_traceLogger.reset(new TraceLogger(memoryManager, _labelManager));
_traceLogger.reset(new TraceLogger(this, memoryManager, _labelManager));
_stepOut = false;
_stepCount = -1;
@ -227,7 +227,7 @@ void Debugger::UpdateBreakpoints()
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
if(bp.HasBreakpointType((BreakpointType)i)) {
_breakpoints[i].push_back(bp);
_breakpointRpnList[i].push_back(expEval.GetRpnList(bp.GetCondition()));
_breakpointRpnList[i].push_back(*expEval.GetRpnList(bp.GetCondition()));
_hasBreakpoint[i] = true;
}
}
@ -237,7 +237,7 @@ void Debugger::UpdateBreakpoints()
}
}
bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value)
bool Debugger::HasMatchingBreakpoint(BreakpointType type, OperationInfo &operationInfo)
{
if(_runToCycle != 0) {
//Disable all breakpoints while stepping backwards
@ -246,14 +246,14 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
UpdateBreakpoints();
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(operationInfo.Address);
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
bool needState = true;
EvalResultType resultType;
for(size_t i = 0, len = breakpoints.size(); i < len; i++) {
Breakpoint &breakpoint = breakpoints[i];
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
if(type == BreakpointType::Global || breakpoint.Matches(operationInfo.Address, absoluteAddr)) {
if(!breakpoint.HasCondition()) {
return true;
} else {
@ -261,12 +261,12 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
GetState(&_debugState, false);
needState = false;
}
if(_breakpointRpnList[(int)type][i]) {
if(_bpExpEval.Evaluate(_breakpointRpnList[(int)type][i], _debugState, resultType, value, addr) != 0) {
if(_breakpointRpnList[(int)type][i].size() > 0) {
if(_bpExpEval.Evaluate(_breakpointRpnList[(int)type][i], _debugState, resultType, operationInfo) != 0) {
return true;
}
} else {
if(_bpExpEval.Evaluate(breakpoint.GetCondition(), _debugState, resultType, value, addr) != 0) {
if(_bpExpEval.Evaluate(breakpoint.GetCondition(), _debugState, resultType, operationInfo) != 0) {
return true;
}
}
@ -280,8 +280,9 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultType)
{
DebugState state;
OperationInfo operationInfo { 0, 0, MemoryOperationType::DummyRead };
GetState(&state);
return _watchExpEval.Evaluate(expression, state, resultType);
return _watchExpEval.Evaluate(expression, state, resultType, operationInfo);
}
void Debugger::RemoveExcessCallstackEntries()
@ -361,7 +362,8 @@ void Debugger::PrivateProcessPpuCycle()
MessageManager::SendNotification(ConsoleNotificationType::PpuViewerDisplayFrame);
}
if(_hasBreakpoint[BreakpointType::Global] && HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) {
OperationInfo operationInfo { 0, 0, MemoryOperationType::DummyRead };
if(_hasBreakpoint[BreakpointType::Global] && HasMatchingBreakpoint(BreakpointType::Global, operationInfo)) {
//Found a matching breakpoint, stop execution
Step(1);
SleepUntilResume();
@ -376,6 +378,8 @@ void Debugger::PrivateProcessPpuCycle()
bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t &value)
{
OperationInfo operationInfo { addr, (int16_t)value, type };
if(type == MemoryOperationType::ExecOpCode) {
if(_runToCycle == 0) {
_rewindCache.clear();
@ -490,8 +494,9 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
} else {
disassemblyInfo = _disassembler->GetDisassemblyInfo(addressInfo);
}
_traceLogger->Log(_debugState.CPU, _debugState.PPU, disassemblyInfo);
_traceLogger->Log(_debugState, disassemblyInfo, operationInfo);
} else {
_traceLogger->LogNonExec(operationInfo);
_profiler->ProcessCycle();
}
@ -502,7 +507,7 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break;
}
if(_hasBreakpoint[breakpointType] && HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) {
if(_hasBreakpoint[breakpointType] && HasMatchingBreakpoint(breakpointType, operationInfo)) {
//Found a matching breakpoint, stop execution
Step(1);
SleepUntilResume();
@ -563,7 +568,8 @@ void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint16_t ad
}
BreakpointType bpType = type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram;
if(_hasBreakpoint[bpType] && HasMatchingBreakpoint(bpType, addr, value)) {
OperationInfo operationInfo { addr, value, type };
if(_hasBreakpoint[bpType] && HasMatchingBreakpoint(bpType, operationInfo)) {
//Found a matching breakpoint, stop execution
Step(1);
SleepUntilResume();

View file

@ -58,7 +58,7 @@ private:
atomic<int32_t> _suspendCount;
vector<Breakpoint> _newBreakpoints;
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
vector<vector<int>*> _breakpointRpnList[BreakpointTypeCount];
vector<vector<int>> _breakpointRpnList[BreakpointTypeCount];
bool _hasBreakpoint[BreakpointTypeCount] = {};
vector<uint8_t> _frozenAddresses;
@ -111,7 +111,7 @@ private:
void PrivateProcessPpuCycle();
bool PrivateProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t &value);
void PrivateProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value);
bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value);
bool HasMatchingBreakpoint(BreakpointType type, OperationInfo &operationInfo);
void UpdateCallstack(uint32_t addr);
void PrivateProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool forNmi);

View file

@ -65,4 +65,11 @@ struct DebugState
State CPU;
PPUDebugState PPU;
CartridgeState Cartridge;
};
struct OperationInfo
{
uint16_t Address;
int16_t Value;
MemoryOperationType OperationType;
};

View file

@ -100,6 +100,10 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
output += std::to_string(EvalValues::Address);
} else if(!token.compare("romaddress")) {
output += std::to_string(EvalValues::AbsoluteAddress);
} else if(!token.compare("iswrite")) {
output += std::to_string(EvalValues::IsWrite);
} else if(!token.compare("isread")) {
output += std::to_string(EvalValues::IsRead);
} else {
string originalExpression = expression.substr(initialPos, pos - initialPos);
int32_t address = _debugger->GetLabelManager()->GetLabelRelativeAddress(originalExpression);
@ -290,15 +294,15 @@ bool ExpressionEvaluator::ToRpn(string expression, vector<int> &outputQueue)
return true;
}
int32_t ExpressionEvaluator::Evaluate(vector<int> *rpnList, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr)
int32_t ExpressionEvaluator::Evaluate(vector<int> &rpnList, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo)
{
int pos = 0;
int right = 0;
int left = 0;
resultType = EvalResultType::Numeric;
for(size_t i = 0, len = rpnList->size(); i < len; i++) {
int token = (*rpnList)[i];
for(size_t i = 0, len = rpnList.size(); i < len; i++) {
int token = rpnList[i];
if(token >= EvalValues::RegA) {
//Replace value with a special value
@ -315,9 +319,11 @@ int32_t ExpressionEvaluator::Evaluate(vector<int> *rpnList, DebugState &state, E
case EvalValues::PpuScanline: token = state.PPU.Scanline; break;
case EvalValues::Nmi: token = state.CPU.NMIFlag; break;
case EvalValues::Irq: token = state.CPU.IRQFlag; break;
case EvalValues::Value: token = memoryValue; break;
case EvalValues::Address: token = memoryAddr; break;
case EvalValues::AbsoluteAddress: token = _debugger->GetAbsoluteAddress(memoryAddr); break;
case EvalValues::Value: token = operationInfo.Value; break;
case EvalValues::Address: token = operationInfo.Address; break;
case EvalValues::AbsoluteAddress: token = _debugger->GetAbsoluteAddress(operationInfo.Address); break;
case EvalValues::IsWrite: token = operationInfo.OperationType == MemoryOperationType::Write; break;
case EvalValues::IsRead: token = operationInfo.OperationType == MemoryOperationType::Read; break;
}
} else if(token >= EvalOperators::Multiplication) {
right = operandStack[--pos];
@ -401,7 +407,7 @@ vector<int>* ExpressionEvaluator::GetRpnList(string expression, vector<int> &out
return outputQueue;
}
int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr, bool& success)
int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo, bool& success)
{
success = true;
vector<int> output;
@ -415,14 +421,14 @@ int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &stat
rpnList = &output;
}
return Evaluate(rpnList, state, resultType, memoryValue, memoryAddr);
return Evaluate(*rpnList, state, resultType, operationInfo);
}
int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr)
int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo)
{
try {
bool success;
int32_t result = PrivateEvaluate(expression, state, resultType, memoryValue, memoryAddr, success);
int32_t result = PrivateEvaluate(expression, state, resultType, operationInfo, success);
if(success) {
return result;
}
@ -437,8 +443,9 @@ bool ExpressionEvaluator::Validate(string expression)
try {
DebugState state;
EvalResultType type;
OperationInfo operationInfo;
bool success;
PrivateEvaluate(expression, state, type, 0, 0, success);
PrivateEvaluate(expression, state, type, operationInfo, success);
return success;
} catch(std::exception e) {
return false;

View file

@ -4,8 +4,8 @@
#include <deque>
#include <unordered_map>
#include "../Utilities/SimpleLock.h"
#include "DebuggerTypes.h"
struct DebugState;
class Debugger;
enum EvalOperators
@ -61,6 +61,8 @@ enum EvalValues
Value = 2000000112,
Address = 2000000113,
AbsoluteAddress = 2000000114,
IsWrite = 2000000115,
IsRead = 2000000116,
};
enum EvalResultType
@ -101,14 +103,14 @@ private:
string GetNextToken(string expression, size_t &pos);
bool ProcessSpecialOperator(EvalOperators evalOp, std::stack<EvalOperators> &opStack, vector<int> &outputQueue);
bool ToRpn(string expression, vector<int> &outputQueue);
int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr, bool &success);
int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo, bool &success);
vector<int>* GetRpnList(string expression, vector<int> &output, bool& success);
public:
ExpressionEvaluator(Debugger* debugger);
int32_t Evaluate(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue = 0, uint32_t memoryAddr = 0);
int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue = 0, uint32_t memoryAddr = 0);
int32_t Evaluate(vector<int> &outputQueue, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo);
int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo);
vector<int>* GetRpnList(string expression);
bool Validate(string expression);

View file

@ -3,16 +3,19 @@
#include "DisassemblyInfo.h"
#include "DebuggerTypes.h"
#include "Console.h"
#include "Debugger.h"
#include "MemoryManager.h"
#include "LabelManager.h"
#include "EmulationSettings.h"
#include "ExpressionEvaluator.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/FolderUtilities.h"
TraceLogger *TraceLogger::_instance = nullptr;
TraceLogger::TraceLogger(shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
TraceLogger::TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager)
{
_expEvaluator = shared_ptr<ExpressionEvaluator>(new ExpressionEvaluator(debugger));
_memoryManager = memoryManager;
_labelManager = labelManager;
_instance = this;
@ -29,6 +32,16 @@ TraceLogger::~TraceLogger()
void TraceLogger::SetOptions(TraceLoggerOptions options)
{
_options = options;
string condition = _options.Condition;
auto lock = _lock.AcquireSafe();
_conditionRpnList.clear();
if(!condition.empty()) {
vector<int> *rpnList = _expEvaluator->GetRpnList(condition);
if(rpnList) {
_conditionRpnList = *rpnList;
}
}
}
void TraceLogger::StartLogging(string filename)
@ -146,24 +159,57 @@ void TraceLogger::GetTraceRow(string &output, State &cpuState, PPUDebugState &pp
}
}
SimpleLock _lock;
void TraceLogger::Log(State &cpuState, PPUDebugState &ppuState, shared_ptr<DisassemblyInfo> disassemblyInfo)
bool TraceLogger::ConditionMatches(DebugState &state, shared_ptr<DisassemblyInfo> &disassemblyInfo, OperationInfo &operationInfo)
{
if(!_conditionRpnList.empty()) {
EvalResultType type;
if(!_expEvaluator->Evaluate(_conditionRpnList, state, type, operationInfo)) {
if(operationInfo.OperationType == MemoryOperationType::ExecOpCode) {
//Condition did not match, keep state/disassembly info for instruction's subsequent cycles
_lastState = state;
_lastDisassemblyInfo = disassemblyInfo;
}
return false;
}
}
return true;
}
void TraceLogger::AddRow(shared_ptr<DisassemblyInfo> &disassemblyInfo, DebugState &state)
{
_disassemblyCache[_currentPos] = disassemblyInfo;
_cpuStateCache[_currentPos] = state.CPU;
_ppuStateCache[_currentPos] = state.PPU;
_currentPos = (_currentPos + 1) % ExecutionLogSize;
_lastDisassemblyInfo.reset();
if(_logToFile) {
GetTraceRow(_outputBuffer, state.CPU, state.PPU, disassemblyInfo, _firstLine);
if(_outputBuffer.size() > 32768) {
_outputFile << _outputBuffer;
_outputBuffer.clear();
}
_firstLine = false;
}
}
void TraceLogger::LogNonExec(OperationInfo& operationInfo)
{
if(_lastDisassemblyInfo) {
auto lock = _lock.AcquireSafe();
if(ConditionMatches(_lastState, _lastDisassemblyInfo, operationInfo)) {
AddRow(_lastDisassemblyInfo, _lastState);
}
}
}
void TraceLogger::Log(DebugState &state, shared_ptr<DisassemblyInfo> disassemblyInfo, OperationInfo &operationInfo)
{
if(disassemblyInfo) {
auto lock = _lock.AcquireSafe();
_disassemblyCache[_currentPos] = disassemblyInfo;
_cpuStateCache[_currentPos] = cpuState;
_ppuStateCache[_currentPos] = ppuState;
_currentPos = (_currentPos + 1) % ExecutionLogSize;
if(_logToFile) {
GetTraceRow(_outputBuffer, cpuState, ppuState, disassemblyInfo, _firstLine);
if(_outputBuffer.size() > 32768) {
_outputFile << _outputBuffer;
_outputBuffer.clear();
}
_firstLine = false;
if(ConditionMatches(state, disassemblyInfo, operationInfo)) {
AddRow(disassemblyInfo, state);
}
}
}

View file

@ -1,10 +1,13 @@
#pragma once
#include "stdafx.h"
#include "DebuggerTypes.h"
#include "../Utilities/SimpleLock.h"
class DisassemblyInfo;
class MemoryManager;
class LabelManager;
class ExpressionEvaluator;
class Debugger;
enum class StatusFlagFormat
{
@ -26,6 +29,8 @@ struct TraceLoggerOptions
bool ShowEffectiveAddresses;
bool UseLabels;
StatusFlagFormat StatusFormat;
char Condition[1000];
};
class TraceLogger
@ -39,6 +44,11 @@ private:
bool _firstLine;
shared_ptr<MemoryManager> _memoryManager;
shared_ptr<LabelManager> _labelManager;
shared_ptr<ExpressionEvaluator> _expEvaluator;
vector<int> _conditionRpnList;
DebugState _lastState;
shared_ptr<DisassemblyInfo> _lastDisassemblyInfo;
constexpr static int ExecutionLogSize = 30000;
bool _logToFile;
@ -47,15 +57,20 @@ private:
PPUDebugState _ppuStateCache[ExecutionLogSize] = {};
shared_ptr<DisassemblyInfo> _disassemblyCache[ExecutionLogSize] = {};
SimpleLock _lock;
string _executionTrace;
void GetStatusFlag(string &output, uint8_t ps);
void AddRow(shared_ptr<DisassemblyInfo> &disassemblyInfo, DebugState &state);
bool ConditionMatches(DebugState &state, shared_ptr<DisassemblyInfo> &disassemblyInfo, OperationInfo &operationInfo);
public:
TraceLogger(shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);
TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager, shared_ptr<LabelManager> labelManager);
~TraceLogger();
void Log(State &cpuState, PPUDebugState &ppuState, shared_ptr<DisassemblyInfo> disassemblyInfo);
void Log(DebugState &state, shared_ptr<DisassemblyInfo> disassemblyInfo, OperationInfo &operationInfo);
void LogNonExec(OperationInfo& operationInfo);
void SetOptions(TraceLoggerOptions options);
void StartLogging(string filename);
void StopLogging();

View file

@ -31,7 +31,6 @@ namespace Mesen.GUI.Debugger.Controls
_regions = regions;
this.Invalidate();
} else {
bool needUpdate = false;
for(int i = 0; i < regions.Count; i++) {
if(_regions[i].Color != regions[i].Color || _regions[i].Name != regions[i].Name || _regions[i].Size != regions[i].Size) {
_regions = regions;

View file

@ -46,9 +46,14 @@ namespace Mesen.GUI.Debugger
this.toolTip.SetToolTip(this.picExpressionWarning, "Condition contains invalid syntax or symbols.");
this.toolTip.SetToolTip(this.chkAbsolute, "Check to set an absolute address based on the exact address in PRG/CHR ROM (not CPU/PPU memory)");
this.toolTip.SetToolTip(this.picHelp,
this.toolTip.SetToolTip(this.picHelp, frmBreakpoint.GetConditionTooltip(false));
}
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: 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 +
@ -57,8 +62,16 @@ namespace Mesen.GUI.Debugger
"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 +
"Address: Current CPU memory address being read/written" + Environment.NewLine +
"RomAddress: Current ROM address being read/written" + 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 +
@ -67,8 +80,9 @@ namespace Mesen.GUI.Debugger
"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."
);
"{$FFFA} -> Returns the NMI handler's address.";
return tooltip;
}
protected override void UpdateConfig()

View file

@ -99,27 +99,7 @@ namespace Mesen.GUI.Debugger
this.ctrlDebuggerCode.SetConfig(ConfigManager.Config.DebugInfo.LeftView);
this.ctrlDebuggerCodeSplit.SetConfig(ConfigManager.Config.DebugInfo.RightView);
this.toolTip.SetToolTip(this.picWatchHelp,
"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 +
"Irq/Nmi: True if the Irq/Nmi flags are set" + 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 +
"[<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."
);
this.toolTip.SetToolTip(this.picWatchHelp, frmBreakpoint.GetConditionTooltip(true));
_notifListener = new InteropEmu.NotificationListener();
_notifListener.OnNotification += _notifListener_OnNotification;

View file

@ -34,16 +34,20 @@
this.btnStopLogging = new System.Windows.Forms.Button();
this.grpLogOptions = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.chkShowEffectiveAddresses = new System.Windows.Forms.CheckBox();
this.chkShowPpuCycles = new System.Windows.Forms.CheckBox();
this.chkShowRegisters = new System.Windows.Forms.CheckBox();
this.chkShowExtraInfo = new System.Windows.Forms.CheckBox();
this.chkIndentCode = new System.Windows.Forms.CheckBox();
this.chkShowByteCode = new System.Windows.Forms.CheckBox();
this.chkShowFrameCount = new System.Windows.Forms.CheckBox();
this.chkShowPpuScanline = new System.Windows.Forms.CheckBox();
this.chkShowCpuCycles = new System.Windows.Forms.CheckBox();
this.chkUseLabels = new System.Windows.Forms.CheckBox();
this.chkShowByteCode = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.chkShowCpuCycles = new System.Windows.Forms.CheckBox();
this.chkShowPpuCycles = new System.Windows.Forms.CheckBox();
this.chkShowPpuScanline = new System.Windows.Forms.CheckBox();
this.chkShowFrameCount = new System.Windows.Forms.CheckBox();
this.chkShowEffectiveAddresses = new System.Windows.Forms.CheckBox();
this.chkShowExtraInfo = new System.Windows.Forms.CheckBox();
this.cboStatusFlagFormat = new System.Windows.Forms.ComboBox();
this.lblCondition = new System.Windows.Forms.Label();
this.txtCondition = new System.Windows.Forms.TextBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.grpExecutionLog = new System.Windows.Forms.GroupBox();
this.txtTraceLog = new System.Windows.Forms.TextBox();
@ -58,14 +62,18 @@
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.label1 = new System.Windows.Forms.Label();
this.cboStatusFlagFormat = new System.Windows.Forms.ComboBox();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.picExpressionWarning = new System.Windows.Forms.PictureBox();
this.picHelp = new System.Windows.Forms.PictureBox();
this.tableLayoutPanel1.SuspendLayout();
this.grpLogOptions.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.grpExecutionLog.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
this.SuspendLayout();
//
// tableLayoutPanel1
@ -78,21 +86,22 @@
this.tableLayoutPanel1.Controls.Add(this.btnStartLogging, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.btnStopLogging, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.grpLogOptions, 0, 1);
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 314);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 274);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 3;
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(442, 206);
this.tableLayoutPanel1.Size = new System.Drawing.Size(781, 181);
this.tableLayoutPanel1.TabIndex = 0;
//
// btnOpenTrace
//
this.btnOpenTrace.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnOpenTrace.Enabled = false;
this.btnOpenTrace.Location = new System.Drawing.Point(344, 3);
this.btnOpenTrace.Location = new System.Drawing.Point(683, 3);
this.btnOpenTrace.Name = "btnOpenTrace";
this.btnOpenTrace.Size = new System.Drawing.Size(95, 23);
this.btnOpenTrace.TabIndex = 2;
@ -126,71 +135,47 @@
//
this.tableLayoutPanel1.SetColumnSpan(this.grpLogOptions, 3);
this.grpLogOptions.Controls.Add(this.tableLayoutPanel2);
this.grpLogOptions.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpLogOptions.Location = new System.Drawing.Point(3, 32);
this.grpLogOptions.Name = "grpLogOptions";
this.grpLogOptions.Size = new System.Drawing.Size(436, 168);
this.grpLogOptions.Size = new System.Drawing.Size(775, 146);
this.grpLogOptions.TabIndex = 3;
this.grpLogOptions.TabStop = false;
this.grpLogOptions.Text = "Log Options";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 3;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 24.18605F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 42.32558F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
this.tableLayoutPanel2.ColumnCount = 4;
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());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.chkShowRegisters, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.chkIndentCode, 0, 7);
this.tableLayoutPanel2.Controls.Add(this.chkShowCpuCycles, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.chkUseLabels, 2, 7);
this.tableLayoutPanel2.Controls.Add(this.chkShowFrameCount, 2, 3);
this.tableLayoutPanel2.Controls.Add(this.chkShowPpuScanline, 2, 2);
this.tableLayoutPanel2.Controls.Add(this.chkShowPpuCycles, 2, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowEffectiveAddresses, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.chkIndentCode, 0, 5);
this.tableLayoutPanel2.Controls.Add(this.chkUseLabels, 3, 5);
this.tableLayoutPanel2.Controls.Add(this.chkShowByteCode, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowExtraInfo, 0, 3);
this.tableLayoutPanel2.Controls.Add(this.label1, 0, 5);
this.tableLayoutPanel2.Controls.Add(this.cboStatusFlagFormat, 1, 5);
this.tableLayoutPanel2.Controls.Add(this.label1, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.chkShowCpuCycles, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.chkShowPpuCycles, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.chkShowPpuScanline, 2, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowFrameCount, 1, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowEffectiveAddresses, 3, 0);
this.tableLayoutPanel2.Controls.Add(this.chkShowExtraInfo, 3, 1);
this.tableLayoutPanel2.Controls.Add(this.cboStatusFlagFormat, 1, 2);
this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel4, 0, 3);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 8;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowCount = 6;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.Size = new System.Drawing.Size(430, 149);
this.tableLayoutPanel2.Size = new System.Drawing.Size(769, 127);
this.tableLayoutPanel2.TabIndex = 0;
//
// chkShowEffectiveAddresses
//
this.chkShowEffectiveAddresses.AutoSize = true;
this.chkShowEffectiveAddresses.Checked = true;
this.chkShowEffectiveAddresses.CheckState = System.Windows.Forms.CheckState.Checked;
this.tableLayoutPanel2.SetColumnSpan(this.chkShowEffectiveAddresses, 2);
this.chkShowEffectiveAddresses.Location = new System.Drawing.Point(3, 49);
this.chkShowEffectiveAddresses.Name = "chkShowEffectiveAddresses";
this.chkShowEffectiveAddresses.Size = new System.Drawing.Size(150, 17);
this.chkShowEffectiveAddresses.TabIndex = 10;
this.chkShowEffectiveAddresses.Text = "Show Effective Addresses";
this.chkShowEffectiveAddresses.UseVisualStyleBackColor = true;
//
// chkShowPpuCycles
//
this.chkShowPpuCycles.AutoSize = true;
this.chkShowPpuCycles.Checked = true;
this.chkShowPpuCycles.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowPpuCycles.Location = new System.Drawing.Point(289, 26);
this.chkShowPpuCycles.Name = "chkShowPpuCycles";
this.chkShowPpuCycles.Size = new System.Drawing.Size(77, 17);
this.chkShowPpuCycles.TabIndex = 5;
this.chkShowPpuCycles.Text = "PPU Cycle";
this.chkShowPpuCycles.UseVisualStyleBackColor = true;
//
// chkShowRegisters
//
this.chkShowRegisters.AutoSize = true;
@ -203,30 +188,27 @@
this.chkShowRegisters.Text = "Registers";
this.chkShowRegisters.UseVisualStyleBackColor = true;
//
// chkShowExtraInfo
//
this.chkShowExtraInfo.AutoSize = true;
this.chkShowExtraInfo.Checked = true;
this.chkShowExtraInfo.CheckState = System.Windows.Forms.CheckState.Checked;
this.tableLayoutPanel2.SetColumnSpan(this.chkShowExtraInfo, 2);
this.chkShowExtraInfo.Location = new System.Drawing.Point(3, 72);
this.chkShowExtraInfo.Name = "chkShowExtraInfo";
this.chkShowExtraInfo.Size = new System.Drawing.Size(204, 17);
this.chkShowExtraInfo.TabIndex = 9;
this.chkShowExtraInfo.Text = "Additional information (IRQ, NMI, etc.)";
this.chkShowExtraInfo.UseVisualStyleBackColor = true;
//
// chkIndentCode
//
this.chkIndentCode.AutoSize = true;
this.tableLayoutPanel2.SetColumnSpan(this.chkIndentCode, 2);
this.chkIndentCode.Location = new System.Drawing.Point(3, 129);
this.tableLayoutPanel2.SetColumnSpan(this.chkIndentCode, 3);
this.chkIndentCode.Location = new System.Drawing.Point(3, 107);
this.chkIndentCode.Name = "chkIndentCode";
this.chkIndentCode.Size = new System.Drawing.Size(194, 17);
this.chkIndentCode.TabIndex = 8;
this.chkIndentCode.Text = "Indent code based on stack pointer";
this.chkIndentCode.UseVisualStyleBackColor = true;
//
// chkUseLabels
//
this.chkUseLabels.AutoSize = true;
this.chkUseLabels.Location = new System.Drawing.Point(332, 107);
this.chkUseLabels.Name = "chkUseLabels";
this.chkUseLabels.Size = new System.Drawing.Size(79, 17);
this.chkUseLabels.TabIndex = 11;
this.chkUseLabels.Text = "Use Labels";
this.chkUseLabels.UseVisualStyleBackColor = true;
//
// chkShowByteCode
//
this.chkShowByteCode.AutoSize = true;
@ -239,55 +221,118 @@
this.chkShowByteCode.Text = "Byte Code";
this.chkShowByteCode.UseVisualStyleBackColor = true;
//
// chkShowFrameCount
// label1
//
this.chkShowFrameCount.AutoSize = true;
this.chkShowFrameCount.Location = new System.Drawing.Point(289, 72);
this.chkShowFrameCount.Name = "chkShowFrameCount";
this.chkShowFrameCount.Size = new System.Drawing.Size(86, 17);
this.chkShowFrameCount.TabIndex = 7;
this.chkShowFrameCount.Text = "Frame Count";
this.chkShowFrameCount.UseVisualStyleBackColor = true;
//
// chkShowPpuScanline
//
this.chkShowPpuScanline.AutoSize = true;
this.chkShowPpuScanline.Checked = true;
this.chkShowPpuScanline.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowPpuScanline.Location = new System.Drawing.Point(289, 49);
this.chkShowPpuScanline.Name = "chkShowPpuScanline";
this.chkShowPpuScanline.Size = new System.Drawing.Size(92, 17);
this.chkShowPpuScanline.TabIndex = 6;
this.chkShowPpuScanline.Text = "PPU Scanline";
this.chkShowPpuScanline.UseVisualStyleBackColor = true;
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 53);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(98, 13);
this.label1.TabIndex = 12;
this.label1.Text = "Status Flag Format:";
//
// chkShowCpuCycles
//
this.chkShowCpuCycles.AutoSize = true;
this.chkShowCpuCycles.Checked = true;
this.chkShowCpuCycles.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowCpuCycles.Location = new System.Drawing.Point(289, 3);
this.chkShowCpuCycles.Location = new System.Drawing.Point(107, 3);
this.chkShowCpuCycles.Name = "chkShowCpuCycles";
this.chkShowCpuCycles.Size = new System.Drawing.Size(82, 17);
this.chkShowCpuCycles.TabIndex = 3;
this.chkShowCpuCycles.Text = "CPU Cycles";
this.chkShowCpuCycles.UseVisualStyleBackColor = true;
//
// chkUseLabels
// chkShowPpuCycles
//
this.chkUseLabels.AutoSize = true;
this.chkUseLabels.Location = new System.Drawing.Point(289, 129);
this.chkUseLabels.Name = "chkUseLabels";
this.chkUseLabels.Size = new System.Drawing.Size(79, 17);
this.chkUseLabels.TabIndex = 11;
this.chkUseLabels.Text = "Use Labels";
this.chkUseLabels.UseVisualStyleBackColor = true;
this.chkShowPpuCycles.AutoSize = true;
this.chkShowPpuCycles.Checked = true;
this.chkShowPpuCycles.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowPpuCycles.Location = new System.Drawing.Point(234, 3);
this.chkShowPpuCycles.Name = "chkShowPpuCycles";
this.chkShowPpuCycles.Size = new System.Drawing.Size(77, 17);
this.chkShowPpuCycles.TabIndex = 5;
this.chkShowPpuCycles.Text = "PPU Cycle";
this.chkShowPpuCycles.UseVisualStyleBackColor = true;
//
// chkShowPpuScanline
//
this.chkShowPpuScanline.AutoSize = true;
this.chkShowPpuScanline.Checked = true;
this.chkShowPpuScanline.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowPpuScanline.Location = new System.Drawing.Point(234, 26);
this.chkShowPpuScanline.Name = "chkShowPpuScanline";
this.chkShowPpuScanline.Size = new System.Drawing.Size(92, 17);
this.chkShowPpuScanline.TabIndex = 6;
this.chkShowPpuScanline.Text = "PPU Scanline";
this.chkShowPpuScanline.UseVisualStyleBackColor = true;
//
// chkShowFrameCount
//
this.chkShowFrameCount.AutoSize = true;
this.chkShowFrameCount.Location = new System.Drawing.Point(107, 26);
this.chkShowFrameCount.Name = "chkShowFrameCount";
this.chkShowFrameCount.Size = new System.Drawing.Size(86, 17);
this.chkShowFrameCount.TabIndex = 7;
this.chkShowFrameCount.Text = "Frame Count";
this.chkShowFrameCount.UseVisualStyleBackColor = true;
//
// chkShowEffectiveAddresses
//
this.chkShowEffectiveAddresses.AutoSize = true;
this.chkShowEffectiveAddresses.Checked = true;
this.chkShowEffectiveAddresses.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowEffectiveAddresses.Location = new System.Drawing.Point(332, 3);
this.chkShowEffectiveAddresses.Name = "chkShowEffectiveAddresses";
this.chkShowEffectiveAddresses.Size = new System.Drawing.Size(150, 17);
this.chkShowEffectiveAddresses.TabIndex = 10;
this.chkShowEffectiveAddresses.Text = "Show Effective Addresses";
this.chkShowEffectiveAddresses.UseVisualStyleBackColor = true;
//
// chkShowExtraInfo
//
this.chkShowExtraInfo.AutoSize = true;
this.chkShowExtraInfo.Checked = true;
this.chkShowExtraInfo.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkShowExtraInfo.Location = new System.Drawing.Point(332, 26);
this.chkShowExtraInfo.Name = "chkShowExtraInfo";
this.chkShowExtraInfo.Size = new System.Drawing.Size(204, 17);
this.chkShowExtraInfo.TabIndex = 9;
this.chkShowExtraInfo.Text = "Additional information (IRQ, NMI, etc.)";
this.chkShowExtraInfo.UseVisualStyleBackColor = true;
//
// cboStatusFlagFormat
//
this.cboStatusFlagFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboStatusFlagFormat.FormattingEnabled = true;
this.cboStatusFlagFormat.Location = new System.Drawing.Point(107, 49);
this.cboStatusFlagFormat.Name = "cboStatusFlagFormat";
this.cboStatusFlagFormat.Size = new System.Drawing.Size(121, 21);
this.cboStatusFlagFormat.TabIndex = 13;
//
// lblCondition
//
this.lblCondition.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblCondition.AutoSize = true;
this.lblCondition.Location = new System.Drawing.Point(3, 6);
this.lblCondition.Name = "lblCondition";
this.lblCondition.Size = new System.Drawing.Size(54, 13);
this.lblCondition.TabIndex = 14;
this.lblCondition.Text = "Condition:";
//
// txtCondition
//
this.txtCondition.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtCondition.Location = new System.Drawing.Point(63, 3);
this.txtCondition.Name = "txtCondition";
this.txtCondition.Size = new System.Drawing.Size(655, 20);
this.txtCondition.TabIndex = 15;
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 2;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnCount = 1;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel1, 0, 1);
this.tableLayoutPanel3.Controls.Add(this.grpExecutionLog, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
@ -296,18 +341,16 @@
this.tableLayoutPanel3.RowCount = 2;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(808, 523);
this.tableLayoutPanel3.Size = new System.Drawing.Size(787, 458);
this.tableLayoutPanel3.TabIndex = 1;
//
// grpExecutionLog
//
this.tableLayoutPanel3.SetColumnSpan(this.grpExecutionLog, 2);
this.grpExecutionLog.Controls.Add(this.txtTraceLog);
this.grpExecutionLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpExecutionLog.Location = new System.Drawing.Point(3, 3);
this.grpExecutionLog.Name = "grpExecutionLog";
this.grpExecutionLog.Size = new System.Drawing.Size(802, 305);
this.grpExecutionLog.Size = new System.Drawing.Size(781, 265);
this.grpExecutionLog.TabIndex = 2;
this.grpExecutionLog.TabStop = false;
this.grpExecutionLog.Text = "Execution Log";
@ -321,7 +364,7 @@
this.txtTraceLog.Name = "txtTraceLog";
this.txtTraceLog.ReadOnly = true;
this.txtTraceLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.txtTraceLog.Size = new System.Drawing.Size(796, 286);
this.txtTraceLog.Size = new System.Drawing.Size(775, 246);
this.txtTraceLog.TabIndex = 1;
//
// tmrUpdateLog
@ -335,7 +378,7 @@
this.showToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(808, 24);
this.menuStrip1.Size = new System.Drawing.Size(787, 24);
this.menuStrip1.TabIndex = 2;
this.menuStrip1.Text = "menuStrip1";
//
@ -414,32 +457,56 @@
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// label1
// tableLayoutPanel4
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 99);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(98, 13);
this.label1.TabIndex = 12;
this.label1.Text = "Status Flag Format:";
this.tableLayoutPanel4.ColumnCount = 4;
this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel4, 4);
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.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.Controls.Add(this.picHelp, 3, 0);
this.tableLayoutPanel4.Controls.Add(this.picExpressionWarning, 2, 0);
this.tableLayoutPanel4.Controls.Add(this.lblCondition, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.txtCondition, 1, 0);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 73);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0, 0, 0, 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(769, 25);
this.tableLayoutPanel4.TabIndex = 16;
//
// cboStatusFlagFormat
// picExpressionWarning
//
this.cboStatusFlagFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboStatusFlagFormat.FormattingEnabled = true;
this.cboStatusFlagFormat.Location = new System.Drawing.Point(107, 95);
this.cboStatusFlagFormat.Name = "cboStatusFlagFormat";
this.cboStatusFlagFormat.Size = new System.Drawing.Size(121, 21);
this.cboStatusFlagFormat.TabIndex = 13;
this.picExpressionWarning.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picExpressionWarning.Location = new System.Drawing.Point(724, 5);
this.picExpressionWarning.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picExpressionWarning.Name = "picExpressionWarning";
this.picExpressionWarning.Size = new System.Drawing.Size(18, 17);
this.picExpressionWarning.TabIndex = 16;
this.picExpressionWarning.TabStop = false;
this.picExpressionWarning.Visible = false;
//
// picHelp
//
this.picHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHelp.Location = new System.Drawing.Point(748, 5);
this.picHelp.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
this.picHelp.Name = "picHelp";
this.picHelp.Size = new System.Drawing.Size(18, 17);
this.picHelp.TabIndex = 17;
this.picHelp.TabStop = false;
//
// frmTraceLogger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(808, 547);
this.ClientSize = new System.Drawing.Size(787, 482);
this.Controls.Add(this.tableLayoutPanel3);
this.Controls.Add(this.menuStrip1);
this.MinimumSize = new System.Drawing.Size(669, 448);
this.Name = "frmTraceLogger";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Trace Logger";
@ -452,6 +519,10 @@
this.grpExecutionLog.PerformLayout();
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.tableLayoutPanel4.ResumeLayout(false);
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@ -491,5 +562,10 @@
private System.Windows.Forms.CheckBox chkUseLabels;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox cboStatusFlagFormat;
private System.Windows.Forms.Label lblCondition;
private System.Windows.Forms.TextBox txtCondition;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
private System.Windows.Forms.PictureBox picExpressionWarning;
private System.Windows.Forms.PictureBox picHelp;
}
}

View file

@ -46,6 +46,9 @@ namespace Mesen.GUI.Debugger
UpdateMenu();
txtTraceLog.Font = new Font(BaseControl.MonospaceFontFamily, 10);
tmrUpdateLog.Start();
this.toolTip.SetToolTip(this.picExpressionWarning, "Condition contains invalid syntax or symbols.");
this.toolTip.SetToolTip(this.picHelp, "When a condition is given, instructions will only be logged by the trace logger if the condition returns a value not equal to 0 or false." + Environment.NewLine + Environment.NewLine + frmBreakpoint.GetConditionTooltip(false));
}
protected override void OnFormClosing(FormClosingEventArgs e)
@ -71,7 +74,10 @@ namespace Mesen.GUI.Debugger
{
_entityBinder.Entity = ConfigManager.Config.DebugInfo.TraceLoggerOptions;
_entityBinder.UpdateObject();
InteropEmu.DebugSetTraceOptions((TraceLoggerOptions)_entityBinder.Entity);
TraceLoggerOptions options = (TraceLoggerOptions)_entityBinder.Entity;
options.Condition = Encoding.UTF8.GetBytes(txtCondition.Text);
Array.Resize(ref options.Condition, 1000);
InteropEmu.DebugSetTraceOptions(options);
}
private void btnStartLogging_Click(object sender, EventArgs e)
@ -141,6 +147,14 @@ namespace Mesen.GUI.Debugger
private void tmrUpdateLog_Tick(object sender, EventArgs e)
{
if(txtCondition.Text.Length > 0) {
EvalResultType resultType;
InteropEmu.DebugEvaluateExpression(txtCondition.Text, out resultType);
picExpressionWarning.Visible = (resultType == EvalResultType.Invalid);
} else {
picExpressionWarning.Visible = false;
}
if(mnuAutoRefresh.Checked) {
RefreshLog();
}

View file

@ -959,6 +959,10 @@ namespace Mesen.GUI
[MarshalAs(UnmanagedType.I1)] public bool ShowEffectiveAddresses;
[MarshalAs(UnmanagedType.I1)] public bool UseLabels;
public StatusFlagFormat StatusFormat;
[NonSerialized]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1000)]
public byte[] Condition;
}
public enum ProfilerDataType