diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index ae30e3b4..e1a1acbd 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -798,6 +798,11 @@ uint8_t* BaseMapper::GetPrgRom() return _prgRom; } +uint8_t* BaseMapper::GetSaveRam() +{ + return _saveRam; +} + uint8_t* BaseMapper::GetWorkRam() { return _workRam; diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index dde0673b..982caaf1 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -228,6 +228,7 @@ public: CartridgeState GetState(); uint8_t* GetPrgRom(); uint8_t* GetWorkRam(); + uint8_t* GetSaveRam(); uint8_t GetMemoryValue(DebugMemoryType memoryType, uint32_t address); void SetMemoryValue(DebugMemoryType memoryType, uint32_t address, uint8_t value); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 90c3ffc8..dfd28d13 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -32,7 +32,7 @@ Debugger::Debugger(shared_ptr console, shared_ptr cpu, shared_ptr< _labelManager.reset(new LabelManager(_mapper)); _assembler.reset(new Assembler(_labelManager)); - _disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), mapper->GetPrgRom(), mapper->GetMemorySize(DebugMemoryType::PrgRom), mapper->GetWorkRam(), mapper->GetMemorySize(DebugMemoryType::WorkRam), this)); + _disassembler.reset(new Disassembler(memoryManager.get(), mapper.get(), this)); _codeDataLogger.reset(new CodeDataLogger(mapper->GetMemorySize(DebugMemoryType::PrgRom), mapper->GetMemorySize(DebugMemoryType::ChrRom))); _memoryDumper.reset(new MemoryDumper(_ppu, _memoryManager, _mapper, _codeDataLogger, this, _disassembler)); _memoryAccessCounter.reset(new MemoryAccessCounter(this)); @@ -135,7 +135,8 @@ bool Debugger::LoadCdlFile(string cdlFilepath) if(_codeDataLogger->LoadCdlFile(cdlFilepath)) { for(int i = 0, len = _mapper->GetMemorySize(DebugMemoryType::PrgRom); i < len; i++) { if(_codeDataLogger->IsCode(i)) { - i = _disassembler->BuildCache(i, -1, 0xFFFF, _codeDataLogger->IsSubEntryPoint(i)) - 1; + AddressTypeInfo info = { i, AddressType::PrgRom }; + i = _disassembler->BuildCache(info, 0, _codeDataLogger->IsSubEntryPoint(i)) - 1; } } @@ -376,7 +377,7 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad } } else if(addr < 0x2000 || absoluteRamAddr >= 0) { if(type == MemoryOperationType::Write) { - _disassembler->InvalidateCache(addr, absoluteRamAddr); + _disassembler->InvalidateCache(addressInfo); } } @@ -390,7 +391,7 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad } } - _disassembler->BuildCache(absoluteAddr, absoluteRamAddr, addr, isSubEntryPoint); + _disassembler->BuildCache(addressInfo, addr, isSubEntryPoint); ProcessStepConditions(addr); @@ -415,7 +416,7 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad if(_codeRunner && _codeRunner->IsRunning() && addr >= 0x3000 && addr < 0x4000) { disassemblyInfo = _codeRunner->GetDisassemblyInfo(addr); } else { - disassemblyInfo = _disassembler->GetDisassemblyInfo(absoluteAddr, absoluteRamAddr, addr); + disassemblyInfo = _disassembler->GetDisassemblyInfo(addressInfo); } _traceLogger->Log(_debugState.CPU, _debugState.PPU, disassemblyInfo); @@ -577,29 +578,26 @@ void Debugger::GenerateCodeOutput() bool showEffectiveAddresses = CheckFlag(DebuggerFlags::ShowEffectiveAddresses); bool showOnlyDiassembledCode = CheckFlag(DebuggerFlags::ShowOnlyDisassembledCode); - //Get code in internal RAM - _disassemblerOutput = _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager); - - for(uint32_t i = 0x2000; i < 0x10000; i += 0x100) { + for(uint32_t i = 0; i < 0x10000; i += 0x100) { //Merge all sequential ranges into 1 chunk - PrgMemoryType memoryType = PrgMemoryType::PrgRom; - int32_t addr = _mapper->ToAbsoluteAddress(i); - if(addr < 0) { - addr = _mapper->ToAbsoluteWorkRamAddress(i); - memoryType = PrgMemoryType::WorkRam; - } + AddressTypeInfo startInfo, currentInfo, endInfo; + GetAbsoluteAddressAndType(i, &startInfo); + currentInfo = startInfo; + GetAbsoluteAddressAndType(i+0x100, &endInfo); + uint32_t startMemoryAddr = i; int32_t startAddr, endAddr; - if(addr >= 0) { - startAddr = addr; + if(startInfo.Address >= 0) { + startAddr = startInfo.Address; endAddr = startAddr + 0xFF; - while(addr + 0x100 == (memoryType == PrgMemoryType::PrgRom ? _mapper->ToAbsoluteAddress(i + 0x100) : _mapper->ToAbsoluteWorkRamAddress(i + 0x100)) && i < 0x10000) { + while(currentInfo.Type == endInfo.Type && currentInfo.Address + 0x100 == endInfo.Address && i < 0x10000) { endAddr += 0x100; - addr += 0x100; + currentInfo = endInfo; i+=0x100; + GetAbsoluteAddressAndType(i + 0x100, &endInfo); } - _disassemblerOutput += _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, memoryType, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager); + _disassemblerOutput += _disassembler->GetCode(startInfo, endAddr, startMemoryAddr, showEffectiveAddresses, showOnlyDiassembledCode, cpuState, _memoryManager, _labelManager); } } } diff --git a/Core/Disassembler.cpp b/Core/Disassembler.cpp index 11160d68..f84535f2 100644 --- a/Core/Disassembler.cpp +++ b/Core/Disassembler.cpp @@ -10,18 +10,20 @@ #include "../Utilities/StringUtilities.h" #include "Debugger.h" -Disassembler::Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize, Debugger* debugger) +Disassembler::Disassembler(MemoryManager* memoryManager, BaseMapper* mapper, Debugger* debugger) { _debugger = debugger; - _internalRam = internalRam; - _prgRom = prgRom; - _prgRam = prgRam; - _prgSize = prgSize; - for(uint32_t i = 0; i < prgSize; i++) { + _memoryManager = memoryManager; + _mapper = mapper; + + for(uint32_t i = 0; i < mapper->GetMemorySize(DebugMemoryType::PrgRom); i++) { _disassembleCache.push_back(shared_ptr(nullptr)); } - for(uint32_t i = 0; i < prgRamSize; i++) { - _disassembleRamCache.push_back(shared_ptr(nullptr)); + for(uint32_t i = 0; i < mapper->GetMemorySize(DebugMemoryType::WorkRam); i++) { + _disassembleWorkRamCache.push_back(shared_ptr(nullptr)); + } + for(uint32_t i = 0; i < mapper->GetMemorySize(DebugMemoryType::SaveRam); i++) { + _disassembleSaveRamCache.push_back(shared_ptr(nullptr)); } for(uint32_t i = 0; i < 0x800; i++) { _disassembleMemoryCache.push_back(shared_ptr(nullptr)); @@ -149,12 +151,42 @@ bool Disassembler::IsUnconditionalJump(uint8_t opCode) return opCode == 0x40 || opCode == 0x60 || opCode == 0x6C || opCode == 0x4C || opCode == 0x20; } -uint32_t Disassembler::BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, uint16_t memoryAddr, bool isSubEntryPoint) +void Disassembler::GetInfo(AddressTypeInfo &info, uint8_t** source, uint32_t &size, vector> **cache) { - if(memoryAddr < 0x2000) { - memoryAddr = memoryAddr & 0x7FF; + switch(info.Type) { + case AddressType::InternalRam: + *source = _memoryManager->GetInternalRAM(); + *cache = &_disassembleMemoryCache; + size = 0x800; + break; + + case AddressType::PrgRom: + *source = _mapper->GetPrgRom(); + *cache = &_disassembleCache; + size = _mapper->GetMemorySize(DebugMemoryType::PrgRom); + break; + + case AddressType::WorkRam: + *source = _mapper->GetWorkRam(); + *cache = &_disassembleWorkRamCache; + size = _mapper->GetMemorySize(DebugMemoryType::WorkRam); + break; + + case AddressType::SaveRam: + *source = _mapper->GetSaveRam(); + *cache = &_disassembleSaveRamCache; + size = _mapper->GetMemorySize(DebugMemoryType::SaveRam); + break; + } +} + + +uint32_t Disassembler::BuildCache(AddressTypeInfo &info, uint16_t cpuAddress, bool isSubEntryPoint) +{ + if(info.Type == AddressType::InternalRam) { + uint16_t memoryAddr = info.Address & 0x7FF; if(!_disassembleMemoryCache[memoryAddr]) { - shared_ptr disInfo(new DisassemblyInfo(&_internalRam[memoryAddr], isSubEntryPoint)); + shared_ptr disInfo(new DisassemblyInfo(_memoryManager->GetInternalRAM()+memoryAddr, isSubEntryPoint)); _disassembleMemoryCache[memoryAddr] = disInfo; memoryAddr += disInfo->GetSize(); } else if(isSubEntryPoint) { @@ -162,21 +194,21 @@ uint32_t Disassembler::BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, } return memoryAddr; } else { - vector> &cache = absoluteRamAddr >= 0 ? _disassembleRamCache : _disassembleCache; - uint8_t *source = absoluteRamAddr >= 0 ? _prgRam : _prgRom; - if(absoluteRamAddr >= 0) { - absoluteAddr = absoluteRamAddr; - } + vector> *cache; + uint8_t *source; + uint32_t size; + GetInfo(info, &source, size, &cache); + int32_t absoluteAddr = info.Address; - if(absoluteAddr >= 0) { - shared_ptr disInfo = cache[absoluteAddr]; + if(info.Address >= 0) { + shared_ptr disInfo = (*cache)[info.Address]; if(!disInfo) { - while(absoluteAddr < (int32_t)_prgSize && !cache[absoluteAddr]) { + while(info.Address < (int32_t)size && !(*cache)[absoluteAddr]) { bool isJump = IsUnconditionalJump(source[absoluteAddr]); - disInfo = shared_ptr(new DisassemblyInfo(&source[absoluteAddr], isSubEntryPoint)); + disInfo = shared_ptr(new DisassemblyInfo(source+absoluteAddr, isSubEntryPoint)); isSubEntryPoint = false; - cache[absoluteAddr] = disInfo; + (*cache)[absoluteAddr] = disInfo; absoluteAddr += disInfo->GetSize(); if(isJump) { @@ -189,21 +221,15 @@ uint32_t Disassembler::BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, disInfo->SetSubEntryPoint(); } - uint8_t opCode = source[absoluteAddr]; + uint8_t opCode = source[info.Address]; if(IsJump(opCode)) { - uint16_t jumpDest = disInfo->GetOpAddr(memoryAddr); - AddressTypeInfo info; - _debugger->GetAbsoluteAddressAndType(jumpDest, &info); + uint16_t jumpDest = disInfo->GetOpAddr(cpuAddress); + AddressTypeInfo addressInfo; + _debugger->GetAbsoluteAddressAndType(jumpDest, &addressInfo); const uint8_t jsrCode = 0x20; - if(info.Address >= 0) { - if(info.Type == AddressType::PrgRom && !_disassembleCache[info.Address]) { - BuildCache(info.Address, -1, jumpDest, opCode == jsrCode); - } else if(info.Type == AddressType::WorkRam && !_disassembleRamCache[info.Address]) { - BuildCache(-1, info.Address, jumpDest, opCode == jsrCode); - } else if(info.Type == AddressType::InternalRam && !_disassembleMemoryCache[jumpDest]) { - BuildCache(-1, -1, jumpDest, opCode == jsrCode); - } + if(addressInfo.Address >= 0) { + BuildCache(addressInfo, jumpDest, opCode == jsrCode); } } @@ -214,16 +240,26 @@ uint32_t Disassembler::BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, } } -void Disassembler::InvalidateCache(uint16_t memoryAddr, int32_t absoluteRamAddr) +void Disassembler::InvalidateCache(AddressTypeInfo &info) { int32_t addr; vector> *cache; - if(memoryAddr < 0x2000) { - addr = memoryAddr & 0x7FF; - cache = &_disassembleMemoryCache; - } else { - addr = absoluteRamAddr; - cache = &_disassembleRamCache; + + switch(info.Type) { + case AddressType::InternalRam: + addr = info.Address & 0x7FF; + cache = &_disassembleMemoryCache; + break; + + case AddressType::WorkRam: + addr = info.Address; + cache = &_disassembleWorkRamCache; + break; + + case AddressType::SaveRam: + addr = info.Address; + cache = &_disassembleSaveRamCache; + break; } if(addr >= 0) { @@ -266,7 +302,8 @@ void Disassembler::RebuildPrgRomCache(uint32_t absoluteAddr, int32_t length) } uint16_t memoryAddr = _debugger->GetRelativeAddress(absoluteAddr, AddressType::PrgRom); - BuildCache(absoluteAddr, -1, memoryAddr, isSubEntryPoint); + AddressTypeInfo info = { (int32_t)absoluteAddr, AddressType::PrgRom }; + BuildCache(info, memoryAddr, isSubEntryPoint); } static const char* hexTable[256] = { @@ -395,7 +432,7 @@ void Disassembler::GetSubHeader(string &out, DisassemblyInfo *info, string &labe } } -string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr memoryManager, shared_ptr labelManager) +string Disassembler::GetCode(AddressTypeInfo &addressInfo, uint32_t endAddr, uint16_t memoryAddr, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr memoryManager, shared_ptr labelManager) { string output; output.reserve(10000000); @@ -410,21 +447,14 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo vector> *cache; uint8_t *source; - uint32_t mask = 0xFFFFFFFF; - if(memoryAddr < 0x2000) { - cache = &_disassembleMemoryCache; - source = _internalRam; - mask = 0x7FF; - } else if(memoryType == PrgMemoryType::WorkRam) { - cache = &_disassembleRamCache; - source = _prgRam; - } else { - cache = &_disassembleCache; - source = _prgRom; - } + uint32_t mask = addressInfo.Type == AddressType::InternalRam ? 0x7FF : 0xFFFFFFFF; + uint32_t size; + uint8_t* internalRam = _memoryManager->GetInternalRAM(); + + GetInfo(addressInfo, &source, size, &cache); string unknownBlockHeader = showOnlyDiassembledCode ? "----" : "__unknown block__"; - uint32_t addr = startAddr; + uint32_t addr = addressInfo.Address; uint32_t byteCount = 0; bool skippingCode = false; shared_ptr cdl = _debugger->GetCodeDataLogger(); @@ -453,11 +483,9 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo infoRef = (*cache)[addr&mask]; info = infoRef.get(); - if(!info && source == _prgRom) { - if(_debugger->CheckFlag(DebuggerFlags::DisassembleEverything) || _debugger->CheckFlag(DebuggerFlags::DisassembleEverythingButData) && !cdl->IsData(addr)) { - speculativeCode = true; - info = new DisassemblyInfo(source + addr, false); - } + if(!info && (_debugger->CheckFlag(DebuggerFlags::DisassembleEverything) || _debugger->CheckFlag(DebuggerFlags::DisassembleEverythingButData) && !cdl->IsData(addr))) { + speculativeCode = true; + info = new DisassemblyInfo(source + (addr & mask), false); } if(info && addr + info->GetSize() <= endAddr) { @@ -484,7 +512,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo info->ToString(code, memoryAddr, memoryManager.get(), labelManager.get()); info->GetByteCode(byteCode); - GetCodeLine(output, code, commentString, memoryAddr, source != _internalRam ? addr : -1, byteCode, effAddress, speculativeCode, true); + GetCodeLine(output, code, commentString, memoryAddr, source != internalRam ? addr : -1, byteCode, effAddress, speculativeCode, true); if(info->IsSubExitPoint()) { GetLine(output, "__sub end__"); @@ -574,14 +602,13 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memo return output; } -shared_ptr Disassembler::GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress) +shared_ptr Disassembler::GetDisassemblyInfo(AddressTypeInfo &info) { - if(memoryAddress < 0x2000) { - return _disassembleMemoryCache[memoryAddress & 0x7FF]; - } else if(absoluteAddress >= 0) { - return _disassembleCache[absoluteAddress]; - } else if(absoluteRamAddress >= 0) { - return _disassembleRamCache[absoluteRamAddress]; + switch(info.Type) { + case AddressType::InternalRam: return _disassembleMemoryCache[info.Address & 0x7FF]; + case AddressType::PrgRom: return _disassembleCache[info.Address]; + case AddressType::WorkRam: return _disassembleWorkRamCache[info.Address]; + case AddressType::SaveRam: return _disassembleSaveRamCache[info.Address]; } return nullptr; diff --git a/Core/Disassembler.h b/Core/Disassembler.h index eedcd951..fd07b090 100644 --- a/Core/Disassembler.h +++ b/Core/Disassembler.h @@ -1,45 +1,48 @@ #pragma once #include "stdafx.h" -#include "BaseMapper.h" +#include "DebuggerTypes.h" struct State; class MemoryManager; class DisassemblyInfo; class LabelManager; class Debugger; +class BaseMapper; class Disassembler { private: Debugger* _debugger; + MemoryManager* _memoryManager; + BaseMapper *_mapper; + vector> _disassembleCache; - vector> _disassembleRamCache; + vector> _disassembleWorkRamCache; + vector> _disassembleSaveRamCache; vector> _disassembleMemoryCache; - uint8_t* _internalRam; - uint8_t* _prgRom; - uint8_t* _prgRam; - uint32_t _prgSize; bool IsJump(uint8_t opCode); bool IsUnconditionalJump(uint8_t opCode); void GetLine(string &out, string code = "", string comment = string(), int32_t cpuAddress = -1, int32_t absoluteAddress = -1); void GetCodeLine(string &out, string &code, string &comment, int32_t cpuAddress, int32_t absoluteAddress, string &byteCode, string &addressing, bool speculativeCode, bool isCode); void GetSubHeader(string &out, DisassemblyInfo *info, string &label, uint16_t relativeAddr, uint16_t resetVector, uint16_t nmiVector, uint16_t irqVector); + + void GetInfo(AddressTypeInfo &info, uint8_t** source, uint32_t &size, vector> **cache); public: - Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize, Debugger* debugger); + Disassembler(MemoryManager* memoryManager, BaseMapper* mapper, Debugger* debugger); ~Disassembler(); void BuildOpCodeTables(bool useLowerCase); - uint32_t BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, uint16_t memoryAddr, bool isSubEntryPoint); - void InvalidateCache(uint16_t memoryAddr, int32_t absoluteRamAddr); + uint32_t BuildCache(AddressTypeInfo &info, uint16_t memoryAddr, bool isSubEntryPoint); + void InvalidateCache(AddressTypeInfo &info); bool IsUnofficialOpCode(uint8_t opCode); - string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr memoryManager, shared_ptr labelManager); + string GetCode(AddressTypeInfo &addressInfo, uint32_t endAddr, uint16_t memoryAddr, bool showEffectiveAddresses, bool showOnlyDiassembledCode, State& cpuState, shared_ptr memoryManager, shared_ptr labelManager); - shared_ptr GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress); + shared_ptr GetDisassemblyInfo(AddressTypeInfo &info); void RebuildPrgRomCache(uint32_t absoluteAddr, int32_t length); }; diff --git a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs index 0918442b..30b38633 100644 --- a/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs +++ b/GUI.NET/Debugger/Controls/ctrlDebuggerCode.Designer.cs @@ -104,7 +104,7 @@ this.mnuNavigateBackward, this.mnuNavigateForward}); this.contextMenuCode.Name = "contextMenuWatch"; - this.contextMenuCode.Size = new System.Drawing.Size(259, 342); + this.contextMenuCode.Size = new System.Drawing.Size(259, 364); this.contextMenuCode.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(this.contextMenuCode_Closed); this.contextMenuCode.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuCode_Opening); // @@ -283,7 +283,7 @@ // mnuGoToLocation // this.mnuGoToLocation.Name = "mnuGoToLocation"; - this.mnuGoToLocation.ShortcutKeyDisplayString = "Double+Click"; + this.mnuGoToLocation.ShortcutKeyDisplayString = "Double Click"; this.mnuGoToLocation.Size = new System.Drawing.Size(258, 22); this.mnuGoToLocation.Text = "Go to Location"; this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);