#pragma once #include "stdafx.h" #include #include #include using std::atomic; using std::deque; using std::unordered_set; #include "Breakpoint.h" #include "TraceLogger.h" #include "../Utilities/SimpleLock.h" #include "CodeDataLogger.h" #include "DebuggerTypes.h" class CPU; class PPU; class MemoryManager; class Console; class Assembler; class Disassembler; class LabelManager; class MemoryDumper; class MemoryAccessCounter; class Profiler; class CodeRunner; class BaseMapper; class Debugger { private: static Debugger* Instance; const static int BreakpointTypeCount = 6; shared_ptr _disassembler; shared_ptr _assembler; shared_ptr _memoryDumper; shared_ptr _codeDataLogger; shared_ptr _memoryAccessCounter; shared_ptr _labelManager; shared_ptr _traceLogger; shared_ptr _profiler; unique_ptr _codeRunner; shared_ptr _console; shared_ptr _cpu; shared_ptr _ppu; shared_ptr _memoryManager; shared_ptr _mapper; bool _bpUpdateNeeded; SimpleLock _bpUpdateLock; atomic _stopFlag; atomic _executionStopped; atomic _suspendCount; vector _newBreakpoints; vector _breakpoints[BreakpointTypeCount]; vector*> _breakpointRpnList[BreakpointTypeCount]; bool _hasBreakpoint[BreakpointTypeCount] = {}; vector _frozenAddresses; bool _hideTopOfCallstack; deque _callstackAbsolute; deque _callstackRelative; unordered_set _functionEntryPoints; ExpressionEvaluator _watchExpEval = ExpressionEvaluator(this); ExpressionEvaluator _bpExpEval = ExpressionEvaluator(this); DebugState _debugState; SimpleLock _breakLock; //Used to alter the executing address via "Set Next Statement" uint16_t *_currentReadAddr; uint8_t *_currentReadValue; int32_t _nextReadAddr; uint16_t _returnToAddress; uint32_t _flags; string _romName; string _disassemblerOutput; atomic _stepCount; atomic _ppuStepCount; atomic _stepCycleCount; atomic _lastInstruction; atomic _stepOut; atomic _stepOverAddr; atomic _sendNotification; int32_t _ppuViewerScanline; int32_t _ppuViewerCycle; uint16_t _ppuScrollX; uint16_t _ppuScrollY; private: void UpdateBreakpoints(); 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); void UpdateCallstack(uint32_t addr); void PrivateProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool forNmi); void ProcessStepConditions(uint32_t addr); bool SleepUntilResume(); public: Debugger(shared_ptr console, shared_ptr cpu, shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper); ~Debugger(); void SetFlags(uint32_t flags); bool CheckFlag(DebuggerFlags flag); void SetBreakpoints(Breakpoint breakpoints[], uint32_t length); shared_ptr GetLabelManager(); void GetFunctionEntryPoints(int32_t* entryPoints, int32_t maxCount); int32_t GetFunctionEntryPointCount(); void GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelative); void GetState(DebugState *state, bool includeMapperInfo = true); void SetState(DebugState state); void Suspend(); void Resume(); void PpuStep(uint32_t count = 1); void Step(uint32_t count = 1, bool sendNotification = true); void StepCycles(uint32_t cycleCount = 1); void StepOver(); void StepOut(); void Run(); bool LoadCdlFile(string cdlFilepath); bool IsMarkedAsCode(uint16_t relativeAddress); shared_ptr GetCodeDataLogger(); void SetNextStatement(uint16_t addr); void SetPpuViewerScanlineCycle(int32_t scanline, int32_t cycle); bool IsExecutionStopped(); void GenerateCodeOutput(); const char* GetCode(uint32_t &length); int32_t GetRelativeAddress(uint32_t addr, AddressType type); int32_t GetAbsoluteAddress(uint32_t addr); void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info); void StartTraceLogger(TraceLoggerOptions options); void StopTraceLogger(); shared_ptr GetProfiler(); shared_ptr GetAssembler(); shared_ptr GetTraceLogger(); shared_ptr GetMemoryDumper(); shared_ptr GetMemoryAccessCounter(); int32_t EvaluateExpression(string expression, EvalResultType &resultType); static bool ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t &value); static void ProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value); static void ProcessPpuCycle(); static void SetLastFramePpuScroll(uint16_t x, uint16_t y); uint32_t GetPpuScroll(); static void ProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool forNmi); static bool IsEnabled(); static void BreakIfDebugging(); void SetFreezeState(uint16_t address, bool frozen); void GetFreezeState(uint16_t startAddress, uint16_t length, bool* freezeState); void StartCodeRunner(uint8_t *byteCode, uint32_t codeLength); void StopCodeRunner(); void SaveRomToDisk(string filename); int32_t FindSubEntryPoint(uint16_t relativeAddress); };