#pragma once #include "stdafx.h" #include "CpuTypes.h" #include "PpuTypes.h" #include "SpcTypes.h" #include "GbTypes.h" #include "DebugTypes.h" #include "DisassemblyInfo.h" #include "DebugUtilities.h" #include "../Utilities/SimpleLock.h" class Console; class Debugger; class LabelManager; class MemoryDumper; class EmuSettings; struct DebugState; struct TraceLoggerOptions { bool LogCpu; bool LogSpc; bool LogNecDsp; bool LogSa1; bool LogGsu; bool LogCx4; bool LogGameboy; bool ShowExtraInfo; bool IndentCode; bool UseLabels; bool UseWindowsEol; bool ExtendZeroPage; char Condition[1000]; char Format[1000]; }; enum class RowDataType { Text = 0, ByteCode, Disassembly, EffectiveAddress, MemoryValue, Align, PC, A, B, C, D, E, F, H, L, X, Y, DB, SP, PS, Cycle, Scanline, HClock, FrameCount, CycleCount }; struct RowPart { RowDataType DataType; string Text; bool DisplayInHex; int MinWidth; }; 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; Console* _console; EmuSettings* _settings; LabelManager* _labelManager; MemoryDumper* _memoryDumper; vector _rowParts; vector _spcRowParts; vector _dspRowParts; vector _gsuRowParts; vector _cx4RowParts; vector _gbRowParts; bool _logCpu[(int)DebugUtilities::GetLastCpuType() + 1] = {}; bool _pendingLog; //CpuState _lastState; //DisassemblyInfo _lastDisassemblyInfo; bool _logToFile; uint32_t _currentPos; uint32_t _logCount; DebugState *_stateCache = nullptr; DisassemblyInfo *_disassemblyCache = nullptr; CpuType* _logCpuType = nullptr; DebugState *_stateCacheCopy = nullptr; DisassemblyInfo *_disassemblyCacheCopy = nullptr; CpuType* _logCpuTypeCopy = nullptr; SimpleLock _lock; template void GetStatusFlag(string &output, uint8_t ps, RowPart& part); void WriteByteCode(DisassemblyInfo &info, RowPart &rowPart, string &output); void WriteDisassembly(DisassemblyInfo &info, RowPart &rowPart, uint8_t sp, uint32_t pc, string &output); void WriteEffectiveAddress(DisassemblyInfo &info, RowPart &rowPart, void *cpuState, string &output, SnesMemoryType cpuMemoryType, CpuType cpuType); void WriteMemoryValue(DisassemblyInfo &info, RowPart &rowPart, void *cpuState, string &output, SnesMemoryType memType, CpuType cpuType); void WriteAlign(int originalSize, RowPart &rowPart, string &output); void AddRow(CpuType cpuType, DisassemblyInfo &disassemblyInfo, DebugState &state); //bool ConditionMatches(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo); void ParseFormatString(vector &rowParts, string format); void GetTraceRow(string &output, CpuType cpuType, DisassemblyInfo &disassemblyInfo, DebugState &state); void GetTraceRow(string &output, CpuState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo, SnesMemoryType memType, CpuType cpuType); void GetTraceRow(string &output, SpcState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo); void GetTraceRow(string &output, NecDspState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo); void GetTraceRow(string &output, GsuState &gsuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo); void GetTraceRow(string& output, Cx4State& cx4State, PpuState& ppuState, DisassemblyInfo& disassemblyInfo); void GetTraceRow(string &output, GbCpuState &gbState, GbPpuState &gbPpuState, DisassemblyInfo &disassemblyInfo); template void WriteValue(string &output, T value, RowPart& rowPart); public: TraceLogger(Debugger* debugger, shared_ptr console); ~TraceLogger(); __forceinline bool IsCpuLogged(CpuType type) { return _logCpu[(int)type]; } void Log(CpuType cpuType, DebugState &state, DisassemblyInfo &disassemblyInfo); void Clear(); //void LogNonExec(OperationInfo& operationInfo); void SetOptions(TraceLoggerOptions options); void StartLogging(string filename); void StopLogging(); void LogExtraInfo(const char *log, uint32_t cycleCount); const char* GetExecutionTrace(uint32_t lineCount); };