mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #5 from Kingcom/master
More debugger enhancements and fixes
This commit is contained in:
commit
2fbac107ca
|
@ -0,0 +1,40 @@
|
|||
disassembly view:
|
||||
|
||||
ctrg+g goto
|
||||
ctrl+e edit breakpoint
|
||||
ctrl+d enable/disable breakpoint
|
||||
ctrl+b add breakpoint
|
||||
right follow branch/position memory view to accessed address
|
||||
left go back one branch level/goto pc
|
||||
up move cursor up one line
|
||||
down move cursor down one line
|
||||
page up move visible area up one page
|
||||
page down move visible area down one page
|
||||
f10 step over
|
||||
f11 step into
|
||||
tab toggle display symbols
|
||||
left click select line/toggle breakpoint if line is already highlighted
|
||||
right click open context menu
|
||||
|
||||
memory view:
|
||||
|
||||
ctrg+g goto
|
||||
ctrl+b add breakpoint
|
||||
left move cursor back one byte/nibble
|
||||
right move cursor ahead one byte/nibble
|
||||
up move cursor up one line
|
||||
down move cursor down one line
|
||||
page up move cursor up one page
|
||||
page down move cursor down one page
|
||||
0-9,A-F overwrite hex nibble
|
||||
any overwrite ansi byte
|
||||
left click select byte/nibble
|
||||
right click open context menu
|
||||
|
||||
breakpoint list:
|
||||
|
||||
up select previous item
|
||||
down select next item
|
||||
delete remove selected breakpoint
|
||||
return edit selected breakpoint
|
||||
space toggle enable state of selected breakpoint
|
|
@ -33,6 +33,9 @@
|
|||
#include "CDVDisoReader.h"
|
||||
#include "Utilities/ScopedPtr.h"
|
||||
|
||||
#include "DebugTools/SymbolMap.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
const wxChar* CDVD_SourceLabels[] =
|
||||
{
|
||||
L"Iso",
|
||||
|
@ -287,6 +290,21 @@ static CDVD_SourceType m_CurrentSourceType = CDVDsrc_NoDisc;
|
|||
void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
||||
{
|
||||
m_SourceFilename[srctype] = newfile;
|
||||
|
||||
// look for symbol file
|
||||
if (g_Conf->EmuOptions.Debugger.EnableDebugger && symbolMap.IsEmpty())
|
||||
{
|
||||
wxString symName;
|
||||
int n = newfile.Last('.');
|
||||
if (n == wxNOT_FOUND)
|
||||
symName = newfile + L".sym";
|
||||
else
|
||||
symName = newfile.substr(0,n) + L".sym";
|
||||
|
||||
wxCharBuffer buf = symName.ToUTF8();
|
||||
symbolMap.LoadNocashSym(buf);
|
||||
symbolMap.UpdateActiveSymbols();
|
||||
}
|
||||
}
|
||||
|
||||
const wxString& CDVDsys_GetFile( CDVD_SourceType srctype )
|
||||
|
|
|
@ -326,6 +326,7 @@ set(pcsx2GuiSources
|
|||
gui/Debugger/CtrlDisassemblyView.cpp
|
||||
gui/Debugger/CtrlRegisterList.cpp
|
||||
gui/Debugger/CtrlMemView.cpp
|
||||
gui/Debugger/DebuggerLists.cpp
|
||||
gui/Debugger/DisassemblyDialog.cpp
|
||||
gui/Debugger/DebugEvents.cpp
|
||||
gui/ExecutorThread.cpp
|
||||
|
@ -381,6 +382,7 @@ set(pcsx2GuiHeaders
|
|||
gui/Debugger/CtrlDisassemblyView.h
|
||||
gui/Debugger/CtrlRegisterList.h
|
||||
gui/Debugger/CtrlMemView.h
|
||||
gui/Debugger/DebuggerLists.h
|
||||
gui/Debugger/DisassemblyDialog.h
|
||||
gui/Debugger/DebugEvents.h
|
||||
gui/i18n.h
|
||||
|
|
|
@ -404,6 +404,31 @@ struct Pcsx2Config
|
|||
}
|
||||
};
|
||||
|
||||
struct DebugOptions
|
||||
{
|
||||
BITFIELD32()
|
||||
bool
|
||||
EnableDebugger :1,
|
||||
ShowDebuggerOnStart :1;
|
||||
BITFIELD_END
|
||||
|
||||
u8 FontWidth;
|
||||
u8 FontHeight;
|
||||
|
||||
DebugOptions();
|
||||
void LoadSave( IniInterface& conf );
|
||||
|
||||
bool operator ==( const DebugOptions& right ) const
|
||||
{
|
||||
return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight );
|
||||
}
|
||||
|
||||
bool operator !=( const DebugOptions& right ) const
|
||||
{
|
||||
return !this->operator ==( right );
|
||||
}
|
||||
};
|
||||
|
||||
BITFIELD32()
|
||||
bool
|
||||
CdvdVerboseReads :1, // enables cdvd read activity verbosely dumped to the console
|
||||
|
@ -429,6 +454,7 @@ struct Pcsx2Config
|
|||
SpeedhackOptions Speedhacks;
|
||||
GamefixOptions Gamefixes;
|
||||
ProfilerOptions Profiler;
|
||||
DebugOptions Debugger;
|
||||
|
||||
TraceLogFilters Trace;
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ u32 CBreakPoints::breakSkipFirstAt_ = 0;
|
|||
u64 CBreakPoints::breakSkipFirstTicks_ = 0;
|
||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck *> CBreakPoints::cleanupMemChecks_;
|
||||
bool CBreakPoints::breakpointTriggered_ = false;
|
||||
|
||||
int addressMask = 0x1FFFFFFF;
|
||||
|
||||
MemCheck::MemCheck()
|
||||
{
|
||||
|
@ -82,9 +85,11 @@ void MemCheck::JitCleanup()
|
|||
|
||||
size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
||||
{
|
||||
addr &= addressMask;
|
||||
|
||||
for (size_t i = 0; i < breakPoints_.size(); ++i)
|
||||
{
|
||||
if (breakPoints_[i].addr == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
||||
if ((breakPoints_[i].addr & addressMask) == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -93,9 +98,11 @@ size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
|||
|
||||
size_t CBreakPoints::FindMemCheck(u32 start, u32 end)
|
||||
{
|
||||
start &= addressMask;
|
||||
end &= addressMask;
|
||||
for (size_t i = 0; i < memChecks_.size(); ++i)
|
||||
{
|
||||
if (memChecks_[i].start == start && memChecks_[i].end == end)
|
||||
if ((memChecks_[i].start & addressMask) == start && (memChecks_[i].end & addressMask) == end)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -291,6 +298,8 @@ static inline u32 NotCached(u32 val)
|
|||
|
||||
MemCheck *CBreakPoints::GetMemCheck(u32 address, int size)
|
||||
{
|
||||
address &= addressMask;
|
||||
|
||||
std::vector<MemCheck>::iterator iter;
|
||||
for (iter = memChecks_.begin(); iter != memChecks_.end(); ++iter)
|
||||
{
|
||||
|
@ -338,14 +347,16 @@ void CBreakPoints::ExecMemCheckJitCleanup()
|
|||
|
||||
void CBreakPoints::SetSkipFirst(u32 pc)
|
||||
{
|
||||
breakSkipFirstAt_ = pc;
|
||||
// breakSkipFirstTicks_ = CoreTiming::GetTicks();
|
||||
breakSkipFirstAt_ = pc & addressMask;
|
||||
breakSkipFirstTicks_ = r5900Debug.getCycles();
|
||||
}
|
||||
|
||||
u32 CBreakPoints::CheckSkipFirst(u32 cmpPc)
|
||||
{
|
||||
cmpPc &= addressMask;
|
||||
u32 pc = breakSkipFirstAt_;
|
||||
if (pc == cmpPc)
|
||||
return 1;
|
||||
if (breakSkipFirstTicks_ == r5900Debug.getCycles())
|
||||
return pc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -375,6 +386,10 @@ const std::vector<BreakPoint> CBreakPoints::GetBreakpoints()
|
|||
return breakPoints_;
|
||||
}
|
||||
|
||||
// including them earlier causes some ambiguities
|
||||
#include "App.h"
|
||||
#include "Debugger/DisassemblyDialog.h"
|
||||
|
||||
void CBreakPoints::Update(u32 addr)
|
||||
{
|
||||
bool resume = false;
|
||||
|
@ -384,14 +399,13 @@ void CBreakPoints::Update(u32 addr)
|
|||
resume = true;
|
||||
}
|
||||
|
||||
if (addr != 0)
|
||||
Cpu->Clear(addr-4,8);
|
||||
else
|
||||
// if (addr != 0)
|
||||
// Cpu->Clear(addr-4,8);
|
||||
// else
|
||||
SysClearExecutionCache();
|
||||
|
||||
if (resume)
|
||||
r5900Debug.resumeCpu();
|
||||
|
||||
// Redraw in order to show the breakpoint.
|
||||
// host->UpdateDisassembly();
|
||||
wxGetApp().GetDisassemblyPtr()->update();
|
||||
}
|
||||
|
|
|
@ -150,6 +150,9 @@ public:
|
|||
|
||||
static void Update(u32 addr = 0);
|
||||
|
||||
static void SetBreakpointTriggered(bool b) { breakpointTriggered_ = b; };
|
||||
static bool GetBreakpointTriggered() { return breakpointTriggered_; };
|
||||
|
||||
private:
|
||||
static size_t FindBreakpoint(u32 addr, bool matchTemp = false, bool temp = false);
|
||||
// Finds exactly, not using a range check.
|
||||
|
@ -158,6 +161,7 @@ private:
|
|||
static std::vector<BreakPoint> breakPoints_;
|
||||
static u32 breakSkipFirstAt_;
|
||||
static u64 breakSkipFirstTicks_;
|
||||
static bool breakpointTriggered_;
|
||||
|
||||
static std::vector<MemCheck> memChecks_;
|
||||
static std::vector<MemCheck *> cleanupMemChecks_;
|
||||
|
|
|
@ -418,6 +418,44 @@ void R5900DebugInterface::setPc(u32 newPc)
|
|||
cpuRegs.pc = newPc;
|
||||
}
|
||||
|
||||
void R5900DebugInterface::setRegister(int cat, int num, u128 newValue)
|
||||
{
|
||||
switch (cat)
|
||||
{
|
||||
case EECAT_GPR:
|
||||
switch (num)
|
||||
{
|
||||
case 32: // pc
|
||||
cpuRegs.pc = newValue._u32[0];
|
||||
break;
|
||||
case 33: // hi
|
||||
cpuRegs.HI.UQ = newValue;
|
||||
break;
|
||||
case 34: // lo
|
||||
cpuRegs.LO.UQ = newValue;
|
||||
break;
|
||||
default:
|
||||
cpuRegs.GPR.r[num].UQ = newValue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EECAT_CP0:
|
||||
cpuRegs.CP0.r[num] = newValue._u32[0];
|
||||
break;
|
||||
case EECAT_CP1:
|
||||
fpuRegs.fpr[num].UL = newValue._u32[0];
|
||||
break;
|
||||
case EECAT_CP2F:
|
||||
VU1.VF[num].UQ = newValue;
|
||||
break;
|
||||
case EECAT_CP2I:
|
||||
VU1.VI[num].UL = newValue._u32[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string R5900DebugInterface::disasm(u32 address)
|
||||
{
|
||||
std::string out;
|
||||
|
@ -429,7 +467,7 @@ std::string R5900DebugInterface::disasm(u32 address)
|
|||
|
||||
bool R5900DebugInterface::isValidAddress(u32 addr)
|
||||
{
|
||||
if (addr < 0x100000)
|
||||
if (addr < 0x80000)
|
||||
return false;
|
||||
if (addr >= 0x10000000 && addr < 0x10010000)
|
||||
return true;
|
||||
|
@ -442,6 +480,11 @@ bool R5900DebugInterface::isValidAddress(u32 addr)
|
|||
}
|
||||
|
||||
|
||||
u32 R5900DebugInterface::getCycles()
|
||||
{
|
||||
return cpuRegs.cycle;
|
||||
}
|
||||
|
||||
//
|
||||
// R3000DebugInterface
|
||||
//
|
||||
|
@ -617,6 +660,32 @@ void R3000DebugInterface::setPc(u32 newPc)
|
|||
psxRegs.pc = newPc;
|
||||
}
|
||||
|
||||
void R3000DebugInterface::setRegister(int cat, int num, u128 newValue)
|
||||
{
|
||||
switch (cat)
|
||||
{
|
||||
case IOPCAT_GPR:
|
||||
switch (num)
|
||||
{
|
||||
case 32: // pc
|
||||
psxRegs.pc = newValue._u32[0];
|
||||
break;
|
||||
case 33: // hi
|
||||
psxRegs.GPR.n.hi = newValue._u32[0];
|
||||
break;
|
||||
case 34: // lo
|
||||
psxRegs.GPR.n.lo = newValue._u32[0];
|
||||
break;
|
||||
default:
|
||||
psxRegs.GPR.r[num] = newValue._u32[0];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string R3000DebugInterface::disasm(u32 address)
|
||||
{
|
||||
std::string out;
|
||||
|
@ -637,3 +706,8 @@ bool R3000DebugInterface::isValidAddress(u32 addr)
|
|||
|
||||
return !(addr & 0x40000000) && vtlb_GetPhyPtr(addr & 0x1FFFFFFF) != NULL;
|
||||
}
|
||||
|
||||
u32 R3000DebugInterface::getCycles()
|
||||
{
|
||||
return psxRegs.cycle;
|
||||
}
|
||||
|
|
|
@ -27,9 +27,11 @@ public:
|
|||
virtual u128 getLO() = 0;
|
||||
virtual u32 getPC() = 0;
|
||||
virtual void setPc(u32 newPc) = 0;
|
||||
virtual void setRegister(int cat, int num, u128 newValue) = 0;
|
||||
|
||||
virtual std::string disasm(u32 address) = 0;
|
||||
virtual bool isValidAddress(u32 address) = 0;
|
||||
virtual u32 getCycles() = 0;
|
||||
|
||||
bool initExpression(const char* exp, PostfixExpression& dest);
|
||||
bool parseExpression(PostfixExpression& exp, u64& dest);
|
||||
|
@ -62,9 +64,11 @@ public:
|
|||
virtual u128 getLO();
|
||||
virtual u32 getPC();
|
||||
virtual void setPc(u32 newPc);
|
||||
virtual void setRegister(int cat, int num, u128 newValue);
|
||||
|
||||
virtual std::string disasm(u32 address);
|
||||
virtual bool isValidAddress(u32 address);
|
||||
virtual u32 getCycles();
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,9 +95,11 @@ public:
|
|||
virtual u128 getLO();
|
||||
virtual u32 getPC();
|
||||
virtual void setPc(u32 newPc);
|
||||
virtual void setRegister(int cat, int num, u128 newValue);
|
||||
|
||||
virtual std::string disasm(u32 address);
|
||||
virtual bool isValidAddress(u32 address);
|
||||
virtual u32 getCycles();
|
||||
};
|
||||
|
||||
extern R5900DebugInterface r5900Debug;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "DebugInterface.h"
|
||||
#include "SymbolMap.h"
|
||||
#include "DebugInterface.h"
|
||||
#include "../R5900.h"
|
||||
|
||||
static std::vector<MIPSAnalyst::AnalyzedFunction> functions;
|
||||
|
||||
|
@ -114,6 +115,11 @@ namespace MIPSAnalyst
|
|||
}
|
||||
*/
|
||||
if (end) {
|
||||
// most functions are aligned to 8 or 16 bytes
|
||||
// add the padding to this one
|
||||
while (r5900Debug.read32(addr+8) == 0)
|
||||
addr += 4;
|
||||
|
||||
currentFunction.end = addr + 4;
|
||||
currentFunction.isStraightLeaf = isStraightLeaf;
|
||||
functions.push_back(currentFunction);
|
||||
|
@ -122,6 +128,7 @@ namespace MIPSAnalyst
|
|||
looking = false;
|
||||
end = false;
|
||||
isStraightLeaf = true;
|
||||
|
||||
currentFunction.start = addr+4;
|
||||
}
|
||||
}
|
||||
|
@ -355,6 +362,10 @@ namespace MIPSAnalyst
|
|||
switch (MIPS_GET_OP(op)) {
|
||||
case 0: // special
|
||||
switch (MIPS_GET_FUNC(op)) {
|
||||
case 0x0C: // syscall
|
||||
info.isSyscall = true;
|
||||
info.branchTarget = 0x80000000+0x180;
|
||||
break;
|
||||
case 0x20: // add
|
||||
case 0x21: // addu
|
||||
info.hasRelevantAddress = true;
|
||||
|
@ -372,6 +383,27 @@ namespace MIPSAnalyst
|
|||
info.hasRelevantAddress = true;
|
||||
info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+((s16)(op & 0xFFFF));
|
||||
break;
|
||||
case 0x10: // cop0
|
||||
switch (MIPS_GET_RS(op))
|
||||
{
|
||||
case 0x10: // tlb
|
||||
switch (MIPS_GET_FUNC(op))
|
||||
{
|
||||
case 0x18: // eret
|
||||
info.isBranch = true;
|
||||
info.isConditional = false;
|
||||
|
||||
// probably shouldn't be hard coded like this...
|
||||
if (cpuRegs.CP0.n.Status.b.ERL) {
|
||||
info.branchTarget = cpuRegs.CP0.n.ErrorEPC;
|
||||
} else {
|
||||
info.branchTarget = cpuRegs.CP0.n.EPC;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: rest
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace MIPSAnalyst
|
|||
|
||||
// branches
|
||||
u32 branchTarget;
|
||||
bool isSyscall;
|
||||
bool isBranch;
|
||||
bool isLinkedBranch;
|
||||
bool isLikelyBranch;
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
static const u32 INVALID_ADDRESS = (u32)-1;
|
||||
|
||||
void UpdateActiveSymbols();
|
||||
|
||||
bool IsEmpty() const { return activeFunctions.empty() && activeLabels.empty() && activeData.empty(); };
|
||||
private:
|
||||
void AssignFunctionIndices();
|
||||
const char *GetLabelName(u32 address) const;
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace PathDefs
|
|||
extern wxDirName GetLangs();
|
||||
extern wxDirName GetCheats();
|
||||
extern wxDirName GetCheatsWS();
|
||||
extern wxDirName GetDocs();
|
||||
|
||||
extern wxDirName Get( FoldersEnum_t folderidx );
|
||||
|
||||
|
@ -81,6 +82,7 @@ namespace PathDefs
|
|||
extern const wxDirName& Langs();
|
||||
extern const wxDirName& Cheats();
|
||||
extern const wxDirName& CheatsWS();
|
||||
extern const wxDirName& Docs();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -371,6 +371,28 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
|||
IniBitBool( FMVinSoftwareHack );
|
||||
}
|
||||
|
||||
|
||||
Pcsx2Config::DebugOptions::DebugOptions()
|
||||
{
|
||||
EnableDebugger = false;
|
||||
ShowDebuggerOnStart = false;
|
||||
FontWidth = 8;
|
||||
FontHeight = 12;
|
||||
}
|
||||
|
||||
void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini )
|
||||
{
|
||||
ScopedIniGroup path( ini, L"Debugger" );
|
||||
|
||||
IniBitBool( EnableDebugger );
|
||||
IniBitBool( ShowDebuggerOnStart );
|
||||
IniBitfield(FontWidth);
|
||||
IniBitfield(FontHeight);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Pcsx2Config::Pcsx2Config()
|
||||
{
|
||||
bitset = 0;
|
||||
|
@ -405,6 +427,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
|
|||
Gamefixes .LoadSave( ini );
|
||||
Profiler .LoadSave( ini );
|
||||
|
||||
Debugger .LoadSave( ini );
|
||||
Trace .LoadSave( ini );
|
||||
|
||||
ini.Flush();
|
||||
|
|
|
@ -230,11 +230,12 @@ void SysCoreThread::GameStartingInThread()
|
|||
{
|
||||
GetMTGS().SendGameCRC(ElfCRC);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (EmuConfig.Debugger.EnableDebugger)
|
||||
{
|
||||
MIPSAnalyst::ScanForFunctions(ElfTextRange.first,ElfTextRange.first+ElfTextRange.second,true);
|
||||
symbolMap.UpdateActiveSymbols();
|
||||
sApp.PostAppMethod(&Pcsx2App::resetDebugger);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (EmuConfig.EnablePatches) ApplyPatch(0);
|
||||
if (EmuConfig.EnableCheats) ApplyCheat(0);
|
||||
|
|
|
@ -95,6 +95,12 @@ namespace PathDefs
|
|||
static const wxDirName retval( L"themes" );
|
||||
return retval;
|
||||
}
|
||||
|
||||
const wxDirName& Docs()
|
||||
{
|
||||
static const wxDirName retval( L"docs" );
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
// Specifies the root folder for the application install.
|
||||
|
@ -191,6 +197,11 @@ namespace PathDefs
|
|||
return GetDocuments() + Base::CheatsWS();
|
||||
}
|
||||
|
||||
wxDirName GetDocs()
|
||||
{
|
||||
return AppRoot() + Base::Docs();
|
||||
}
|
||||
|
||||
wxDirName GetSavestates()
|
||||
{
|
||||
return GetDocuments() + Base::Savestates();
|
||||
|
|
|
@ -88,9 +88,22 @@ void Pcsx2App::OpenMainFrame()
|
|||
MainEmuFrame* mainFrame = new MainEmuFrame( NULL, pxGetAppName() );
|
||||
m_id_MainFrame = mainFrame->GetId();
|
||||
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||
#endif
|
||||
{
|
||||
DisassemblyDialog* disassembly = new DisassemblyDialog( mainFrame );
|
||||
m_id_Disassembler = disassembly->GetId();
|
||||
|
||||
if (g_Conf->EmuOptions.Debugger.ShowDebuggerOnStart)
|
||||
disassembly->Show();
|
||||
}
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
else {
|
||||
m_id_Disassembler = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
PostIdleAppMethod( &Pcsx2App::OpenProgramLog );
|
||||
|
||||
SetTopWindow( mainFrame ); // not really needed...
|
||||
|
|
|
@ -1043,6 +1043,7 @@ protected:
|
|||
DbgCon.WriteLn( Color_Gray, "(SysExecute) received." );
|
||||
|
||||
CoreThread.ResetQuick();
|
||||
symbolMap.Clear();
|
||||
|
||||
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
|
||||
if( m_UseCDVDsrc )
|
||||
|
|
|
@ -229,10 +229,10 @@ bool BreakpointWindow::fetchDialogData()
|
|||
onChange = checkOnChange->GetValue();
|
||||
|
||||
// parse address
|
||||
wxCharBuffer addressText = editAddress->GetLabel().ToUTF8();
|
||||
wxCharBuffer addressText = editAddress->GetValue().ToUTF8();
|
||||
if (cpu->initExpression(addressText,exp) == false)
|
||||
{
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetLabel().wchar_str().data());
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetValue().wchar_str().data());
|
||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ bool BreakpointWindow::fetchDialogData()
|
|||
u64 value;
|
||||
if (cpu->parseExpression(exp,value) == false)
|
||||
{
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetLabel().wchar_str().data());
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetValue().wchar_str().data());
|
||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
@ -249,17 +249,17 @@ bool BreakpointWindow::fetchDialogData()
|
|||
if (memory)
|
||||
{
|
||||
// parse size
|
||||
wxCharBuffer sizeText = editSize->GetLabel().ToUTF8();
|
||||
wxCharBuffer sizeText = editSize->GetValue().ToUTF8();
|
||||
if (cpu->initExpression(sizeText,exp) == false)
|
||||
{
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetLabel().wchar_str().data());
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetValue().wchar_str().data());
|
||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cpu->parseExpression(exp,value) == false)
|
||||
{
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetLabel().wchar_str().data());
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetValue().wchar_str().data());
|
||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ bool BreakpointWindow::fetchDialogData()
|
|||
}
|
||||
|
||||
// condition
|
||||
wxCharBuffer conditionText = editCondition->GetLabel().ToUTF8();
|
||||
wxCharBuffer conditionText = editCondition->GetValue().ToUTF8();
|
||||
strncpy(condition,conditionText,sizeof(condition));
|
||||
condition[sizeof(condition)-1] = 0;
|
||||
|
||||
|
@ -276,7 +276,7 @@ bool BreakpointWindow::fetchDialogData()
|
|||
{
|
||||
if (cpu->initExpression(condition,compiledCondition) == false)
|
||||
{
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editCondition->GetLabel().wchar_str().data());
|
||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editCondition->GetValue().wchar_str().data());
|
||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "DebugEvents.h"
|
||||
#include "BreakpointWindow.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/clipbrd.h>
|
||||
|
@ -65,8 +66,8 @@ CtrlDisassemblyView::CtrlDisassemblyView(wxWindow* parent, DebugInterface* _cpu)
|
|||
{
|
||||
manager.setCpu(cpu);
|
||||
windowStart = 0x100000;
|
||||
rowHeight = 14;
|
||||
charWidth = 8;
|
||||
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
||||
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||
displaySymbols = true;
|
||||
visibleRows = 1;
|
||||
|
||||
|
@ -105,9 +106,13 @@ WXLRESULT CtrlDisassemblyView::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPA
|
|||
switch (nMsg)
|
||||
{
|
||||
case 0x0104: // WM_SYSKEYDOWN, make f10 usable
|
||||
if (wParam == 0x79) // f10
|
||||
{
|
||||
postEvent(debEVT_STEPOVER,0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return wxWindow::MSWWindowProc(nMsg,wParam,lParam);
|
||||
}
|
||||
|
@ -684,7 +689,10 @@ void CtrlDisassemblyView::keydownEvent(wxKeyEvent& evt)
|
|||
break;
|
||||
case WXK_F10:
|
||||
postEvent(debEVT_STEPOVER,0);
|
||||
break;
|
||||
return;
|
||||
case WXK_F11:
|
||||
postEvent(debEVT_STEPINTO,0);
|
||||
return;
|
||||
default:
|
||||
evt.Skip();
|
||||
break;
|
||||
|
@ -1051,3 +1059,11 @@ void CtrlDisassemblyView::editBreakpoint()
|
|||
postEvent(debEVT_UPDATE,0);
|
||||
}
|
||||
}
|
||||
|
||||
void CtrlDisassemblyView::getOpcodeText(u32 address, char* dest)
|
||||
{
|
||||
DisassemblyLineInfo line;
|
||||
address = manager.getStartAddress(address);
|
||||
manager.getLine(address,displaySymbols,line);
|
||||
sprintf(dest,"%s %s",line.name.c_str(),line.params.c_str());
|
||||
}
|
|
@ -22,6 +22,7 @@ public:
|
|||
void scanFunctions();
|
||||
void clearFunctions() { manager.clear(); };
|
||||
void redraw();
|
||||
void getOpcodeText(u32 address, char* dest);
|
||||
|
||||
u32 getInstructionSizeAt(u32 address)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "CtrlMemView.h"
|
||||
#include "DebugTools/Debug.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "BreakpointWindow.h"
|
||||
#include "DebugEvents.h"
|
||||
|
@ -35,8 +36,8 @@ enum MemoryViewMenuIdentifiers
|
|||
CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS), cpu(_cpu)
|
||||
{
|
||||
rowHeight = 12;
|
||||
charWidth = 8;
|
||||
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight;
|
||||
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||
windowStart = 0x480000;
|
||||
curAddress = windowStart;
|
||||
rowSize = 16;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "DebugTools/Debug.h"
|
||||
|
||||
#include "DebugEvents.h"
|
||||
#include "AppConfig.h"
|
||||
|
||||
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
|
||||
EVT_PAINT(CtrlRegisterList::paintEvent)
|
||||
|
@ -18,14 +19,17 @@ enum DisassemblyMenuIdentifiers
|
|||
ID_REGISTERLIST_DISPLAY32 = 1,
|
||||
ID_REGISTERLIST_DISPLAY64,
|
||||
ID_REGISTERLIST_DISPLAY128,
|
||||
ID_REGISTERLIST_CHANGELOWER,
|
||||
ID_REGISTERLIST_CHANGEUPPER,
|
||||
ID_REGISTERLIST_CHANGEVALUE
|
||||
};
|
||||
|
||||
|
||||
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER), cpu(_cpu)
|
||||
{
|
||||
rowHeight = 14;
|
||||
charWidth = 8;
|
||||
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
||||
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||
category = 0;
|
||||
maxBits = 128;
|
||||
|
||||
|
@ -48,12 +52,6 @@ CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
|||
currentRows.push_back(0);
|
||||
}
|
||||
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
||||
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
|
||||
|
||||
SetDoubleBuffered(true);
|
||||
SetInitialBestSize(ClientToWindowSize(GetMinClientSize()));
|
||||
}
|
||||
|
@ -297,6 +295,46 @@ void CtrlRegisterList::render(wxDC& dc)
|
|||
}
|
||||
}
|
||||
|
||||
void CtrlRegisterList::changeValue(RegisterChangeMode mode)
|
||||
{
|
||||
wchar_t str[64];
|
||||
|
||||
u128 oldValue = cpu->getRegister(category,currentRows[category]);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case LOWER64:
|
||||
swprintf(str,64,L"0x%016llX",oldValue._u64[0]);
|
||||
break;
|
||||
case UPPER64:
|
||||
swprintf(str,64,L"0x%016llX",oldValue._u64[1]);
|
||||
break;
|
||||
case CHANGE32:
|
||||
swprintf(str,64,L"0x%08X",oldValue._u32[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
u64 newValue;
|
||||
if (executeExpressionWindow(this,cpu,newValue,str))
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case LOWER64:
|
||||
oldValue._u64[0] = newValue;
|
||||
break;
|
||||
case UPPER64:
|
||||
oldValue._u64[1] = newValue;
|
||||
break;
|
||||
case CHANGE32:
|
||||
oldValue._u32[0] = newValue;
|
||||
break;
|
||||
}
|
||||
|
||||
cpu->setRegister(category,currentRows[category],oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||
{
|
||||
switch (evt.GetId())
|
||||
|
@ -319,6 +357,21 @@ void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
|||
postEvent(debEVT_UPDATELAYOUT,0);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGELOWER:
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEUPPER:
|
||||
changeValue(UPPER64);
|
||||
Refresh();
|
||||
break;
|
||||
case ID_REGISTERLIST_CHANGEVALUE:
|
||||
if (cpu->getRegisterSize(category) == 32)
|
||||
changeValue(CHANGE32);
|
||||
else
|
||||
changeValue(LOWER64);
|
||||
Refresh();
|
||||
break;
|
||||
default:
|
||||
wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
||||
break;
|
||||
|
@ -374,6 +427,36 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
|||
setCurrentRow(row);
|
||||
}
|
||||
|
||||
wxMenu menu;
|
||||
int bits = cpu->getRegisterSize(category);
|
||||
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||
menu.AppendSeparator();
|
||||
|
||||
if (bits >= 64)
|
||||
{
|
||||
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
||||
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
||||
} else {
|
||||
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||
}
|
||||
|
||||
switch (maxBits)
|
||||
{
|
||||
case 128:
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
||||
break;
|
||||
case 64:
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY64,true);
|
||||
break;
|
||||
case 32:
|
||||
menu.Check(ID_REGISTERLIST_DISPLAY32,true);
|
||||
break;
|
||||
}
|
||||
|
||||
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
|
||||
PopupMenu(&menu,evt.GetPosition());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -46,9 +46,12 @@ public:
|
|||
return GetMinClientSize();
|
||||
}
|
||||
private:
|
||||
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
||||
|
||||
void render(wxDC& dc);
|
||||
void refreshChangedRegs();
|
||||
void setCurrentRow(int row);
|
||||
void changeValue(RegisterChangeMode mode);
|
||||
|
||||
void postEvent(wxEventType type, wxString text);
|
||||
void postEvent(wxEventType type, int value);
|
||||
|
@ -68,5 +71,4 @@ private:
|
|||
u32 lastPc;
|
||||
int category;
|
||||
int maxBits;
|
||||
wxMenu menu;
|
||||
};
|
|
@ -8,6 +8,7 @@ DEFINE_LOCAL_EVENT_TYPE( debEVT_GOTOINDISASM )
|
|||
DEFINE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPOVER )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPINTO )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_UPDATE )
|
||||
|
||||
bool parseExpression(const char* exp, DebugInterface* cpu, u64& dest)
|
||||
|
@ -22,9 +23,9 @@ void displayExpressionError(wxWindow* parent)
|
|||
wxMessageBox(wxString(getExpressionError(),wxConvUTF8),L"Invalid expression",wxICON_ERROR);
|
||||
}
|
||||
|
||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest)
|
||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, const wxString& defaultValue)
|
||||
{
|
||||
wxString result = wxGetTextFromUser(L"Enter expression",L"Expression",wxEmptyString,parent);
|
||||
wxString result = wxGetTextFromUser(L"Enter expression",L"Expression",defaultValue,parent);
|
||||
if (result.empty())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ DECLARE_LOCAL_EVENT_TYPE( debEVT_GOTOINDISASM, wxNewEventType() )
|
|||
DECLARE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPOVER, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPINTO, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_UPDATE, wxNewEventType() )
|
||||
|
||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest);
|
||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, const wxString& defaultValue = wxEmptyString);
|
||||
|
|
|
@ -0,0 +1,334 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "DebuggerLists.h"
|
||||
#include "BreakpointWindow.h"
|
||||
#include "DebugEvents.h"
|
||||
|
||||
void insertListViewColumns(wxListCtrl* list, GenericListViewColumn* columns, int count)
|
||||
{
|
||||
int totalWidth = list->GetSize().x;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
wxListItem column;
|
||||
column.SetText(columns[i].name);
|
||||
column.SetWidth(totalWidth * columns[i].size);
|
||||
|
||||
list->InsertColumn(i,column);
|
||||
}
|
||||
}
|
||||
|
||||
void resizeListViewColumns(wxListCtrl* list, GenericListViewColumn* columns, int count, int totalWidth)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
list->SetColumnWidth(i,totalWidth*columns[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// BreakpointList
|
||||
//
|
||||
|
||||
BEGIN_EVENT_TABLE(BreakpointList, wxWindow)
|
||||
EVT_SIZE(BreakpointList::sizeEvent)
|
||||
EVT_KEY_DOWN(BreakpointList::keydownEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_CONDITION, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT };
|
||||
|
||||
GenericListViewColumn breakpointColumns[BPL_COLUMNCOUNT] = {
|
||||
{ L"Type", 0.12f },
|
||||
{ L"Offset", 0.12f },
|
||||
{ L"Size/Label", 0.18f },
|
||||
{ L"Opcode", 0.28f },
|
||||
{ L"Condition", 0.17f },
|
||||
{ L"Hits", 0.05f },
|
||||
{ L"Enabled", 0.08f }
|
||||
};
|
||||
|
||||
BreakpointList::BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly)
|
||||
: wxListView(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxLC_VIRTUAL|wxLC_REPORT|wxLC_SINGLE_SEL|wxNO_BORDER), cpu(_cpu), disasm(_disassembly)
|
||||
{
|
||||
insertListViewColumns(this,breakpointColumns,BPL_COLUMNCOUNT);
|
||||
}
|
||||
|
||||
void BreakpointList::sizeEvent(wxSizeEvent& evt)
|
||||
{
|
||||
resizeListViewColumns(this,breakpointColumns,BPL_COLUMNCOUNT,evt.GetSize().x);
|
||||
}
|
||||
|
||||
void BreakpointList::update()
|
||||
{
|
||||
int newRows = getTotalBreakpointCount();
|
||||
SetItemCount(newRows);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
int BreakpointList::getTotalBreakpointCount()
|
||||
{
|
||||
int count = (int)CBreakPoints::GetMemChecks().size();
|
||||
for (size_t i = 0; i < CBreakPoints::GetBreakpoints().size(); i++)
|
||||
{
|
||||
if (!displayedBreakPoints_[i].temporary) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
wxString BreakpointList::OnGetItemText(long item, long col) const
|
||||
{
|
||||
wchar_t dest[256];
|
||||
bool isMemory;
|
||||
int index = getBreakpointIndex(item,isMemory);
|
||||
if (index == -1) return L"Invalid";
|
||||
|
||||
switch (col)
|
||||
{
|
||||
case BPL_TYPE:
|
||||
{
|
||||
if (isMemory) {
|
||||
switch ((int)displayedMemChecks_[index].cond) {
|
||||
case MEMCHECK_READ:
|
||||
wcscpy(dest,L"Read");
|
||||
break;
|
||||
case MEMCHECK_WRITE:
|
||||
wcscpy(dest,L"Write");
|
||||
break;
|
||||
case MEMCHECK_READWRITE:
|
||||
wcscpy(dest,L"Read/Write");
|
||||
break;
|
||||
case MEMCHECK_WRITE | MEMCHECK_WRITE_ONCHANGE:
|
||||
wcscpy(dest,L"Write Change");
|
||||
break;
|
||||
case MEMCHECK_READWRITE | MEMCHECK_WRITE_ONCHANGE:
|
||||
wcscpy(dest,L"Read/Write Change");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wcscpy(dest,L"Execute");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_OFFSET:
|
||||
{
|
||||
if (isMemory) {
|
||||
swprintf(dest,256,L"0x%08X",displayedMemChecks_[index].start);
|
||||
} else {
|
||||
swprintf(dest,256,L"0x%08X",displayedBreakPoints_[index].addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_SIZELABEL:
|
||||
{
|
||||
if (isMemory) {
|
||||
auto mc = displayedMemChecks_[index];
|
||||
if (mc.end == 0)
|
||||
swprintf(dest,256,L"0x%08X",1);
|
||||
else
|
||||
swprintf(dest,256,L"0x%08X",mc.end-mc.start);
|
||||
} else {
|
||||
const std::string sym = symbolMap.GetLabelString(displayedBreakPoints_[index].addr);
|
||||
if (!sym.empty())
|
||||
{
|
||||
swprintf(dest,256,L"%S",sym.c_str());
|
||||
} else {
|
||||
wcscpy(dest,L"-");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_OPCODE:
|
||||
{
|
||||
if (isMemory) {
|
||||
wcscpy(dest,L"-");
|
||||
} else {
|
||||
char temp[256];
|
||||
disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp);
|
||||
swprintf(dest,256,L"%S",temp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_CONDITION:
|
||||
{
|
||||
if (isMemory || displayedBreakPoints_[index].hasCond == false) {
|
||||
wcscpy(dest,L"-");
|
||||
} else {
|
||||
swprintf(dest,256,L"%S",displayedBreakPoints_[index].cond.expressionString);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_HITS:
|
||||
{
|
||||
if (isMemory) {
|
||||
swprintf(dest,256,L"%d",displayedMemChecks_[index].numHits);
|
||||
} else {
|
||||
swprintf(dest,256,L"-");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BPL_ENABLED:
|
||||
{
|
||||
if (isMemory) {
|
||||
swprintf(dest,256,L"%S",displayedMemChecks_[index].cond & MEMCHECK_BREAK ? "true" : "false");
|
||||
} else {
|
||||
swprintf(dest,256,L"%S",displayedBreakPoints_[index].enabled ? "true" : "false");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return L"Invalid";
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void BreakpointList::keydownEvent(wxKeyEvent& evt)
|
||||
{
|
||||
int sel = GetFirstSelected();
|
||||
switch (evt.GetKeyCode())
|
||||
{
|
||||
case WXK_DELETE:
|
||||
if (sel+1 == GetItemCount())
|
||||
Select(sel-1);
|
||||
removeBreakpoint(sel);
|
||||
break;
|
||||
case WXK_UP:
|
||||
if (sel > 0)
|
||||
Select(sel-1);
|
||||
break;
|
||||
case WXK_DOWN:
|
||||
if (sel+1 < GetItemCount())
|
||||
Select(sel+1);
|
||||
break;
|
||||
case WXK_RETURN:
|
||||
editBreakpoint(sel);
|
||||
break;
|
||||
case WXK_SPACE:
|
||||
toggleEnabled(sel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int BreakpointList::getBreakpointIndex(int itemIndex, bool& isMemory) const
|
||||
{
|
||||
// memory breakpoints first
|
||||
if (itemIndex < (int)displayedMemChecks_.size())
|
||||
{
|
||||
isMemory = true;
|
||||
return itemIndex;
|
||||
}
|
||||
|
||||
itemIndex -= (int)displayedMemChecks_.size();
|
||||
|
||||
size_t i = 0;
|
||||
while (i < displayedBreakPoints_.size())
|
||||
{
|
||||
if (displayedBreakPoints_[i].temporary)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// the index is 0 when there are no more breakpoints to skip
|
||||
if (itemIndex == 0)
|
||||
{
|
||||
isMemory = false;
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
i++;
|
||||
itemIndex--;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BreakpointList::reloadBreakpoints()
|
||||
{
|
||||
// Update the items we're displaying from the debugger.
|
||||
displayedBreakPoints_ = CBreakPoints::GetBreakpoints();
|
||||
displayedMemChecks_= CBreakPoints::GetMemChecks();
|
||||
update();
|
||||
}
|
||||
|
||||
void BreakpointList::editBreakpoint(int itemIndex)
|
||||
{
|
||||
bool isMemory;
|
||||
int index = getBreakpointIndex(itemIndex, isMemory);
|
||||
if (index == -1) return;
|
||||
|
||||
BreakpointWindow win(this,cpu);
|
||||
if (isMemory)
|
||||
{
|
||||
auto mem = displayedMemChecks_[index];
|
||||
win.loadFromMemcheck(mem);
|
||||
if (win.ShowModal() == wxID_OK)
|
||||
{
|
||||
CBreakPoints::RemoveMemCheck(mem.start,mem.end);
|
||||
win.addBreakpoint();
|
||||
}
|
||||
} else {
|
||||
auto bp = displayedBreakPoints_[index];
|
||||
win.loadFromBreakpoint(bp);
|
||||
if (win.ShowModal() == wxID_OK)
|
||||
{
|
||||
CBreakPoints::RemoveBreakPoint(bp.addr);
|
||||
win.addBreakpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointList::toggleEnabled(int itemIndex)
|
||||
{
|
||||
bool isMemory;
|
||||
int index = getBreakpointIndex(itemIndex, isMemory);
|
||||
if (index == -1) return;
|
||||
|
||||
if (isMemory) {
|
||||
MemCheck mcPrev = displayedMemChecks_[index];
|
||||
CBreakPoints::ChangeMemCheck(mcPrev.start, mcPrev.end, mcPrev.cond, MemCheckResult(mcPrev.result ^ MEMCHECK_BREAK));
|
||||
} else {
|
||||
BreakPoint bpPrev = displayedBreakPoints_[index];
|
||||
CBreakPoints::ChangeBreakPoint(bpPrev.addr, !bpPrev.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointList::gotoBreakpointAddress(int itemIndex)
|
||||
{
|
||||
bool isMemory;
|
||||
int index = getBreakpointIndex(itemIndex,isMemory);
|
||||
if (index == -1) return;
|
||||
|
||||
if (isMemory)
|
||||
{
|
||||
u32 address = displayedMemChecks_[index].start;
|
||||
postEvent(debEVT_GOTOINMEMORYVIEW,address);
|
||||
} else {
|
||||
u32 address = displayedBreakPoints_[index].addr;
|
||||
postEvent(debEVT_GOTOINDISASM,address);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointList::removeBreakpoint(int itemIndex)
|
||||
{
|
||||
bool isMemory;
|
||||
int index = getBreakpointIndex(itemIndex,isMemory);
|
||||
if (index == -1) return;
|
||||
|
||||
if (isMemory)
|
||||
{
|
||||
auto mc = displayedMemChecks_[index];
|
||||
CBreakPoints::RemoveMemCheck(mc.start, mc.end);
|
||||
} else {
|
||||
u32 address = displayedBreakPoints_[index].addr;
|
||||
CBreakPoints::RemoveBreakPoint(address);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointList::postEvent(wxEventType type, int value)
|
||||
{
|
||||
wxCommandEvent event( type, GetId() );
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(value);
|
||||
wxPostEvent(this,event);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include <wx/listctrl.h>
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "CtrlDisassemblyView.h"
|
||||
|
||||
struct GenericListViewColumn
|
||||
{
|
||||
wchar_t *name;
|
||||
float size;
|
||||
int flags;
|
||||
};
|
||||
|
||||
class BreakpointList: public wxListView
|
||||
{
|
||||
public:
|
||||
BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly);
|
||||
void reloadBreakpoints();
|
||||
void update();
|
||||
DECLARE_EVENT_TABLE()
|
||||
protected:
|
||||
wxString OnGetItemText(long item, long col) const;
|
||||
|
||||
void sizeEvent(wxSizeEvent& evt);
|
||||
void keydownEvent(wxKeyEvent& evt);
|
||||
private:
|
||||
int getBreakpointIndex(int itemIndex, bool& isMemory) const;
|
||||
int getTotalBreakpointCount();
|
||||
void editBreakpoint(int itemIndex);
|
||||
void toggleEnabled(int itemIndex);
|
||||
void gotoBreakpointAddress(int itemIndex);
|
||||
void removeBreakpoint(int itemIndex);
|
||||
void postEvent(wxEventType type, int value);
|
||||
|
||||
std::vector<BreakPoint> displayedBreakPoints_;
|
||||
std::vector<MemCheck> displayedMemChecks_;
|
||||
DebugInterface* cpu;
|
||||
CtrlDisassemblyView* disasm;
|
||||
};
|
|
@ -5,6 +5,11 @@
|
|||
#include "DebugTools/DisassemblyManager.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "BreakpointWindow.h"
|
||||
#include "PathDefs.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
||||
EVT_COMMAND( wxID_ANY, debEVT_SETSTATUSBARTEXT, DisassemblyDialog::onDebuggerEvent )
|
||||
|
@ -13,9 +18,39 @@ BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
|||
EVT_COMMAND( wxID_ANY, debEVT_RUNTOPOS, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_GOTOINDISASM, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_STEPOVER, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_STEPINTO, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_CLOSE( DisassemblyDialog::onClose )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
DebuggerHelpDialog::DebuggerHelpDialog(wxWindow* parent)
|
||||
: wxDialog(parent,wxID_ANY,L"Help")
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxTextCtrl* textControl = new wxTextCtrl(this,wxID_ANY,L"",wxDefaultPosition,wxDefaultSize,
|
||||
wxTE_MULTILINE|wxTE_READONLY);
|
||||
textControl->SetMinSize(wxSize(400,300));
|
||||
auto fileName = PathDefs::GetDocs().ToString()+L"/debugger.txt";
|
||||
wxTextFile file(fileName);
|
||||
if (file.Open())
|
||||
{
|
||||
wxString text = file.GetFirstLine();
|
||||
while (!file.Eof())
|
||||
{
|
||||
text += file.GetNextLine()+L"\r\n";
|
||||
}
|
||||
|
||||
textControl->SetLabel(text);
|
||||
textControl->SetSelection(0,0);
|
||||
}
|
||||
|
||||
sizer->Add(textControl,1,wxEXPAND);
|
||||
SetSizerAndFit(sizer);
|
||||
}
|
||||
|
||||
|
||||
CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
||||
: wxPanel(parent), cpu(_cpu)
|
||||
{
|
||||
|
@ -39,11 +74,34 @@ CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
|||
|
||||
// create bottom section
|
||||
bottomTabs->AddPage(memory,L"Memory");
|
||||
|
||||
breakpointList = new BreakpointList(bottomTabs,cpu,disassembly);
|
||||
bottomTabs->AddPage(breakpointList,L"Breakpoints");
|
||||
|
||||
mainSizer->Add(bottomTabs,1,wxEXPAND);
|
||||
|
||||
mainSizer->Layout();
|
||||
}
|
||||
|
||||
void CpuTabPage::setBottomTabPage(wxWindow* win)
|
||||
{
|
||||
for (size_t i = 0; i < bottomTabs->GetPageCount(); i++)
|
||||
{
|
||||
if (bottomTabs->GetPage(i) == win)
|
||||
{
|
||||
bottomTabs->SetSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CpuTabPage::update()
|
||||
{
|
||||
breakpointList->reloadBreakpoints();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
||||
wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ),
|
||||
currentCpu(NULL)
|
||||
|
@ -63,6 +121,7 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
|||
|
||||
stepIntoButton = new wxButton( panel, wxID_ANY, L"Step Into" );
|
||||
stepIntoButton->Enable(false);
|
||||
Connect( stepIntoButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisassemblyDialog::onStepIntoClicked ) );
|
||||
topRowSizer->Add(stepIntoButton,0,wxBOTTOM,2);
|
||||
|
||||
stepOverButton = new wxButton( panel, wxID_ANY, L"Step Over" );
|
||||
|
@ -99,11 +158,43 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
|||
setDebugMode(true);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
WXLRESULT DisassemblyDialog::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
{
|
||||
switch (nMsg)
|
||||
{
|
||||
case WM_SHOWWINDOW:
|
||||
{
|
||||
WXHWND hwnd = GetHWND();
|
||||
|
||||
u32 style = GetWindowLong((HWND)hwnd,GWL_STYLE);
|
||||
style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
|
||||
SetWindowLong((HWND)hwnd,GWL_STYLE,style);
|
||||
|
||||
u32 exStyle = GetWindowLong((HWND)hwnd,GWL_EXSTYLE);
|
||||
exStyle |= (WS_EX_CONTEXTHELP);
|
||||
SetWindowLong((HWND)hwnd,GWL_EXSTYLE,exStyle);
|
||||
}
|
||||
break;
|
||||
case WM_SYSCOMMAND:
|
||||
if (wParam == SC_CONTEXTHELP)
|
||||
{
|
||||
DebuggerHelpDialog help(this);
|
||||
help.ShowModal();
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return wxFrame::MSWWindowProc(nMsg,wParam,lParam);
|
||||
}
|
||||
#endif
|
||||
|
||||
void DisassemblyDialog::onBreakRunClicked(wxCommandEvent& evt)
|
||||
{
|
||||
if (r5900Debug.isCpuPaused())
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(r5900Debug.getPC()))
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
r5900Debug.resumeCpu();
|
||||
} else
|
||||
|
@ -115,6 +206,11 @@ void DisassemblyDialog::onStepOverClicked(wxCommandEvent& evt)
|
|||
stepOver();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onStepIntoClicked(wxCommandEvent& evt)
|
||||
{
|
||||
stepInto();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
||||
{
|
||||
wxNotebook* notebook = (wxNotebook*)wxWindow::FindWindowById(evt.GetId());
|
||||
|
@ -130,7 +226,7 @@ void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
|||
if (currentCpu != NULL)
|
||||
{
|
||||
currentCpu->getDisassembly()->SetFocus();
|
||||
currentCpu->Refresh();
|
||||
currentCpu->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,6 +277,48 @@ void DisassemblyDialog::stepOver()
|
|||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
|
||||
void DisassemblyDialog::stepInto()
|
||||
{
|
||||
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||
return;
|
||||
|
||||
// todo: breakpoints for iop
|
||||
if (currentCpu != eeTab)
|
||||
return;
|
||||
|
||||
CtrlDisassemblyView* disassembly = currentCpu->getDisassembly();
|
||||
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
u32 currentPc = r5900Debug.getPC();
|
||||
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(&r5900Debug,r5900Debug.getPC());
|
||||
u32 breakpointAddress = currentPc+disassembly->getInstructionSizeAt(currentPc);
|
||||
if (info.isBranch)
|
||||
{
|
||||
if (info.isConditional == false)
|
||||
{
|
||||
breakpointAddress = info.branchTarget;
|
||||
} else {
|
||||
if (info.conditionMet)
|
||||
{
|
||||
breakpointAddress = info.branchTarget;
|
||||
} else {
|
||||
breakpointAddress = currentPc+2*4;
|
||||
disassembly->scrollStepping(breakpointAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.isSyscall)
|
||||
breakpointAddress = info.branchTarget;
|
||||
|
||||
CBreakPoints::AddBreakPoint(breakpointAddress,true);
|
||||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
|
||||
void DisassemblyDialog::onBreakpointClick(wxCommandEvent& evt)
|
||||
{
|
||||
if (currentCpu == NULL)
|
||||
|
@ -209,7 +347,11 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
|||
} else if (type == debEVT_GOTOINMEMORYVIEW)
|
||||
{
|
||||
if (currentCpu != NULL)
|
||||
{
|
||||
currentCpu->showMemoryView();
|
||||
currentCpu->getMemoryView()->gotoAddress(evt.GetInt());
|
||||
currentCpu->getDisassembly()->SetFocus();
|
||||
}
|
||||
} else if (type == debEVT_RUNTOPOS)
|
||||
{
|
||||
// todo: breakpoints for iop
|
||||
|
@ -229,19 +371,28 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
|||
{
|
||||
if (currentCpu != NULL)
|
||||
stepOver();
|
||||
} else if (type == debEVT_STEPINTO)
|
||||
{
|
||||
if (currentCpu != NULL)
|
||||
stepInto();
|
||||
} else if (type == debEVT_UPDATE)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onClose(wxCloseEvent& evt)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::update()
|
||||
{
|
||||
if (currentCpu != NULL)
|
||||
{
|
||||
stepOverButton->Enable(true);
|
||||
breakpointButton->Enable(true);
|
||||
currentCpu->Refresh();
|
||||
currentCpu->update();
|
||||
} else {
|
||||
stepOverButton->Enable(false);
|
||||
breakpointButton->Enable(false);
|
||||
|
@ -269,13 +420,17 @@ void DisassemblyDialog::setDebugMode(bool debugMode)
|
|||
breakRunButton->SetLabel(L"Run");
|
||||
|
||||
stepOverButton->Enable(true);
|
||||
stepIntoButton->Enable(true);
|
||||
|
||||
eeTab->getDisassembly()->gotoPc();
|
||||
iopTab->getDisassembly()->gotoPc();
|
||||
|
||||
// Defocuses main window even when not debugging, causing savestate hotkeys to fail
|
||||
/*if (currentCpu != NULL)
|
||||
currentCpu->getDisassembly()->SetFocus();*/
|
||||
if (CBreakPoints::GetBreakpointTriggered())
|
||||
{
|
||||
if (currentCpu != NULL)
|
||||
currentCpu->getDisassembly()->SetFocus();
|
||||
CBreakPoints::SetBreakpointTriggered(false);
|
||||
}
|
||||
} else {
|
||||
breakRunButton->SetLabel(L"Break");
|
||||
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
#include "CtrlRegisterList.h"
|
||||
#include "CtrlMemView.h"
|
||||
#include "DebugEvents.h"
|
||||
#include "DebuggerLists.h"
|
||||
|
||||
class DebuggerHelpDialog: public wxDialog
|
||||
{
|
||||
public:
|
||||
DebuggerHelpDialog(wxWindow* parent);
|
||||
};
|
||||
|
||||
class CpuTabPage: public wxPanel
|
||||
{
|
||||
|
@ -17,12 +24,16 @@ public:
|
|||
CtrlRegisterList* getRegisterList() { return registerList; };
|
||||
CtrlMemView* getMemoryView() { return memory; };
|
||||
wxNotebook* getBottomTabs() { return bottomTabs; };
|
||||
void update();
|
||||
void showMemoryView() { setBottomTabPage(memory); };
|
||||
private:
|
||||
void setBottomTabPage(wxWindow* win);
|
||||
DebugInterface* cpu;
|
||||
CtrlDisassemblyView* disassembly;
|
||||
CtrlRegisterList* registerList;
|
||||
CtrlMemView* memory;
|
||||
wxNotebook* bottomTabs;
|
||||
BreakpointList* breakpointList;
|
||||
};
|
||||
|
||||
class DisassemblyDialog : public wxFrame
|
||||
|
@ -38,14 +49,21 @@ public:
|
|||
void reset();
|
||||
void setDebugMode(bool debugMode);
|
||||
|
||||
#ifdef WIN32
|
||||
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
||||
#endif
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
protected:
|
||||
void onBreakRunClicked(wxCommandEvent& evt);
|
||||
void onStepOverClicked(wxCommandEvent& evt);
|
||||
void onStepIntoClicked(wxCommandEvent& evt);
|
||||
void onDebuggerEvent(wxCommandEvent& evt);
|
||||
void onPageChanging(wxCommandEvent& evt);
|
||||
void onBreakpointClick(wxCommandEvent& evt);
|
||||
void onClose(wxCloseEvent& evt);
|
||||
void stepOver();
|
||||
void stepInto();
|
||||
private:
|
||||
CpuTabPage* eeTab;
|
||||
CpuTabPage* iopTab;
|
||||
|
|
|
@ -339,9 +339,14 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
|||
m_menubar.Append( &m_menuCDVD, _("CD&VD") );
|
||||
m_menubar.Append( &m_menuConfig, _("&Config") );
|
||||
m_menubar.Append( &m_menuMisc, _("&Misc") );
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
m_menubar.Append( &m_menuDebug, _("&Debug") );
|
||||
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||
#endif
|
||||
{
|
||||
m_menubar.Append( &m_menuDebug, _("&Debug") );
|
||||
}
|
||||
|
||||
SetMenuBar( &m_menubar );
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -507,11 +512,15 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
|||
m_menuMisc.AppendSeparator();
|
||||
m_menuMisc.Append( MenuId_ChangeLang, L"Change Language" ); // Always in English
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||
#endif
|
||||
{
|
||||
m_menuDebug.Append(MenuId_Debug_Open, _("Open Debug Window..."), wxEmptyString);
|
||||
//m_menuDebug.Append(MenuId_Debug_MemoryDump, _("Memory Dump..."), wxEmptyString);
|
||||
m_menuDebug.Append(MenuId_Debug_Logging, _("Logging..."), wxEmptyString);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_MenuItem_Console.Check( g_Conf->ProgLogBox.Visible );
|
||||
|
||||
ConnectMenus();
|
||||
|
|
|
@ -178,6 +178,8 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<None Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||
<None Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||
<None Include="..\..\Utilities\folderdesc.txt" />
|
||||
<None Include="..\..\Docs\License.txt" />
|
||||
<None Include="..\..\x86\aVUzerorec.S" />
|
||||
|
|
|
@ -207,6 +207,12 @@
|
|||
<None Include="..\..\gui\Dialogs\BaseConfigurationDialog.inl">
|
||||
<Filter>AppHost\Dialogs</Filter>
|
||||
</None>
|
||||
<None Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</None>
|
||||
<None Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\Patch.cpp">
|
||||
|
|
|
@ -424,6 +424,7 @@
|
|||
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
||||
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
||||
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
||||
|
@ -708,6 +709,7 @@
|
|||
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
||||
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
||||
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
||||
|
|
|
@ -844,13 +844,15 @@
|
|||
<ClCompile Include="..\..\DebugTools\SymbolMap.cpp">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\sif2.cpp">
|
||||
<Filter>System\Ps2\EmotionEngine\DMAC\Sif</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Gte.cpp">
|
||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</ClCompile> </ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
<Filter>Misc</Filter>
|
||||
|
@ -1255,10 +1257,12 @@
|
|||
<ClInclude Include="..\..\DebugTools\SymbolMap.h">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Gte.h">
|
||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</ClInclude> </ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||
<Filter>AppHost\Resources</Filter>
|
||||
|
|
|
@ -424,6 +424,7 @@
|
|||
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
||||
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
||||
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
||||
|
@ -708,6 +709,7 @@
|
|||
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
||||
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
||||
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
||||
|
|
|
@ -850,7 +850,9 @@
|
|||
<ClCompile Include="..\..\Gte.cpp">
|
||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</ClCompile> </ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
<Filter>Misc</Filter>
|
||||
|
@ -1258,7 +1260,9 @@
|
|||
<ClInclude Include="..\..\Gte.h">
|
||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||
<Filter>AppHost\Debugger</Filter>
|
||||
</ClInclude> </ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||
<Filter>AppHost\Resources</Filter>
|
||||
|
|
|
@ -1271,20 +1271,76 @@ int cop2flags(u32 code)
|
|||
void dynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc))
|
||||
{
|
||||
CBreakPoints::SetSkipFirst(0xFFFFFFFF);
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||
if (cond && !cond->Evaluate())
|
||||
return;
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
GetCoreThread().PauseSelf();
|
||||
recExitExecution();
|
||||
}
|
||||
|
||||
void dynarecMemcheck()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
return;
|
||||
|
||||
iFlushCall(FLUSH_INTERPRETER);
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
GetCoreThread().PauseSelf();
|
||||
recExitExecution();
|
||||
}
|
||||
|
||||
void recMemcheck(u32 bits, bool store)
|
||||
{
|
||||
iFlushCall(FLUSH_INTERPRETER);
|
||||
|
||||
// compute accessed address
|
||||
_eeMoveGPRtoR(ECX, _Rs_);
|
||||
if (_Imm_ != 0)
|
||||
xADD(ecx, _Imm_);
|
||||
if (bits == 128)
|
||||
xAND(ecx, ~0x0F);
|
||||
|
||||
xMOV(edx,ecx);
|
||||
xADD(edx,bits/8);
|
||||
|
||||
// ecx = access address
|
||||
// edx = access address+size
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if ((checks[i].cond & MEMCHECK_BREAK) == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store == true)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_READ) == 0 && store == false)
|
||||
continue;
|
||||
|
||||
// logic: memAddress < bpEnd && bpStart < memAddress+memSize
|
||||
|
||||
xMOV(eax,checks[i].end);
|
||||
xCMP(ecx,eax); // address < end
|
||||
xForwardJGE8 next1; // if address >= end then goto next1
|
||||
|
||||
xMOV(eax,checks[i].start);
|
||||
xCMP(eax,edx); // start < address+size
|
||||
xForwardJGE8 next2; // if start >= address+size then goto next2
|
||||
|
||||
// hit the breakpoint
|
||||
xCALL(&dynarecMemcheck);
|
||||
|
||||
next1.SetTarget();
|
||||
next2.SetTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void recompileNextInstruction(int delayslot)
|
||||
{
|
||||
static u8 s_bFlushReg = 1;
|
||||
|
@ -1304,6 +1360,54 @@ void recompileNextInstruction(int delayslot)
|
|||
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
||||
|
||||
cpuRegs.code = *(int *)s_pCode;
|
||||
|
||||
if (CBreakPoints::GetMemChecks().size() != 0)
|
||||
{
|
||||
switch (cpuRegs.code >> 26)
|
||||
{
|
||||
case 0x20: // lb
|
||||
case 0x24: // lbu
|
||||
recMemcheck(8,false);
|
||||
break;
|
||||
case 0x28: // sb
|
||||
recMemcheck(8,true);
|
||||
break;
|
||||
case 0x21: // lh
|
||||
case 0x25: // lhu
|
||||
recMemcheck(16,false);
|
||||
break;
|
||||
case 0x22: // lwl
|
||||
case 0x23: // lw
|
||||
case 0x26: // lwr
|
||||
recMemcheck(32,false);
|
||||
break;
|
||||
case 0x29: // sh
|
||||
recMemcheck(16,true);
|
||||
break;
|
||||
case 0x2A: // swl
|
||||
case 0x2B: // sw
|
||||
case 0x2E: // swr
|
||||
recMemcheck(32,true);
|
||||
break;
|
||||
case 0x37: // ld
|
||||
case 0x1B: // ldr
|
||||
case 0x1A: // ldl
|
||||
recMemcheck(64,false);
|
||||
break;
|
||||
case 0x3F: // sd
|
||||
case 0x3D: // sdr
|
||||
case 0x2C: // sdl
|
||||
recMemcheck(64,true);
|
||||
break;
|
||||
case 0x1E: // lq
|
||||
recMemcheck(128,false);
|
||||
break;
|
||||
case 0x1F: // sq
|
||||
recMemcheck(128,true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!delayslot) {
|
||||
pc += 4;
|
||||
g_cpuFlushedPC = false;
|
||||
|
@ -1554,6 +1658,44 @@ bool skipMPEG_By_Pattern(u32 sPC) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool needsBreakpoint(u32 pc)
|
||||
{
|
||||
if (CBreakPoints::IsAddressBreakPoint(pc))
|
||||
return true;
|
||||
|
||||
if (CBreakPoints::GetMemChecks().size() == 0)
|
||||
return false;
|
||||
|
||||
u32 op = memRead32(pc);
|
||||
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 0x20: // lb
|
||||
case 0x21: // lh
|
||||
case 0x22: // lwl
|
||||
case 0x23: // lw
|
||||
case 0x24: // lbu
|
||||
case 0x25: // lhu
|
||||
case 0x26: // lwr
|
||||
case 0x28: // sb
|
||||
case 0x29: // sh
|
||||
case 0x2A: // swl
|
||||
case 0x2B: // sw
|
||||
case 0x2E: // swr
|
||||
case 0x37: // ld
|
||||
case 0x1B: // ldr
|
||||
case 0x3F: // sd
|
||||
case 0x3D: // sdr
|
||||
case 0x1A: // ldl
|
||||
case 0x2C: // sdl
|
||||
case 0x1E: // lq
|
||||
case 0x1F: // sq
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void __fastcall recRecompile( const u32 startpc )
|
||||
{
|
||||
u32 i = 0;
|
||||
|
@ -1634,7 +1776,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
|||
s_branchTo = -1;
|
||||
|
||||
// compile breakpoints as individual blocks
|
||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
||||
if (needsBreakpoint(i))
|
||||
{
|
||||
s_nEndBlock = i + 4;
|
||||
goto StartRecomp;
|
||||
|
@ -1644,7 +1786,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
|||
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
||||
|
||||
// stop before breakpoints
|
||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
||||
if (needsBreakpoint(i))
|
||||
{
|
||||
s_nEndBlock = i;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue