mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-08 23:07:31 +00:00
Better branch lines
This commit is contained in:
parent
48aac7cf9f
commit
ea397351c3
@ -19,6 +19,7 @@
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "ext/xxhash.h"
|
||||
|
||||
#include <CommDlg.h>
|
||||
#include <tchar.h>
|
||||
@ -53,6 +54,157 @@ void CtrlDisAsmView::deinit()
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool used;
|
||||
u32 end;
|
||||
} LaneInfo;
|
||||
#define NUM_LANES 16
|
||||
|
||||
void CtrlDisAsmView::scanFunctions()
|
||||
{
|
||||
u32 pos = windowStart;
|
||||
u32 windowEnd = windowStart+visibleRows*instructionSize;
|
||||
|
||||
visibleFunctionAddresses.clear();
|
||||
strayLines.clear();
|
||||
|
||||
while (pos < windowEnd)
|
||||
{
|
||||
SymbolInfo info;
|
||||
if (symbolMap.GetSymbolInfo(&info,pos))
|
||||
{
|
||||
u32 hash = XXH32(Memory::GetPointer(info.address),info.size,0xBACD7814);
|
||||
u32 funcEnd = info.address+info.size;
|
||||
|
||||
visibleFunctionAddresses.push_back(info.address);
|
||||
|
||||
auto it = functions.find(info.address);
|
||||
if (it != functions.end() && it->second.hash == hash)
|
||||
{
|
||||
// function is unchaged
|
||||
pos = funcEnd;
|
||||
continue;
|
||||
}
|
||||
|
||||
DisassemblyFunction func;
|
||||
func.hash = hash;
|
||||
|
||||
LaneInfo lanes[NUM_LANES];
|
||||
for (int i = 0; i < NUM_LANES; i++)
|
||||
lanes[i].used = false;
|
||||
|
||||
|
||||
for (int funcPos = info.address; funcPos < funcEnd; funcPos += instructionSize)
|
||||
{
|
||||
MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(debugger,funcPos);
|
||||
if (opInfo.isBranch && !opInfo.isBranchToRegister && !opInfo.isLinkedBranch)
|
||||
{
|
||||
BranchLine line;
|
||||
if (opInfo.branchTarget < funcPos)
|
||||
{
|
||||
line.first = opInfo.branchTarget;
|
||||
line.second = funcPos;
|
||||
line.type = LINE_UP;
|
||||
} else {
|
||||
line.first = funcPos;
|
||||
line.second = opInfo.branchTarget;
|
||||
line.type = LINE_DOWN;
|
||||
}
|
||||
|
||||
func.lines.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < func.lines.size(); i++)
|
||||
{
|
||||
for (int l = 0; l < NUM_LANES; l++)
|
||||
{
|
||||
if (func.lines[i].first > lanes[l].end)
|
||||
lanes[l].used = false;
|
||||
}
|
||||
|
||||
int lane = -1;
|
||||
for (int i = 0; i < NUM_LANES; i++)
|
||||
{
|
||||
if (lanes[i].used == false)
|
||||
{
|
||||
lane = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lane == -1)
|
||||
{
|
||||
// error
|
||||
continue;
|
||||
}
|
||||
|
||||
lanes[lane].end = func.lines[i].second;
|
||||
lanes[lane].used = true;
|
||||
func.lines[i].laneIndex = lane;
|
||||
}
|
||||
|
||||
functions[info.address] = func;
|
||||
pos = funcEnd;
|
||||
} else {
|
||||
MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(debugger,pos);
|
||||
if (opInfo.isBranch && !opInfo.isBranchToRegister && !opInfo.isLinkedBranch)
|
||||
{
|
||||
BranchLine line;
|
||||
if (opInfo.branchTarget < pos)
|
||||
{
|
||||
line.first = opInfo.branchTarget;
|
||||
line.second = pos;
|
||||
line.type = LINE_UP;
|
||||
} else {
|
||||
line.first = pos;
|
||||
line.second = opInfo.branchTarget;
|
||||
line.type = LINE_DOWN;
|
||||
}
|
||||
|
||||
strayLines.push_back(line);
|
||||
}
|
||||
|
||||
pos += instructionSize;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate lanes for strayBranches
|
||||
LaneInfo lanes[NUM_LANES];
|
||||
for (int i = 0; i < NUM_LANES; i++)
|
||||
lanes[i].used = false;
|
||||
|
||||
for (int i = 0; i < strayLines.size(); i++)
|
||||
{
|
||||
for (int l = 0; l < NUM_LANES; l++)
|
||||
{
|
||||
if (strayLines[i].first > lanes[l].end)
|
||||
lanes[l].used = false;
|
||||
}
|
||||
|
||||
int lane = -1;
|
||||
for (int i = 0; i < NUM_LANES; i++)
|
||||
{
|
||||
if (lanes[i].used == false)
|
||||
{
|
||||
lane = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lane == -1)
|
||||
{
|
||||
// error
|
||||
continue;
|
||||
}
|
||||
|
||||
lanes[lane].end = strayLines[i].second;
|
||||
lanes[lane].used = true;
|
||||
strayLines[i].laneIndex = lane;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@ -319,17 +471,93 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CtrlDisAsmView::drawBranchLine(HDC hdc, BranchLine& line)
|
||||
{
|
||||
u32 windowEnd = windowStart+(visibleRows+2)*instructionSize;
|
||||
|
||||
int topY;
|
||||
int bottomY;
|
||||
if (line.first < windowStart)
|
||||
{
|
||||
topY = -1;
|
||||
} else if (line.first >= windowEnd)
|
||||
{
|
||||
topY = rect.bottom+1;
|
||||
} else {
|
||||
int row = (line.first-windowStart)/instructionSize;
|
||||
topY = row*rowHeight + rowHeight/2;
|
||||
}
|
||||
|
||||
if (line.second < windowStart)
|
||||
{
|
||||
bottomY = -1;
|
||||
} else if (line.second >= windowEnd)
|
||||
{
|
||||
bottomY = rect.bottom+1;
|
||||
} else {
|
||||
int row = (line.second-windowStart)/instructionSize;
|
||||
bottomY = row*rowHeight + rowHeight/2;
|
||||
}
|
||||
|
||||
if ((topY < 0 && bottomY < 0) || (topY > rect.bottom && bottomY > rect.bottom))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int x = pixelPositions.arrowsStart+line.laneIndex*8;
|
||||
if (topY < 0) // first is not visible, but second is
|
||||
{
|
||||
MoveToEx(hdc,x-2,bottomY,0);
|
||||
LineTo(hdc,x+2,bottomY);
|
||||
LineTo(hdc,x+2,0);
|
||||
|
||||
if (line.type == LINE_DOWN)
|
||||
{
|
||||
MoveToEx(hdc,x,bottomY-4,0);
|
||||
LineTo(hdc,x-4,bottomY);
|
||||
LineTo(hdc,x+1,bottomY+5);
|
||||
}
|
||||
} else if (bottomY > rect.bottom) // second is not visible, but first is
|
||||
{
|
||||
MoveToEx(hdc,x-2,topY,0);
|
||||
LineTo(hdc,x+2,topY);
|
||||
LineTo(hdc,x+2,rect.bottom);
|
||||
|
||||
if (line.type == LINE_UP)
|
||||
{
|
||||
MoveToEx(hdc,x,topY-4,0);
|
||||
LineTo(hdc,x-4,topY);
|
||||
LineTo(hdc,x+1,topY+5);
|
||||
}
|
||||
} else { // both are visible
|
||||
if (line.type == LINE_UP)
|
||||
{
|
||||
MoveToEx(hdc,x-2,bottomY,0);
|
||||
LineTo(hdc,x+2,bottomY);
|
||||
LineTo(hdc,x+2,topY);
|
||||
LineTo(hdc,x-4,topY);
|
||||
|
||||
MoveToEx(hdc,x,topY-4,0);
|
||||
LineTo(hdc,x-4,topY);
|
||||
LineTo(hdc,x+1,topY+5);
|
||||
} else {
|
||||
MoveToEx(hdc,x-2,topY,0);
|
||||
LineTo(hdc,x+2,topY);
|
||||
LineTo(hdc,x+2,bottomY);
|
||||
LineTo(hdc,x-4,bottomY);
|
||||
|
||||
MoveToEx(hdc,x,bottomY-4,0);
|
||||
LineTo(hdc,x-4,bottomY);
|
||||
LineTo(hdc,x+1,bottomY+5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (!debugger->isAlive()) return;
|
||||
|
||||
struct branch
|
||||
{
|
||||
int src,dst,srcAddr;
|
||||
};
|
||||
branch branches[256];
|
||||
int numBranches=0;
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC actualHdc = BeginPaint(wnd, &ps);
|
||||
HDC hdc = CreateCompatibleDC(actualHdc);
|
||||
@ -425,39 +653,23 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
|
||||
SelectObject(hdc,boldfont);
|
||||
TextOutA(hdc,pixelPositions.opcodeStart,rowY1+2,opcode,(int)strlen(opcode));
|
||||
SelectObject(hdc,font);
|
||||
|
||||
if (info.isBranch && info.isConditional)
|
||||
}
|
||||
|
||||
SelectObject(hdc,condPen);
|
||||
for (int i = 0; i < visibleFunctionAddresses.size(); i++)
|
||||
{
|
||||
auto it = functions.find(visibleFunctionAddresses[i]);
|
||||
DisassemblyFunction& func = it->second;
|
||||
|
||||
for (int l = 0; l < func.lines.size(); l++)
|
||||
{
|
||||
branches[numBranches].src=rowY1 + rowHeight/2;
|
||||
branches[numBranches].srcAddr=address/instructionSize;
|
||||
branches[numBranches].dst=(int)(rowY1+((__int64)branchTarget-(__int64)address)*rowHeight/instructionSize + rowHeight/2);
|
||||
numBranches++;
|
||||
drawBranchLine(hdc,func.lines[l]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < numBranches; i++)
|
||||
for (int i = 0; i < strayLines.size(); i++)
|
||||
{
|
||||
SelectObject(hdc,condPen);
|
||||
int x=pixelPositions.arrowsStart+i*8;
|
||||
MoveToEx(hdc,x-2,branches[i].src,0);
|
||||
|
||||
if (branches[i].dst < 0)
|
||||
{
|
||||
LineTo(hdc,x+2,branches[i].src);
|
||||
LineTo(hdc,x+2,0);
|
||||
} else if (branches[i].dst > rect.bottom)
|
||||
{
|
||||
LineTo(hdc,x+2,branches[i].src);
|
||||
LineTo(hdc,x+2,rect.bottom);
|
||||
} else {
|
||||
LineTo(hdc,x+2,branches[i].src);
|
||||
LineTo(hdc,x+2,branches[i].dst);
|
||||
LineTo(hdc,x-4,branches[i].dst);
|
||||
|
||||
MoveToEx(hdc,x,branches[i].dst-4,0);
|
||||
LineTo(hdc,x-4,branches[i].dst);
|
||||
LineTo(hdc,x+1,branches[i].dst+5);
|
||||
}
|
||||
drawBranchLine(hdc,strayLines[i]);
|
||||
}
|
||||
|
||||
SelectObject(hdc,oldFont);
|
||||
|
@ -28,6 +28,22 @@ using std::min;
|
||||
using std::max;
|
||||
|
||||
|
||||
typedef enum { LINE_UP, LINE_DOWN, LINE_RIGHT } LineType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 first;
|
||||
u32 second;
|
||||
LineType type;
|
||||
int laneIndex;
|
||||
} BranchLine;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 hash;
|
||||
std::vector<BranchLine> lines;
|
||||
} DisassemblyFunction;
|
||||
|
||||
class CtrlDisAsmView
|
||||
{
|
||||
HWND wnd;
|
||||
@ -35,6 +51,10 @@ class CtrlDisAsmView
|
||||
HFONT boldfont;
|
||||
RECT rect;
|
||||
|
||||
std::map<u32,DisassemblyFunction> functions;
|
||||
std::vector<u32> visibleFunctionAddresses;
|
||||
std::vector<BranchLine> strayLines;
|
||||
|
||||
u32 curAddress;
|
||||
u32 selectRangeStart;
|
||||
u32 selectRangeEnd;
|
||||
@ -78,6 +98,7 @@ class CtrlDisAsmView
|
||||
bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels);
|
||||
void parseDisasm(const char* disasm, char* opcode, char* arguments);
|
||||
void updateStatusBarText();
|
||||
void drawBranchLine(HDC hdc, BranchLine& line);
|
||||
public:
|
||||
CtrlDisAsmView(HWND _wnd);
|
||||
~CtrlDisAsmView();
|
||||
@ -97,6 +118,7 @@ public:
|
||||
void scrollAddressIntoView();
|
||||
bool curAddressIsVisible();
|
||||
void redraw();
|
||||
void scanFunctions();
|
||||
|
||||
void getOpcodeText(u32 address, char* dest);
|
||||
u32 yToAddress(int y);
|
||||
@ -144,6 +166,7 @@ public:
|
||||
void scrollWindow(int lines)
|
||||
{
|
||||
windowStart += lines*instructionSize;
|
||||
scanFunctions();
|
||||
redraw();
|
||||
}
|
||||
|
||||
@ -154,5 +177,6 @@ public:
|
||||
selectRangeStart = extend ? std::min(selectRangeStart, newAddress) : newAddress;
|
||||
selectRangeEnd = extend ? std::max(selectRangeEnd, after) : after;
|
||||
updateStatusBarText();
|
||||
scanFunctions();
|
||||
}
|
||||
};
|
@ -810,6 +810,7 @@ void CDisasm::SetDebugMode(bool _bDebug, bool switchPC)
|
||||
if (switchPC)
|
||||
ptr->gotoPC();
|
||||
|
||||
ptr->scanFunctions();
|
||||
CtrlMemView *mem = CtrlMemView::getFrom(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW));
|
||||
mem->redraw();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user