diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index c9048686..aa7ab4a6 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -549,15 +549,25 @@ void BaseMapper::NotifyVRAMAddressChange(uint16_t addr) } //Debugger Helper Functions +uint8_t* BaseMapper::GetPrgRom() +{ + return _prgRom; +} + +uint8_t* BaseMapper::GetWorkRam() +{ + return _workRam; +} + void BaseMapper::GetPrgCopy(uint8_t **buffer) { *buffer = new uint8_t[_prgSize]; memcpy(*buffer, _prgRom, _prgSize); } -uint32_t BaseMapper::GetPrgSize() +uint32_t BaseMapper::GetPrgSize(bool getWorkRamSize) { - return _prgSize; + return getWorkRamSize ? GetWorkRamSize() : _prgSize; } void BaseMapper::GetChrRomCopy(uint8_t **buffer) @@ -586,6 +596,15 @@ int32_t BaseMapper::ToAbsoluteAddress(uint16_t addr) return -1; } +int32_t BaseMapper::ToAbsoluteRamAddress(uint16_t addr) +{ + uint8_t *prgRamAddr = _prgPages[addr >> 8] + (addr & 0xFF); + if(prgRamAddr >= _workRam && prgRamAddr < _workRam + GetWorkRamSize()) { + return (uint32_t)(prgRamAddr - _workRam); + } + return -1; +} + int32_t BaseMapper::ToAbsoluteChrAddress(uint16_t addr) { uint8_t *chrAddr = _chrPages[addr >> 8] + (addr & 0xFF); @@ -608,18 +627,4 @@ int32_t BaseMapper::FromAbsoluteAddress(uint32_t addr) //Address is currently not mapped return -1; -} - -vector BaseMapper::GetPRGRanges() -{ - vector memoryRanges; - - for(uint32_t i = 0x8000; i <= 0xFFFF; i += 0x100) { - int32_t pageStart = ToAbsoluteAddress((uint16_t)i); - int32_t pageEnd = ToAbsoluteAddress((uint16_t)i + 0xFF); - memoryRanges.push_back(pageStart); - memoryRanges.push_back(pageEnd); - } - - return memoryRanges; } \ No newline at end of file diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index 940c3d5c..b04765d4 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -168,13 +168,15 @@ public: void WriteVRAM(uint16_t addr, uint8_t value); //Debugger Helper Functions + uint8_t* GetPrgRom(); + uint8_t* GetWorkRam(); void GetPrgCopy(uint8_t **buffer); - uint32_t GetPrgSize(); + uint32_t GetPrgSize(bool getWorkRamSize = false); void GetChrRomCopy(uint8_t **buffer); uint32_t GetChrSize(bool getRamSize = false); void GetChrRamCopy(uint8_t **buffer); int32_t ToAbsoluteAddress(uint16_t addr); + int32_t ToAbsoluteRamAddress(uint16_t addr); int32_t ToAbsoluteChrAddress(uint16_t addr); int32_t FromAbsoluteAddress(uint32_t addr); - vector GetPRGRanges(); }; \ No newline at end of file diff --git a/Core/CPU.cpp b/Core/CPU.cpp index 47d10bab..e323edb0 100644 --- a/Core/CPU.cpp +++ b/Core/CPU.cpp @@ -3,6 +3,7 @@ #include "PPU.h" #include "APU.h" #include "DeltaModulationChannel.h" +#include "TraceLogger.h" CPU* CPU::Instance = nullptr; @@ -106,6 +107,7 @@ void CPU::IncCycleCount() //Update the DMC buffer when the stall period is completed _dmcDmaRunning = false; DeltaModulationChannel::SetReadBuffer(); + TraceLogger::LogStatic("DMC DMA End"); } } @@ -126,6 +128,7 @@ void CPU::IncCycleCount() void CPU::RunDMATransfer(uint8_t* spriteRAM, uint8_t offsetValue) { + TraceLogger::LogStatic("Sprite DMA Start"); Instance->_spriteDmaTransfer = true; //"The CPU is suspended during the transfer, which will take 513 or 514 cycles after the $4014 write tick." @@ -149,12 +152,15 @@ void CPU::RunDMATransfer(uint8_t* spriteRAM, uint8_t offsetValue) } Instance->_spriteDmaTransfer = false; + + TraceLogger::LogStatic("Sprite DMA End"); } void CPU::StartDmcTransfer() { //"DMC DMA adds 4 cycles normally, 2 if it lands on the $4014 write or during OAM DMA" //3 cycles if it lands on the last write cycle of any instruction + TraceLogger::LogStatic("DMC DMA Start"); Instance->_dmcDmaRunning = true; if(Instance->_spriteDmaTransfer) { if(Instance->_spriteDmaCounter == 2) { diff --git a/Core/CPU.h b/Core/CPU.h index 624c5b44..684607bd 100644 --- a/Core/CPU.h +++ b/Core/CPU.h @@ -4,6 +4,7 @@ #include "MemoryManager.h" #include "PPU.h" #include "Snapshotable.h" +#include "TraceLogger.h" namespace PSFlags { @@ -643,11 +644,15 @@ private: SetFlags(PSFlags::Interrupt); SetPC(MemoryReadWord(CPU::NMIVector)); + + TraceLogger::LogStatic("NMI"); } else { Push((uint8_t)flags); SetFlags(PSFlags::Interrupt); SetPC(MemoryReadWord(CPU::IRQVector)); + + TraceLogger::LogStatic("IRQ"); } //Since we just set the flag to prevent interrupts, do not run one right away after this (fixes nmi_and_brk & nmi_and_irq tests) @@ -665,10 +670,14 @@ private: SetPC(MemoryReadWord(CPU::NMIVector)); _state.NMIFlag = false; + + TraceLogger::LogStatic("NMI"); } else { Push((uint8_t)PS()); SetFlags(PSFlags::Interrupt); SetPC(MemoryReadWord(CPU::IRQVector)); + + TraceLogger::LogStatic("IRQ"); } } diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 47c3676e..94397cf1 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -22,9 +22,7 @@ Debugger::Debugger(shared_ptr console, shared_ptr cpu, shared_ptr< _memoryManager = memoryManager; _mapper = mapper; - uint8_t *prgBuffer; - mapper->GetPrgCopy(&prgBuffer); - _disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), prgBuffer, mapper->GetPrgSize())); + _disassembler.reset(new Disassembler(memoryManager->GetInternalRAM(), mapper->GetPrgRom(), mapper->GetPrgSize(), mapper->GetWorkRam(), mapper->GetPrgSize(true))); _codeDataLogger.reset(new CodeDataLogger(mapper->GetPrgSize(), mapper->GetChrSize())); _stepOut = false; @@ -67,7 +65,7 @@ bool Debugger::LoadCdlFile(string cdlFilepath) if(_codeDataLogger->LoadCdlFile(cdlFilepath)) { for(int i = 0, len = _mapper->GetPrgSize(); i < len; i++) { if(_codeDataLogger->IsCode(i)) { - i = _disassembler->BuildCache(i, 0xFFFF) - 1; + i = _disassembler->BuildCache(i, -1, 0xFFFF, false) - 1; } } return true; @@ -241,27 +239,38 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad //Check if a breakpoint has been hit and freeze execution if one has bool breakDone = false; int32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr); + int32_t absoluteRamAddr = _mapper->ToAbsoluteRamAddress(addr); + if(absoluteAddr >= 0) { - if(type == MemoryOperationType::ExecOpCode) { - _codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code); - _disassembler->BuildCache(absoluteAddr, addr); - _lastInstruction = _memoryManager->DebugRead(addr); - - if(_traceLogger) { - DebugState state; - GetState(&state); - _traceLogger->Log(state, _disassembler->GetDisassemblyInfo(absoluteAddr)); - } - - UpdateCallstack(addr); - ProcessStepConditions(addr); - - breakDone = SleepUntilResume(); - } else if(type == MemoryOperationType::ExecOperand) { + if(type == MemoryOperationType::ExecOperand) { _codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code); } else { _codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Data); } + } else if(addr < 0x2000 || absoluteRamAddr >= 0) { + if(type == MemoryOperationType::Write) { + _disassembler->InvalidateCache(addr, absoluteRamAddr); + } + } + + if(type == MemoryOperationType::ExecOpCode) { + if(absoluteAddr >= 0) { + _codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code); + } + + bool isSubEntryPoint = _lastInstruction == 0x20; //Previous instruction was a JSR + _disassembler->BuildCache(absoluteAddr, absoluteRamAddr, addr, isSubEntryPoint); + _lastInstruction = _memoryManager->DebugRead(addr); + + UpdateCallstack(addr); + ProcessStepConditions(addr); + + if(_traceLogger) { + DebugState state; + GetState(&state); + _traceLogger->Log(state, _disassembler->GetDisassemblyInfo(absoluteAddr, absoluteRamAddr, addr)); + } + breakDone = SleepUntilResume(); } if(!breakDone && _hasBreakpoint) { @@ -393,26 +402,36 @@ bool Debugger::IsCodeChanged() string Debugger::GenerateOutput() { std::ostringstream output; - vector memoryRanges = _mapper->GetPRGRanges(); - //RAM code viewer doesn't work well yet - //output << _disassembler->GetRAMCode(); + //Get code in internal RAM + output << _disassembler->GetCode(0x0000, 0x1FFF, 0x0000, PrgMemoryType::PrgRom); + output << "2000:::--END OF INTERNAL RAM--\n"; - uint16_t memoryAddr = 0x8000; - for(size_t i = 0, size = memoryRanges.size(); i < size; i += 2) { - int32_t startRange = memoryRanges[i]; + for(uint32_t i = 0x4100; i < 0x10000; i += 0x100) { //Merge all sequential ranges into 1 chunk - if(startRange != -1) { - for(size_t j = i+1; j < size - 1; j+=2) { - if(memoryRanges[j] + 1 == memoryRanges[j + 1]) { - i+=2; - } else { - break; - } + int32_t romAddr = _mapper->ToAbsoluteAddress(i); + int32_t ramAddr = _mapper->ToAbsoluteRamAddress(i); + uint32_t startMemoryAddr = i; + int32_t startAddr, endAddr; + + if(romAddr >= 0) { + startAddr = romAddr; + endAddr = startAddr + 0xFF; + while(romAddr + 0x100 == _mapper->ToAbsoluteAddress(i + 0x100) && i < 0x10000) { + endAddr += 0x100; + romAddr += 0x100; + i+=0x100; } - output << _disassembler->GetCode(startRange, memoryRanges[i+1], memoryAddr); - } else { - memoryAddr += 0x100; + output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, PrgMemoryType::PrgRom); + } else if(ramAddr >= 0) { + startAddr = ramAddr; + endAddr = startAddr + 0xFF; + while(ramAddr + 0x100 == _mapper->ToAbsoluteRamAddress(i + 0x100) && i < 0x10000) { + endAddr += 0x100; + ramAddr += 0x100; + i += 0x100; + } + output << _disassembler->GetCode(startAddr, endAddr, startMemoryAddr, PrgMemoryType::WorkRam); } } diff --git a/Core/Disassembler.cpp b/Core/Disassembler.cpp index 25203a33..f7ed8256 100644 --- a/Core/Disassembler.cpp +++ b/Core/Disassembler.cpp @@ -1,38 +1,42 @@ #include "stdafx.h" #include "Disassembler.h" #include "DisassemblyInfo.h" +#include "BaseMapper.h" -Disassembler::Disassembler(uint8_t* internalRAM, uint8_t* prgROM, uint32_t prgSize) +Disassembler::Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize) { - _internalRAM = internalRAM; - _prgROM = prgROM; + _internalRam = internalRam; + _prgRom = prgRom; + _prgRam = prgRam; _prgSize = prgSize; for(uint32_t i = 0; i < prgSize; i++) { _disassembleCache.push_back(shared_ptr(nullptr)); } - for(uint32_t i = 0; i < 0x2000; i++) { + for(uint32_t i = 0; i < prgRamSize; i++) { + _disassembleRamCache.push_back(shared_ptr(nullptr)); + } + for(uint32_t i = 0; i < 0x800; i++) { _disassembleMemoryCache.push_back(shared_ptr(nullptr)); } - string opName[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - "BRK", "ORA", "", "", "NOP", "ORA", "ASL", "", "PHP", "ORA", "ASL", "", "NOP", "ORA", "ASL", "", //0 - "BPL", "ORA", "", "", "NOP", "ORA", "ASL", "", "CLC", "ORA", "", "", "NOP", "ORA", "ASL", "", //1 - "JSR", "AND", "", "", "BIT", "AND", "ROL", "", "PLP", "AND", "ROL", "", "BIT", "AND", "ROL", "", //2 - "BMI", "AND", "", "", "NOP", "AND", "ROL", "", "SEC", "AND", "", "", "NOP", "AND", "ROL", "", //3 - "RTI", "EOR", "", "", "NOP", "EOR", "LSR", "", "PHA", "EOR", "LSR", "", "JMP", "EOR", "LSR", "", //4 - "BVC", "EOR", "", "", "NOP", "EOR", "LSR", "", "CLI", "EOR", "", "", "NOP", "EOR", "LSR", "", //5 - "RTS", "ADC", "", "", "NOP", "ADC", "ROR", "", "PLA", "ADC", "ROR", "", "JMP", "ADC", "ROR", "", //6 - "BVS", "ADC", "", "", "NOP", "ADC", "ROR", "", "SEI", "ADC", "", "", "NOP", "ADC", "ROR", "", //7 - "NOP", "STA", "NOP", "", "STY", "STA", "STX", "", "DEY", "NOP", "TXA", "", "STY", "STA", "STX", "", //8 - "BCC", "STA", "", "", "STY", "STA", "STX", "", "TYA", "STA", "TXS", "", "", "STA", "", "", //9 - "LDY", "LDA", "LDX", "", "LDY", "LDA", "LDX", "", "TAY", "LDA", "TAX", "", "LDY", "LDA", "LDX", "", //A - "BCS", "LDA", "", "", "LDY", "LDA", "LDX", "", "CLV", "LDA", "TSX", "", "LDY", "LDA", "LDX", "", //B - "CPY", "CPA", "NOP", "", "CPY", "CPA", "DEC", "", "INY", "CPA", "DEX", "", "CPY", "CPA", "DEC", "", //C - "BNE", "CPA", "", "", "NOP", "CPA", "DEC", "", "CLD", "CPA", "", "", "NOP", "CPA", "DEC", "", //D - "CPX", "SBC", "NOP", "", "CPX", "SBC", "INC", "", "INX", "SBC", "NOP", "", "CPX", "SBC", "INC", "", //E - "BEQ", "SBC", "", "", "NOP", "SBC", "INC", "", "SED", "SBC", "", "", "NOP", "SBC", "INC", "" //F + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + "BRK", "ORA", "", "SLO*", "NOP", "ORA", "ASL", "SLO*", "PHP", "ORA", "ASL", "AAC*", "NOP", "ORA", "ASL", "SLO*", //0 + "BPL", "ORA", "", "SLO*", "NOP", "ORA", "ASL", "SLO*", "CLC", "ORA", "NOP*", "SLO*", "NOP", "ORA", "ASL", "SLO*", //1 + "JSR", "AND", "", "RLA*", "BIT", "AND", "ROL", "RLA*", "PLP", "AND", "ROL", "AAC*", "BIT", "AND", "ROL", "RLA*", //2 + "BMI", "AND", "", "RLA*", "NOP", "AND", "ROL", "RLA*", "SEC", "AND", "NOP*", "RLA*", "NOP", "AND", "ROL", "RLA*", //3 + "RTI", "EOR", "", "SRE*", "NOP", "EOR", "LSR", "SRE*", "PHA", "EOR", "LSR", "ASR*", "JMP", "EOR", "LSR", "SRE*", //4 + "BVC", "EOR", "", "SRE*", "NOP", "EOR", "LSR", "SRE*", "CLI", "EOR", "NOP*", "SRE*", "NOP", "EOR", "LSR", "SRE*", //5 + "RTS", "ADC", "", "RRA*", "NOP", "ADC", "ROR", "RRA*", "PLA", "ADC", "ROR", "ARR*", "JMP", "ADC", "ROR", "RRA*", //6 + "BVS", "ADC", "", "RRA*", "NOP", "ADC", "ROR", "RRA*", "SEI", "ADC", "NOP*", "RRA*", "NOP", "ADC", "ROR", "RRA*", //7 + "NOP", "STA", "NOP", "SAX*", "STY", "STA", "STX", "SAX*", "DEY", "NOP", "TXA", "", "STY", "STA", "STX", "SAX*", //8 + "BCC", "STA", "", "AXA*", "STY", "STA", "STX", "SAX*", "TYA", "STA", "TXS", "TAS*", "SYA*", "STA", "SXA", "AXA*", //9 + "LDY", "LDA", "LDX", "LAX*", "LDY", "LDA", "LDX", "LAX*", "TAY", "LDA", "TAX", "ATX*", "LDY", "LDA", "LDX", "LAX*", //A + "BCS", "LDA", "", "LAX*", "LDY", "LDA", "LDX", "LAX*", "CLV", "LDA", "TSX", "LAS*", "LDY", "LDA", "LDX", "LAX*", //B + "CPY", "CPA", "NOP", "DCP*", "CPY", "CPA", "DEC", "DCP*", "INY", "CPA", "DEX", "AXS*", "CPY", "CPA", "DEC", "DCP*", //C + "BNE", "CPA", "", "DCP*", "NOP", "CPA", "DEC", "DCP*", "CLD", "CPA", "NOP*", "DCP*", "NOP", "CPA", "DEC", "DCP*", //D + "CPX", "SBC", "NOP", "ISB*", "CPX", "SBC", "INC", "ISB*", "INX", "SBC", "NOP", "SBC*", "CPX", "SBC", "INC", "ISB*", //E + "BEQ", "SBC", "", "ISB*", "NOP", "SBC", "INC", "ISB*", "SED", "SBC", "NOP*", "ISB*", "NOP", "SBC", "INC", "ISB*" //F }; AddrMode opMode[256] = { @@ -87,28 +91,34 @@ Disassembler::Disassembler(uint8_t* internalRAM, uint8_t* prgROM, uint32_t prgSi Disassembler::~Disassembler() { - if(_prgROM) { - delete[] _prgROM; - } } -uint32_t Disassembler::BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr) +uint32_t Disassembler::BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, uint16_t memoryAddr, bool isSubEntryPoint) { if(memoryAddr < 0x2000) { memoryAddr = memoryAddr & 0x7FF; if(!_disassembleMemoryCache[memoryAddr]) { - shared_ptr disInfo(new DisassemblyInfo(&_internalRAM[memoryAddr])); + shared_ptr disInfo(new DisassemblyInfo(&_internalRam[memoryAddr], isSubEntryPoint)); _disassembleMemoryCache[memoryAddr] = disInfo; memoryAddr += disInfo->GetSize(); + } else if(isSubEntryPoint) { + _disassembleMemoryCache[memoryAddr]->SetSubEntryPoint(); } return memoryAddr; } else { - if(!_disassembleCache[absoluteAddr]) { - while(absoluteAddr < _prgSize && !_disassembleCache[absoluteAddr]) { - shared_ptr disInfo(new DisassemblyInfo(&_prgROM[absoluteAddr])); - _disassembleCache[absoluteAddr] = disInfo; + vector> &cache = absoluteRamAddr >= 0 ? _disassembleRamCache : _disassembleCache; + uint8_t *source = absoluteRamAddr >= 0 ? _prgRam : _prgRom; + if(absoluteRamAddr >= 0) { + absoluteAddr = absoluteRamAddr; + } - uint8_t opCode = _prgROM[absoluteAddr]; + if(!cache[absoluteAddr]) { + while(absoluteAddr < (int32_t)_prgSize && !cache[absoluteAddr]) { + shared_ptr disInfo(new DisassemblyInfo(&source[absoluteAddr], isSubEntryPoint)); + isSubEntryPoint = false; + cache[absoluteAddr] = disInfo; + + uint8_t opCode = source[absoluteAddr]; absoluteAddr += disInfo->GetSize(); if(opCode == 0x10 || opCode == 0x20 || opCode == 0x30 || opCode == 0x40 || opCode == 0x50 || opCode == 0x60 || opCode == 0x70 || opCode == 0x90 || opCode == 0xB0 || opCode == 0xD0 || opCode == 0xF0 || opCode == 0x4C || opCode == 0x6C) { //Hit a jump/return instruction, can't assume that what follows is actual code, stop disassembling @@ -116,56 +126,66 @@ uint32_t Disassembler::BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr) } } } else { - absoluteAddr += _disassembleCache[absoluteAddr]->GetSize(); + if(isSubEntryPoint) { + cache[absoluteAddr]->SetSubEntryPoint(); + } + absoluteAddr += cache[absoluteAddr]->GetSize(); } return absoluteAddr; } } -string Disassembler::GetRAMCode() +void Disassembler::InvalidateCache(uint16_t memoryAddr, int32_t absoluteRamAddr) { - std::ostringstream output; - - uint32_t addr = 0x0000; - uint32_t byteCount = 0; - while(addr < 0x2000) { - shared_ptr info; - if(info = _disassembleMemoryCache[addr&0x7FF]) { - if(byteCount > 0) { - output << "\n"; - byteCount = 0; - } - output << std::hex << std::uppercase << addr << ":" << info->ToString(addr) << "\n"; - addr += info->GetSize(); - } else { - if(byteCount >= 8) { - output << "\n"; - byteCount = 0; - } - if(byteCount == 0) { - output << std::hex << std::uppercase << addr << ":" << ".db"; - } - output << std::hex << " $" << std::setfill('0') << std::setw(2) << (short)_internalRAM[addr]; - - byteCount++; - addr++; - } + uint32_t addr; + vector> *cache; + if(memoryAddr < 0x2000) { + addr = memoryAddr & 0x7FF; + cache = &_disassembleMemoryCache; + } else { + addr = absoluteRamAddr; + cache = &_disassembleRamCache; + } + + if(addr >= 0) { + for(int i = 1; i <= 2; i++) { + int offsetAddr = (int)addr - i; + if(offsetAddr >= 0) { + if((*cache)[offsetAddr] != nullptr) { + if((*cache)[offsetAddr]->GetSize() >= (uint32_t)i + 1) { + //Invalidate any instruction that overlapped this address + (*cache)[offsetAddr] = nullptr; + } + } + } + } + (*cache)[addr] = nullptr; } - - output << "\n1FFF:--END OF INTERNAL RAM--\n"; - - return output.str(); } -string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &memoryAddr) +string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType) { std::ostringstream output; + 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 addr = startAddr; uint32_t byteCount = 0; while(addr <= endAddr) { shared_ptr info; - if(info = _disassembleCache[addr]) { + if(info = (*cache)[addr&mask]) { if(byteCount > 0) { output << "\n"; byteCount = 0; @@ -181,7 +201,7 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &mem if(byteCount == 0) { output << std::hex << std::uppercase << memoryAddr << ":" << addr << "::" << ".db"; } - output << std::hex << " $" << std::setfill('0') << std::setw(2) << (short)_prgROM[addr]; + output << std::hex << " $" << std::setfill('0') << std::setw(2) << (short)source[addr]; byteCount++; addr++; @@ -193,7 +213,15 @@ string Disassembler::GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &mem return output.str(); } -shared_ptr Disassembler::GetDisassemblyInfo(uint32_t address) +shared_ptr Disassembler::GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress) { - return _disassembleCache[address]; + if(memoryAddress < 0x2000) { + return _disassembleMemoryCache[memoryAddress & 0x7FF]; + } else if(absoluteAddress >= 0) { + return _disassembleCache[absoluteAddress]; + } else if(absoluteRamAddress >= 0) { + return _disassembleRamCache[absoluteRamAddress]; + } + + return nullptr; } \ No newline at end of file diff --git a/Core/Disassembler.h b/Core/Disassembler.h index 34d473d4..8eb9409b 100644 --- a/Core/Disassembler.h +++ b/Core/Disassembler.h @@ -1,6 +1,6 @@ #pragma once #include "stdafx.h" -#include "CPU.h" +#include "BaseMapper.h" class DisassemblyInfo; @@ -8,18 +8,21 @@ class Disassembler { private: vector> _disassembleCache; + vector> _disassembleRamCache; vector> _disassembleMemoryCache; - uint8_t* _internalRAM; - uint8_t* _prgROM; + uint8_t* _internalRam; + uint8_t* _prgRom; + uint8_t* _prgRam; uint32_t _prgSize; public: - Disassembler(uint8_t* internalRAM, uint8_t* prgROM, uint32_t prgSize); + Disassembler(uint8_t* internalRam, uint8_t* prgRom, uint32_t prgSize, uint8_t* prgRam, uint32_t prgRamSize); ~Disassembler(); - uint32_t BuildCache(uint32_t absoluteAddr, uint16_t memoryAddr); - string GetRAMCode(); - string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t &memoryAddr); + uint32_t BuildCache(int32_t absoluteAddr, int32_t absoluteRamAddr, uint16_t memoryAddr, bool isSubEntryPoint); + void InvalidateCache(uint16_t memoryAddr, int32_t absoluteRamAddr); - shared_ptr GetDisassemblyInfo(uint32_t address); + string GetCode(uint32_t startAddr, uint32_t endAddr, uint16_t memoryAddr, PrgMemoryType memoryType); + + shared_ptr GetDisassemblyInfo(int32_t absoluteAddress, int32_t absoluteRamAddress, uint16_t memoryAddress); }; diff --git a/Core/DisassemblyInfo.cpp b/Core/DisassemblyInfo.cpp index d1b95fb6..bd9aee49 100644 --- a/Core/DisassemblyInfo.cpp +++ b/Core/DisassemblyInfo.cpp @@ -31,7 +31,7 @@ void DisassemblyInfo::Initialize(uint32_t memoryAddr) output << DisassemblyInfo::OPName[opCode]; if(opCode == 0x40 || opCode == 0x60) { //Make end of function/interrupt routines more obvious - output << " ---------------------------"; + output << " ---->"; } if(DisassemblyInfo::OPName[opCode].empty()) { @@ -103,15 +103,28 @@ void DisassemblyInfo::Initialize(uint32_t memoryAddr) break; } + if(_isSubEntryPoint) { + output << " <----"; + } + _disassembly = output.str(); } -DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer) +DisassemblyInfo::DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint) { _opPointer = opPointer; + _isSubEntryPoint = isSubEntryPoint; Initialize(); } + +void DisassemblyInfo::SetSubEntryPoint() +{ + if(!_isSubEntryPoint) { + _isSubEntryPoint = true; + Initialize(); + } +} string DisassemblyInfo::ToString(uint32_t memoryAddr) { diff --git a/Core/DisassemblyInfo.h b/Core/DisassemblyInfo.h index 4d4edc0c..1049fd5c 100644 --- a/Core/DisassemblyInfo.h +++ b/Core/DisassemblyInfo.h @@ -12,6 +12,7 @@ public: private: string _disassembly; uint8_t *_opPointer = nullptr; + bool _isSubEntryPoint = false; uint32_t _opSize = 0; AddrMode _opMode; uint32_t _lastAddr = 0; @@ -20,8 +21,9 @@ private: void Initialize(uint32_t memoryAddr = 0); public: - DisassemblyInfo(uint8_t* opPointer); + DisassemblyInfo(uint8_t* opPointer, bool isSubEntryPoint); + void SetSubEntryPoint(); string ToString(uint32_t memoryAddr); uint32_t GetSize(); }; diff --git a/Core/TraceLogger.cpp b/Core/TraceLogger.cpp index c61eb9ed..a7803367 100644 --- a/Core/TraceLogger.cpp +++ b/Core/TraceLogger.cpp @@ -3,10 +3,13 @@ #include "DisassemblyInfo.h" #include "DebugState.h" +TraceLogger *TraceLogger::_instance = nullptr; + TraceLogger::TraceLogger(string outputFilepath, TraceLoggerOptions options) { _outputFile.open(outputFilepath, ios::out | ios::binary); _options = options; + _instance = this; } TraceLogger::~TraceLogger() @@ -14,6 +17,17 @@ TraceLogger::~TraceLogger() if(_outputFile) { _outputFile.close(); } + + if(_instance == this) { + _instance = nullptr; + } +} + +void TraceLogger::LogStatic(string log) +{ + if(_instance) { + _instance->_outputFile << "--- " << log << " ---" << std::endl; + } } void TraceLogger::Log(DebugState &state, shared_ptr disassemblyInfo) diff --git a/Core/TraceLogger.h b/Core/TraceLogger.h index f309beb2..918474fa 100644 --- a/Core/TraceLogger.h +++ b/Core/TraceLogger.h @@ -1,7 +1,8 @@ #pragma once #include "stdafx.h" -#include "DebugState.h" -#include "DisassemblyInfo.h" + +class DisassemblyInfo; +struct DebugState; struct TraceLoggerOptions { @@ -11,6 +12,7 @@ struct TraceLoggerOptions class TraceLogger { private: + static TraceLogger *_instance; TraceLoggerOptions _options; string _outputFilepath; ofstream _outputFile; @@ -20,4 +22,6 @@ public: ~TraceLogger(); void Log(DebugState &state, shared_ptr disassemblyInfo); + + static void LogStatic(string log); }; \ No newline at end of file