#pragma once #include "stdafx.h" #include "DebuggerTypes.h" #include "../Utilities/SimpleLock.h" #include "DisassemblyInfo.h" #include "ExpressionEvaluator.h" class MemoryManager; class LabelManager; class Debugger; enum class RowDataType { Text = 0, ByteCode, Disassembly, EffectiveAddress, MemoryValue, Align, PC, A, X, Y, SP, PS, Cycle, Scanline, FrameCount, CycleCount }; struct RowPart { RowDataType DataType; string Text; bool DisplayInHex; int MinWidth; }; struct TraceLoggerOptions { bool ShowExtraInfo; bool IndentCode; bool UseLabels; bool UseWindowsEol; bool ExtendZeroPage; char Condition[1000]; char Format[1000]; }; class TraceLogger { private: static constexpr int ExecutionLogSize = 30000; //Must be static to be thread-safe when switching game static string _executionTrace; TraceLoggerOptions _options; string _outputFilepath; string _outputBuffer; ofstream _outputFile; shared_ptr _memoryManager; shared_ptr _labelManager; shared_ptr _expEvaluator; ExpressionData _conditionData; vector _rowParts; bool _pendingLog; DebugState _lastState; DisassemblyInfo _lastDisassemblyInfo; bool _logToFile; uint16_t _currentPos; uint32_t _logCount; State _cpuStateCache[ExecutionLogSize] = {}; PPUDebugState _ppuStateCache[ExecutionLogSize] = {}; DisassemblyInfo _disassemblyCache[ExecutionLogSize]; State _cpuStateCacheCopy[ExecutionLogSize] = {}; PPUDebugState _ppuStateCacheCopy[ExecutionLogSize] = {}; DisassemblyInfo _disassemblyCacheCopy[ExecutionLogSize]; SimpleLock _lock; void GetStatusFlag(string &output, uint8_t ps, RowPart& part); void AddRow(DisassemblyInfo &disassemblyInfo, DebugState &state); bool ConditionMatches(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo); void GetTraceRow(string &output, State &cpuState, PPUDebugState &ppuState, DisassemblyInfo &disassemblyInfo); template void WriteValue(string &output, T value, RowPart& rowPart); public: TraceLogger(Debugger* debugger, shared_ptr memoryManager, shared_ptr labelManager); ~TraceLogger(); void Log(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo); void Clear(); void LogNonExec(OperationInfo& operationInfo); void SetOptions(TraceLoggerOptions options); void StartLogging(string filename); void StopLogging(); void LogExtraInfo(const char *log, uint64_t cycleCount); const char* GetExecutionTrace(uint32_t lineCount); };