Merge pull request #3965 from Kingcom/GEDebugger

Display lists tab
This commit is contained in:
Henrik Rydgård 2013-09-28 16:41:09 -07:00
commit 4a6c2e33fa
11 changed files with 528 additions and 7 deletions

View file

@ -32,6 +32,7 @@
#include "Core/Config.h"
#include <windowsx.h>
#include <commctrl.h>
#include "TabDisplayLists.h"
enum PauseAction {
PAUSE_CONTINUE,
@ -129,6 +130,9 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView",L"Display List");
displayList = CtrlDisplayListView::getFrom(wnd);
lists = new TabDisplayLists(_hInstance,m_hDlg);
tabs->AddTabDialog(lists,L"Lists");
// set window position
int x = g_Config.iGEWindowX == -1 ? windowRect.left : g_Config.iGEWindowX;
int y = g_Config.iGEWindowY == -1 ? windowRect.top : g_Config.iGEWindowY;
@ -186,6 +190,8 @@ void CGEDebugger::UpdatePreviews() {
if (gpuDebug->GetCurrentDisplayList(list)) {
displayList->setDisplayList(list);
}
lists->Update();
}
void CGEDebugger::UpdateSize(WORD width, WORD height)

View file

@ -31,6 +31,7 @@ enum {
};
class CtrlDisplayListView;
class TabDisplayLists;
class CGEDebugger : public Dialog {
public:
@ -48,6 +49,7 @@ private:
void SavePosition();
CtrlDisplayListView* displayList;
TabDisplayLists* lists;
SimpleGLWindow *frameWindow;
SimpleGLWindow *texWindow;
TabControl* tabs;

View file

@ -0,0 +1,269 @@
#include "Windows/GEDebugger/TabDisplayLists.h"
#include "Windows/GEDebugger/GEDebugger.h"
#include "Windows/GEDebugger/CtrlDisplayListView.h"
#include "Windows/WindowsHost.h"
#include "Windows/WndMainWindow.h"
#include "Windows/main.h"
#include "GPU/GPUInterface.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/GPUState.h"
#include "Core/Config.h"
#include <windowsx.h>
#include <commctrl.h>
enum { WM_GEDBG_LISTS_CHANGELIST = WM_USER+400, WM_GEDBG_LISTS_GOTOSTACKPC };
//
// CtrlDisplayListStack
//
enum { DLS_PC = 0, DLS_BASE, DLS_OFFSET, DLS_COLUMNCOUNT };
const GenericListViewColumn displayListStackColumns[3] = {
{ L"PC", 0.34f },
{ L"Base", 0.33f },
{ L"Offset", 0.33f },
};
CtrlDisplayListStack::CtrlDisplayListStack(HWND hwnd): GenericListControl(hwnd,displayListStackColumns,DLS_COLUMNCOUNT)
{
list.stackptr = 0;
Update();
}
void CtrlDisplayListStack::GetColumnText(wchar_t* dest, int row, int col)
{
DisplayListStackEntry value = list.stack[row];
switch (col)
{
case DLS_BASE:
wsprintf(dest,L"0x%08X",value.baseAddr);
break;
case DLS_OFFSET:
wsprintf(dest,L"0x%08X",value.offsetAddr);
break;
case DLS_PC:
wsprintf(dest,L"0x%08X",value.pc);
break;
}
}
void CtrlDisplayListStack::OnDoubleClick(int itemIndex, int column)
{
SendMessage(GetParent(GetHandle()),WM_GEDBG_LISTS_GOTOSTACKPC,itemIndex,0);
}
//
// CtrlDisplayListStack
//
enum { ADL_STARTPC = 0, ADL_PC, ADL_STALL, ADL_STATE, APL_STARTED, APL_INTERRUPTED, ADL_COLUMNCOUNT };
const GenericListViewColumn allDisplayListsColumns[ADL_COLUMNCOUNT] = {
{ L"Start PC", 0.18f },
{ L"PC", 0.18f },
{ L"Stall", 0.18f },
{ L"State", 0.16f },
{ L"Started", 0.15f },
{ L"Interrupted", 0.15f },
};
CtrlAllDisplayLists::CtrlAllDisplayLists(HWND hwnd): GenericListControl(hwnd,allDisplayListsColumns,ADL_COLUMNCOUNT)
{
Update();
}
void CtrlAllDisplayLists::GetColumnText(wchar_t* dest, int row, int col)
{
DisplayList& list = lists[row];
switch (col)
{
case ADL_STALL:
wsprintf(dest,L"0x%08X",list.stall);
break;
case ADL_PC:
wsprintf(dest,L"0x%08X",list.pc);
break;
case ADL_STARTPC:
wsprintf(dest,L"0x%08X",list.startpc);
break;
case ADL_STATE:
switch (list.state)
{
case PSP_GE_DL_STATE_NONE:
wcscpy(dest,L"None");
break;
case PSP_GE_DL_STATE_QUEUED:
wcscpy(dest,L"Queued");
break;
case PSP_GE_DL_STATE_RUNNING:
wcscpy(dest,L"Running");
break;
case PSP_GE_DL_STATE_COMPLETED:
wcscpy(dest,L"Completed");
break;
case PSP_GE_DL_STATE_PAUSED:
wcscpy(dest,L"Paused");
break;
}
break;
case APL_STARTED:
wcscpy(dest,list.started ? L"Yes" : L"No");
break;
case APL_INTERRUPTED:
wcscpy(dest,list.interrupted ? L"Yes" : L"No");
break;
}
}
bool CtrlAllDisplayLists::WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue)
{
switch (msg)
{
case WM_KEYDOWN:
if (wParam == VK_RETURN)
{
int item = GetSelectedIndex();
SendMessage(GetParent(GetHandle()),WM_GEDBG_LISTS_CHANGELIST,item,0);
}
break;
case WM_GETDLGCODE:
if (lParam && ((MSG*)lParam)->message == WM_KEYDOWN)
{
if (wParam == VK_RETURN)
{
returnValue = DLGC_WANTMESSAGE;
return true;
}
}
}
return false;
}
void CtrlAllDisplayLists::OnDoubleClick(int itemIndex, int column)
{
SendMessage(GetParent(GetHandle()),WM_GEDBG_LISTS_CHANGELIST,itemIndex,0);
}
//
// TabDisplayLists
//
TabDisplayLists::TabDisplayLists(HINSTANCE _hInstance, HWND _hParent)
: Dialog((LPCSTR)IDD_TABDISPLAYLISTS, _hInstance, _hParent)
{
displayList = CtrlDisplayListView::getFrom(GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_SELECTEDLIST));
stack = new CtrlDisplayListStack(GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_STACK));
allLists = new CtrlAllDisplayLists(GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_ALLLISTS));
activeList = -1;
}
TabDisplayLists::~TabDisplayLists()
{
delete stack;
delete allLists;
}
void TabDisplayLists::UpdateSize(WORD width, WORD height)
{
struct Position
{
int x,y;
int w,h;
};
Position positions[3];
int borderMargin = 5;
int betweenControlsMargin = 5;
// All Lists
positions[0].x = borderMargin;
positions[0].y = borderMargin;
positions[0].w = width*2/3;
positions[0].h = min(height*2/5,200);
// Stack
positions[1].x = positions[0].x+positions[0].w+betweenControlsMargin;
positions[1].y = borderMargin;
positions[1].w = width-positions[1].x-borderMargin;
positions[1].h = positions[0].h;
// Current List
positions[2].x = borderMargin;
positions[2].y = positions[0].y+positions[0].h+betweenControlsMargin;
positions[2].w = width-2*borderMargin;
positions[2].h = height-positions[2].y-borderMargin;
HWND handles[3] = {
GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_ALLLISTS),
GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_STACK),
GetDlgItem(m_hDlg,IDC_GEDBG_LISTS_SELECTEDLIST)
};
for (int i = 0; i < 3; i++)
{
MoveWindow(handles[i],positions[i].x,positions[i].y,positions[i].w,positions[i].h,TRUE);
}
}
void TabDisplayLists::Update(bool reload)
{
if (reload)
{
lists = gpuDebug->ActiveDisplayLists();
}
if (activeList != -1)
{
DisplayList currentList = lists[activeList];
displayList->setDisplayList(currentList);
stack->setDisplayList(currentList);
}
allLists->setDisplayLists(lists);
}
BOOL TabDisplayLists::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_INITDIALOG:
return TRUE;
case WM_SIZE:
UpdateSize(LOWORD(lParam), HIWORD(lParam));
return TRUE;
case WM_NOTIFY:
switch (wParam)
{
case IDC_GEDBG_LISTS_STACK:
stack->HandleNotify(lParam);
break;
case IDC_GEDBG_LISTS_ALLLISTS:
allLists->HandleNotify(lParam);
break;
}
break;
case WM_GEDBG_LISTS_CHANGELIST:
activeList = wParam;
Update();
break;
case WM_GEDBG_LISTS_GOTOSTACKPC:
{
u32 pc = lists[activeList].stack[wParam].pc;
displayList->gotoAddr(pc);
}
break;
}
return FALSE;
}

