Debugger: Show effective address/memory value in disassembly + update trace logger to use the same code
This commit is contained in:
parent
26e90e90a1
commit
c9eb9cef52
20 changed files with 234 additions and 143 deletions
|
@ -137,7 +137,7 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
|
|||
|
||||
_memoryManager->Initialize(shared_from_this());
|
||||
|
||||
_cpu.reset(new Cpu(_memoryManager));
|
||||
_cpu.reset(new Cpu(_memoryManager.get()));
|
||||
_memoryManager->IncrementMasterClockValue<160>();
|
||||
|
||||
//if(_debugger) {
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
<ClInclude Include="ControlDeviceState.h" />
|
||||
<ClInclude Include="ControlManager.h" />
|
||||
<ClInclude Include="Cpu.h" />
|
||||
<ClInclude Include="DummyCpu.h" />
|
||||
<ClInclude Include="ExpressionEvaluator.h" />
|
||||
<ClInclude Include="RegisterHandlerB.h" />
|
||||
<ClInclude Include="CpuTypes.h" />
|
||||
|
|
|
@ -188,6 +188,9 @@
|
|||
<ClInclude Include="ExpressionEvaluator.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DummyCpu.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
|
|
@ -655,6 +655,7 @@ Move operations
|
|||
****************/
|
||||
void Cpu::MVN()
|
||||
{
|
||||
#ifndef DUMMYCPU
|
||||
_state.DBR = _operand & 0xFF;
|
||||
uint32_t destBank = _state.DBR << 16;
|
||||
uint32_t srcBank = (_operand << 8) & 0xFF0000;
|
||||
|
@ -671,15 +672,17 @@ void Cpu::MVN()
|
|||
|
||||
if(_state.A != 0xFFFF) {
|
||||
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
}
|
||||
} while(_state.A != 0xFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cpu::MVP()
|
||||
{
|
||||
#ifndef DUMMYCPU
|
||||
_state.DBR = _operand & 0xFF;
|
||||
uint32_t destBank = _state.DBR << 16;
|
||||
uint32_t srcBank = (_operand << 8) & 0xFF0000;
|
||||
|
@ -696,11 +699,12 @@ void Cpu::MVP()
|
|||
|
||||
if(_state.A != 0xFFFF) {
|
||||
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
}
|
||||
} while(_state.A != 0xFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************
|
||||
|
|
28
Core/Cpu.cpp
28
Core/Cpu.cpp
|
@ -3,7 +3,7 @@
|
|||
#include "Cpu.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
Cpu::Cpu(shared_ptr<MemoryManager> memoryManager)
|
||||
Cpu::Cpu(MemoryManager* memoryManager)
|
||||
{
|
||||
_memoryManager = memoryManager;
|
||||
_state = {};
|
||||
|
@ -338,7 +338,9 @@ uint8_t Cpu::GetOpCode()
|
|||
|
||||
void Cpu::Idle()
|
||||
{
|
||||
#ifndef DUMMYCPU
|
||||
_memoryManager->IncrementMasterClockValue<6>();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t Cpu::ReadOperandByte()
|
||||
|
@ -361,10 +363,22 @@ uint32_t Cpu::ReadOperandLong()
|
|||
return (b3 << 16) | (b2 << 8) | b1;
|
||||
}
|
||||
|
||||
uint8_t Cpu::ReadCode(uint16_t addr, MemoryOperationType type)
|
||||
uint8_t Cpu::Read(uint32_t addr, MemoryOperationType type)
|
||||
{
|
||||
_state.CycleCount++;
|
||||
return _memoryManager->Read((_state.K << 16) | addr, type);
|
||||
|
||||
#ifdef DUMMYCPU
|
||||
uint8_t value = _memoryManager->Peek(addr);
|
||||
LogRead(addr, value);
|
||||
return value;
|
||||
#else
|
||||
return _memoryManager->Read(addr, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t Cpu::ReadCode(uint16_t addr, MemoryOperationType type)
|
||||
{
|
||||
return Read((_state.K << 16) | addr, type);
|
||||
}
|
||||
|
||||
uint16_t Cpu::ReadCodeWord(uint16_t addr, MemoryOperationType type)
|
||||
|
@ -376,8 +390,7 @@ uint16_t Cpu::ReadCodeWord(uint16_t addr, MemoryOperationType type)
|
|||
|
||||
uint8_t Cpu::ReadData(uint32_t addr, MemoryOperationType type)
|
||||
{
|
||||
_state.CycleCount++;
|
||||
return _memoryManager->Read(addr & 0xFFFFFF, type);
|
||||
return Read(addr & 0xFFFFFF, type);
|
||||
}
|
||||
|
||||
uint16_t Cpu::ReadDataWord(uint32_t addr, MemoryOperationType type)
|
||||
|
@ -398,7 +411,12 @@ uint32_t Cpu::ReadDataLong(uint32_t addr, MemoryOperationType type)
|
|||
void Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
_state.CycleCount++;
|
||||
|
||||
#ifdef DUMMYCPU
|
||||
LogWrite(addr, value);
|
||||
#else
|
||||
_memoryManager->Write(addr, value, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cpu::WriteWord(uint32_t addr, uint16_t value, MemoryOperationType type)
|
||||
|
|
40
Core/Cpu.h
40
Core/Cpu.h
|
@ -1,4 +1,10 @@
|
|||
#pragma once
|
||||
#if (defined(DUMMYCPU) && !defined(__DUMMYCPU__H)) || (!defined(DUMMYCPU) && !defined(__CPU__H))
|
||||
#ifdef DUMMYCPU
|
||||
#define __DUMMYCPU__H
|
||||
#else
|
||||
#define __CPU__H
|
||||
#endif
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CpuTypes.h"
|
||||
|
||||
|
@ -25,7 +31,7 @@ private:
|
|||
|
||||
typedef void(Cpu::*Func)();
|
||||
|
||||
shared_ptr<MemoryManager> _memoryManager;
|
||||
MemoryManager* _memoryManager;
|
||||
|
||||
bool _immediateMode = false;
|
||||
|
||||
|
@ -53,6 +59,8 @@ private:
|
|||
uint16_t ReadOperandWord();
|
||||
uint32_t ReadOperandLong();
|
||||
|
||||
uint8_t Read(uint32_t addr, MemoryOperationType type);
|
||||
|
||||
void SetSP(uint16_t sp);
|
||||
void SetPS(uint8_t ps);
|
||||
|
||||
|
@ -285,7 +293,7 @@ private:
|
|||
void AddrMode_StkRelIndIdxY();
|
||||
|
||||
public:
|
||||
Cpu(shared_ptr<MemoryManager> memoryManager);
|
||||
Cpu(MemoryManager* memoryManager);
|
||||
~Cpu();
|
||||
|
||||
void Reset();
|
||||
|
@ -295,4 +303,30 @@ public:
|
|||
void SetIrqSource(IrqSource source);
|
||||
bool CheckIrqSource(IrqSource source);
|
||||
void ClearIrqSource(IrqSource source);
|
||||
|
||||
#ifdef DUMMYCPU
|
||||
private:
|
||||
uint32_t _writeCounter = 0;
|
||||
uint32_t _writeAddresses[10];
|
||||
uint8_t _writeValue[10];
|
||||
|
||||
uint32_t _readCounter = 0;
|
||||
uint32_t _readAddresses[10];
|
||||
uint8_t _readValue[10];
|
||||
|
||||
uint32_t _valueSize = 0;
|
||||
|
||||
void LogRead(uint32_t addr, uint8_t value);
|
||||
void LogWrite(uint32_t addr, uint8_t value);
|
||||
|
||||
public:
|
||||
void SetDummyState(CpuState &state);
|
||||
|
||||
uint32_t GetWriteCount();
|
||||
uint32_t GetReadCount();
|
||||
void GetWriteInfo(uint32_t index, uint32_t &addr, uint8_t &value);
|
||||
void GetReadInfo(uint32_t index, uint32_t &addr, uint8_t &value);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
|
@ -107,7 +107,8 @@ struct CodeLineData
|
|||
uint8_t Flags;
|
||||
|
||||
int32_t EffectiveAddress;
|
||||
int32_t Value;
|
||||
uint16_t Value;
|
||||
uint8_t ValueSize;
|
||||
|
||||
uint8_t ByteCode[4];
|
||||
char Text[1000];
|
||||
|
|
|
@ -71,7 +71,6 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
|
|||
|
||||
DebugState debugState;
|
||||
GetState(&debugState);
|
||||
_traceLogger->LogEffectiveAddress(_cpu->GetLastOperand());
|
||||
|
||||
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
|
||||
_traceLogger->Log(debugState, disInfo);
|
||||
|
|
|
@ -235,9 +235,13 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
|||
vector<shared_ptr<DisassemblyInfo>> *cache;
|
||||
GetSource(result.Address, &source, sourceLength, &cache);
|
||||
disInfo = (*cache)[result.Address.Address];
|
||||
|
||||
CpuState state = _console->GetCpu()->GetState();
|
||||
state.PC = (uint16_t)result.CpuAddress;
|
||||
state.K = (result.CpuAddress >> 16);
|
||||
|
||||
if(!disInfo) {
|
||||
disInfo.reset(new DisassemblyInfo(source + result.Address.Address, 0));
|
||||
disInfo.reset(new DisassemblyInfo(source + result.Address.Address, state.PS));
|
||||
} else {
|
||||
data.Flags |= (uint8_t)LineFlags::VerifiedCode;
|
||||
}
|
||||
|
@ -247,8 +251,14 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
|||
memcpy(data.Text, text.c_str(), std::min<int>((int)text.size(), 1000));
|
||||
|
||||
data.OpSize = disInfo->GetOperandSize() + 1;
|
||||
data.EffectiveAddress = disInfo->GetEffectiveAddress();
|
||||
data.Value = _memoryManager->Peek(result.CpuAddress);
|
||||
|
||||
MemoryManager *memoryManager = _console->GetMemoryManager().get();
|
||||
data.EffectiveAddress = disInfo->GetEffectiveAddress(state, memoryManager);
|
||||
if(data.EffectiveAddress >= 0) {
|
||||
data.Value = disInfo->GetMemoryValue(data.EffectiveAddress, memoryManager, data.ValueSize);
|
||||
} else {
|
||||
data.ValueSize = 0;
|
||||
}
|
||||
|
||||
disInfo->GetByteCode(data.ByteCode);
|
||||
data.Comment[0] = 0;
|
||||
|
@ -266,7 +276,7 @@ bool Disassembler::GetLineData(uint32_t lineIndex, CodeLineData &data)
|
|||
return false;
|
||||
}
|
||||
|
||||
int32_t Disassembler::SearchCode(const char *searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards)
|
||||
int32_t Disassembler::SearchDisassembly(const char *searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards)
|
||||
{
|
||||
auto lock = _disassemblyLock.AcquireSafe();
|
||||
int step = searchBackwards ? -1 : 1;
|
||||
|
|
|
@ -46,5 +46,5 @@ public:
|
|||
uint32_t GetLineCount();
|
||||
uint32_t GetLineIndex(uint32_t cpuAddress);
|
||||
bool GetLineData(uint32_t lineIndex, CodeLineData &data);
|
||||
int32_t SearchCode(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards);
|
||||
int32_t SearchDisassembly(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards);
|
||||
};
|
|
@ -3,6 +3,7 @@
|
|||
#include "DisassemblyInfo.h"
|
||||
#include "CpuTypes.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "DummyCpu.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/FastString.h"
|
||||
|
||||
|
@ -17,8 +18,7 @@ DisassemblyInfo::DisassemblyInfo(uint8_t *opPointer, uint8_t cpuFlags)
|
|||
|
||||
void DisassemblyInfo::Initialize(uint8_t *opPointer, uint8_t cpuFlags)
|
||||
{
|
||||
_flags = cpuFlags;
|
||||
_effectiveAddress = -1;
|
||||
_flags = cpuFlags & (ProcFlags::MemoryMode8 | ProcFlags::IndexMode8);
|
||||
|
||||
_byteCode[0] = opPointer[0];
|
||||
_addrMode = DisassemblyInfo::OpMode[_byteCode[0]];
|
||||
|
@ -55,7 +55,7 @@ void DisassemblyInfo::GetDisassembly(string &out, uint32_t memoryAddr)
|
|||
case AddrMode::AbsLng: str.Write(operand); break;
|
||||
case AddrMode::AbsLngJmp: str.Write(operand); break;
|
||||
case AddrMode::Acc: break;
|
||||
case AddrMode::BlkMov: str.Write(operand[1], operand[2], " -> "); str.Write(operand[3], operand[4]); break;
|
||||
case AddrMode::BlkMov: str.Write('$', operand[1], operand[2], " -> "); str.Write('$', operand[3], operand[4]); break;
|
||||
case AddrMode::DirIdxIndX: str.Write('(', operand, ",X)"); break;
|
||||
case AddrMode::DirIdxX: str.Write(operand, ",X"); break;
|
||||
case AddrMode::DirIdxY: str.Write(operand, ",Y"); break;
|
||||
|
@ -177,76 +177,36 @@ void DisassemblyInfo::GetByteCode(string &out)
|
|||
out += str.ToString();
|
||||
}
|
||||
|
||||
void DisassemblyInfo::GetEffectiveAddressString(string &out)
|
||||
void DisassemblyInfo::GetEffectiveAddressString(string &out, CpuState &state, MemoryManager* memoryManager)
|
||||
{
|
||||
int32_t effectiveAddress = GetEffectiveAddress();
|
||||
int32_t effectiveAddress = GetEffectiveAddress(state, memoryManager);
|
||||
if(effectiveAddress >= 0) {
|
||||
out += " [" + HexUtilities::ToHex24(effectiveAddress) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyInfo::SetEffectiveAddress(int32_t effectiveAddress)
|
||||
int32_t DisassemblyInfo::GetEffectiveAddress(CpuState &state, MemoryManager *memoryManager)
|
||||
{
|
||||
_effectiveAddress = effectiveAddress;
|
||||
}
|
||||
|
||||
int32_t DisassemblyInfo::GetEffectiveAddress()
|
||||
{
|
||||
if(_addrMode > AddrMode::ImmM && _addrMode != AddrMode::Acc && _addrMode != AddrMode::Imp && _addrMode != AddrMode::Stk) {
|
||||
return _effectiveAddress;
|
||||
if(_addrMode > AddrMode::ImmM && _addrMode != AddrMode::Acc && _addrMode != AddrMode::Imp && _addrMode != AddrMode::Stk && _addrMode != AddrMode::Rel && _addrMode != AddrMode::RelLng && _addrMode != AddrMode::BlkMov) {
|
||||
DummyCpu cpu(memoryManager);
|
||||
state.PS &= ~(ProcFlags::IndexMode8 | ProcFlags::MemoryMode8);
|
||||
state.PS |= _flags;
|
||||
cpu.SetDummyState(state);
|
||||
cpu.Exec();
|
||||
return cpu.GetLastOperand();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*auto getProgramAddress = [&state](uint16_t addr) { return (state.K << 16) | addr; };
|
||||
auto getDataAddress = [&state](uint16_t addr) { return (state.DBR << 16) | addr; };
|
||||
auto getDirectAddress = [&state](uint8_t baseAddress, uint16_t offset = 0, bool allowEmulationMode = true) {
|
||||
if(allowEmulationMode && state.EmulationMode && (state.D & 0xFF) == 0) {
|
||||
//TODO: Check if new instruction or not (PEI)
|
||||
return (uint16_t)((state.D & 0xFF00) | ((baseAddress + offset) & 0xFF));
|
||||
} else {
|
||||
return (uint16_t)(state.D + baseAddress + offset);
|
||||
}
|
||||
};
|
||||
|
||||
auto getDirectAddressIndirectWord = [&state, mm, &getDirectAddress](uint8_t baseAddress, uint16_t offset = 0, bool allowEmulationMode = true) {
|
||||
uint8_t b1 = mm->Peek(getDirectAddress(baseAddress, offset + 0));
|
||||
uint8_t b2 = mm->Peek(getDirectAddress(baseAddress, offset + 1));
|
||||
return (b2 << 8) | b1;
|
||||
};
|
||||
|
||||
auto getDirectAddressIndirectLong = [&state, mm, &getDirectAddress](uint8_t baseAddress, uint16_t offset = 0, bool allowEmulationMode = true) {
|
||||
uint8_t b1 = mm->Peek(getDirectAddress(baseAddress, offset + 0));
|
||||
uint8_t b2 = mm->Peek(getDirectAddress(baseAddress, offset + 1));
|
||||
uint8_t b3 = mm->Peek(getDirectAddress(baseAddress, offset + 2));
|
||||
return (b3 << 16) | (b2 << 8) | b1;
|
||||
};
|
||||
|
||||
|
||||
uint32_t bank = (state.K << 16);
|
||||
uint32_t opAddr = GetOperandAddress(bank | state.PC);
|
||||
switch(_addrMode) {
|
||||
case AddrMode::AbsIdxX: return opAddr + state.X;
|
||||
case AddrMode::AbsIdxY: return opAddr + state.Y;
|
||||
case AddrMode::AbsLngIdxX: return opAddr + state.X;
|
||||
case AddrMode::AbsIdxXInd: return getProgramAddress(mm->PeekWord(getProgramAddress(opAddr + state.X)));
|
||||
case AddrMode::AbsInd: return getProgramAddress(mm->PeekWord(opAddr));
|
||||
case AddrMode::AbsIndLng: return mm->PeekLong(opAddr);
|
||||
|
||||
case AddrMode::BlkMov: break; //TODO
|
||||
|
||||
case AddrMode::Dir: return getDirectAddress(opAddr);
|
||||
case AddrMode::DirIdxX: return getDirectAddress(opAddr, state.X);
|
||||
case AddrMode::DirIdxY: return getDirectAddress(opAddr, state.Y);
|
||||
|
||||
case AddrMode::DirInd: return getDirectAddressIndirectWord(opAddr);
|
||||
case AddrMode::DirIdxIndX: return getDirectAddressIndirectWord(opAddr, state.X);
|
||||
case AddrMode::DirIndIdxY: return getDirectAddressIndirectWord(opAddr) + state.Y;
|
||||
case AddrMode::DirIndLng: return getDirectAddressIndirectLong(opAddr);
|
||||
case AddrMode::DirIndLngIdxY: return getDirectAddressIndirectLong(opAddr) + state.Y;
|
||||
|
||||
case AddrMode::StkRel: return opAddr + state.SP;
|
||||
case AddrMode::StkRelIndIdxY: break;
|
||||
}*/
|
||||
uint16_t DisassemblyInfo::GetMemoryValue(uint32_t effectiveAddress, MemoryManager *memoryManager, uint8_t &valueSize)
|
||||
{
|
||||
if(_flags & ProcFlags::MemoryMode8) {
|
||||
valueSize = 1;
|
||||
return memoryManager->Peek(effectiveAddress);
|
||||
} else {
|
||||
valueSize = 2;
|
||||
return memoryManager->PeekWord(effectiveAddress);
|
||||
}
|
||||
}
|
||||
|
||||
string DisassemblyInfo::OpName[256] = {
|
||||
|
|
|
@ -19,7 +19,6 @@ private:
|
|||
uint8_t _opSize;
|
||||
AddrMode _addrMode;
|
||||
uint8_t _flags;
|
||||
int32_t _effectiveAddress;
|
||||
|
||||
public:
|
||||
DisassemblyInfo();
|
||||
|
@ -37,13 +36,8 @@ public:
|
|||
void GetByteCode(uint8_t copyBuffer[4]);
|
||||
void GetByteCode(string &out);
|
||||
|
||||
void SetEffectiveAddress(int32_t effectiveAddress);
|
||||
void GetEffectiveAddressString(string &out);
|
||||
int32_t GetEffectiveAddress();
|
||||
|
||||
/*int32_t GetMemoryValue(CpuState& cpuState, MemoryManager* memoryManager);
|
||||
uint16_t GetJumpDestination(uint16_t pc, MemoryManager* memoryManager);
|
||||
uint16_t GetIndirectJumpDestination(MemoryManager* memoryManager);
|
||||
*/
|
||||
void GetEffectiveAddressString(string &out, CpuState &state, MemoryManager* memoryManager);
|
||||
int32_t GetEffectiveAddress(CpuState &state, MemoryManager *memoryManager);
|
||||
uint16_t GetMemoryValue(uint32_t effectiveAddress, MemoryManager *memoryManager, uint8_t &valueSize);
|
||||
};
|
||||
|
||||
|
|
55
Core/DummyCpu.h
Normal file
55
Core/DummyCpu.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#define DUMMYCPU
|
||||
#define Cpu DummyCpu
|
||||
#include "Cpu.h"
|
||||
#include "Cpu.cpp"
|
||||
#include "Cpu.Instructions.cpp"
|
||||
#undef Cpu
|
||||
#undef DUMMYCPU
|
||||
|
||||
void DummyCpu::SetDummyState(CpuState &state)
|
||||
{
|
||||
_state = state;
|
||||
|
||||
_writeCounter = 0;
|
||||
_readCounter = 0;
|
||||
}
|
||||
|
||||
uint32_t DummyCpu::GetWriteCount()
|
||||
{
|
||||
return _writeCounter;
|
||||
}
|
||||
|
||||
uint32_t DummyCpu::GetReadCount()
|
||||
{
|
||||
return _readCounter;
|
||||
}
|
||||
|
||||
void DummyCpu::LogRead(uint32_t addr, uint8_t value)
|
||||
{
|
||||
_readAddresses[_readCounter] = addr;
|
||||
_readValue[_readCounter] = value;
|
||||
_readCounter++;
|
||||
}
|
||||
|
||||
void DummyCpu::LogWrite(uint32_t addr, uint8_t value)
|
||||
{
|
||||
_writeAddresses[_writeCounter] = addr;
|
||||
_writeValue[_writeCounter] = value;
|
||||
_writeCounter++;
|
||||
}
|
||||
|
||||
void DummyCpu::GetWriteInfo(uint32_t index, uint32_t &addr, uint8_t &value)
|
||||
{
|
||||
addr = _writeAddresses[index];
|
||||
value = _writeValue[index];
|
||||
}
|
||||
|
||||
void DummyCpu::GetReadInfo(uint32_t index, uint32_t &addr, uint8_t &value)
|
||||
{
|
||||
addr = _readAddresses[index];
|
||||
value = _readValue[index];
|
||||
}
|
|
@ -185,6 +185,13 @@ uint8_t MemoryManager::Peek(uint32_t addr)
|
|||
return value;
|
||||
}
|
||||
|
||||
uint16_t MemoryManager::PeekWord(uint32_t addr)
|
||||
{
|
||||
uint8_t lsb = Peek(addr);
|
||||
uint8_t msb = Peek((addr + 1) & 0xFFFFFF);
|
||||
return (msb << 8) | lsb;
|
||||
}
|
||||
|
||||
void MemoryManager::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
||||
{
|
||||
IncrementMasterClock(addr);
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
uint8_t Read(uint32_t addr, MemoryOperationType type);
|
||||
uint8_t ReadDma(uint32_t addr);
|
||||
uint8_t Peek(uint32_t addr);
|
||||
uint16_t PeekWord(uint32_t addr);
|
||||
|
||||
void Write(uint32_t addr, uint8_t value, MemoryOperationType type);
|
||||
void WriteDma(uint32_t addr, uint8_t value);
|
||||
|
|
|
@ -218,18 +218,28 @@ void TraceLogger::GetTraceRow(string &output, CpuState &cpuState, PpuState &ppuS
|
|||
case RowDataType::EffectiveAddress:
|
||||
{
|
||||
string effectiveAddress;
|
||||
disassemblyInfo.GetEffectiveAddressString(effectiveAddress);
|
||||
disassemblyInfo.GetEffectiveAddressString(effectiveAddress, cpuState, _memoryManager.get());
|
||||
WriteValue(output, effectiveAddress, rowPart);
|
||||
break;
|
||||
}
|
||||
|
||||
case RowDataType::MemoryValue:
|
||||
{
|
||||
/*int32_t value = disassemblyInfo.GetMemoryValue(cpuState, _memoryManager.get());
|
||||
if(value >= 0) {
|
||||
output += rowPart.DisplayInHex ? "= $" : "= ";
|
||||
WriteValue(output, (uint8_t)value, rowPart);
|
||||
}*/
|
||||
int32_t address = disassemblyInfo.GetEffectiveAddress(cpuState, _memoryManager.get());
|
||||
if(address >= 0) {
|
||||
uint8_t valueSize;
|
||||
uint16_t value = disassemblyInfo.GetMemoryValue(address, _memoryManager.get(), valueSize);
|
||||
if(rowPart.DisplayInHex) {
|
||||
output += "= $";
|
||||
if(valueSize == 2) {
|
||||
WriteValue(output, (uint16_t)value, rowPart);
|
||||
} else {
|
||||
WriteValue(output, (uint8_t)value, rowPart);
|
||||
}
|
||||
} else {
|
||||
output += "= ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -284,6 +294,14 @@ void TraceLogger::AddRow(DisassemblyInfo &disassemblyInfo, DebugState &state)
|
|||
_logCount++;
|
||||
}
|
||||
|
||||
if(_logToFile) {
|
||||
GetTraceRow(_outputBuffer, _cpuStateCache[_currentPos], _ppuStateCache[_currentPos], _disassemblyCache[_currentPos]);
|
||||
if(_outputBuffer.size() > 32768) {
|
||||
_outputFile << _outputBuffer;
|
||||
_outputBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
_currentPos = (_currentPos + 1) % ExecutionLogSize;
|
||||
}
|
||||
/*
|
||||
|
@ -297,25 +315,6 @@ void TraceLogger::LogNonExec(OperationInfo& operationInfo)
|
|||
}
|
||||
}*/
|
||||
|
||||
void TraceLogger::LogEffectiveAddress(uint32_t effectiveAddress)
|
||||
{
|
||||
uint32_t pos;
|
||||
if(_currentPos > 0) {
|
||||
pos = _currentPos - 1;
|
||||
} else {
|
||||
pos = ExecutionLogSize - 1;
|
||||
}
|
||||
|
||||
_disassemblyCache[pos].SetEffectiveAddress(effectiveAddress);
|
||||
if(_logToFile) {
|
||||
GetTraceRow(_outputBuffer, _cpuStateCache[pos], _ppuStateCache[pos], _disassemblyCache[pos]);
|
||||
if(_outputBuffer.size() > 32768) {
|
||||
_outputFile << _outputBuffer;
|
||||
_outputBuffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TraceLogger::Log(DebugState &state, DisassemblyInfo &disassemblyInfo)
|
||||
{
|
||||
auto lock = _lock.AcquireSafe();
|
||||
|
|
|
@ -97,8 +97,6 @@ public:
|
|||
TraceLogger(Debugger* debugger, shared_ptr<MemoryManager> memoryManager);
|
||||
~TraceLogger();
|
||||
|
||||
void LogEffectiveAddress(uint32_t effectiveAddress);
|
||||
|
||||
void Log(DebugState &state, DisassemblyInfo &disassemblyInfo);
|
||||
//void LogNonExec(OperationInfo& operationInfo);
|
||||
void SetOptions(TraceLoggerOptions options);
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C"
|
|||
DllExport void __stdcall GetDisassemblyLineData(uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(lineIndex, data); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineCount() { return GetDebugger()->GetDisassembler()->GetLineCount(); }
|
||||
DllExport uint32_t __stdcall GetDisassemblyLineIndex(uint32_t cpuAddress) { return GetDebugger()->GetDisassembler()->GetLineIndex(cpuAddress); }
|
||||
DllExport int32_t __stdcall SearchDisassembly(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards) { return GetDebugger()->GetDisassembler()->SearchCode(searchString, startPosition, endPosition, searchBackwards); }
|
||||
DllExport int32_t __stdcall SearchDisassembly(const char* searchString, int32_t startPosition, int32_t endPosition, bool searchBackwards) { return GetDebugger()->GetDisassembler()->SearchDisassembly(searchString, startPosition, endPosition, searchBackwards); }
|
||||
|
||||
DllExport void __stdcall SetTraceOptions(TraceLoggerOptions options) { GetDebugger()->GetTraceLogger()->SetOptions(options); }
|
||||
DllExport void __stdcall StartTraceLogger(char* filename) { GetDebugger()->GetTraceLogger()->StartLogging(filename); }
|
||||
|
|
|
@ -21,11 +21,27 @@ namespace Mesen.GUI.Debugger
|
|||
public string Comment;
|
||||
|
||||
public Int32 EffectiveAddress;
|
||||
public Int32 Value;
|
||||
public UInt16 Value;
|
||||
public byte ValueSize;
|
||||
|
||||
public string GetEffectiveAddressString()
|
||||
{
|
||||
return "[" + EffectiveAddress.ToString("X6") + "]";
|
||||
if(EffectiveAddress >= 0) {
|
||||
return "[" + EffectiveAddress.ToString("X6") + "]";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public string GetValueString()
|
||||
{
|
||||
if(ValueSize == 1) {
|
||||
return " = $" + Value.ToString("X2");
|
||||
} else if(ValueSize == 2) {
|
||||
return " = $" + Value.ToString("X4");
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public int Indentation
|
||||
|
@ -58,6 +74,7 @@ namespace Mesen.GUI.Debugger
|
|||
this.EffectiveAddress = data.EffectiveAddress;
|
||||
this.Flags = (LineFlags)data.Flags;
|
||||
this.Value = data.Value;
|
||||
this.ValueSize = data.ValueSize;
|
||||
}
|
||||
|
||||
private string ConvertString(byte[] stringArray)
|
||||
|
@ -81,7 +98,8 @@ namespace Mesen.GUI.Debugger
|
|||
public byte Flags;
|
||||
|
||||
public Int32 EffectiveAddress;
|
||||
public Int32 Value;
|
||||
public UInt16 Value;
|
||||
public byte ValueSize;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] ByteCode;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
{
|
||||
public partial class ctrlTextbox : Control
|
||||
{
|
||||
private Regex _codeRegex = new Regex("^(\\s*)([a-z]{3})([*]{0,1})($|[ ]){1}([(]{0,1})(([$][0-9a-f]*)|(#[@$:_0-9a-z]*)|([@_a-z]([@_a-z0-9])*){0,1}(\\+(\\d+)){0,1}){0,1}([)]{0,1})(,X|,Y){0,1}([)]{0,1})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private Regex _codeRegex = new Regex("^(\\s*)([a-z]{3})([*]{0,1})($|[ ]){1}([(\\[]{0,1})(([$][0-9a-f]*)|(#[@$:_0-9a-z]*)|([@_a-z]([@_a-z0-9])*){0,1}(\\+(\\d+)){0,1}){0,1}([)\\]]{0,1})(,X|,Y){0,1}([)\\]]{0,1})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
public event EventHandler ScrollPositionChanged;
|
||||
public event EventHandler SelectedLineChanged;
|
||||
private bool _disableScrollPositionChangedEvent;
|
||||
|
@ -902,8 +902,6 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
private void DrawLineText(Graphics g, int currentLine, int marginLeft, int positionY, CodeLineData lineData, float codeStringLength, Color? textColor, int lineHeight)
|
||||
{
|
||||
string codeString = lineData.Text;
|
||||
string addressString = lineData.EffectiveAddress>= 0 ? (" [" + lineData.EffectiveAddress.ToString("X6") + "]") : "";
|
||||
float addressStringLength = g.MeasureString(addressString, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width;
|
||||
string commentString = lineData.Comment;
|
||||
|
||||
DebugInfo info = ConfigManager.Config.Debug;
|
||||
|
@ -962,24 +960,15 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
int codePartCount = colors.Count;
|
||||
|
||||
List<string> parts = new List<string>() { padding, opcode, invalidStar, " ", paren1, operand, paren2, indirect, paren3 };
|
||||
string memoryAddress = "";
|
||||
if(!string.IsNullOrWhiteSpace(addressString)) {
|
||||
colors.Add(info.CodeEffectiveAddressColor);
|
||||
parts.Add(addressString);
|
||||
memoryAddress = addressString.Substring(3).Trim();
|
||||
|
||||
//Update the contents of "arrayPosition" based on the address string, rather than use the one from the original address
|
||||
int plusIndex = memoryAddress.IndexOf("+");
|
||||
arrayPosition = plusIndex >= 0 ? memoryAddress.Substring(plusIndex+1) : "";
|
||||
} else if(operand.Length > 0 && operand[0] != '#') {
|
||||
memoryAddress = operand.Trim();
|
||||
if(lineData.EffectiveAddress >= 0) {
|
||||
colors.Add(info.CodeEffectiveAddressColor);
|
||||
parts.Add(" [" + lineData.EffectiveAddress.ToString("X6") + "]");
|
||||
}
|
||||
|
||||
if(this.ShowMemoryValues && memoryAddress.Length > 0) {
|
||||
if(lineData.Value >= 0) {
|
||||
colors.Add(defaultColor);
|
||||
parts.Add(" = $" + lineData.Value.ToString("X4"));
|
||||
}
|
||||
if(this.ShowMemoryValues && lineData.ValueSize > 0) {
|
||||
colors.Add(defaultColor);
|
||||
parts.Add(lineData.GetValueString());
|
||||
}
|
||||
|
||||
//Display the rest of the line (used by trace logger)
|
||||
|
|
Loading…
Add table
Reference in a new issue