1 #pragma once 2 3 #include "stdafx.h" 4 #include <atomic> 5 #include <deque> 6 #include <unordered_set> 7 using std::atomic; 8 using std::deque; 9 using std::unordered_set; 10 11 #include "../Utilities/SimpleLock.h" 12 #include "DebuggerTypes.h" 13 14 class CPU; 15 class APU; 16 class PPU; 17 class MemoryManager; 18 class Console; 19 class Assembler; 20 class Disassembler; 21 class LabelManager; 22 class MemoryDumper; 23 class MemoryAccessCounter; 24 class Profiler; 25 class CodeRunner; 26 class BaseMapper; 27 class ScriptHost; 28 class TraceLogger; 29 class PerformanceTracker; 30 class Breakpoint; 31 class CodeDataLogger; 32 class ExpressionEvaluator; 33 class DummyCpu; 34 struct ExpressionData; 35 36 enum EvalResultType : int32_t; 37 enum class CdlStripFlag; 38 39 class Debugger 40 { 41 private: 42 static constexpr int BreakpointTypeCount = 8; 43 44 //Must be static to be thread-safe when switching game 45 static string _disassemblerOutput; 46 47 shared_ptr<Disassembler> _disassembler; 48 shared_ptr<Assembler> _assembler; 49 shared_ptr<MemoryDumper> _memoryDumper; 50 shared_ptr<CodeDataLogger> _codeDataLogger; 51 shared_ptr<MemoryAccessCounter> _memoryAccessCounter; 52 shared_ptr<LabelManager> _labelManager; 53 shared_ptr<TraceLogger> _traceLogger; 54 shared_ptr<Profiler> _profiler; 55 shared_ptr<PerformanceTracker> _performanceTracker; 56 unique_ptr<CodeRunner> _codeRunner; 57 58 shared_ptr<Console> _console; 59 shared_ptr<CPU> _cpu; 60 shared_ptr<PPU> _ppu; 61 shared_ptr<APU> _apu; 62 shared_ptr<MemoryManager> _memoryManager; 63 shared_ptr<BaseMapper> _mapper; 64 65 shared_ptr<DummyCpu> _dummyCpu; 66 bool _bpDummyCpuRequired; 67 bool _breakOnFirstCycle; 68 69 bool _hasScript; 70 SimpleLock _scriptLock; 71 int _nextScriptId; 72 vector<shared_ptr<ScriptHost>> _scripts; 73 74 atomic<int32_t> _preventResume; 75 atomic<bool> _stopFlag; 76 atomic<bool> _executionStopped; 77 atomic<int32_t> _suspendCount; 78 vector<Breakpoint> _breakpoints[BreakpointTypeCount]; 79 vector<ExpressionData> _breakpointRpnList[BreakpointTypeCount]; 80 bool _hasBreakpoint[BreakpointTypeCount] = {}; 81 82 vector<uint8_t> _frozenAddresses; 83 84 uint32_t _opCodeCycle; 85 MemoryOperationType _memoryOperationType; 86 87 deque<StackFrameInfo> _callstack; 88 deque<int32_t> _subReturnAddresses; 89 90 int32_t _stepOutReturnAddress; 91 92 unordered_set<uint32_t> _functionEntryPoints; 93 94 unique_ptr<ExpressionEvaluator> _watchExpEval; 95 unique_ptr<ExpressionEvaluator> _bpExpEval; 96 DebugState _debugState; 97 98 SimpleLock _breakLock; 99 100 //Used to alter the executing address via "Set Next Statement" 101 uint16_t *_currentReadAddr; 102 uint8_t *_currentReadValue; 103 int32_t _nextReadAddr; 104 uint16_t _returnToAddress; 105 106 uint32_t _flags; 107 108 string _romName; 109 atomic<int32_t> _stepCount; 110 atomic<int32_t> _ppuStepCount; 111 atomic<int32_t> _stepCycleCount; 112 atomic<uint8_t> _lastInstruction; 113 atomic<bool> _stepOut; 114 atomic<int32_t> _stepOverAddr; 115 BreakSource _breakSource; 116 117 atomic<bool> _released; 118 SimpleLock _releaseLock; 119 120 bool _enableBreakOnUninitRead; 121 122 atomic<bool> _breakRequested; 123 bool _pausedForDebugHelper; 124 125 atomic<int32_t> _breakOnScanline; 126 127 bool _proccessPpuCycle[341]; 128 std::unordered_map<int, int> _ppuViewerUpdateCycle; 129 130 uint16_t _ppuScrollX; 131 uint16_t _ppuScrollY; 132 133 uint64_t _prevInstructionCycle; 134 uint64_t _curInstructionCycle; 135 uint64_t _runToCycle; 136 bool _needRewind; 137 138 vector<stringstream> _rewindCache; 139 vector<uint64_t> _rewindPrevInstructionCycleCache; 140 141 uint32_t _inputOverride[4]; 142 143 vector<DebugEventInfo> _prevDebugEvents; 144 vector<DebugEventInfo> _debugEvents; 145 146 private: 147 bool ProcessBreakpoints(BreakpointType type, OperationInfo &operationInfo, bool allowBreak = true, bool allowMark = true); 148 void ProcessAllBreakpoints(OperationInfo &operationInfo); 149 150 void AddCallstackFrame(uint16_t source, uint16_t target, StackFrameFlags flags); 151 void UpdateCallstack(uint8_t currentInstruction, uint32_t addr); 152 153 void ProcessStepConditions(uint16_t addr); 154 bool SleepUntilResume(BreakSource source, uint32_t breakpointId = 0, BreakpointType bpType = BreakpointType::Global, uint16_t bpAddress = 0, uint8_t bpValue = 0, MemoryOperationType bpMemOpType = MemoryOperationType::Read); 155 156 void AddDebugEvent(DebugEventType type, uint16_t address = -1, uint8_t value = 0, int16_t breakpointId = -1, int8_t ppuLatch = -1); 157 158 void UpdatePpuCyclesToProcess(); 159 void ResetStepState(); 160 161 public: 162 Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<APU> apu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper); 163 ~Debugger(); 164 165 void ReleaseDebugger(bool needPause); 166 167 void SetPpu(shared_ptr<PPU> ppu); 168 Console* GetConsole(); 169 170 void SetFlags(uint32_t flags); 171 bool CheckFlag(DebuggerFlags flag); 172 173 void SetBreakpoints(Breakpoint breakpoints[], uint32_t length); 174 175 shared_ptr<LabelManager> GetLabelManager(); 176 177 void GetFunctionEntryPoints(int32_t* entryPoints, int32_t maxCount); 178 int32_t GetFunctionEntryPointCount(); 179 180 void GetCallstack(StackFrameInfo* callstackArray, uint32_t &callstackSize); 181 182 void GetInstructionProgress(InstructionProgress &state); 183 void GetApuState(ApuState *state); 184 __forceinline void GetState(DebugState *state, bool includeMapperInfo = true); 185 void SetState(DebugState state); 186 187 void Suspend(); 188 void Resume(); 189 190 void Break(); 191 void ResumeFromBreak(); 192 193 void PpuStep(uint32_t count = 1); 194 void Step(uint32_t count = 1, BreakSource source = BreakSource::CpuStep); 195 void StepCycles(uint32_t cycleCount = 1); 196 void StepOver(); 197 void StepOut(); 198 void StepBack(); 199 void Run(); 200 201 void BreakImmediately(BreakSource source); 202 void BreakOnScanline(int16_t scanline); 203 204 bool LoadCdlFile(string cdlFilepath); 205 void SetCdlData(uint8_t* cdlData, uint32_t length); 206 void ResetCdl(); 207 void UpdateCdlCache(); 208 bool IsMarkedAsCode(uint16_t relativeAddress); 209 shared_ptr<CodeDataLogger> GetCodeDataLogger(); 210 211 void SetNextStatement(uint16_t addr); 212 213 void SetPpuViewerScanlineCycle(int32_t ppuViewerId, int32_t scanline, int32_t cycle); 214 void ClearPpuViewerSettings(int32_t ppuViewer); 215 216 bool IsExecutionStopped(); 217 218 bool IsPauseIconShown(); 219 void PreventResume(); 220 void AllowResume(); 221 222 void GenerateCodeOutput(); 223 const char* GetCode(uint32_t &length); 224 225 int32_t GetRelativeAddress(uint32_t addr, AddressType type); 226 int32_t GetRelativePpuAddress(uint32_t addr, PpuAddressType type); 227 int32_t GetAbsoluteAddress(uint32_t addr); 228 int32_t GetAbsoluteChrAddress(uint32_t addr); 229 230 void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info); 231 void GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info); 232 233 shared_ptr<Profiler> GetProfiler(); 234 shared_ptr<Assembler> GetAssembler(); 235 shared_ptr<TraceLogger> GetTraceLogger(); 236 shared_ptr<MemoryDumper> GetMemoryDumper(); 237 shared_ptr<MemoryAccessCounter> GetMemoryAccessCounter(); 238 shared_ptr<PerformanceTracker> GetPerformanceTracker(); 239 240 int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache); 241 242 bool IsPpuCycleToProcess(); 243 void ProcessPpuCycle(); 244 bool ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t &value); 245 void ProcessVramReadOperation(MemoryOperationType type, uint16_t addr, uint8_t &value); 246 void ProcessVramWriteOperation(uint16_t addr, uint8_t &value); 247 248 void SetLastFramePpuScroll(uint16_t addr, uint8_t xScroll, bool updateHorizontalScrollOnly); 249 uint32_t GetPpuScroll(); 250 251 void ProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool forNmi); 252 253 void AddTrace(const char *log); 254 255 void SetFreezeState(uint16_t address, bool frozen); 256 void GetFreezeState(uint16_t startAddress, uint16_t length, bool* freezeState); 257 258 void StartCodeRunner(uint8_t *byteCode, uint32_t codeLength); 259 void StopCodeRunner(); 260 261 void GetNesHeader(uint8_t* header); 262 void SaveRomToDisk(string filename, bool saveAsIps, uint8_t* header, CdlStripFlag cdlStripflag); 263 void RevertPrgChrChanges(); 264 bool HasPrgChrChanges(); 265 266 int32_t FindSubEntryPoint(uint16_t relativeAddress); 267 268 void SetInputOverride(uint8_t port, uint32_t state); 269 270 int32_t LoadScript(string name, string content, int32_t scriptId); 271 void RemoveScript(int32_t scriptId); 272 const char* GetScriptLog(int32_t scriptId); 273 274 void ResetCounters(); 275 276 void UpdateProgramCounter(uint16_t &addr, uint8_t &value); 277 278 void ProcessScriptSaveState(uint16_t &addr, uint8_t &value); 279 void ProcessCpuOperation(uint16_t &addr, uint8_t &value, MemoryOperationType type); 280 void ProcessPpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type); 281 void ProcessEvent(EventType type); 282 283 void GetDebugEvents(uint32_t* pictureBuffer, DebugEventInfo *infoArray, uint32_t &maxEventCount, bool returnPreviousFrameData); 284 uint32_t GetDebugEventCount(bool returnPreviousFrameData); 285 286 uint32_t GetScreenPixel(uint8_t x, uint8_t y); 287 };