2015-07-02 03:17:14 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <atomic>
|
2015-08-09 18:47:27 +00:00
|
|
|
#include <deque>
|
2016-11-20 18:15:37 +00:00
|
|
|
#include <unordered_set>
|
2015-07-02 03:17:14 +00:00
|
|
|
using std::atomic;
|
2015-08-09 18:47:27 +00:00
|
|
|
using std::deque;
|
2016-11-20 18:15:37 +00:00
|
|
|
using std::unordered_set;
|
2015-07-02 03:17:14 +00:00
|
|
|
|
|
|
|
#include "../Utilities/SimpleLock.h"
|
2016-11-23 03:38:14 +00:00
|
|
|
#include "DebuggerTypes.h"
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2016-06-18 00:53:05 +00:00
|
|
|
class CPU;
|
2017-08-30 22:31:27 +00:00
|
|
|
class APU;
|
2016-06-18 00:53:05 +00:00
|
|
|
class PPU;
|
2015-07-02 03:17:14 +00:00
|
|
|
class MemoryManager;
|
|
|
|
class Console;
|
2017-03-07 22:51:14 +00:00
|
|
|
class Assembler;
|
2015-07-02 03:17:14 +00:00
|
|
|
class Disassembler;
|
2016-11-23 03:38:14 +00:00
|
|
|
class LabelManager;
|
2016-12-02 00:38:48 +00:00
|
|
|
class MemoryDumper;
|
|
|
|
class MemoryAccessCounter;
|
2016-12-09 00:30:41 +00:00
|
|
|
class Profiler;
|
2017-03-12 02:03:45 +00:00
|
|
|
class CodeRunner;
|
2017-04-01 02:14:16 +00:00
|
|
|
class BaseMapper;
|
2017-08-30 22:31:27 +00:00
|
|
|
class ScriptHost;
|
2018-07-01 19:21:05 +00:00
|
|
|
class TraceLogger;
|
|
|
|
class Breakpoint;
|
|
|
|
class CodeDataLogger;
|
2018-08-03 00:44:48 +00:00
|
|
|
class ExpressionEvaluator;
|
|
|
|
struct ExpressionData;
|
2018-07-01 19:21:05 +00:00
|
|
|
|
2018-08-03 00:44:48 +00:00
|
|
|
enum EvalResultType : int32_t;
|
2018-07-01 19:21:05 +00:00
|
|
|
enum class CdlStripFlag;
|
2016-06-05 14:26:05 +00:00
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
class Debugger
|
|
|
|
{
|
|
|
|
private:
|
2018-07-01 19:21:05 +00:00
|
|
|
static constexpr int BreakpointTypeCount = 6;
|
2016-11-19 02:32:07 +00:00
|
|
|
|
2017-09-29 01:27:38 +00:00
|
|
|
//Must be static to be thread-safe when switching game
|
|
|
|
static string _disassemblerOutput;
|
|
|
|
|
2017-03-11 20:01:33 +00:00
|
|
|
shared_ptr<Disassembler> _disassembler;
|
2017-03-07 22:51:14 +00:00
|
|
|
shared_ptr<Assembler> _assembler;
|
2016-11-19 04:50:05 +00:00
|
|
|
shared_ptr<MemoryDumper> _memoryDumper;
|
|
|
|
shared_ptr<CodeDataLogger> _codeDataLogger;
|
2016-12-02 00:38:48 +00:00
|
|
|
shared_ptr<MemoryAccessCounter> _memoryAccessCounter;
|
2016-12-09 00:30:41 +00:00
|
|
|
shared_ptr<LabelManager> _labelManager;
|
|
|
|
shared_ptr<TraceLogger> _traceLogger;
|
|
|
|
shared_ptr<Profiler> _profiler;
|
2017-03-12 02:03:45 +00:00
|
|
|
unique_ptr<CodeRunner> _codeRunner;
|
2016-11-19 04:50:05 +00:00
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
shared_ptr<Console> _console;
|
|
|
|
shared_ptr<CPU> _cpu;
|
|
|
|
shared_ptr<PPU> _ppu;
|
2017-08-30 22:31:27 +00:00
|
|
|
shared_ptr<APU> _apu;
|
2015-07-02 03:17:14 +00:00
|
|
|
shared_ptr<MemoryManager> _memoryManager;
|
|
|
|
shared_ptr<BaseMapper> _mapper;
|
2017-08-30 22:31:27 +00:00
|
|
|
|
|
|
|
bool _hasScript;
|
2017-11-11 00:04:22 +00:00
|
|
|
SimpleLock _scriptLock;
|
2017-08-30 22:31:27 +00:00
|
|
|
int _nextScriptId;
|
|
|
|
vector<shared_ptr<ScriptHost>> _scripts;
|
2016-01-09 18:15:43 +00:00
|
|
|
|
2017-10-07 17:01:42 +00:00
|
|
|
atomic<int32_t> _preventResume;
|
2016-06-04 12:55:52 +00:00
|
|
|
atomic<bool> _stopFlag;
|
2016-01-26 21:47:21 +00:00
|
|
|
atomic<bool> _executionStopped;
|
2016-06-04 12:55:52 +00:00
|
|
|
atomic<int32_t> _suspendCount;
|
2016-11-19 02:32:07 +00:00
|
|
|
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
|
2018-08-03 00:44:48 +00:00
|
|
|
vector<ExpressionData> _breakpointRpnList[BreakpointTypeCount];
|
2016-12-14 04:28:28 +00:00
|
|
|
bool _hasBreakpoint[BreakpointTypeCount] = {};
|
2016-01-09 18:15:43 +00:00
|
|
|
|
2017-03-03 01:33:25 +00:00
|
|
|
vector<uint8_t> _frozenAddresses;
|
|
|
|
|
2018-03-06 02:18:29 +00:00
|
|
|
deque<StackFrameInfo> _callstack;
|
2018-02-25 17:47:39 +00:00
|
|
|
deque<int32_t> _subReturnAddresses;
|
|
|
|
|
|
|
|
int32_t _stepOutReturnAddress;
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2016-11-20 18:15:37 +00:00
|
|
|
unordered_set<uint32_t> _functionEntryPoints;
|
|
|
|
|
2018-08-03 00:44:48 +00:00
|
|
|
unique_ptr<ExpressionEvaluator> _watchExpEval;
|
|
|
|
unique_ptr<ExpressionEvaluator> _bpExpEval;
|
2016-01-26 21:47:21 +00:00
|
|
|
DebugState _debugState;
|
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
SimpleLock _breakLock;
|
|
|
|
|
2016-10-23 14:16:08 +00:00
|
|
|
//Used to alter the executing address via "Set Next Statement"
|
|
|
|
uint16_t *_currentReadAddr;
|
|
|
|
uint8_t *_currentReadValue;
|
2017-03-12 02:03:45 +00:00
|
|
|
int32_t _nextReadAddr;
|
|
|
|
uint16_t _returnToAddress;
|
2015-08-18 01:59:22 +00:00
|
|
|
|
2016-06-05 14:26:05 +00:00
|
|
|
uint32_t _flags;
|
|
|
|
|
2016-06-18 00:53:05 +00:00
|
|
|
string _romName;
|
2015-08-10 00:45:45 +00:00
|
|
|
atomic<int32_t> _stepCount;
|
2016-06-04 19:38:48 +00:00
|
|
|
atomic<int32_t> _ppuStepCount;
|
2015-07-02 03:17:14 +00:00
|
|
|
atomic<int32_t> _stepCycleCount;
|
|
|
|
atomic<uint8_t> _lastInstruction;
|
|
|
|
atomic<bool> _stepOut;
|
|
|
|
atomic<int32_t> _stepOverAddr;
|
2018-03-10 19:31:05 +00:00
|
|
|
|
2018-06-07 23:32:34 +00:00
|
|
|
bool _enableBreakOnUninitRead;
|
|
|
|
|
2018-01-02 04:13:24 +00:00
|
|
|
atomic<bool> _breakRequested;
|
2018-03-10 19:31:05 +00:00
|
|
|
bool _pausedForDebugHelper;
|
|
|
|
|
2018-02-24 16:07:27 +00:00
|
|
|
atomic<int32_t> _breakOnScanline;
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2018-04-10 21:05:54 +00:00
|
|
|
bool _proccessPpuCycle[341];
|
|
|
|
std::unordered_map<int, int> _ppuViewerUpdateCycle;
|
2016-11-27 01:44:23 +00:00
|
|
|
|
2016-12-02 23:10:37 +00:00
|
|
|
uint16_t _ppuScrollX;
|
|
|
|
uint16_t _ppuScrollY;
|
|
|
|
|
2017-08-02 02:49:50 +00:00
|
|
|
int32_t _prevInstructionCycle;
|
|
|
|
int32_t _curInstructionCycle;
|
|
|
|
int32_t _runToCycle;
|
|
|
|
bool _needRewind;
|
2018-01-01 15:33:06 +00:00
|
|
|
|
2017-08-02 02:49:50 +00:00
|
|
|
vector<stringstream> _rewindCache;
|
2018-01-01 15:33:06 +00:00
|
|
|
vector<uint32_t> _rewindPrevInstructionCycleCache;
|
2017-08-02 02:49:50 +00:00
|
|
|
|
2017-08-06 03:26:21 +00:00
|
|
|
uint32_t _inputOverride[4];
|
|
|
|
|
2018-07-27 01:29:56 +00:00
|
|
|
vector<DebugEventInfo> _prevDebugEvents;
|
2018-02-19 03:41:50 +00:00
|
|
|
vector<DebugEventInfo> _debugEvents;
|
|
|
|
vector<vector<int>> _debugEventMarkerRpn;
|
2018-02-16 22:36:37 +00:00
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
private:
|
2018-02-22 22:02:17 +00:00
|
|
|
void ProcessBreakpoints(BreakpointType type, OperationInfo &operationInfo, bool allowBreak = true);
|
2016-11-22 05:14:49 +00:00
|
|
|
|
2018-03-06 02:18:29 +00:00
|
|
|
void AddCallstackFrame(uint16_t source, uint16_t target, StackFrameFlags flags);
|
2018-02-25 15:38:45 +00:00
|
|
|
void UpdateCallstack(uint8_t currentInstruction, uint32_t addr);
|
2016-11-22 05:14:49 +00:00
|
|
|
|
2018-03-24 15:22:43 +00:00
|
|
|
void ProcessStepConditions(uint16_t addr);
|
2018-02-24 16:07:27 +00:00
|
|
|
bool SleepUntilResume(BreakSource source = BreakSource::Break);
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2018-02-20 04:23:26 +00:00
|
|
|
void AddDebugEvent(DebugEventType type, uint16_t address = -1, uint8_t value = 0, int16_t breakpointId = -1, int8_t ppuLatch = -1);
|
|
|
|
|
2018-04-10 21:05:54 +00:00
|
|
|
void UpdatePpuCyclesToProcess();
|
|
|
|
|
2015-07-02 03:17:14 +00:00
|
|
|
public:
|
2017-08-30 22:31:27 +00:00
|
|
|
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);
|
2015-07-02 03:17:14 +00:00
|
|
|
~Debugger();
|
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
Console* GetConsole();
|
|
|
|
|
2016-06-05 14:26:05 +00:00
|
|
|
void SetFlags(uint32_t flags);
|
|
|
|
bool CheckFlag(DebuggerFlags flag);
|
|
|
|
|
2016-01-09 18:15:43 +00:00
|
|
|
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
|
2016-11-23 03:38:14 +00:00
|
|
|
|
|
|
|
shared_ptr<LabelManager> GetLabelManager();
|
2016-11-22 23:28:59 +00:00
|
|
|
|
2017-03-10 04:50:20 +00:00
|
|
|
void GetFunctionEntryPoints(int32_t* entryPoints, int32_t maxCount);
|
|
|
|
int32_t GetFunctionEntryPointCount();
|
|
|
|
|
2018-03-06 02:18:29 +00:00
|
|
|
void GetCallstack(StackFrameInfo* callstackArray, uint32_t &callstackSize);
|
2016-11-26 22:48:11 +00:00
|
|
|
|
2018-01-02 04:23:18 +00:00
|
|
|
void GetApuState(ApuState *state);
|
2018-02-19 03:41:50 +00:00
|
|
|
__forceinline void GetState(DebugState *state, bool includeMapperInfo = true);
|
2016-11-26 22:48:11 +00:00
|
|
|
void SetState(DebugState state);
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2016-06-04 12:55:52 +00:00
|
|
|
void Suspend();
|
|
|
|
void Resume();
|
|
|
|
|
2018-01-02 04:13:24 +00:00
|
|
|
void Break();
|
|
|
|
void ResumeFromBreak();
|
|
|
|
|
2016-06-04 19:38:48 +00:00
|
|
|
void PpuStep(uint32_t count = 1);
|
2017-10-07 17:01:42 +00:00
|
|
|
void Step(uint32_t count = 1);
|
2015-07-02 03:17:14 +00:00
|
|
|
void StepCycles(uint32_t cycleCount = 1);
|
|
|
|
void StepOver();
|
|
|
|
void StepOut();
|
2017-08-02 02:49:50 +00:00
|
|
|
void StepBack();
|
2015-07-02 03:17:14 +00:00
|
|
|
void Run();
|
2018-07-01 19:21:05 +00:00
|
|
|
|
|
|
|
void BreakImmediately();
|
2018-02-24 16:07:27 +00:00
|
|
|
void BreakOnScanline(int16_t scanline);
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2015-08-17 23:32:10 +00:00
|
|
|
bool LoadCdlFile(string cdlFilepath);
|
2018-02-23 13:28:29 +00:00
|
|
|
void SetCdlData(uint8_t* cdlData, uint32_t length);
|
2017-08-20 02:00:12 +00:00
|
|
|
void ResetCdl();
|
|
|
|
void UpdateCdlCache();
|
2016-11-28 00:43:17 +00:00
|
|
|
bool IsMarkedAsCode(uint16_t relativeAddress);
|
2016-12-06 04:35:07 +00:00
|
|
|
shared_ptr<CodeDataLogger> GetCodeDataLogger();
|
2015-08-17 23:32:10 +00:00
|
|
|
|
2015-08-18 01:59:22 +00:00
|
|
|
void SetNextStatement(uint16_t addr);
|
2018-04-10 21:05:54 +00:00
|
|
|
|
|
|
|
void SetPpuViewerScanlineCycle(int32_t ppuViewerId, int32_t scanline, int32_t cycle);
|
|
|
|
void ClearPpuViewerSettings(int32_t ppuViewer);
|
2015-08-18 01:59:22 +00:00
|
|
|
|
2016-11-26 22:48:11 +00:00
|
|
|
bool IsExecutionStopped();
|
|
|
|
|
2018-03-10 19:31:05 +00:00
|
|
|
bool IsPauseIconShown();
|
2017-10-07 17:01:42 +00:00
|
|
|
void PreventResume();
|
|
|
|
void AllowResume();
|
|
|
|
|
2017-03-07 22:51:14 +00:00
|
|
|
void GenerateCodeOutput();
|
2017-03-10 04:50:20 +00:00
|
|
|
const char* GetCode(uint32_t &length);
|
2016-01-10 18:23:19 +00:00
|
|
|
|
2016-11-23 03:38:14 +00:00
|
|
|
int32_t GetRelativeAddress(uint32_t addr, AddressType type);
|
|
|
|
int32_t GetAbsoluteAddress(uint32_t addr);
|
2017-08-14 00:45:36 +00:00
|
|
|
int32_t GetAbsoluteChrAddress(uint32_t addr);
|
2017-12-31 22:22:54 +00:00
|
|
|
int32_t GetRelativeChrAddress(uint32_t addr);
|
2018-02-11 02:23:22 +00:00
|
|
|
|
2016-11-23 03:38:14 +00:00
|
|
|
void GetAbsoluteAddressAndType(uint32_t relativeAddr, AddressTypeInfo* info);
|
2018-02-11 02:23:22 +00:00
|
|
|
void GetPpuAbsoluteAddressAndType(uint32_t relativeAddr, PpuAddressTypeInfo* info);
|
2016-01-10 18:23:19 +00:00
|
|
|
|
2016-12-09 00:30:41 +00:00
|
|
|
shared_ptr<Profiler> GetProfiler();
|
2017-03-07 22:51:14 +00:00
|
|
|
shared_ptr<Assembler> GetAssembler();
|
2017-03-04 20:18:00 +00:00
|
|
|
shared_ptr<TraceLogger> GetTraceLogger();
|
2016-11-19 04:50:05 +00:00
|
|
|
shared_ptr<MemoryDumper> GetMemoryDumper();
|
2016-12-02 00:38:48 +00:00
|
|
|
shared_ptr<MemoryAccessCounter> GetMemoryAccessCounter();
|
2016-11-19 04:50:05 +00:00
|
|
|
|
2018-08-03 00:44:48 +00:00
|
|
|
int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache);
|
2015-07-02 03:17:14 +00:00
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
void ProcessPpuCycle();
|
|
|
|
bool ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t &value);
|
|
|
|
void ProcessVramReadOperation(MemoryOperationType type, uint16_t addr, uint8_t &value);
|
|
|
|
void ProcessVramWriteOperation(uint16_t addr, uint8_t &value);
|
2017-08-30 22:31:27 +00:00
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
void SetLastFramePpuScroll(uint16_t addr, uint8_t xScroll, bool updateHorizontalScrollOnly);
|
2016-12-02 23:10:37 +00:00
|
|
|
uint32_t GetPpuScroll();
|
|
|
|
|
2018-07-01 19:21:05 +00:00
|
|
|
void ProcessInterrupt(uint16_t cpuAddr, uint16_t destCpuAddr, bool forNmi);
|
|
|
|
|
|
|
|
void AddTrace(const char *log);
|
2018-06-21 00:17:33 +00:00
|
|
|
|
2017-03-03 01:33:25 +00:00
|
|
|
void SetFreezeState(uint16_t address, bool frozen);
|
|
|
|
void GetFreezeState(uint16_t startAddress, uint16_t length, bool* freezeState);
|
2017-03-05 03:24:41 +00:00
|
|
|
|
2017-03-12 02:03:45 +00:00
|
|
|
void StartCodeRunner(uint8_t *byteCode, uint32_t codeLength);
|
|
|
|
void StopCodeRunner();
|
|
|
|
|
2017-08-12 20:52:45 +00:00
|
|
|
void GetNesHeader(uint8_t* header);
|
2018-01-01 17:09:33 +00:00
|
|
|
void SaveRomToDisk(string filename, bool saveAsIps, uint8_t* header, CdlStripFlag cdlStripflag);
|
2017-08-22 03:11:14 +00:00
|
|
|
void RevertPrgChrChanges();
|
|
|
|
bool HasPrgChrChanges();
|
2017-03-10 01:42:53 +00:00
|
|
|
|
|
|
|
int32_t FindSubEntryPoint(uint16_t relativeAddress);
|
2017-08-06 03:26:21 +00:00
|
|
|
|
|
|
|
void SetInputOverride(uint8_t port, uint32_t state);
|
2017-08-30 22:31:27 +00:00
|
|
|
|
2017-10-07 19:16:14 +00:00
|
|
|
int32_t LoadScript(string name, string content, int32_t scriptId);
|
2017-08-30 22:31:27 +00:00
|
|
|
void RemoveScript(int32_t scriptId);
|
|
|
|
const char* GetScriptLog(int32_t scriptId);
|
2017-10-05 23:44:37 +00:00
|
|
|
|
2017-10-06 00:48:18 +00:00
|
|
|
void ResetCounters();
|
|
|
|
|
2017-10-07 23:48:45 +00:00
|
|
|
void UpdateProgramCounter(uint16_t &addr, uint8_t &value);
|
|
|
|
|
2017-10-05 23:44:37 +00:00
|
|
|
void ProcessScriptSaveState(uint16_t &addr, uint8_t &value);
|
2017-10-07 23:48:45 +00:00
|
|
|
void ProcessCpuOperation(uint16_t &addr, uint8_t &value, MemoryOperationType type);
|
2017-09-08 21:20:40 +00:00
|
|
|
void ProcessPpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type);
|
2017-08-30 22:31:27 +00:00
|
|
|
void ProcessEvent(EventType type);
|
2018-02-16 22:36:37 +00:00
|
|
|
|
2018-07-27 01:29:56 +00:00
|
|
|
void GetDebugEvents(uint32_t* pictureBuffer, DebugEventInfo *infoArray, uint32_t &maxEventCount, bool returnPreviousFrameData);
|
|
|
|
uint32_t GetDebugEventCount(bool returnPreviousFrameData);
|
2018-07-01 19:21:05 +00:00
|
|
|
|
|
|
|
uint32_t GetScreenPixel(uint8_t x, uint8_t y);
|
2015-07-02 03:17:14 +00:00
|
|
|
};
|