diff --git a/Core/CPU.h b/Core/CPU.h
index 062c47e5..4a850fce 100644
--- a/Core/CPU.h
+++ b/Core/CPU.h
@@ -5,6 +5,7 @@
#include "Snapshotable.h"
#include "TraceLogger.h"
#include "EmulationSettings.h"
+#include "CpuState.h"
namespace PSFlags
{
@@ -24,9 +25,9 @@ namespace PSFlags
enum AddrMode
{
None, Acc, Imp, Imm, Rel,
- Zero, ZeroX, ZeroY,
+ Zero, Abs, ZeroX, ZeroY,
Ind, IndX, IndY, IndYW,
- Abs, AbsX, AbsXW, AbsY, AbsYW
+ AbsX, AbsXW, AbsY, AbsYW
};
enum class IRQSource
@@ -37,22 +38,6 @@ enum class IRQSource
FdsDisk = 8,
};
-struct State
-{
- uint16_t PC = 0;
- uint8_t SP = 0;
- uint8_t A = 0;
- uint8_t X = 0;
- uint8_t Y = 0;
- uint8_t PS = 0;
- uint32_t IRQFlag = 0;
- int32_t CycleCount = 0;
- bool NMIFlag = false;
-
- //Used by debugger
- uint16_t DebugPC = 0;
-};
-
class CPU : public Snapshotable
{
public:
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index d8241ed8..d92b1021 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -321,7 +321,7 @@
true
true
WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
- true
+ false
AnySuitable
true
Speed
@@ -333,6 +333,11 @@
true
+
+
+ false
+
+
Console
@@ -435,6 +440,7 @@
+
@@ -583,6 +589,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index 4274fa9d..50cde7ec 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -1117,6 +1117,12 @@
Nes\Mappers\Unif
+
+ Nes
+
+
+ Nes
+
diff --git a/Core/CpuState.h b/Core/CpuState.h
new file mode 100644
index 00000000..df902bff
--- /dev/null
+++ b/Core/CpuState.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "stdafx.h"
+
+struct State
+{
+ uint16_t PC = 0;
+ uint8_t SP = 0;
+ uint8_t A = 0;
+ uint8_t X = 0;
+ uint8_t Y = 0;
+ uint8_t PS = 0;
+ uint32_t IRQFlag = 0;
+ int32_t CycleCount = 0;
+ bool NMIFlag = false;
+
+ //Used by debugger
+ uint16_t DebugPC = 0;
+};
\ No newline at end of file
diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp
index 356aab18..0d3f0d7e 100644
--- a/Core/Debugger.cpp
+++ b/Core/Debugger.cpp
@@ -33,6 +33,7 @@ Debugger::Debugger(shared_ptr console, shared_ptr cpu, shared_ptr<
_memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger, this));
_memoryAccessCounter.reset(new MemoryAccessCounter(this));
_profiler.reset(new Profiler(this));
+ _traceLogger.reset(new TraceLogger(memoryManager, _labelManager));
_stepOut = false;
_stepCount = -1;
@@ -381,12 +382,8 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
breakDone = SleepUntilResume();
- shared_ptr logger = _traceLogger;
- if(logger) {
- DebugState state;
- GetState(&state);
- logger->Log(state, _disassembler->GetDisassemblyInfo(absoluteAddr, absoluteRamAddr, addr));
- }
+ GetState(&_debugState, false);
+ _traceLogger->Log(_debugState.CPU, _debugState.PPU, _disassembler->GetDisassemblyInfo(absoluteAddr, absoluteRamAddr, addr));
} else {
_profiler->ProcessCycle();
}
@@ -623,17 +620,6 @@ void Debugger::SetNextStatement(uint16_t addr)
}
}
-void Debugger::StartTraceLogger(TraceLoggerOptions options)
-{
- string traceFilepath = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), "Trace - " + FolderUtilities::GetFilename(_romName, false) + ".log");
- _traceLogger.reset(new TraceLogger(traceFilepath, _memoryManager, options));
-}
-
-void Debugger::StopTraceLogger()
-{
- _traceLogger.reset();
-}
-
void Debugger::ProcessPpuCycle()
{
if(Debugger::Instance) {
@@ -682,6 +668,11 @@ void Debugger::GetFunctionEntryPoints(int32_t* entryPoints)
entryPoints[i] = -1;
}
+shared_ptr Debugger::GetTraceLogger()
+{
+ return _traceLogger;
+}
+
shared_ptr Debugger::GetMemoryDumper()
{
return _memoryDumper;
diff --git a/Core/Debugger.h b/Core/Debugger.h
index 2cfdcd64..a95eb4c4 100644
--- a/Core/Debugger.h
+++ b/Core/Debugger.h
@@ -155,7 +155,7 @@ public:
void StopTraceLogger();
shared_ptr GetProfiler();
-
+ shared_ptr GetTraceLogger();
shared_ptr GetMemoryDumper();
shared_ptr GetMemoryAccessCounter();
diff --git a/Core/Disassembler.cpp b/Core/Disassembler.cpp
index 3aabcf16..866b5109 100644
--- a/Core/Disassembler.cpp
+++ b/Core/Disassembler.cpp
@@ -78,9 +78,9 @@ void Disassembler::BuildOpCodeTables(bool useLowerCase)
if(useLowerCase) {
string name = opName[i];
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
- DisassemblyInfo::OPName[i] = name;
+ DisassemblyInfo::OPName[i] = name + " ";
} else {
- DisassemblyInfo::OPName[i] = opName[i];
+ DisassemblyInfo::OPName[i] = opName[i] + " ";
}
DisassemblyInfo::OPMode[i] = opMode[i];
@@ -341,8 +341,11 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo
output += commentLines;
output += labelLine;
- string effectiveAddress = showEffectiveAddresses ? info->GetEffectiveAddressString(cpuState, memoryManager, labelManager) : "";
- output += GetLine(" " + info->ToString(memoryAddr, memoryManager, labelManager), commentString, memoryAddr, source != _internalRam ? addr : -1, info->GetByteCode(), effectiveAddress, speculativeCode);
+ char* effectiveAddress = info->GetEffectiveAddressString(cpuState, memoryManager.get(), labelManager.get());
+ if(!effectiveAddress) {
+ effectiveAddress = "";
+ }
+ output += GetLine(" " + string(info->ToString(memoryAddr, memoryManager.get(), labelManager.get())), commentString, memoryAddr, source != _internalRam ? addr : -1, info->GetByteCode(), effectiveAddress, speculativeCode);
if(info->IsSubExitPoint()) {
output += GetLine("__sub end__") + GetLine();
diff --git a/Core/DisassemblyInfo.cpp b/Core/DisassemblyInfo.cpp
index bc74f82d..9b9aa91a 100644
--- a/Core/DisassemblyInfo.cpp
+++ b/Core/DisassemblyInfo.cpp
@@ -8,69 +8,112 @@ string DisassemblyInfo::OPName[256];
AddrMode DisassemblyInfo::OPMode[256];
uint32_t DisassemblyInfo::OPSize[256];
-string DisassemblyInfo::ToString(uint32_t memoryAddr, shared_ptr memoryManager, shared_ptr labelManager)
+static const char* hexTable[256] = {
+ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
+ "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
+ "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
+ "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
+ "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
+ "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
+ "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
+ "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
+ "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
+ "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
+ "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
+ "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
+ "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
+ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
+};
+
+char* DisassemblyInfo::ToString(uint32_t memoryAddr, MemoryManager* memoryManager, LabelManager* labelManager)
{
- string out;
- out.reserve(25);
+ uint16_t length;
+ return ToString(memoryAddr, memoryManager, labelManager, length);
+}
+char* DisassemblyInfo::ToString(uint32_t memoryAddr, MemoryManager* memoryManager, LabelManager* labelManager, uint16_t &length)
+{
uint8_t opCode = *_opPointer;
-
- if(DisassemblyInfo::OPName[opCode].empty()) {
- out = "invalid opcode";
- } else {
- out = DisassemblyInfo::OPName[opCode];
- }
+ memcpy(_toStringBuffer, DisassemblyInfo::OPName[opCode].c_str(), 4);
+
+ length = 4;
+ uint16_t* ptrPos = &length;
uint16_t opAddr = GetOpAddr(memoryAddr);
- string operandValue;
- if(labelManager && _opMode != AddrMode::Imm) {
- operandValue = labelManager->GetLabel(opAddr, true);
- }
-
- if(operandValue.empty()) {
- if(_opSize == 2 && _opMode != AddrMode::Rel) {
- operandValue += "$" + HexUtilities::ToHex((uint8_t)opAddr);
- } else {
- operandValue += "$" + HexUtilities::ToHex((uint16_t)opAddr);
- }
+ uint8_t operandLength = 0;
+ char operandBuffer[7];
+ char* opBuffer = operandBuffer;
+
+ operandBuffer[0] = '$';
+ if(_opSize == 2 && _opMode != AddrMode::Rel) {
+ memcpy(operandBuffer + 1, hexTable[opAddr], 2);
+ operandLength = 3;
+ } else {
+ memcpy(operandBuffer + 1, hexTable[opAddr >> 8], 2);
+ memcpy(operandBuffer + 3, hexTable[opAddr & 0xFF], 2);
+ operandLength = 5;
}
- out += " ";
+ auto writeChar = [=](char c) -> void {
+ _toStringBuffer[(*ptrPos)++] = c;
+ };
+
+ auto copyOperand = [=]() -> void {
+ if(labelManager && _opMode != AddrMode::Imm) {
+ string label = labelManager->GetLabel(opAddr, true);
+ if(!label.empty()) {
+ memcpy(_toStringBuffer + (*ptrPos), label.c_str(), label.size());
+ (*ptrPos) += (uint16_t)label.size();
+ return;
+ }
+ }
+ memcpy(_toStringBuffer + (*ptrPos), opBuffer, operandLength);
+ (*ptrPos) += operandLength;
+ };
switch(_opMode) {
- case AddrMode::Acc: out += "A"; break;
- case AddrMode::Imm: out += "#" + operandValue; break;
- case AddrMode::Ind: out += "(" + operandValue + ")"; break;
- case AddrMode::IndX: out += "(" + operandValue + ",X)"; break;
+ case AddrMode::Acc: writeChar('A'); break;
+ case AddrMode::Imm: writeChar('#'); copyOperand(); break;
+ case AddrMode::Ind: writeChar('('); copyOperand(); writeChar(')'); break;
+ case AddrMode::IndX: writeChar('('); copyOperand(); memcpy(_toStringBuffer + length, ",X)", 3); length += 3; break;
case AddrMode::IndY:
case AddrMode::IndYW:
- out += "(" + operandValue + "),Y";
+ writeChar('(');
+ copyOperand();
+ memcpy(_toStringBuffer + length, "),Y", 3);
+ length += 3;
break;
case AddrMode::Abs:
case AddrMode::Rel:
case AddrMode::Zero:
- out += operandValue;
+ copyOperand();
break;
case AddrMode::AbsX:
case AddrMode::AbsXW:
case AddrMode::ZeroX:
- out += operandValue + ",X";
+ copyOperand();
+ memcpy(_toStringBuffer + length, ",X", 2);
+ length += 2;
break;
case AddrMode::AbsY:
case AddrMode::AbsYW:
case AddrMode::ZeroY:
- out += operandValue + ",Y";
+ copyOperand();
+ memcpy(_toStringBuffer + length, ",Y", 2);
+ length += 2;
break;
default: break;
}
-
- return out;
+ _toStringBuffer[length] = 0;
+ return _toStringBuffer;
}
uint16_t DisassemblyInfo::GetOpAddr(uint16_t memoryAddr)
@@ -105,32 +148,53 @@ void DisassemblyInfo::SetSubEntryPoint()
_isSubEntryPoint = true;
}
-string DisassemblyInfo::GetEffectiveAddressString(State& cpuState, shared_ptr memoryManager, shared_ptr labelManager)
+char* DisassemblyInfo::GetEffectiveAddressString(State& cpuState, MemoryManager* memoryManager, LabelManager* labelManager)
{
- int32_t effectiveAddress = GetEffectiveAddress(cpuState, memoryManager);
- if(effectiveAddress < 0) {
- return "";
+ uint16_t length;
+ return GetEffectiveAddressString(cpuState, memoryManager, labelManager, length);
+}
+
+char* DisassemblyInfo::GetEffectiveAddressString(State& cpuState, MemoryManager* memoryManager, LabelManager* labelManager, uint16_t& length)
+{
+ if(_opMode <= AddrMode::Abs) {
+ length = 0;
+ return nullptr;
} else {
+ int32_t effectiveAddress = GetEffectiveAddress(cpuState, memoryManager);
+
+ _effectiveAddressBuffer[0] = ' ';
+ _effectiveAddressBuffer[1] = '@';
+ _effectiveAddressBuffer[2] = ' ';
+
if(labelManager) {
string label = labelManager->GetLabel(effectiveAddress, true);
if(!label.empty()) {
- return " @ " + label;
+ memcpy(_effectiveAddressBuffer + 3, label.c_str(), label.size());
+ length = (uint16_t)label.size() + 3;
+ _effectiveAddressBuffer[length] = 0;
+
+ return _effectiveAddressBuffer;
}
}
-
- string output;
- output = " @ $";
+
+ _effectiveAddressBuffer[3] = '$';
+
if(_opMode == AddrMode::ZeroX || _opMode == AddrMode::ZeroY) {
- output += HexUtilities::ToHex((uint8_t)effectiveAddress);
+ memcpy(_effectiveAddressBuffer + 4, hexTable[effectiveAddress], 2);
+ _effectiveAddressBuffer[6] = 0;
+ length = 6;
} else {
- output += HexUtilities::ToHex((uint16_t)effectiveAddress);
+ memcpy(_effectiveAddressBuffer + 4, hexTable[effectiveAddress >> 8], 2);
+ memcpy(_effectiveAddressBuffer + 6, hexTable[effectiveAddress & 0xFF], 2);
+ _effectiveAddressBuffer[8] = 0;
+ length = 8;
}
-
- return output;
+
+ return _effectiveAddressBuffer;
}
}
-int32_t DisassemblyInfo::GetEffectiveAddress(State& cpuState, shared_ptr memoryManager)
+int32_t DisassemblyInfo::GetEffectiveAddress(State& cpuState, MemoryManager* memoryManager)
{
switch(_opMode) {
case AddrMode::ZeroX: return (uint8_t)(*(_opPointer + 1) + cpuState.X); break;
diff --git a/Core/DisassemblyInfo.h b/Core/DisassemblyInfo.h
index 2a8928c3..7f89f700 100644
--- a/Core/DisassemblyInfo.h
+++ b/Core/DisassemblyInfo.h
@@ -20,15 +20,21 @@ private:
uint32_t _opSize = 0;
AddrMode _opMode;
+ char _toStringBuffer[1000];
+ char _effectiveAddressBuffer[1000];
+
public:
DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint);
void SetSubEntryPoint();
- int32_t GetEffectiveAddress(State& cpuState, shared_ptr memoryManager);
- string GetEffectiveAddressString(State& cpuState, shared_ptr memoryManager, shared_ptr labelManager);
+ int32_t GetEffectiveAddress(State& cpuState, MemoryManager* memoryManager);
+
+ char* GetEffectiveAddressString(State& cpuState, MemoryManager* memoryManager, LabelManager* labelManager);
+ char* GetEffectiveAddressString(State& cpuState, MemoryManager* memoryManager, LabelManager* labelManager, uint16_t &length);
- string ToString(uint32_t memoryAddr, shared_ptr memoryManager, shared_ptr labelManager);
+ char* ToString(uint32_t memoryAddr, MemoryManager* memoryManager, LabelManager* labelManager);
+ char* ToString(uint32_t memoryAddr, MemoryManager* memoryManager, LabelManager* labelManager, uint16_t &length);
string GetByteCode();
uint32_t GetSize();
uint16_t GetOpAddr(uint16_t memoryAddr);
diff --git a/Core/LabelManager.cpp b/Core/LabelManager.cpp
index e58511e5..8b2eedfe 100644
--- a/Core/LabelManager.cpp
+++ b/Core/LabelManager.cpp
@@ -24,6 +24,10 @@ void LabelManager::SetLabel(uint32_t address, AddressType addressType, string la
_codeLabels.erase(address);
if(!label.empty()) {
+ if(label.size() > 400) {
+ //Restrict labels to 400 bytes
+ label = label.substr(0, 400);
+ }
_codeLabels.emplace(address, label);
_codeLabelReverseLookup.emplace(label, address);
}
diff --git a/Core/PPU.h b/Core/PPU.h
index 17aca67b..b0990f65 100644
--- a/Core/PPU.h
+++ b/Core/PPU.h
@@ -4,6 +4,7 @@
#include "Snapshotable.h"
#include "MemoryManager.h"
#include "EmulationSettings.h"
+#include "PpuState.h"
enum class NesModel;
@@ -20,75 +21,6 @@ enum PPURegisters
SpriteDMA = 0x4014,
};
-struct PPUControlFlags
-{
- bool VerticalWrite;
- uint16_t SpritePatternAddr;
- uint16_t BackgroundPatternAddr;
- bool LargeSprites;
- bool VBlank;
-
- bool Grayscale;
- bool BackgroundMask;
- bool SpriteMask;
- bool BackgroundEnabled;
- bool SpritesEnabled;
- bool IntensifyRed;
- bool IntensifyGreen;
- bool IntensifyBlue;
-};
-
-struct PPUStatusFlags
-{
- bool SpriteOverflow;
- bool Sprite0Hit;
- bool VerticalBlank;
-};
-
-struct PPUState
-{
- uint8_t Control;
- uint8_t Mask;
- uint8_t Status;
- uint32_t SpriteRamAddr;
- uint16_t VideoRamAddr;
- uint8_t XScroll;
- uint16_t TmpVideoRamAddr;
- bool WriteToggle;
-
- uint16_t HighBitShift;
- uint16_t LowBitShift;
-};
-
-struct TileInfo
-{
- uint8_t LowByte;
- uint8_t HighByte;
- uint32_t PaletteOffset;
-
- uint16_t TileAddr; //used by HD ppu
- uint8_t OffsetY; //used by HD ppu
-};
-
-struct SpriteInfo : TileInfo
-{
- bool HorizontalMirror;
- bool BackgroundPriority;
- uint8_t SpriteX;
-
- bool VerticalMirror; //used by HD ppu
-};
-
-struct PPUDebugState
-{
- PPUControlFlags ControlFlags;
- PPUStatusFlags StatusFlags;
- PPUState State;
- int32_t Scanline;
- uint32_t Cycle;
- uint32_t FrameCount;
-};
-
class PPU : public IMemoryHandler, public Snapshotable
{
protected:
diff --git a/Core/PpuState.h b/Core/PpuState.h
new file mode 100644
index 00000000..e1e7bc14
--- /dev/null
+++ b/Core/PpuState.h
@@ -0,0 +1,71 @@
+#pragma once
+#include "stdafx.h"
+
+struct PPUControlFlags
+{
+ bool VerticalWrite;
+ uint16_t SpritePatternAddr;
+ uint16_t BackgroundPatternAddr;
+ bool LargeSprites;
+ bool VBlank;
+
+ bool Grayscale;
+ bool BackgroundMask;
+ bool SpriteMask;
+ bool BackgroundEnabled;
+ bool SpritesEnabled;
+ bool IntensifyRed;
+ bool IntensifyGreen;
+ bool IntensifyBlue;
+};
+
+struct PPUStatusFlags
+{
+ bool SpriteOverflow;
+ bool Sprite0Hit;
+ bool VerticalBlank;
+};
+
+struct PPUState
+{
+ uint8_t Control;
+ uint8_t Mask;
+ uint8_t Status;
+ uint32_t SpriteRamAddr;
+ uint16_t VideoRamAddr;
+ uint8_t XScroll;
+ uint16_t TmpVideoRamAddr;
+ bool WriteToggle;
+
+ uint16_t HighBitShift;
+ uint16_t LowBitShift;
+};
+
+struct TileInfo
+{
+ uint8_t LowByte;
+ uint8_t HighByte;
+ uint32_t PaletteOffset;
+
+ uint16_t TileAddr; //used by HD ppu
+ uint8_t OffsetY; //used by HD ppu
+};
+
+struct SpriteInfo : TileInfo
+{
+ bool HorizontalMirror;
+ bool BackgroundPriority;
+ uint8_t SpriteX;
+
+ bool VerticalMirror; //used by HD ppu
+};
+
+struct PPUDebugState
+{
+ PPUControlFlags ControlFlags;
+ PPUStatusFlags StatusFlags;
+ PPUState State;
+ int32_t Scanline;
+ uint32_t Cycle;
+ uint32_t FrameCount;
+};
\ No newline at end of file
diff --git a/Core/TraceLogger.cpp b/Core/TraceLogger.cpp
index d31e9c3a..1292f7df 100644
--- a/Core/TraceLogger.cpp
+++ b/Core/TraceLogger.cpp
@@ -4,38 +4,58 @@
#include "DebugState.h"
#include "Console.h"
#include "MemoryManager.h"
+#include "LabelManager.h"
#include "../Utilities/HexUtilities.h"
+#include "../Utilities/FolderUtilities.h"
TraceLogger *TraceLogger::_instance = nullptr;
-TraceLogger::TraceLogger(string outputFilepath, shared_ptr memoryManager, TraceLoggerOptions options)
+TraceLogger::TraceLogger(shared_ptr memoryManager, shared_ptr labelManager)
{
_memoryManager = memoryManager;
- _outputFile.open(outputFilepath, ios::out | ios::binary);
- _options = options;
- _firstLine = true;
+ _labelManager = labelManager;
_instance = this;
+ _currentPos = 0;
+ _logToFile = false;
}
TraceLogger::~TraceLogger()
{
- Console::Pause();
- if(_instance == this) {
- _instance = nullptr;
- }
-
- if(_outputFile) {
- if(!_outputBuffer.empty()) {
- _outputFile << _outputBuffer;
- }
- _outputFile.close();
- }
- Console::Resume();
+ StopLogging();
+ _instance = nullptr;
}
+void TraceLogger::SetOptions(TraceLoggerOptions options)
+{
+ _options = options;
+}
+
+void TraceLogger::StartLogging(string filename)
+{
+ _outputFile.open(filename, ios::out | ios::binary);
+ _logToFile = true;
+ _firstLine = true;
+}
+
+void TraceLogger::StopLogging()
+{
+ if(_logToFile) {
+ Console::Pause();
+ if(_outputFile) {
+ if(!_outputBuffer.empty()) {
+ _outputFile << _outputBuffer;
+ }
+ _outputFile.close();
+ }
+ Console::Resume();
+ _logToFile = false;
+ }
+}
+
+
void TraceLogger::LogStatic(string log)
{
- if(_instance && _instance->_options.ShowExtraInfo) {
+ if(_instance && _instance->_logToFile && _instance->_options.ShowExtraInfo && !_instance->_firstLine) {
//Flush current buffer
_instance->_outputFile << _instance->_outputBuffer;
_instance->_outputBuffer.clear();
@@ -44,75 +64,108 @@ void TraceLogger::LogStatic(string log)
}
}
-void TraceLogger::Log(DebugState &state, shared_ptr disassemblyInfo)
+void TraceLogger::GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, shared_ptr &disassemblyInfo, bool firstLine)
+{
+ //Roughly adjust PPU cycle & scanline to take into account the PPU already ran 3 cycles by the time we get here
+ short ppuCycle = (short)ppuState.Cycle - 3;
+ short scanline = (short)ppuState.Scanline;
+ if(ppuCycle < 0) {
+ ppuCycle = 341 + ppuCycle;
+ scanline--;
+ if(scanline < -1) {
+ scanline = EmulationSettings::GetNesModel() == NesModel::NTSC ? 260 : 310;
+ }
+ }
+
+ if(!firstLine) {
+ output += "\n";
+ }
+
+ output += HexUtilities::ToHex(cpuState.DebugPC) + " ";
+
+ if(_options.ShowByteCode) {
+ output += disassemblyInfo->GetByteCode() + std::string(13 - disassemblyInfo->GetByteCode().size(), ' ');
+ }
+
+ int indentLevel = 0;
+ if(_options.IndentCode) {
+ indentLevel = 0xFF - cpuState.SP;
+ output += std::string(indentLevel, ' ');
+ }
+
+ uint16_t disassemblyLength = 0;
+ uint16_t effectiveAddressLength = 0;
+ LabelManager* labelManager = _options.UseLabels ? _labelManager.get() : nullptr;
+ char* disassembly = disassemblyInfo->ToString(cpuState.DebugPC, _memoryManager.get(), labelManager, disassemblyLength);
+ char* effectiveAddress = (_options.ShowEffectiveAddresses ? disassemblyInfo->GetEffectiveAddressString(cpuState, _memoryManager.get(), labelManager, effectiveAddressLength) : nullptr);
+
+ output += disassembly;
+ if(effectiveAddress) {
+ output += effectiveAddress;
+ }
+ output += std::string(32 - disassemblyLength - effectiveAddressLength, ' ');
+
+ if(_options.ShowRegisters) {
+ output += " A:" + HexUtilities::ToHex(cpuState.A) +
+ " X:" + HexUtilities::ToHex(cpuState.X) +
+ " Y:" + HexUtilities::ToHex(cpuState.Y) +
+ " P:" + HexUtilities::ToHex(cpuState.PS) +
+ " SP:" + HexUtilities::ToHex(cpuState.SP);
+ }
+
+ if(_options.ShowPpuCycles) {
+ string str = std::to_string(ppuCycle);
+ output += " CYC:" + std::string(3 - str.size(), ' ') + str;
+ }
+
+ if(_options.ShowPpuScanline) {
+ string str = std::to_string(scanline);
+ output += " SL:" + std::string(3 - str.size(), ' ') + str;
+ }
+
+ if(_options.ShowPpuFrames) {
+ output += " FC:" + std::to_string(ppuState.FrameCount);
+ }
+
+ if(_options.ShowCpuCycles) {
+ output += " CPU Cycle:" + std::to_string(cpuState.CycleCount);
+ }
+}
+
+SimpleLock _lock;
+void TraceLogger::Log(State &cpuState, PPUDebugState &ppuState, shared_ptr disassemblyInfo)
{
if(disassemblyInfo) {
- State &cpuState = state.CPU;
- PPUDebugState &ppuState = state.PPU;
-
- string disassembly = disassemblyInfo->ToString(cpuState.DebugPC, _memoryManager, nullptr);
-
- //Roughly adjust PPU cycle & scanline to take into account the PPU already ran 3 cycles by the time we get here
- short ppuCycle = (short)ppuState.Cycle - 3;
- short scanline = (short)ppuState.Scanline;
- if(ppuCycle < 0) {
- ppuCycle = 341 + ppuCycle;
- scanline--;
- if(scanline < -1) {
- scanline = EmulationSettings::GetNesModel() == NesModel::NTSC ? 260 : 310;
+ 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(!_firstLine) {
- _outputBuffer += "\n";
- }
-
- _outputBuffer += HexUtilities::ToHex(cpuState.DebugPC) + " ";
-
- if(_options.ShowByteCode) {
- _outputBuffer += disassemblyInfo->GetByteCode() + std::string(13 - disassemblyInfo->GetByteCode().size(), ' ');
- }
-
- int indentLevel = 0;
- if(_options.IndentCode) {
- indentLevel = 0xFF - state.CPU.SP;
- _outputBuffer += std::string(indentLevel, ' ');
- }
-
- string codeString = disassembly + (_options.ShowEffectiveAddresses ? disassemblyInfo->GetEffectiveAddressString(state.CPU, _memoryManager, nullptr) : "");
- _outputBuffer += codeString + std::string(32 - codeString.size(), ' ');
-
- if(_options.ShowRegisters) {
- _outputBuffer += " A:" + HexUtilities::ToHex(cpuState.A) +
- " X:" + HexUtilities::ToHex(cpuState.X) +
- " Y:" + HexUtilities::ToHex(cpuState.Y) +
- " P:" + HexUtilities::ToHex(cpuState.PS) +
- " SP:" + HexUtilities::ToHex(cpuState.SP);
- }
-
- if(_options.ShowPpuCycles) {
- string str = std::to_string(ppuCycle);
- _outputBuffer += " CYC:" + std::string(3 - str.size(), ' ') + str;
- }
-
- if(_options.ShowPpuScanline) {
- string str = std::to_string(scanline);
- _outputBuffer += " SL:" + std::string(3 - str.size(), ' ') + str;
- }
-
- if(_options.ShowPpuFrames) {
- _outputBuffer += " FC:" + std::to_string(ppuState.FrameCount);
- }
-
- if(_options.ShowCpuCycles) {
- _outputBuffer += " CPU Cycle:" + std::to_string(cpuState.CycleCount);
- }
-
- if(_outputBuffer.size() > 32768) {
- _outputFile << _outputBuffer;
- _outputBuffer.clear();
- }
-
- _firstLine = false;
}
+}
+
+const char* TraceLogger::GetExecutionTrace(uint32_t lineCount)
+{
+ _executionTrace.clear();
+ auto lock = _lock.AcquireSafe();
+ int startPos = _currentPos + ExecutionLogSize - lineCount;
+ bool firstLine = true;
+ for(int i = 0; i < (int)lineCount; i++) {
+ int index = (startPos + i) % ExecutionLogSize;
+ if(_disassemblyCache[index]) {
+ GetTraceRow(_executionTrace, _cpuStateCache[index], _ppuStateCache[index], _disassemblyCache[index], firstLine);
+ firstLine = false;
+ }
+ }
+ return _executionTrace.c_str();
}
\ No newline at end of file
diff --git a/Core/TraceLogger.h b/Core/TraceLogger.h
index ac18e1f6..30b4792a 100644
--- a/Core/TraceLogger.h
+++ b/Core/TraceLogger.h
@@ -1,9 +1,11 @@
#pragma once
#include "stdafx.h"
+#include "CpuState.h"
+#include "PpuState.h"
class DisassemblyInfo;
class MemoryManager;
-struct DebugState;
+class LabelManager;
struct TraceLoggerOptions
{
@@ -16,6 +18,7 @@ struct TraceLoggerOptions
bool ShowExtraInfo;
bool IndentCode;
bool ShowEffectiveAddresses;
+ bool UseLabels;
};
class TraceLogger
@@ -28,12 +31,30 @@ private:
ofstream _outputFile;
bool _firstLine;
shared_ptr _memoryManager;
+ shared_ptr _labelManager;
+
+ constexpr static int ExecutionLogSize = 30000;
+ bool _logToFile;
+ uint16_t _currentPos;
+ State _cpuStateCache[ExecutionLogSize] = {};
+ PPUDebugState _ppuStateCache[ExecutionLogSize] = {};
+ int _memoryAddrCache[ExecutionLogSize] = {};
+ shared_ptr _disassemblyCache[ExecutionLogSize] = {};
+
+ string _executionTrace;
public:
- TraceLogger(string outputFilepath, shared_ptr memoryManager, TraceLoggerOptions options);
+ TraceLogger(shared_ptr memoryManager, shared_ptr labelManager);
~TraceLogger();
- void Log(DebugState &state, shared_ptr disassemblyInfo);
+ void Log(State &cpuState, PPUDebugState &ppuState, shared_ptr disassemblyInfo);
+ void SetOptions(TraceLoggerOptions options);
+ void StartLogging(string filename);
+ void StopLogging();
+
+ void GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, shared_ptr &disassemblyInfo, bool firstLine);
+ const char* GetExecutionTrace(uint32_t lineCount);
static void LogStatic(string log);
+
};
\ No newline at end of file
diff --git a/GUI.NET/Config/DebugInfo.cs b/GUI.NET/Config/DebugInfo.cs
index 023c1757..641af507 100644
--- a/GUI.NET/Config/DebugInfo.cs
+++ b/GUI.NET/Config/DebugInfo.cs
@@ -144,6 +144,19 @@ namespace Mesen.GUI.Config
public bool BreakOnOpen = true;
public bool BreakOnReset = true;
+ public bool TraceAutoRefresh = true;
+ public int TraceLineCount = 1000;
+ public bool TraceIndentCode = false;
+ public bool TraceShowByteCode = true;
+ public bool TraceShowCpuCycles = false;
+ public bool TraceShowEffectiveAddresses = true;
+ public bool TraceShowExtraInfo = true;
+ public bool TraceShowFrameCount = false;
+ public bool TraceShowPpuCycles = true;
+ public bool TraceShowPpuScanline = true;
+ public bool TraceShowRegisters = true;
+ internal bool TraceUseLabels;
+
public DebugInfo()
{
LeftView = new DebugViewInfo();
diff --git a/GUI.NET/Debugger/frmTraceLogger.Designer.cs b/GUI.NET/Debugger/frmTraceLogger.Designer.cs
index d0ccf1e0..1a6eb37b 100644
--- a/GUI.NET/Debugger/frmTraceLogger.Designer.cs
+++ b/GUI.NET/Debugger/frmTraceLogger.Designer.cs
@@ -27,24 +27,43 @@
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.btnOpenTrace = new System.Windows.Forms.Button();
this.btnStartLogging = new System.Windows.Forms.Button();
this.btnStopLogging = new System.Windows.Forms.Button();
this.grpLogOptions = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
- this.chkShowCpuCycles = new System.Windows.Forms.CheckBox();
+ this.chkShowEffectiveAddresses = new System.Windows.Forms.CheckBox();
this.chkShowPpuCycles = new System.Windows.Forms.CheckBox();
this.chkShowRegisters = new System.Windows.Forms.CheckBox();
- this.chkShowPpuScanline = new System.Windows.Forms.CheckBox();
- this.chkShowFrameCount = new System.Windows.Forms.CheckBox();
this.chkShowExtraInfo = new System.Windows.Forms.CheckBox();
- this.chkShowByteCode = new System.Windows.Forms.CheckBox();
this.chkIndentCode = new System.Windows.Forms.CheckBox();
- this.chkShowEffectiveAddresses = 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.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
+ this.grpExecutionLog = new System.Windows.Forms.GroupBox();
+ this.txtTraceLog = new System.Windows.Forms.TextBox();
+ this.tmrUpdateLog = new System.Windows.Forms.Timer(this.components);
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.logLinesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnu100Lines = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnu1000Lines = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnu10000Lines = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnu30000Lines = new System.Windows.Forms.ToolStripMenuItem();
+ this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
+ this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.tableLayoutPanel1.SuspendLayout();
this.grpLogOptions.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
+ this.tableLayoutPanel3.SuspendLayout();
+ this.grpExecutionLog.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
@@ -57,23 +76,21 @@
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.Controls.Add(this.chkIndentCode, 0, 2);
- this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 314);
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(339, 193);
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(442, 206);
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(241, 3);
+ this.btnOpenTrace.Location = new System.Drawing.Point(344, 3);
this.btnOpenTrace.Name = "btnOpenTrace";
this.btnOpenTrace.Size = new System.Drawing.Size(95, 23);
this.btnOpenTrace.TabIndex = 2;
@@ -107,52 +124,55 @@
//
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(333, 132);
+ this.grpLogOptions.Size = new System.Drawing.Size(436, 168);
this.grpLogOptions.TabIndex = 3;
this.grpLogOptions.TabStop = false;
- this.grpLogOptions.Text = "Log Contents";
+ this.grpLogOptions.Text = "Log Options";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 3;
- this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
+ this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33332F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
this.tableLayoutPanel2.Controls.Add(this.chkShowEffectiveAddresses, 0, 3);
- this.tableLayoutPanel2.Controls.Add(this.chkShowCpuCycles, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.chkShowPpuCycles, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowRegisters, 0, 0);
- this.tableLayoutPanel2.Controls.Add(this.chkShowPpuScanline, 1, 1);
- this.tableLayoutPanel2.Controls.Add(this.chkShowFrameCount, 2, 1);
this.tableLayoutPanel2.Controls.Add(this.chkShowExtraInfo, 0, 4);
+ this.tableLayoutPanel2.Controls.Add(this.chkIndentCode, 0, 6);
this.tableLayoutPanel2.Controls.Add(this.chkShowByteCode, 0, 2);
+ this.tableLayoutPanel2.Controls.Add(this.chkShowFrameCount, 2, 2);
+ this.tableLayoutPanel2.Controls.Add(this.chkShowPpuScanline, 2, 1);
+ this.tableLayoutPanel2.Controls.Add(this.chkShowCpuCycles, 2, 0);
+ this.tableLayoutPanel2.Controls.Add(this.chkUseLabels, 2, 6);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
- this.tableLayoutPanel2.RowCount = 6;
+ this.tableLayoutPanel2.RowCount = 7;
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());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel2.Size = new System.Drawing.Size(327, 113);
+ this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel2.Size = new System.Drawing.Size(430, 149);
this.tableLayoutPanel2.TabIndex = 0;
//
- // chkShowCpuCycles
+ // chkShowEffectiveAddresses
//
- this.chkShowCpuCycles.AutoSize = true;
- this.chkShowCpuCycles.Checked = true;
- this.chkShowCpuCycles.CheckState = System.Windows.Forms.CheckState.Checked;
- this.chkShowCpuCycles.Location = new System.Drawing.Point(111, 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;
+ 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, 72);
+ 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
//
@@ -178,28 +198,6 @@
this.chkShowRegisters.Text = "Registers";
this.chkShowRegisters.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(111, 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(220, 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;
- //
// chkShowExtraInfo
//
this.chkShowExtraInfo.AutoSize = true;
@@ -213,6 +211,17 @@
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.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;
+ //
// chkShowByteCode
//
this.chkShowByteCode.AutoSize = true;
@@ -225,48 +234,201 @@
this.chkShowByteCode.Text = "Byte Code";
this.chkShowByteCode.UseVisualStyleBackColor = true;
//
- // chkIndentCode
+ // chkShowFrameCount
//
- this.chkIndentCode.AutoSize = true;
- this.tableLayoutPanel1.SetColumnSpan(this.chkIndentCode, 3);
- this.chkIndentCode.Location = new System.Drawing.Point(3, 170);
- 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;
+ this.chkShowFrameCount.AutoSize = true;
+ this.chkShowFrameCount.Location = new System.Drawing.Point(289, 49);
+ 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
+ // chkShowPpuScanline
//
- 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, 72);
- 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;
+ this.chkShowPpuScanline.AutoSize = true;
+ this.chkShowPpuScanline.Checked = true;
+ this.chkShowPpuScanline.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkShowPpuScanline.Location = new System.Drawing.Point(289, 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;
+ //
+ // 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.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
+ //
+ 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;
+ //
+ // tableLayoutPanel3
+ //
+ this.tableLayoutPanel3.ColumnCount = 2;
+ 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.Controls.Add(this.tableLayoutPanel1, 0, 1);
+ this.tableLayoutPanel3.Controls.Add(this.grpExecutionLog, 0, 0);
+ this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 24);
+ this.tableLayoutPanel3.Name = "tableLayoutPanel3";
+ 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.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.TabIndex = 2;
+ this.grpExecutionLog.TabStop = false;
+ this.grpExecutionLog.Text = "Execution Log";
+ //
+ // txtTraceLog
+ //
+ this.txtTraceLog.BackColor = System.Drawing.SystemColors.Window;
+ this.txtTraceLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTraceLog.Location = new System.Drawing.Point(3, 16);
+ this.txtTraceLog.Multiline = true;
+ 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.TabIndex = 1;
+ //
+ // tmrUpdateLog
+ //
+ this.tmrUpdateLog.Interval = 150;
+ this.tmrUpdateLog.Tick += new System.EventHandler(this.tmrUpdateLog_Tick);
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ 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.TabIndex = 2;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // showToolStripMenuItem
+ //
+ this.showToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.logLinesToolStripMenuItem,
+ this.mnuAutoRefresh,
+ this.toolStripMenuItem1,
+ this.mnuRefresh});
+ this.showToolStripMenuItem.Name = "showToolStripMenuItem";
+ this.showToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+ this.showToolStripMenuItem.Text = "View";
+ //
+ // logLinesToolStripMenuItem
+ //
+ this.logLinesToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.mnu100Lines,
+ this.mnu1000Lines,
+ this.mnu10000Lines,
+ this.mnu30000Lines});
+ this.logLinesToolStripMenuItem.Name = "logLinesToolStripMenuItem";
+ this.logLinesToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
+ this.logLinesToolStripMenuItem.Text = "Line Count";
+ //
+ // mnu100Lines
+ //
+ this.mnu100Lines.Name = "mnu100Lines";
+ this.mnu100Lines.Size = new System.Drawing.Size(104, 22);
+ this.mnu100Lines.Text = "100";
+ this.mnu100Lines.Click += new System.EventHandler(this.mnu100Lines_Click);
+ //
+ // mnu1000Lines
+ //
+ this.mnu1000Lines.Checked = true;
+ this.mnu1000Lines.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.mnu1000Lines.Name = "mnu1000Lines";
+ this.mnu1000Lines.Size = new System.Drawing.Size(104, 22);
+ this.mnu1000Lines.Text = "1000";
+ this.mnu1000Lines.Click += new System.EventHandler(this.mnu1000Lines_Click);
+ //
+ // mnu10000Lines
+ //
+ this.mnu10000Lines.Name = "mnu10000Lines";
+ this.mnu10000Lines.Size = new System.Drawing.Size(104, 22);
+ this.mnu10000Lines.Text = "10000";
+ this.mnu10000Lines.Click += new System.EventHandler(this.mnu10000Lines_Click);
+ //
+ // mnu30000Lines
+ //
+ this.mnu30000Lines.Name = "mnu30000Lines";
+ this.mnu30000Lines.Size = new System.Drawing.Size(104, 22);
+ this.mnu30000Lines.Text = "30000";
+ this.mnu30000Lines.Click += new System.EventHandler(this.mnu30000Lines_Click);
+ //
+ // mnuAutoRefresh
+ //
+ this.mnuAutoRefresh.Checked = true;
+ this.mnuAutoRefresh.CheckOnClick = true;
+ this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.mnuAutoRefresh.Name = "mnuAutoRefresh";
+ this.mnuAutoRefresh.Size = new System.Drawing.Size(141, 22);
+ this.mnuAutoRefresh.Text = "Auto-refresh";
+ //
+ // toolStripMenuItem1
+ //
+ this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(138, 6);
+ //
+ // mnuRefresh
+ //
+ this.mnuRefresh.Name = "mnuRefresh";
+ this.mnuRefresh.ShortcutKeys = System.Windows.Forms.Keys.F5;
+ this.mnuRefresh.Size = new System.Drawing.Size(141, 22);
+ this.mnuRefresh.Text = "Refresh";
+ this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// frmTraceLogger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(339, 193);
- this.Controls.Add(this.tableLayoutPanel1);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
+ this.ClientSize = new System.Drawing.Size(808, 547);
+ this.Controls.Add(this.tableLayoutPanel3);
+ this.Controls.Add(this.menuStrip1);
this.Name = "frmTraceLogger";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Trace Logger";
this.tableLayoutPanel1.ResumeLayout(false);
- this.tableLayoutPanel1.PerformLayout();
this.grpLogOptions.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
+ this.tableLayoutPanel3.ResumeLayout(false);
+ this.grpExecutionLog.ResumeLayout(false);
+ this.grpExecutionLog.PerformLayout();
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
+ this.PerformLayout();
}
@@ -287,5 +449,20 @@
private System.Windows.Forms.CheckBox chkIndentCode;
private System.Windows.Forms.Button btnOpenTrace;
private System.Windows.Forms.CheckBox chkShowEffectiveAddresses;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
+ private System.Windows.Forms.TextBox txtTraceLog;
+ private System.Windows.Forms.Timer tmrUpdateLog;
+ private System.Windows.Forms.GroupBox grpExecutionLog;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem showToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem logLinesToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh;
+ private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
+ private System.Windows.Forms.ToolStripMenuItem mnuRefresh;
+ private System.Windows.Forms.ToolStripMenuItem mnu100Lines;
+ private System.Windows.Forms.ToolStripMenuItem mnu1000Lines;
+ private System.Windows.Forms.ToolStripMenuItem mnu10000Lines;
+ private System.Windows.Forms.ToolStripMenuItem mnu30000Lines;
+ private System.Windows.Forms.CheckBox chkUseLabels;
}
}
\ No newline at end of file
diff --git a/GUI.NET/Debugger/frmTraceLogger.cs b/GUI.NET/Debugger/frmTraceLogger.cs
index 548f335f..1ed4a630 100644
--- a/GUI.NET/Debugger/frmTraceLogger.cs
+++ b/GUI.NET/Debugger/frmTraceLogger.cs
@@ -9,29 +9,65 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Config;
+using Mesen.GUI.Controls;
using Mesen.GUI.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmTraceLogger : BaseForm
{
+ private int _lineCount;
private bool _loggingEnabled = false;
+ private string _lastFilename;
public frmTraceLogger()
{
InitializeComponent();
+
+ DebugInfo debugInfo = ConfigManager.Config.DebugInfo;
+ mnuAutoRefresh.Checked = debugInfo.TraceAutoRefresh;
+ _lineCount = debugInfo.TraceLineCount;
+ chkIndentCode.Checked = debugInfo.TraceIndentCode;
+ chkShowByteCode.Checked = debugInfo.TraceShowByteCode;
+ chkShowCpuCycles.Checked = debugInfo.TraceShowCpuCycles;
+ chkShowEffectiveAddresses.Checked = debugInfo.TraceShowEffectiveAddresses;
+ chkShowExtraInfo.Checked = debugInfo.TraceShowExtraInfo;
+ chkShowFrameCount.Checked = debugInfo.TraceShowFrameCount;
+ chkShowPpuCycles.Checked = debugInfo.TraceShowPpuCycles;
+ chkShowPpuScanline.Checked = debugInfo.TraceShowPpuScanline;
+ chkShowRegisters.Checked = debugInfo.TraceShowRegisters;
+ chkUseLabels.Checked = debugInfo.TraceUseLabels;
+
+ UpdateMenu();
+ txtTraceLog.Font = new Font(BaseControl.MonospaceFontFamily, 10);
+ tmrUpdateLog.Start();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
+ DebugInfo debugInfo = ConfigManager.Config.DebugInfo;
+ debugInfo.TraceAutoRefresh = mnuAutoRefresh.Checked;
+ debugInfo.TraceLineCount = _lineCount;
+ debugInfo.TraceIndentCode = chkIndentCode.Checked;
+ debugInfo.TraceShowByteCode = chkShowByteCode.Checked;
+ debugInfo.TraceShowCpuCycles = chkShowCpuCycles.Checked;
+ debugInfo.TraceShowEffectiveAddresses = chkShowEffectiveAddresses.Checked;
+ debugInfo.TraceShowExtraInfo = chkShowExtraInfo.Checked;
+ debugInfo.TraceShowFrameCount = chkShowFrameCount.Checked;
+ debugInfo.TraceShowPpuCycles = chkShowPpuCycles.Checked;
+ debugInfo.TraceShowPpuScanline = chkShowPpuScanline.Checked;
+ debugInfo.TraceShowRegisters = chkShowRegisters.Checked;
+ debugInfo.TraceUseLabels = chkUseLabels.Checked;
+ ConfigManager.ApplyChanges();
+
if(_loggingEnabled) {
InteropEmu.DebugStopTraceLogger();
}
}
- private void btnStartLogging_Click(object sender, EventArgs e)
+ private void SetOptions()
{
TraceLoggerOptions options = new TraceLoggerOptions() {
ShowByteCode = chkShowByteCode.Checked,
@@ -42,16 +78,31 @@ namespace Mesen.GUI.Debugger
ShowPpuScanline = chkShowPpuScanline.Checked,
ShowRegisters = chkShowRegisters.Checked,
IndentCode = chkIndentCode.Checked,
- ShowEffectiveAddresses = chkShowEffectiveAddresses.Checked
+ ShowEffectiveAddresses = chkShowEffectiveAddresses.Checked,
+ UseLabels = chkUseLabels.Checked
};
- InteropEmu.DebugStartTraceLogger(options);
+ InteropEmu.DebugSetTraceOptions(options);
+ }
- btnStartLogging.Enabled = false;
- btnStopLogging.Enabled = true;
- btnOpenTrace.Enabled = true;
+ private void btnStartLogging_Click(object sender, EventArgs e)
+ {
+ using(SaveFileDialog sfd = new SaveFileDialog()) {
+ sfd.FileName = "Trace logs (*.txt)|*.txt";
+ sfd.FileName = "Trace - " + InteropEmu.GetRomInfo().GetRomName() + ".txt";
+ sfd.InitialDirectory = ConfigManager.DebuggerFolder;
+ if(sfd.ShowDialog() == DialogResult.OK) {
+ _lastFilename = sfd.FileName;
+ SetOptions();
+ InteropEmu.DebugStartTraceLogger(sfd.FileName);
- _loggingEnabled = true;
+ btnStartLogging.Enabled = false;
+ btnStopLogging.Enabled = true;
+ btnOpenTrace.Enabled = false;
+
+ _loggingEnabled = true;
+ }
+ }
}
private void btnStopLogging_Click(object sender, EventArgs e)
@@ -59,13 +110,80 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugStopTraceLogger();
btnStartLogging.Enabled = true;
btnStopLogging.Enabled = false;
+ btnOpenTrace.Enabled = true;
}
private void btnOpenTrace_Click(object sender, EventArgs e)
{
try {
- System.Diagnostics.Process.Start(Path.Combine(ConfigManager.DebuggerFolder, "Trace - " + InteropEmu.GetRomInfo().GetRomName() + ".log"));
+ System.Diagnostics.Process.Start(_lastFilename);
} catch { }
}
+
+ private void RefreshLog()
+ {
+ SetOptions();
+ string newTrace = InteropEmu.DebugGetExecutionTrace((UInt32)_lineCount).Replace("\n", Environment.NewLine);
+
+ if(newTrace != txtTraceLog.Text) {
+ txtTraceLog.Text = newTrace;
+ txtTraceLog.SelectionStart = txtTraceLog.TextLength;
+ txtTraceLog.ScrollToCaret();
+ }
+ }
+
+ private void UpdateMenu()
+ {
+ mnu30000Lines.Checked = _lineCount == 30000;
+ mnu10000Lines.Checked = _lineCount == 10000;
+ mnu1000Lines.Checked = _lineCount == 1000;
+ mnu100Lines.Checked = _lineCount == 100;
+
+ if(_lineCount >= 10000) {
+ mnuAutoRefresh.Checked = false;
+ } else if(_lineCount == 1000) {
+ tmrUpdateLog.Interval = 250;
+ } else {
+ tmrUpdateLog.Interval = 150;
+ }
+
+ mnuAutoRefresh.Enabled = _lineCount < 10000;
+ }
+
+ private void tmrUpdateLog_Tick(object sender, EventArgs e)
+ {
+ if(mnuAutoRefresh.Checked) {
+ RefreshLog();
+ }
+ }
+
+ private void mnu30000Lines_Click(object sender, EventArgs e)
+ {
+ _lineCount = 30000;
+ UpdateMenu();
+ }
+
+ private void mnu10000Lines_Click(object sender, EventArgs e)
+ {
+ _lineCount = 10000;
+ UpdateMenu();
+ }
+
+ private void mnu1000Lines_Click(object sender, EventArgs e)
+ {
+ _lineCount = 1000;
+ UpdateMenu();
+ }
+
+ private void mnu100Lines_Click(object sender, EventArgs e)
+ {
+ _lineCount = 100;
+ UpdateMenu();
+ }
+
+ private void mnuRefresh_Click(object sender, EventArgs e)
+ {
+ RefreshLog();
+ }
}
}
diff --git a/GUI.NET/Debugger/frmTraceLogger.resx b/GUI.NET/Debugger/frmTraceLogger.resx
index 8766f298..24e4a526 100644
--- a/GUI.NET/Debugger/frmTraceLogger.resx
+++ b/GUI.NET/Debugger/frmTraceLogger.resx
@@ -120,4 +120,10 @@
17, 17
+
+ 107, 17
+
+
+ 238, 17
+
\ No newline at end of file
diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs
index af7064ba..753b8bb7 100644
--- a/GUI.NET/InteropEmu.cs
+++ b/GUI.NET/InteropEmu.cs
@@ -195,10 +195,13 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void DebugSetNextStatement(UInt16 addr);
[DllImport(DLLPath)] public static extern Int32 DebugEvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string expression, out EvalResultType resultType);
-
- [DllImport(DLLPath)] public static extern void DebugStartTraceLogger(TraceLoggerOptions options);
- [DllImport(DLLPath)] public static extern void DebugStopTraceLogger();
+ [DllImport(DLLPath)] public static extern void DebugStartTraceLogger([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename);
+ [DllImport(DLLPath)] public static extern void DebugStopTraceLogger();
+ [DllImport(DLLPath)] public static extern void DebugSetTraceOptions(TraceLoggerOptions options);
+ [DllImport(DLLPath, EntryPoint = "DebugGetExecutionTrace")] private static extern IntPtr DebugGetExecutionTraceWrapper(UInt32 lineCount);
+ public static string DebugGetExecutionTrace(UInt32 lineCount) { return PtrToStringUtf8(InteropEmu.DebugGetExecutionTraceWrapper(lineCount)); }
+
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugLoadCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string cdlFilepath);
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugSaveCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string cdlFilepath);
[DllImport(DLLPath)] public static extern void DebugGetCdlRatios(ref CdlRatios ratios);
@@ -806,6 +809,7 @@ namespace Mesen.GUI
[MarshalAs(UnmanagedType.I1)] public bool ShowExtraInfo;
[MarshalAs(UnmanagedType.I1)] public bool IndentCode;
[MarshalAs(UnmanagedType.I1)] public bool ShowEffectiveAddresses;
+ [MarshalAs(UnmanagedType.I1)] public bool UseLabels;
}
public enum ProfilerDataType
diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp
index 0ac928a7..7693b80c 100644
--- a/InteropDLL/DebugWrapper.cpp
+++ b/InteropDLL/DebugWrapper.cpp
@@ -74,8 +74,10 @@ extern "C"
DllExport int32_t __stdcall DebugEvaluateExpression(char* expression, EvalResultType *resultType) { return GetDebugger()->EvaluateExpression(expression, *resultType); }
- DllExport void __stdcall DebugStartTraceLogger(TraceLoggerOptions options) { GetDebugger()->StartTraceLogger(options); }
- DllExport void __stdcall DebugStopTraceLogger() { GetDebugger()->StopTraceLogger(); }
+ DllExport void __stdcall DebugSetTraceOptions(TraceLoggerOptions options) { GetDebugger()->GetTraceLogger()->SetOptions(options); }
+ DllExport void __stdcall DebugStartTraceLogger(char* filename) { GetDebugger()->GetTraceLogger()->StartLogging(filename); }
+ DllExport void __stdcall DebugStopTraceLogger() { GetDebugger()->GetTraceLogger()->StopLogging(); }
+ DllExport const char* DebugGetExecutionTrace(uint32_t lineCount) { return GetDebugger()->GetTraceLogger()->GetExecutionTrace(lineCount); }
DllExport void __stdcall DebugSetMemoryValue(DebugMemoryType type, uint32_t address, uint8_t value) { return GetDebugger()->GetMemoryDumper()->SetMemoryValue(type, address, value); }
DllExport int32_t __stdcall DebugGetMemorySize(DebugMemoryType type) { return GetDebugger()->GetMemorySize(type); }