View file

@ -0,0 +1,56 @@
#pragma once
#include "Common/CommonWindows.h"
#include "Globals.h"
#include "Windows/resource.h"
#include "Windows/W32Util/DialogManager.h"
#include "Windows/W32Util/Misc.h"
#include "GPU/Common/GPUDebugInterface.h"
class CtrlDisplayListView;
class CtrlDisplayListStack: public GenericListControl
{
public:
CtrlDisplayListStack(HWND hwnd);
void setDisplayList(DisplayList& _list) { list = _list; Update(); }
protected:
virtual bool WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue) { return false; };
virtual void GetColumnText(wchar_t* dest, int row, int col);
virtual int GetRowCount() { return list.stackptr; };
virtual void OnDoubleClick(int itemIndex, int column);
private:
DisplayList list;
};
class CtrlAllDisplayLists: public GenericListControl
{
public:
CtrlAllDisplayLists(HWND hwnd);
void setDisplayLists(std::vector<DisplayList>& _lists) { lists = _lists; Update(); };
protected:
virtual bool WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue);
virtual void GetColumnText(wchar_t* dest, int row, int col);
virtual int GetRowCount() { return (int) lists.size(); };
virtual void OnDoubleClick(int itemIndex, int column);
private:
std::vector<DisplayList> lists;
};
class TabDisplayLists : public Dialog
{
public:
TabDisplayLists(HINSTANCE _hInstance, HWND _hParent);
~TabDisplayLists();
void Update(bool reload = true);
protected:
BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam);
private:
void UpdateSize(WORD width, WORD height);
CtrlDisplayListView* displayList;
CtrlDisplayListStack* stack;
CtrlAllDisplayLists* allLists;
std::vector<DisplayList> lists;
int activeList;
};

