#pragma once #include "stdafx.h" #include using std::atomic; #include "CPU.h" #include "PPU.h" #include "Breakpoint.h" #include "../Utilities/SimpleLock.h" class MemoryManager; class Console; class Disassembler; struct DebugState { State CPU; PPUDebugState PPU; }; enum class DebugMemoryType { CpuMemory = 0, PpuMemory = 1, SpriteMemory = 2, SecondarySpriteMemory = 3, PrgRom = 4, ChrRom = 5, }; class Debugger { private: static Debugger* Instance; unique_ptr _disassembler; shared_ptr _console; shared_ptr _cpu; shared_ptr _ppu; shared_ptr _memoryManager; shared_ptr _mapper; vector> _readBreakpoints; vector> _writeBreakpoints; vector> _execBreakpoints; SimpleLock _bpLock; SimpleLock _breakLock; string _outputCache; atomic _stepCount; atomic _stepCycleCount; atomic _lastInstruction; atomic _stepOut; atomic _stepOverAddr; private: void PrivateCheckBreakpoint(BreakpointType type, uint32_t addr); shared_ptr GetMatchingBreakpoint(BreakpointType type, uint32_t addr); bool SleepUntilResume(); public: Debugger(shared_ptr console, shared_ptr cpu, shared_ptr ppu, shared_ptr memoryManager, shared_ptr mapper); ~Debugger(); void AddBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr, bool enabled); void RemoveBreakpoint(BreakpointType type, uint32_t address, bool isAbsoluteAddr); vector> GetBreakpoints(); vector GetExecBreakpointAddresses(); uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer); void GetState(DebugState *state); void Step(uint32_t count = 1); void StepCycles(uint32_t cycleCount = 1); void StepOver(); void StepOut(); void Run(); bool IsCodeChanged(); string GenerateOutput(); string* GetCode(); uint8_t GetMemoryValue(uint32_t addr); uint32_t GetRelativeAddress(uint32_t addr); static void CheckBreakpoint(BreakpointType type, uint32_t addr); };