#include "stdafx.h" #include "Debugger.h" #include "Console.h" #include "Cpu.h" #include "Ppu.h" #include "BaseCartridge.h" #include "MemoryManager.h" #include "NotificationManager.h" #include "CpuTypes.h" #include "DisassemblyInfo.h" #include "TraceLogger.h" #include "MemoryDumper.h" #include "CodeDataLogger.h" #include "Disassembler.h" #include "../Utilities/HexUtilities.h" #include "../Utilities/FolderUtilities.h" Debugger::Debugger(shared_ptr console) { _console = console; _cpu = console->GetCpu(); _ppu = console->GetPpu(); _memoryManager = console->GetMemoryManager(); _codeDataLogger.reset(new CodeDataLogger(console->GetCartridge()->DebugGetPrgRomSize())); _disassembler.reset(new Disassembler(console, _codeDataLogger)); _traceLogger.reset(new TraceLogger(this, _memoryManager)); _memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, console->GetCartridge())); _cpuStepCount = 0; string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_console->GetCartridge()->GetRomInfo().RomPath, false) + ".cdl"); _codeDataLogger->LoadCdlFile(cdlFile); //TODO: Thread safety uint32_t prgRomSize = console->GetCartridge()->DebugGetPrgRomSize(); AddressInfo addrInfo; addrInfo.Type = SnesMemoryType::PrgRom; for(uint32_t i = 0; i < prgRomSize; i++) { if(_codeDataLogger->IsCode(i)) { addrInfo.Address = (int32_t)i; i += _disassembler->BuildCache(addrInfo, _codeDataLogger->GetCpuFlags(i)) - 1; } } } Debugger::~Debugger() { string cdlFile = FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_console->GetCartridge()->GetRomInfo().RomPath, false) + ".cdl"); _codeDataLogger->SaveCdlFile(cdlFile); } void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType type) { AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(addr); CpuState state = _cpu->GetState(); if(type == MemoryOperationType::ExecOpCode) { if(addressInfo.Address >= 0) { if(addressInfo.Type == SnesMemoryType::PrgRom) { uint8_t flags = CdlFlags::Code | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8)); if(_prevOpCode == 0x20 || _prevOpCode == 0x5C || _prevOpCode == 0xDC || _prevOpCode == 0xFC) { flags |= CdlFlags::SubEntryPoint; } _codeDataLogger->SetFlags(addressInfo.Address, flags); } _disassembler->BuildCache(addressInfo, state.PS); } DebugState debugState; GetState(&debugState); _traceLogger->LogEffectiveAddress(_cpu->GetLastOperand()); DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo); _traceLogger->Log(debugState, disInfo); _prevOpCode = value; if(value == 0x00 || value == 0xCB) { //break on BRK/WAI _cpuStepCount = 1; } if(_cpuStepCount > 0) { _cpuStepCount--; if(_cpuStepCount == 0) { _disassembler->Disassemble(); _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak); while(_cpuStepCount == 0) { std::this_thread::sleep_for(std::chrono::duration(10)); } } } } else if(type == MemoryOperationType::ExecOperand) { if(addressInfo.Type == SnesMemoryType::PrgRom && addressInfo.Address >= 0) { _codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8))); } } else { if(addressInfo.Type == SnesMemoryType::PrgRom && addressInfo.Address >= 0) { _codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Data | (state.PS & (CdlFlags::IndexMode8 | CdlFlags::MemoryMode8))); } } } void Debugger::ProcessCpuWrite(uint32_t addr, uint8_t value, MemoryOperationType type) { AddressInfo addressInfo = _memoryManager->GetAbsoluteAddress(addr); if(addressInfo.Address >= 0 && (addressInfo.Type == SnesMemoryType::WorkRam || addressInfo.Type == SnesMemoryType::SaveRam)) { _disassembler->InvalidateCache(addressInfo); } } void Debugger::Run() { _cpuStepCount = -1; } void Debugger::Step(int32_t stepCount) { _cpuStepCount = stepCount; } bool Debugger::IsExecutionStopped() { //TODO return false; } void Debugger::GetState(DebugState *state) { state->Cpu = _cpu->GetState(); state->Ppu = _ppu->GetState(); } shared_ptr Debugger::GetTraceLogger() { return _traceLogger; } shared_ptr Debugger::GetMemoryDumper() { return _memoryDumper; } shared_ptr Debugger::GetDisassembler() { return _disassembler; }