View file

@ -284,6 +284,7 @@
<ClCompile Include="DinputDevice.cpp" />
<ClCompile Include="EmuThread.cpp" />
<ClCompile Include="GEDebugger\SimpleGLWindow.cpp" />
<ClCompile Include="GEDebugger\TabDisplayLists.cpp" />
<ClCompile Include="InputDevice.cpp" />
<ClCompile Include="KeyboardDevice.cpp" />
<ClCompile Include="W32Util\DialogManager.cpp" />
@ -329,6 +330,7 @@
<ClInclude Include="DinputDevice.h" />
<ClInclude Include="EmuThread.h" />
<ClInclude Include="GEDebugger\SimpleGLWindow.h" />
<ClInclude Include="GEDebugger\TabDisplayLists.h" />
<ClInclude Include="InputDevice.h" />
<ClInclude Include="KeyboardDevice.h" />
<ClInclude Include="W32Util\DialogManager.h" />

View file

@ -125,6 +125,9 @@
<ClCompile Include="W32Util\TabControl.cpp">
<Filter>Windows\W32Util</Filter>
</ClCompile>
<ClCompile Include="GEDebugger\TabDisplayLists.cpp">
<Filter>Windows\GE Debugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Debugger\CtrlDisAsmView.h">
@ -224,6 +227,9 @@
<ClInclude Include="W32Util\TabControl.h">
<Filter>Windows\W32Util</Filter>
</ClInclude>
<ClInclude Include="GEDebugger\TabDisplayLists.h">
<Filter>Windows\GE Debugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="icon1.ico">

