2006-06-15 04:19:30 +00:00
|
|
|
#include <stdio.h>
|
2006-12-26 21:53:04 +00:00
|
|
|
#include <boost/bind.hpp>
|
2006-06-15 04:19:30 +00:00
|
|
|
#include "DisAsm.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "win32/InputBox.h"
|
2007-02-20 21:16:34 +00:00
|
|
|
#include "string_cast.h"
|
2007-02-21 01:33:20 +00:00
|
|
|
#include "lexical_cast_ex.h"
|
2006-06-15 04:19:30 +00:00
|
|
|
#include "WinUtils.h"
|
2008-03-03 00:38:28 +00:00
|
|
|
#include "../Ps2Const.h"
|
2007-02-21 19:24:59 +00:00
|
|
|
#include "win32/DeviceContext.h"
|
2007-12-01 04:08:34 +00:00
|
|
|
#include "win32/ClientDeviceContext.h"
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
#define CLSNAME _T("CDisAsm")
|
2006-06-15 04:19:30 +00:00
|
|
|
#define YSPACE 3
|
|
|
|
#define YMARGIN 1
|
|
|
|
|
|
|
|
#define ID_DISASM_GOTOPC 40001
|
|
|
|
#define ID_DISASM_GOTOADDRESS 40002
|
|
|
|
#define ID_DISASM_GOTOEA 40003
|
|
|
|
#define ID_DISASM_EDITCOMMENT 40004
|
|
|
|
#define ID_DISASM_FINDCALLERS 40005
|
|
|
|
#define ID_DISASM_GOTOPREV 40006
|
|
|
|
#define ID_DISASM_GOTONEXT 40007
|
|
|
|
|
|
|
|
using namespace Framework;
|
2006-12-26 21:53:04 +00:00
|
|
|
using namespace boost;
|
2007-02-20 21:16:34 +00:00
|
|
|
using namespace std;
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
CDisAsm::CDisAsm(HWND hParent, RECT* pR, CVirtualMachine& virtualMachine, CMIPS* pCtx) :
|
2007-12-01 04:08:34 +00:00
|
|
|
m_virtualMachine(virtualMachine),
|
|
|
|
m_font(CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 49, _T("Courier New")))
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
HistoryReset();
|
|
|
|
|
|
|
|
m_nArrow = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_ARROW));
|
|
|
|
m_nArrowMask = WinUtils::CreateMask(m_nArrow, 0xFF00FF);
|
|
|
|
|
|
|
|
m_nBPoint = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BREAKPOINT));
|
|
|
|
m_nBPointMask = WinUtils::CreateMask(m_nBPoint, 0xFF00FF);
|
|
|
|
|
|
|
|
if(!DoesWindowClassExist(CLSNAME))
|
|
|
|
{
|
|
|
|
WNDCLASSEX w;
|
|
|
|
memset(&w, 0, sizeof(WNDCLASSEX));
|
|
|
|
w.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
w.lpfnWndProc = CWindow::WndProc;
|
|
|
|
w.lpszClassName = CLSNAME;
|
2007-02-21 20:53:33 +00:00
|
|
|
w.hbrBackground = NULL;
|
2006-06-15 04:19:30 +00:00
|
|
|
w.hInstance = GetModuleHandle(NULL);
|
|
|
|
w.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
w.style = CS_DBLCLKS | CS_OWNDC;
|
|
|
|
RegisterClassEx(&w);
|
|
|
|
}
|
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
Create(WS_EX_CLIENTEDGE, CLSNAME, _T(""), WS_VISIBLE | WS_VSCROLL | WS_CHILD, pR, hParent, NULL);
|
2006-06-15 04:19:30 +00:00
|
|
|
SetClassPtr();
|
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
m_virtualMachine.m_OnMachineStateChange.connect(bind(&CDisAsm::OnMachineStateChange, this));
|
|
|
|
m_virtualMachine.m_OnRunningStateChange.connect(bind(&CDisAsm::OnRunningStateChange, this));
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
m_pCtx = pCtx;
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = 0x4000;
|
|
|
|
si.nPos = 0x2000;
|
|
|
|
si.fMask = SIF_RANGE | SIF_POS;
|
|
|
|
SetScrollInfo(m_hWnd, SB_VERT, &si, FALSE);
|
|
|
|
|
|
|
|
m_nSelected = 0;
|
2007-02-21 19:24:59 +00:00
|
|
|
m_nSelectionEnd = -1;
|
2006-06-15 04:19:30 +00:00
|
|
|
m_nAddress = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CDisAsm::~CDisAsm()
|
|
|
|
{
|
|
|
|
DeleteObject(m_nArrow);
|
|
|
|
DeleteObject(m_nArrowMask);
|
|
|
|
DeleteObject(m_nBPoint);
|
|
|
|
DeleteObject(m_nBPointMask);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::SetAddress(uint32 nAddress)
|
|
|
|
{
|
|
|
|
m_nAddress = nAddress;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
2006-12-26 21:53:04 +00:00
|
|
|
void CDisAsm::OnMachineStateChange()
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
if(!IsAddressVisible(m_pCtx->m_State.nPC))
|
|
|
|
{
|
2007-11-22 19:49:28 +00:00
|
|
|
m_nAddress = m_pCtx->m_State.nPC & 0xFFFFFFFC;
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
2007-12-01 04:08:34 +00:00
|
|
|
Redraw();
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2006-12-26 21:53:04 +00:00
|
|
|
void CDisAsm::OnRunningStateChange()
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2007-12-01 04:08:34 +00:00
|
|
|
Redraw();
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
2007-12-01 04:08:34 +00:00
|
|
|
/*
|
2006-06-15 04:19:30 +00:00
|
|
|
HFONT CDisAsm::GetFont()
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
return CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 49, _T("Courier New"));
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
2007-12-01 04:08:34 +00:00
|
|
|
*/
|
2006-06-15 04:19:30 +00:00
|
|
|
void CDisAsm::GotoAddress()
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
const TCHAR* sValue;
|
2006-06-15 04:19:30 +00:00
|
|
|
uint32 nAddress;
|
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-02-21 01:33:20 +00:00
|
|
|
Win32::CInputBox i(
|
|
|
|
_T("Goto Address"),
|
|
|
|
_T("Enter new address:"),
|
|
|
|
(_T("0x") + lexical_cast_hex<tstring>(m_nAddress, 8)).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
sValue = i.GetValue(m_hWnd);
|
|
|
|
if(sValue != NULL)
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
_stscanf(sValue, _T("%x"), &nAddress);
|
2006-06-15 04:19:30 +00:00
|
|
|
if(nAddress & 0x03)
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
MessageBox(m_hWnd, _T("Invalid address"), NULL, 16);
|
2006-06-15 04:19:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_nAddress != nAddress)
|
|
|
|
{
|
|
|
|
HistorySave(m_nAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nAddress = nAddress;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::GotoPC()
|
|
|
|
{
|
2007-11-05 01:28:31 +00:00
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nAddress = m_pCtx->m_State.nPC;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::GotoEA()
|
|
|
|
{
|
|
|
|
uint32 nOpcode, nAddress;
|
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nOpcode = GetInstruction(m_nSelected);
|
|
|
|
if(m_pCtx->m_pArch->IsInstructionBranch(m_pCtx, m_nSelected, nOpcode))
|
|
|
|
{
|
|
|
|
nAddress = m_pCtx->m_pArch->GetInstructionEffectiveAddress(m_pCtx, m_nSelected, nOpcode);
|
|
|
|
|
|
|
|
if(m_nAddress != nAddress)
|
|
|
|
{
|
|
|
|
HistorySave(m_nAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nAddress = nAddress;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::EditComment()
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
tstring sCommentConv;
|
|
|
|
const TCHAR* sValue;
|
2006-06-28 21:10:19 +00:00
|
|
|
const char* sComment;
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sComment = m_pCtx->m_Comments.Find(m_nSelected);
|
|
|
|
|
|
|
|
if(sComment != NULL)
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
sCommentConv = string_cast<tstring>(sComment);
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
sCommentConv = _T("");
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
Win32::CInputBox i(_T("Edit Comment"), _T("Enter new comment:"), sCommentConv.c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
sValue = i.GetValue(m_hWnd);
|
|
|
|
|
|
|
|
if(sValue != NULL)
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
m_pCtx->m_Comments.InsertTag(m_nSelected, string_cast<string>(sValue).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::FindCallers()
|
|
|
|
{
|
2007-11-05 01:28:31 +00:00
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Searching callers...\r\n");
|
|
|
|
|
2008-03-03 00:38:28 +00:00
|
|
|
for(int i = 0; i < PS2::EERAMSIZE; i += 4)
|
|
|
|
{
|
|
|
|
uint32 nVal = m_pCtx->m_pMemoryMap->GetWord(i);
|
|
|
|
if(((nVal & 0xFC000000) == 0x0C000000) || ((nVal & 0xFC000000) == 0x08000000))
|
|
|
|
{
|
|
|
|
nVal &= 0x3FFFFFF;
|
|
|
|
nVal *= 4;
|
|
|
|
if(nVal == m_nSelected)
|
|
|
|
{
|
|
|
|
printf("JAL: 0x%0.8X\r\n", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-06-15 04:19:30 +00:00
|
|
|
printf("Done.\r\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CDisAsm::GetFontHeight()
|
|
|
|
{
|
|
|
|
SIZE s;
|
2007-12-01 04:08:34 +00:00
|
|
|
Win32::CClientDeviceContext dc(m_hWnd);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-12-01 04:08:34 +00:00
|
|
|
dc.SelectObject(m_font);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-12-01 04:08:34 +00:00
|
|
|
GetTextExtentPoint32(dc, _T("0"), 1, &s);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
return s.cy;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CDisAsm::GetLineCount()
|
|
|
|
{
|
|
|
|
unsigned int nFontCY, nLines;
|
|
|
|
RECT rwin;
|
|
|
|
|
|
|
|
GetClientRect(&rwin);
|
|
|
|
|
|
|
|
nFontCY = GetFontHeight();
|
|
|
|
|
|
|
|
nLines = (rwin.bottom - (YMARGIN * 2)) / (nFontCY + YSPACE);
|
|
|
|
nLines++;
|
|
|
|
|
|
|
|
return nLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CDisAsm::IsAddressVisible(uint32 nAddress)
|
|
|
|
{
|
|
|
|
uint32 nTop, nBottom;
|
|
|
|
|
|
|
|
nTop = m_nAddress;
|
|
|
|
nBottom = nTop + ((GetLineCount() - 1) * 4);
|
|
|
|
|
|
|
|
if(nAddress < nTop) return false;
|
|
|
|
if(nAddress > nBottom) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
CDisAsm::SelectionRangeType CDisAsm::GetSelectionRange()
|
|
|
|
{
|
|
|
|
if(m_nSelectionEnd == -1)
|
|
|
|
{
|
|
|
|
return SelectionRangeType(m_nSelected, m_nSelected);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_nSelectionEnd > m_nSelected)
|
|
|
|
{
|
|
|
|
return SelectionRangeType(m_nSelected, m_nSelectionEnd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return SelectionRangeType(m_nSelectionEnd, m_nSelected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
void CDisAsm::HistoryReset()
|
|
|
|
{
|
|
|
|
m_nHistoryPosition = -1;
|
|
|
|
m_nHistorySize = 0;
|
|
|
|
memset(m_nHistory, 0, sizeof(uint32) * HISTORY_STACK_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::HistorySave(uint32 nAddress)
|
|
|
|
{
|
|
|
|
if(m_nHistorySize == HISTORY_STACK_MAX)
|
|
|
|
{
|
|
|
|
memmove(m_nHistory + 1, m_nHistory, HISTORY_STACK_MAX - 1);
|
|
|
|
m_nHistorySize--;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nHistory[m_nHistorySize] = nAddress;
|
|
|
|
m_nHistoryPosition = m_nHistorySize;
|
|
|
|
m_nHistorySize++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::HistoryGoBack()
|
|
|
|
{
|
|
|
|
uint32 nAddress;
|
|
|
|
|
|
|
|
if(m_nHistoryPosition == -1) return;
|
|
|
|
|
|
|
|
nAddress = HistoryGetPrevious();
|
|
|
|
m_nHistory[m_nHistoryPosition] = m_nAddress;
|
|
|
|
m_nAddress = nAddress;
|
|
|
|
|
|
|
|
m_nHistoryPosition--;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::HistoryGoForward()
|
|
|
|
{
|
|
|
|
uint32 nAddress;
|
|
|
|
|
|
|
|
if(m_nHistoryPosition == m_nHistorySize) return;
|
|
|
|
|
|
|
|
nAddress = HistoryGetNext();
|
|
|
|
m_nHistoryPosition++;
|
|
|
|
m_nHistory[m_nHistoryPosition] = m_nAddress;
|
|
|
|
m_nAddress = nAddress;
|
|
|
|
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CDisAsm::HistoryGetPrevious()
|
|
|
|
{
|
|
|
|
return m_nHistory[m_nHistoryPosition];
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CDisAsm::HistoryGetNext()
|
|
|
|
{
|
|
|
|
if(m_nHistoryPosition == m_nHistorySize) return 0;
|
|
|
|
return m_nHistory[m_nHistoryPosition + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CDisAsm::HistoryHasPrevious()
|
|
|
|
{
|
|
|
|
return (m_nHistorySize != 0) && (m_nHistoryPosition != -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CDisAsm::HistoryHasNext()
|
|
|
|
{
|
|
|
|
return (m_nHistorySize != 0) && (m_nHistoryPosition != (m_nHistorySize - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::UpdateMouseSelection(unsigned int nX, unsigned int nY)
|
|
|
|
{
|
|
|
|
uint32 nNew;
|
|
|
|
if(nX <= 18) return;
|
|
|
|
nNew = nY / (GetFontHeight() + YSPACE);
|
|
|
|
nNew = (m_nAddress + (nNew * 4));
|
2007-02-21 19:24:59 +00:00
|
|
|
|
|
|
|
if(GetKeyState(VK_SHIFT) & 0x8000)
|
|
|
|
{
|
|
|
|
m_nSelectionEnd = nNew;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_nSelectionEnd = -1;
|
|
|
|
if(nNew == m_nSelected) return;
|
|
|
|
m_nSelected = nNew;
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CDisAsm::GetAddressAtPosition(unsigned int nX, unsigned int nY)
|
|
|
|
{
|
|
|
|
uint32 nAddress;
|
|
|
|
nAddress = nY / (GetFontHeight() + YSPACE);
|
|
|
|
nAddress = (m_nAddress + (nAddress * 4));
|
|
|
|
return nAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CDisAsm::GetInstruction(uint32 nAddress)
|
|
|
|
{
|
|
|
|
//Address translation perhaps?
|
|
|
|
return m_pCtx->m_pMemoryMap->GetWord(nAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::ToggleBreakpoint(uint32 nAddress)
|
|
|
|
{
|
2007-11-05 01:28:31 +00:00
|
|
|
// if(CPS2VM::m_nStatus == PS2VM_STATUS_RUNNING)
|
|
|
|
if(m_virtualMachine.GetStatus() == CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
MessageBeep(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_pCtx->ToggleBreakpoint(nAddress);
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDisAsm::UpdatePosition(int nDelta)
|
|
|
|
{
|
|
|
|
m_nAddress += nDelta;
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnSetFocus()
|
|
|
|
{
|
|
|
|
if(m_nFocus) return TRUE;
|
|
|
|
m_nFocus = true;
|
|
|
|
Redraw();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnKillFocus()
|
|
|
|
{
|
|
|
|
m_nFocus = false;
|
|
|
|
Redraw();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-07-09 00:45:09 +00:00
|
|
|
long CDisAsm::OnLeftButtonDown(int nX, int nY)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
UpdateMouseSelection(nX, nY);
|
|
|
|
SetFocus();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-07-09 00:45:09 +00:00
|
|
|
long CDisAsm::OnRightButtonUp(int nX, int nY)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
POINT pt;
|
|
|
|
HMENU hMenu;
|
|
|
|
unsigned int nPosition;
|
2007-02-20 21:16:34 +00:00
|
|
|
TCHAR sTemp[256];
|
2006-06-15 04:19:30 +00:00
|
|
|
uint32 nAddress;
|
|
|
|
uint32 nOpcode;
|
|
|
|
|
|
|
|
pt.x = nX;
|
|
|
|
pt.y = nY;
|
|
|
|
ClientToScreen(m_hWnd, &pt);
|
|
|
|
|
|
|
|
nPosition = 0;
|
|
|
|
|
|
|
|
hMenu = CreatePopupMenu();
|
2007-02-20 21:16:34 +00:00
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_GOTOPC, _T("Goto PC"));
|
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_GOTOADDRESS, _T("Goto Address..."));
|
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_EDITCOMMENT, _T("Edit Comment..."));
|
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_FINDCALLERS, _T("Find Callers"));
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
if(m_nSelected != MIPS_INVALID_PC)
|
|
|
|
{
|
|
|
|
nOpcode = GetInstruction(m_nSelected);
|
|
|
|
if(m_pCtx->m_pArch->IsInstructionBranch(m_pCtx, m_nSelected, nOpcode))
|
|
|
|
{
|
|
|
|
nAddress = m_pCtx->m_pArch->GetInstructionEffectiveAddress(m_pCtx, m_nSelected, nOpcode);
|
2007-02-20 21:16:34 +00:00
|
|
|
_sntprintf(sTemp, countof(sTemp), _T("Go to 0x%0.8X"), nAddress);
|
2006-06-15 04:19:30 +00:00
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_GOTOEA, sTemp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(HistoryHasPrevious())
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
_sntprintf(sTemp, countof(sTemp), _T("Go back (0x%0.8X)"), HistoryGetPrevious());
|
2006-06-15 04:19:30 +00:00
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_GOTOPREV, sTemp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(HistoryHasNext())
|
|
|
|
{
|
2007-02-20 21:16:34 +00:00
|
|
|
_sntprintf(sTemp, countof(sTemp), _T("Go forward (0x%0.8X)"), HistoryGetNext());
|
2006-06-15 04:19:30 +00:00
|
|
|
InsertMenu(hMenu, nPosition++, MF_BYPOSITION, ID_DISASM_GOTONEXT, sTemp);
|
|
|
|
}
|
|
|
|
|
|
|
|
TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, m_hWnd, NULL);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-07-09 00:45:09 +00:00
|
|
|
long CDisAsm::OnMouseMove(WPARAM nButton, int nX, int nY)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
if(!(nButton & MK_LBUTTON)) return TRUE;
|
|
|
|
UpdateMouseSelection(nX, nY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnSize(unsigned int nType, unsigned int nX, unsigned int nY)
|
|
|
|
{
|
|
|
|
CCustomDrawn::OnSize(nType, nX, nY);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnMouseWheel(short nZ)
|
|
|
|
{
|
|
|
|
if(nZ < 0)
|
|
|
|
{
|
|
|
|
UpdatePosition(12);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdatePosition(-12);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnVScroll(unsigned int nType, unsigned int nTrackPos)
|
|
|
|
{
|
|
|
|
switch(nType)
|
|
|
|
{
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
UpdatePosition(4);
|
|
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
|
|
UpdatePosition(-4);
|
|
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
UpdatePosition(40);
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
UpdatePosition(-40);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnKeyDown(unsigned int nKey)
|
|
|
|
{
|
|
|
|
switch(nKey)
|
|
|
|
{
|
|
|
|
case VK_F9:
|
|
|
|
ToggleBreakpoint(m_nSelected);
|
|
|
|
break;
|
|
|
|
case VK_DOWN:
|
|
|
|
m_nSelected += 4;
|
|
|
|
if(!IsAddressVisible(m_nSelected))
|
|
|
|
{
|
|
|
|
UpdatePosition(4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VK_UP:
|
|
|
|
m_nSelected -= 4;
|
|
|
|
if(!IsAddressVisible(m_nSelected))
|
|
|
|
{
|
|
|
|
UpdatePosition(-4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-07-09 00:45:09 +00:00
|
|
|
long CDisAsm::OnLeftButtonDblClk(int nX, int nY)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
if(nX > 18)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ToggleBreakpoint(GetAddressAtPosition(nX, nY));
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CDisAsm::OnCommand(unsigned short nID, unsigned short nMsg, HWND hFrom)
|
|
|
|
{
|
|
|
|
switch(nID)
|
|
|
|
{
|
|
|
|
case ID_DISASM_GOTOPC:
|
|
|
|
GotoPC();
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case ID_DISASM_GOTOADDRESS:
|
|
|
|
GotoAddress();
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case ID_DISASM_GOTOEA:
|
|
|
|
GotoEA();
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case ID_DISASM_EDITCOMMENT:
|
|
|
|
EditComment();
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case ID_DISASM_FINDCALLERS:
|
|
|
|
FindCallers();
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case ID_DISASM_GOTOPREV:
|
|
|
|
HistoryGoBack();
|
|
|
|
break;
|
|
|
|
case ID_DISASM_GOTONEXT:
|
|
|
|
HistoryGoForward();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-02-21 01:33:20 +00:00
|
|
|
long CDisAsm::OnCopy()
|
|
|
|
{
|
|
|
|
if(!OpenClipboard(m_hWnd))
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EmptyClipboard();
|
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
SelectionRangeType SelectionRange;
|
2007-02-21 01:33:20 +00:00
|
|
|
HGLOBAL hMemory;
|
2007-02-21 19:24:59 +00:00
|
|
|
tstring sText;
|
|
|
|
|
|
|
|
SelectionRange = GetSelectionRange();
|
2007-02-21 01:33:20 +00:00
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
for(uint32 i = SelectionRange.first; i <= SelectionRange.second; i += 4)
|
|
|
|
{
|
|
|
|
char sDisAsm[256];
|
|
|
|
uint32 nOpcode;
|
2007-02-21 01:33:20 +00:00
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
if(i != SelectionRange.first)
|
|
|
|
{
|
|
|
|
sText += _T("\r\n");
|
|
|
|
}
|
2007-02-21 01:33:20 +00:00
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
nOpcode = GetInstruction(i);
|
|
|
|
|
|
|
|
sText += lexical_cast_hex<tstring>(i, 8) + _T(" ");
|
|
|
|
sText += lexical_cast_hex<tstring>(nOpcode, 8) + _T(" ");
|
|
|
|
|
|
|
|
m_pCtx->m_pArch->GetInstructionMnemonic(m_pCtx, i, nOpcode, sDisAsm, countof(sDisAsm));
|
|
|
|
|
|
|
|
sText += string_cast<tstring>(sDisAsm);
|
|
|
|
for(size_t j = strlen(sDisAsm); j < 15; j++)
|
|
|
|
{
|
|
|
|
sText += _T(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pCtx->m_pArch->GetInstructionOperands(m_pCtx, i, nOpcode, sDisAsm, countof(sDisAsm));
|
|
|
|
sText += string_cast<tstring>(sDisAsm);
|
|
|
|
|
|
|
|
}
|
2007-02-21 01:33:20 +00:00
|
|
|
|
|
|
|
hMemory = GlobalAlloc(GMEM_MOVEABLE, (sText.length() + 1) * sizeof(TCHAR));
|
|
|
|
_tcscpy(reinterpret_cast<TCHAR*>(GlobalLock(hMemory)), sText.c_str());
|
|
|
|
GlobalUnlock(hMemory);
|
|
|
|
|
|
|
|
#ifdef _UNICODE
|
|
|
|
SetClipboardData(CF_UNICODETEXT, hMemory);
|
|
|
|
#else
|
|
|
|
SetClipboardData(CF_TEXT, hMemory);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CloseClipboard();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
void CDisAsm::Paint(HDC hDC)
|
|
|
|
{
|
|
|
|
HDC hMem;
|
|
|
|
RECT rmarg, rwin, rsel;
|
|
|
|
HPEN nPen, nLtGrayPen;
|
|
|
|
SIZE s;
|
|
|
|
uint32 nData, nAddress, nEffAddr;
|
2007-02-20 21:16:34 +00:00
|
|
|
TCHAR sTemp[256];
|
2006-06-15 04:19:30 +00:00
|
|
|
char sDisAsm[256];
|
2006-06-28 21:10:19 +00:00
|
|
|
const char* sTag;
|
2006-06-15 04:19:30 +00:00
|
|
|
int nLines, i;
|
|
|
|
unsigned int nY;
|
|
|
|
bool nCommentDrawn;
|
2006-10-12 06:16:48 +00:00
|
|
|
CMIPSAnalysis::SUBROUTINE* pSub;
|
2007-02-21 19:24:59 +00:00
|
|
|
SelectionRangeType SelectionRange;
|
2007-12-01 04:08:34 +00:00
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
Win32::CDeviceContext DeviceContext(hDC);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
GetClientRect(&rwin);
|
|
|
|
|
|
|
|
BitBlt(hDC, 0, 0, rwin.right, rwin.bottom, NULL, 0, 0, WHITENESS);
|
2007-12-01 04:08:34 +00:00
|
|
|
SelectObject(hDC, m_font);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
GetTextExtentPoint32(hDC, _T("0"), 1, &s);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
nLines = (rwin.bottom - (YMARGIN * 2)) / (s.cy + YSPACE);
|
|
|
|
nLines++;
|
|
|
|
|
|
|
|
SetRect(&rmarg, 0, 0, 17, rwin.bottom);
|
|
|
|
FillRect(hDC, &rmarg, (HBRUSH)COLOR_WINDOW);
|
|
|
|
|
|
|
|
nLtGrayPen = CreatePen(PS_SOLID, 2, RGB(0x40, 0x40, 0x40));
|
|
|
|
|
|
|
|
nPen = CreatePen(PS_SOLID, 0, RGB(0x80, 0x80, 0x80));
|
|
|
|
SelectObject(hDC, nPen);
|
|
|
|
MoveToEx(hDC, 17, 0, NULL);
|
|
|
|
LineTo(hDC, 17, rwin.bottom);
|
|
|
|
DeleteObject(nPen);
|
|
|
|
|
|
|
|
SetBkMode(hDC, TRANSPARENT);
|
|
|
|
|
|
|
|
nY = YMARGIN;
|
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
SelectionRange = GetSelectionRange();
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
for(i = 0; i < nLines; i++)
|
|
|
|
{
|
|
|
|
nAddress = m_nAddress + (i * 4);
|
|
|
|
|
|
|
|
//Not thread safe...?
|
2007-11-06 02:08:51 +00:00
|
|
|
if(m_pCtx->m_breakpoints.find(nAddress) != m_pCtx->m_breakpoints.end())
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
|
|
|
|
|
|
|
|
hMem = CreateCompatibleDC(hDC);
|
|
|
|
SelectObject(hMem, m_nBPointMask);
|
|
|
|
BitBlt(hDC, 1, nY + 1, 15, 15, hMem, 0, 0, SRCAND);
|
|
|
|
DeleteDC(hMem);
|
|
|
|
|
|
|
|
hMem = CreateCompatibleDC(hDC);
|
|
|
|
SelectObject(hMem, m_nBPoint);
|
|
|
|
BitBlt(hDC, 1, nY + 1, 15, 15, hMem, 0, 0, SRCPAINT);
|
|
|
|
DeleteDC(hMem);
|
|
|
|
}
|
|
|
|
|
2007-11-05 01:28:31 +00:00
|
|
|
// if(CPS2VM::m_nStatus != PS2VM_STATUS_RUNNING)
|
|
|
|
if(m_virtualMachine.GetStatus() != CVirtualMachine::RUNNING)
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
if(nAddress == m_pCtx->m_State.nPC)
|
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
|
|
|
|
|
|
|
|
hMem = CreateCompatibleDC(hDC);
|
|
|
|
SelectObject(hMem, m_nArrowMask);
|
|
|
|
BitBlt(hDC, 3, nY + 2, 13, 13, hMem, 0, 0, SRCAND);
|
|
|
|
DeleteDC(hMem);
|
|
|
|
|
|
|
|
hMem = CreateCompatibleDC(hDC);
|
|
|
|
SelectObject(hMem, m_nArrow);
|
|
|
|
BitBlt(hDC, 3, nY + 2, 13, 13, hMem, 0, 0, SRCPAINT);
|
|
|
|
DeleteDC(hMem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-21 19:24:59 +00:00
|
|
|
if(
|
|
|
|
(nAddress >= SelectionRange.first) &&
|
|
|
|
(nAddress <= SelectionRange.second)
|
|
|
|
)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
SetRect(&rsel, 18, nY, rwin.right, nY + s.cy + YSPACE);
|
|
|
|
if(m_nFocus)
|
|
|
|
{
|
|
|
|
FillRect(hDC, &rsel, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FillRect(hDC, &rsel, (HBRUSH)GetStockObject(GRAY_BRUSH));
|
|
|
|
}
|
|
|
|
SetTextColor(hDC, RGB(0xFF, 0xFF, 0xFF));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
|
|
|
|
}
|
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
_sntprintf(sTemp, countof(sTemp), _T("%0.8X"), nAddress);
|
|
|
|
TextOut(hDC, 20, nY, sTemp, (int)_tcslen(sTemp));
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
pSub = m_pCtx->m_pAnalysis->FindSubroutine(nAddress);
|
|
|
|
if(pSub != NULL)
|
|
|
|
{
|
|
|
|
SelectObject(hDC, nLtGrayPen);
|
|
|
|
if(nAddress == pSub->nStart)
|
|
|
|
{
|
|
|
|
MoveToEx(hDC, 90, nY + s.cy + YSPACE, NULL);
|
|
|
|
LineTo(hDC, 90, nY + ((s.cy + YSPACE) / 2) - 1);
|
|
|
|
LineTo(hDC, 95, nY + ((s.cy + YSPACE) / 2));
|
|
|
|
}
|
|
|
|
else if(nAddress == pSub->nEnd)
|
|
|
|
{
|
|
|
|
MoveToEx(hDC, 90, nY, NULL);
|
|
|
|
LineTo(hDC, 90, nY + ((s.cy + YSPACE) / 2));
|
|
|
|
LineTo(hDC, 95, nY + ((s.cy + YSPACE) / 2));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MoveToEx(hDC, 90, nY, NULL);
|
|
|
|
LineTo(hDC, 90, nY + s.cy + YSPACE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nData = GetInstruction(nAddress);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(100, nY, lexical_cast_hex<tstring>(nData, 8).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
m_pCtx->m_pArch->GetInstructionMnemonic(m_pCtx, nAddress, nData, sDisAsm, 256);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(200, nY, string_cast<tstring>(sDisAsm).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
m_pCtx->m_pArch->GetInstructionOperands(m_pCtx, nAddress, nData, sDisAsm, 256);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(300, nY, string_cast<tstring>(sDisAsm).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
nCommentDrawn = false;
|
|
|
|
|
|
|
|
sTag = m_pCtx->m_Functions.Find(nAddress);
|
|
|
|
if(sTag != NULL)
|
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x00, 0x80));
|
|
|
|
strcpy(sDisAsm, "@");
|
|
|
|
strcat(sDisAsm, sTag);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(450, nY, string_cast<tstring>(sDisAsm).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
nCommentDrawn = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!nCommentDrawn)
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pArch->IsInstructionBranch(m_pCtx, nAddress, nData))
|
|
|
|
{
|
|
|
|
nEffAddr = m_pCtx->m_pArch->GetInstructionEffectiveAddress(m_pCtx, nAddress, nData);
|
|
|
|
sTag = m_pCtx->m_Functions.Find(nEffAddr);
|
|
|
|
if(sTag != NULL)
|
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x00, 0x80));
|
|
|
|
strcpy(sDisAsm, "-> ");
|
|
|
|
strcat(sDisAsm, sTag);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(450, nY, string_cast<tstring>(sDisAsm).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
nCommentDrawn = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sTag = m_pCtx->m_Comments.Find(nAddress);
|
|
|
|
if(sTag != NULL && !nCommentDrawn)
|
|
|
|
{
|
|
|
|
SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
|
|
|
|
strcpy(sDisAsm, ";");
|
|
|
|
strcat(sDisAsm, sTag);
|
2007-02-21 19:24:59 +00:00
|
|
|
DeviceContext.TextOut(450, nY, string_cast<tstring>(sDisAsm).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nY += s.cy + YSPACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteObject(nLtGrayPen);
|
|
|
|
}
|