View file

@ -2,6 +2,7 @@
#include <WinUser.h>
#include "Misc.h"
#include "util/text/utf8.h"
#include <commctrl.h>
namespace W32Util
{
@ -85,4 +86,136 @@ namespace W32Util
SetWindowPos(hwnd, style, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
}
}
GenericListControl::GenericListControl(HWND hwnd, const GenericListViewColumn* _columns, int _columnCount)
: handle(hwnd), columns(_columns),columnCount(_columnCount),valid(false)
{
DWORD style = GetWindowLong(handle,GWL_STYLE) | LVS_REPORT;
SetWindowLong(handle, GWL_STYLE, style);
SetWindowLongPtr(handle,GWLP_USERDATA,(LONG_PTR)this);
oldProc = (WNDPROC) SetWindowLongPtr(handle,GWLP_WNDPROC,(LONG_PTR)wndProc);
SendMessage(handle, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.iSubItem = 0;
lvc.fmt = LVCFMT_LEFT;
RECT rect;
GetClientRect(handle,&rect);
int totalListSize = rect.right-rect.left;
for (int i = 0; i < columnCount; i++) {
lvc.cx = columns[i].size * totalListSize;
lvc.pszText = columns[i].name;
ListView_InsertColumn(handle, i, &lvc);
}
valid = true;
}
void GenericListControl::HandleNotify(LPARAM lParam)
{
LPNMHDR mhdr = (LPNMHDR) lParam;
if (mhdr->code == NM_DBLCLK)
{
LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam;
if (item->iItem != -1 && item->iItem < GetRowCount())
OnDoubleClick(item->iItem,item->iSubItem);
return;
}
if (mhdr->code == NM_RCLICK)
{
const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE)lParam;
if (item->iItem != -1 && item->iItem < GetRowCount())
OnRightClick(item->iItem,item->iSubItem);
return;
}
if (mhdr->code == LVN_GETDISPINFO)
{
NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)lParam;
stringBuffer[0] = 0;
GetColumnText(stringBuffer,dispInfo->item.iItem,dispInfo->item.iSubItem);
if (stringBuffer[0] == 0)
wcscat(stringBuffer,L"Invalid");
dispInfo->item.pszText = stringBuffer;
return;
}
}
void GenericListControl::Update()
{
int newRows = GetRowCount();
int items = ListView_GetItemCount(handle);
while (items < newRows)
{
LVITEM lvI;
lvI.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
lvI.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.state = 0;
lvI.iItem = items;
lvI.iImage = items;
ListView_InsertItem(handle, &lvI);
items++;
}
while (items > newRows)
{
ListView_DeleteItem(handle,--items);
}
ResizeColumns();
InvalidateRect(handle,NULL,true);
UpdateWindow(handle);
}
void GenericListControl::ResizeColumns()
{
RECT rect;
GetClientRect(handle,&rect);
int totalListSize = rect.right-rect.left;
for (int i = 0; i < columnCount; i++)
{
ListView_SetColumnWidth(handle,i,columns[i].size * totalListSize);
}
}
LRESULT CALLBACK GenericListControl::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
GenericListControl* list = (GenericListControl*) GetWindowLongPtr(hwnd,GWLP_USERDATA);
LRESULT returnValue;
if (list->valid && list->WindowMessage(msg,wParam,lParam,returnValue) == true)
return returnValue;
switch (msg)
{
case WM_SIZE:
list->ResizeColumns();
break;
}
return (LRESULT)CallWindowProc((WNDPROC)list->oldProc,hwnd,msg,wParam,lParam);
}
int GenericListControl::GetSelectedIndex()
{
return ListView_GetNextItem(handle, -1, LVNI_SELECTED);
}

View file

@ -9,4 +9,36 @@ namespace W32Util
void NiceSizeFormat(size_t size, char *out);
BOOL CopyTextToClipboard(HWND hwnd, const char *text);
void MakeTopMost(HWND hwnd, bool topMost);
}
}
struct GenericListViewColumn
{
wchar_t *name;
float size;
};
class GenericListControl
{
public:
GenericListControl(HWND hwnd, const GenericListViewColumn* _columns, int _columnCount);
void HandleNotify(LPARAM lParam);
void Update();
int GetSelectedIndex();
HWND GetHandle() { return handle; };
protected:
virtual bool WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue) = 0;
virtual void GetColumnText(wchar_t* dest, int row, int col) = 0;
virtual int GetRowCount() = 0;
virtual void OnDoubleClick(int itemIndex, int column) { };
virtual void OnRightClick(int itemIndex, int column) { };
private:
static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void ResizeColumns();
HWND handle;
WNDPROC oldProc;
const GenericListViewColumn* columns;
int columnCount;
wchar_t stringBuffer[256];
bool valid;
};

View file

@ -106,7 +106,7 @@ void TabControl::PreviousTab(bool cycle)
{
int index = TabCtrl_GetCurSel(hwnd);
if (index == 0 && cycle)
index = tabs.size()-1;
index = (int) tabs.size()-1;
ShowTab(index);
}
@ -127,7 +127,7 @@ void TabControl::OnResize()
GetWindowRect(hwnd,&tabRect);
MapWindowPoints(HWND_DESKTOP,GetParent(hwnd),(LPPOINT)&tabRect,2);
InvalidateRect(hwnd,NULL,FALSE);
InvalidateRect(hwnd,NULL,TRUE);
UpdateWindow(hwnd);
// now resize tab children
@ -137,11 +137,11 @@ void TabControl::OnResize()
for (size_t i = 0; i < tabs.size(); i++)
{
InvalidateRect(tabs[i],NULL,FALSE);
MoveWindow(tabs[i],tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,FALSE);
MoveWindow(tabs[i],tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE);
if (i == current)
{
InvalidateRect(tabs[i],NULL,FALSE);
InvalidateRect(tabs[i],NULL,TRUE);
UpdateWindow(tabs[i]);
}
}

View file

@ -177,6 +177,17 @@ BEGIN
CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS ,10,216,480,180
END
IDD_TABDISPLAYLISTS DIALOGEX 0, 0, 316, 183
STYLE DS_SETFONT | DS_FIXEDSYS
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_GEDBG_LISTS_ALLLISTS,"SysListView32",LVS_ALIGNLEFT | LVS_SHOWSELALWAYS | LVS_REPORT | WS_BORDER | WS_TABSTOP,7,7,217,86
CONTROL "",IDC_GEDBG_LISTS_STACK,"SysListView32",LVS_ALIGNLEFT | LVS_SHOWSELALWAYS | LVS_REPORT | WS_BORDER | WS_TABSTOP,7,95,302,81
CONTROL "",IDC_GEDBG_LISTS_SELECTEDLIST,"CtrlDisplayListView",WS_BORDER,225,7,84,89
END
#include "aboutbox.rc"
IDD_MEMORY DIALOGEX 0, 0, 566, 287

View file

@ -77,6 +77,7 @@
#define ID_DEBUG_DSIPLAYFUNCTIONLIST 248
#define ID_MEMVIEW_COPYADDRESS 249
#define IDD_GEDEBUGGER 250
#define IDD_TABDISPLAYLISTS 251
#define IDC_STOPGO 1001
#define IDC_ADDRESS 1002
@ -265,6 +266,9 @@
#define IDC_GEDBG_MAINTAB 40120
#define IDC_GEDBG_TEX 40121
#define IDC_GEDBG_STEP 40122
#define IDC_GEDBG_LISTS_ALLLISTS 40123
#define IDC_GEDBG_LISTS_STACK 40124
#define IDC_GEDBG_LISTS_SELECTEDLIST 40125
// Dummy option to let the buffered rendering hotkey cycle through all the options.
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
@ -276,8 +280,8 @@
// Next default values for new objects
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 251
#define _APS_NEXT_COMMAND_VALUE 40123
#define _APS_NEXT_RESOURCE_VALUE 252
#define _APS_NEXT_COMMAND_VALUE 40126
#define _APS_NEXT_CONTROL_VALUE 1181
#define _APS_NEXT_SYMED_VALUE 101
#endif