Merge pull request #4062 from unknownbrackets/debugger

Show tabs for depth/stencil in ge debugger, other improvements
This commit is contained in:
Henrik Rydgård 2013-10-06 23:59:54 -07:00
commit 8f7a9656c8
19 changed files with 369 additions and 133 deletions

View file

@ -38,9 +38,10 @@ enum GPUDebugBufferFormat {
GPU_DBG_FORMAT_8888 = 3,
GPU_DBG_FORMAT_INVALID = 0xFF,
// These don't, they're for depth buffers.
// These don't, they're for depth/stencil buffers.
GPU_DBG_FORMAT_FLOAT = 0x10,
GPU_DBG_FORMAT_16BIT = 0x11,
GPU_DBG_FORMAT_8BIT = 0x12,
};
struct GPUDebugBuffer {
@ -170,6 +171,9 @@ public:
virtual u32 GetVertexAddress() = 0;
virtual u32 GetIndexAddress() = 0;
virtual GPUgstate GetGState() = 0;
// Needs to be called from the GPU thread.
// Calling from a separate thread (e.g. UI) may fail.
virtual void SetCmdValue(u32 op) = 0;
// Needs to be called from the GPU thread, so on the same thread as a notification is fine.
// Calling from a separate thread (e.g. UI) may fail.

View file

@ -386,10 +386,10 @@ void FramebufferManagerDX9::SetRenderFrameBuffer() {
gstate_c.framebufChanged = false;
// Get parameters
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.fbwidth & 0x3C0;
u32 z_address = (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8);
u32 z_address = gstate.getDepthBufRawAddress();
int z_stride = gstate.zbwidth & 0x3C0;
// Yeah this is not completely right. but it'll do for now.

View file

@ -516,10 +516,10 @@ void FramebufferManager::SetRenderFrameBuffer() {
gstate_c.framebufChanged = false;
// Get parameters
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.fbwidth & 0x3C0;
u32 z_address = (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8);
u32 z_address = gstate.getDepthBufRawAddress();
int z_stride = gstate.zbwidth & 0x3C0;
// Yeah this is not completely right. but it'll do for now.
@ -1402,7 +1402,7 @@ void FramebufferManager::Resized() {
}
bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) {
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.fbwidth & 0x3C0;
VirtualFramebuffer *vfb = currentRenderVfb_;
@ -1429,10 +1429,10 @@ bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) {
}
bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.fbwidth & 0x3C0;
u32 z_address = (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8);
u32 z_address = gstate.getDepthBufRawAddress();
int z_stride = gstate.zbwidth & 0x3C0;
VirtualFramebuffer *vfb = currentRenderVfb_;
@ -1462,7 +1462,7 @@ bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
}
bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.fbwidth & 0x3C0;
VirtualFramebuffer *vfb = currentRenderVfb_;
@ -1478,7 +1478,7 @@ bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
}
#ifndef USING_GLES2
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_16BIT, true);
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_8BIT, true);
if (vfb->fbo)
fbo_bind_for_read(vfb->fbo);
glReadBuffer(GL_STENCIL_ATTACHMENT);

View file

@ -1100,9 +1100,10 @@ std::vector<GPUDebugOp> GPUCommon::DissassembleOpRange(u32 startpc, u32 endpc) {
std::vector<GPUDebugOp> result;
GPUDebugOp info;
u32 prev = Memory::Read_U32(startpc - 4);
// Don't trigger a pause.
u32 prev = Memory::IsValidAddress(startpc - 4) ? Memory::Read_U32(startpc - 4) : 0;
for (u32 pc = startpc; pc < endpc; pc += 4) {
u32 op = Memory::Read_U32(pc);
u32 op = Memory::IsValidAddress(pc) ? Memory::Read_U32(pc) : 0;
GeDisassembleOp(pc, op, prev, buffer);
prev = op;
@ -1130,3 +1131,12 @@ u32 GPUCommon::GetIndexAddress() {
GPUgstate GPUCommon::GetGState() {
return gstate;
}
void GPUCommon::SetCmdValue(u32 op) {
u32 cmd = op >> 24;
u32 diff = op ^ gstate.cmdmem[cmd];
PreExecuteOp(op, diff);
gstate.cmdmem[cmd] = op;
ExecuteOp(op, diff);
}

View file

@ -152,6 +152,7 @@ public:
virtual u32 GetVertexAddress();
virtual u32 GetIndexAddress();
virtual GPUgstate GetGState();
virtual void SetCmdValue(u32 op);
virtual DisplayList* getList(int listid)
{

View file

@ -212,8 +212,13 @@ struct GPUgstate
float tgenMatrix[12];
float boneMatrix[12 * 8]; // Eight bone matrices.
u32 getFrameBufRawAddress() const { return (fbptr & 0xFFFFFF) | ((fbwidth & 0xFF0000) << 8); }
// 0x44000000 is uncached VRAM.
u32 getFrameBufAddress() const { return 0x44000000 | getFrameBufRawAddress(); }
GEBufferFormat FrameBufFormat() const { return static_cast<GEBufferFormat>(framebufpixformat & 3); }
int FrameBufStride() const { return fbwidth&0x7C0; }
u32 getDepthBufRawAddress() const { return (zbptr & 0xFFFFFF) | ((zbwidth & 0xFF0000) << 8); }
u32 getDepthBufAddress() const { return 0x44000000 | getDepthBufRawAddress(); }
int DepthBufStride() const { return zbwidth&0x7C0; }
// Pixel Pipeline

View file

@ -431,11 +431,11 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
break;
case GE_CMD_FRAMEBUFPTR:
fb.data = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8));
fb.data = Memory::GetPointer(gstate.getFrameBufAddress());
break;
case GE_CMD_FRAMEBUFWIDTH:
fb.data = Memory::GetPointer(0x44000000 | (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8));
fb.data = Memory::GetPointer(gstate.getFrameBufAddress());
break;
case GE_CMD_FRAMEBUFPIXFORMAT:
@ -532,11 +532,11 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
break;
case GE_CMD_ZBUFPTR:
depthbuf.data = Memory::GetPointer(0x44000000 | (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8));
depthbuf.data = Memory::GetPointer(gstate.getDepthBufAddress());
break;
case GE_CMD_ZBUFWIDTH:
depthbuf.data = Memory::GetPointer(0x44000000 | (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8));
depthbuf.data = Memory::GetPointer(gstate.getDepthBufAddress());
break;
case GE_CMD_AMBIENTCOLOR:

View file

@ -1,7 +1,8 @@
#include "Windows/GEDebugger/CtrlDisplayListView.h"
#include "Core/Config.h"
#include "Windows/GEDebugger/GEDebugger.h"
#include "Windows/InputBox.h"
#include "Windows/Main.h"
#include "Core/Config.h"
#include <algorithm>
const PTCHAR CtrlDisplayListView::windowClass = _T("CtrlDisplayListView");
@ -166,6 +167,8 @@ void CtrlDisplayListView::onPaint(WPARAM wParam, LPARAM lParam)
HICON breakPoint = (HICON)LoadIcon(GetModuleHandle(0),(LPCWSTR)IDI_STOP);
auto disasm = gpuDebug->DissassembleOpRange(windowStart, windowStart + (visibleRows + 2) * instructionSize);
for (int i = 0; i < visibleRows+2; i++)
{
unsigned int address=windowStart + i*instructionSize;
@ -210,7 +213,7 @@ void CtrlDisplayListView::onPaint(WPARAM wParam, LPARAM lParam)
}
SetTextColor(hdc,textColor);
GPUDebugOp op = gpuDebug->DissassembleOp(address);
GPUDebugOp op = i < (int)disasm.size() ? disasm[i] : GPUDebugOp();
char addressText[64];
sprintf(addressText,"%08X %08X",op.pc,op.op);
@ -328,7 +331,7 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
redraw();
}
break;
case IDC_DEBUG_LIST_SETSTALL:
case ID_GEDBG_SETSTALLADDR:
{
gpuDebug->ResetListStall(list.id,curAddress);
list.stall = curAddress;
@ -354,6 +357,24 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
redraw();
}
break;
case ID_GEDBG_GOTOPC:
setCurAddress(list.pc);
scrollAddressIntoView();
redraw();
break;
case ID_GEDBG_GOTOADDR:
{
u32 newAddress = curAddress;
if (!InputBox_GetHex(GetModuleHandle(NULL), wnd, L"Address", curAddress, newAddress)) {
break;
}
if (Memory::IsValidAddress(newAddress)) {
setCurAddress(newAddress);
scrollAddressIntoView();
redraw();
}
}
break;
}
return;
}

View file

@ -41,6 +41,7 @@ enum PauseAction {
PAUSE_GETDEPTHBUF,
PAUSE_GETSTENCILBUF,
PAUSE_GETTEX,
PAUSE_SETCMDVALUE,
};
static bool attached = false;
@ -65,6 +66,13 @@ static GPUDebugBuffer bufferFrame;
static GPUDebugBuffer bufferDepth;
static GPUDebugBuffer bufferStencil;
static GPUDebugBuffer bufferTex;
static u32 pauseSetCmdValue;
enum PrimaryDisplayType {
PRIMARY_FRAMEBUF,
PRIMARY_DEPTHBUF,
PRIMARY_STENCILBUF,
};
// TODO: Simplify and move out of windows stuff, just block in a common way for everyone.
@ -137,6 +145,13 @@ static void RunPauseAction() {
case PAUSE_GETTEX:
bufferResult = gpuDebug->GetCurrentTexture(bufferTex);
break;
case PAUSE_SETCMDVALUE:
gpuDebug->SetCmdValue(pauseSetCmdValue);
break;
default:
ERROR_LOG(HLE, "Unsupported pause action, forgot to add it to the switch.");
}
actionWait.notify_one();
@ -151,7 +166,7 @@ static void ForceUnpause() {
}
CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), primaryDisplay(PRIMARY_FRAMEBUF), frameWindow(NULL), texWindow(NULL) {
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), frameWindow(NULL), texWindow(NULL) {
breakCmds.resize(256, false);
Core_ListenShutdown(ForceUnpause);
@ -175,6 +190,14 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView",L"Display List");
displayList = CtrlDisplayListView::getFrom(wnd);
fbTabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_FBTABS));
fbTabs->SetMinTabWidth(50);
// Must be in the same order as PrimaryDisplayType.
fbTabs->AddTab(NULL, L"Color");
fbTabs->AddTab(NULL, L"Depth");
fbTabs->AddTab(NULL, L"Stencil");
fbTabs->ShowTab(0, true);
flags = new TabStateFlags(_hInstance, m_hDlg);
tabs->AddTabDialog(flags, L"Flags");
@ -201,28 +224,24 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
}
CGEDebugger::~CGEDebugger() {
delete frameWindow;
delete texWindow;
delete flags;
delete lighting;
delete textureState;
delete settings;
delete lists;
delete tabs;
delete fbTabs;
}
void CGEDebugger::SetupPreviews() {
if (frameWindow == NULL) {
frameWindow = SimpleGLWindow::GetFrom(GetDlgItem(m_hDlg, IDC_GEDBG_FRAME));
frameWindow->Initialize(SimpleGLWindow::ALPHA_IGNORE | SimpleGLWindow::RESIZE_SHRINK_CENTER);
// TODO: Why doesn't this work?
frameWindow->Clear();
}
if (texWindow == NULL) {
texWindow = SimpleGLWindow::GetFrom(GetDlgItem(m_hDlg, IDC_GEDBG_TEX));
texWindow->Initialize(SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_SHRINK_CENTER);
// TODO: Why doesn't this work?
texWindow->Clear();
}
}
@ -230,31 +249,42 @@ void CGEDebugger::SetupPreviews() {
void CGEDebugger::UpdatePreviews() {
// TODO: Do something different if not paused?
wchar_t desc[256];
GPUDebugBuffer *primaryBuffer = NULL;
GPUgstate state;
bufferResult = false;
switch (primaryDisplay) {
if (gpuDebug != NULL) {
state = gpuDebug->GetGState();
}
switch (PrimaryDisplayType(fbTabs->CurrentTabIndex())) {
case PRIMARY_FRAMEBUF:
SetPauseAction(PAUSE_GETFRAMEBUF);
primaryBuffer = &bufferFrame;
_snwprintf(desc, ARRAY_SIZE(desc), L"Color: 0x%08x (%dx%d)", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight());
break;
case PRIMARY_DEPTHBUF:
SetPauseAction(PAUSE_GETDEPTHBUF);
primaryBuffer = &bufferDepth;
_snwprintf(desc, ARRAY_SIZE(desc), L"Depth: 0x%08x (%dx%d)", state.getDepthBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight());
break;
case PRIMARY_STENCILBUF:
SetPauseAction(PAUSE_GETSTENCILBUF);
primaryBuffer = &bufferStencil;
_snwprintf(desc, ARRAY_SIZE(desc), L"Stencil: 0x%08x (%dx%d)", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight());
break;
}
if (bufferResult && primaryBuffer != NULL) {
auto fmt = SimpleGLWindow::Format(primaryBuffer->GetFormat());
frameWindow->Draw(primaryBuffer->GetData(), primaryBuffer->GetStride(), primaryBuffer->GetHeight(), primaryBuffer->GetFlipped(), fmt);
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, desc);
} else {
ERROR_LOG(COMMON, "Unable to get buffer for main display.");
frameWindow->Clear();
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, L"Failed");
}
bufferResult = false;
@ -265,20 +295,25 @@ void CGEDebugger::UpdatePreviews() {
texWindow->Draw(bufferTex.GetData(), bufferTex.GetStride(), bufferTex.GetHeight(), bufferTex.GetFlipped(), fmt);
if (gpuDebug != NULL) {
auto state = gpuDebug->GetGState();
if (state.isTextureAlphaUsed()) {
texWindow->SetFlags(SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_SHRINK_CENTER);
} else {
texWindow->SetFlags(SimpleGLWindow::RESIZE_SHRINK_CENTER);
}
_snwprintf(desc, ARRAY_SIZE(desc), L"Texture: 0x%08x (%dx%d)", state.getTextureAddress(0), state.getTextureWidth(0), state.getTextureHeight(0));
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, desc);
}
} else {
ERROR_LOG(COMMON, "Unable to get texture (may be no texture set.)");
texWindow->Clear();
if (gpuDebug == NULL || state.isTextureMapEnabled()) {
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"Texture: failed");
} else {
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"Texture: disabled");
}
}
DisplayList list;
if (gpuDebug->GetCurrentDisplayList(list)) {
if (gpuDebug != NULL && gpuDebug->GetCurrentDisplayList(list)) {
displayList->setDisplayList(list);
}
@ -357,6 +392,13 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
case IDC_GEDBG_MAINTAB:
tabs->HandleNotify(lParam);
break;
case IDC_GEDBG_FBTABS:
fbTabs->HandleNotify(lParam);
// TODO: Move this somewhere...
if (attached && gpuDebug != NULL) {
UpdatePreviews();
}
break;
}
break;
@ -378,6 +420,9 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
case IDC_GEDBG_RESUME:
frameWindow->Clear();
texWindow->Clear();
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, L"");
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"");
// TODO: detach? Should probably have separate UI, or just on activate?
breakNextOp = false;
breakNextDraw = false;
@ -432,6 +477,13 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
SendMessage(m_hDlg,WM_COMMAND,IDC_GEDBG_RESUME,0);
}
break;
case WM_GEDBG_SETCMDWPARAM:
{
pauseSetCmdValue = (u32)wParam;
SetPauseAction(PAUSE_SETCMDVALUE);
}
break;
}
return FALSE;

View file

@ -29,7 +29,8 @@ enum {
WM_GEDBG_BREAK_DRAW,
WM_GEDBG_STEPDISPLAYLIST,
WM_GEDBG_TOGGLEPCBREAKPOINT,
WM_GEDBG_RUNTOWPARAM
WM_GEDBG_RUNTOWPARAM,
WM_GEDBG_SETCMDWPARAM,
};
class CtrlDisplayListView;
@ -61,13 +62,6 @@ private:
void UpdateSize(WORD width, WORD height);
void SavePosition();
enum PrimaryDisplayType {
PRIMARY_FRAMEBUF,
PRIMARY_DEPTHBUF,
PRIMARY_STENCILBUF,
};
PrimaryDisplayType primaryDisplay;
CtrlDisplayListView *displayList;
TabDisplayLists *lists;
TabStateFlags *flags;
@ -77,6 +71,7 @@ private:
SimpleGLWindow *frameWindow;
SimpleGLWindow *texWindow;
TabControl *tabs;
TabControl *fbTabs;
int minWidth,minHeight;
};

View file

@ -227,6 +227,9 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
} else if (fmt == FORMAT_16BIT) {
glfmt = GL_UNSIGNED_SHORT;
components = GL_RED;
} else if (fmt == FORMAT_8BIT) {
glfmt = GL_UNSIGNED_BYTE;
components = GL_RED;
} else {
_dbg_assert_msg_(COMMON, false, "Invalid SimpleGLWindow format.");
}
@ -254,6 +257,11 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
void SimpleGLWindow::Redraw() {
DrawChecker();
if (tw_ == 0 && th_ == 0) {
Swap();
return;
}
if (flags_ & ALPHA_BLEND) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -306,8 +314,63 @@ void SimpleGLWindow::Redraw() {
}
void SimpleGLWindow::Clear() {
DrawChecker();
Swap();
tw_ = 0;
th_ = 0;
Redraw();
}
bool SimpleGLWindow::DragStart(int mouseX, int mouseY) {
// Only while zoomed in, otherwise it's shrink to fit mode or fixed.
if (!zoom_) {
return false;
}
dragging_ = true;
SetCapture(hWnd_);
dragStartX_ = mouseX - offsetX_;
dragStartY_ = mouseY - offsetY_;
dragLastUpdate_ = GetTickCount();
return true;
}
bool SimpleGLWindow::DragContinue(int mouseX, int mouseY) {
if (!dragging_) {
return false;
}
offsetX_ = mouseX - dragStartX_;
offsetY_ = mouseY - dragStartY_;
const u32 MS_BETWEEN_DRAG_REDRAWS = 5;
if (GetTickCount() - dragLastUpdate_ > MS_BETWEEN_DRAG_REDRAWS) {
Redraw();
}
return true;
}
bool SimpleGLWindow::DragEnd(int mouseX, int mouseY) {
if (!dragging_) {
return false;
}
dragging_ = false;
ReleaseCapture();
Redraw();
return true;
}
bool SimpleGLWindow::ToggleZoom() {
// Reset the offset when zooming out (or in, doesn't matter.)
offsetX_ = 0;
offsetY_ = 0;
zoom_ = !zoom_;
Redraw();
return true;
}
SimpleGLWindow *SimpleGLWindow::GetFrom(HWND hwnd) {
@ -320,48 +383,42 @@ LRESULT CALLBACK SimpleGLWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA
switch(msg)
{
case WM_NCCREATE:
// Allocate a new CustCtrl structure for this window.
win = new SimpleGLWindow(hwnd);
// Continue with window creation.
return win != NULL;
return win != NULL ? TRUE : FALSE;
case WM_NCDESTROY:
delete win;
return 0;
case WM_LBUTTONDBLCLK:
win->zoom_ = !win->zoom_;
// Reset the offset when zooming out (or in, doesn't matter.)
win->offsetX_ = 0;
win->offsetY_ = 0;
// Redrawn in WM_LBUTTONUP.
return 0;
case WM_LBUTTONDOWN:
// Only while zoomed in, otherwise it's shrink to fit mode or fixed.
if (win->zoom_) {
win->dragging_ = true;
win->dragStartX_ = GET_X_LPARAM(lParam) - win->offsetX_;
win->dragStartY_ = GET_Y_LPARAM(lParam) - win->offsetY_;
win->dragLastUpdate_ = GetTickCount();
}
return 0;
case WM_LBUTTONUP:
win->dragging_ = false;
win->Redraw();
return 0;
case WM_MOUSEMOVE:
if (win->dragging_) {
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
win->offsetX_ = x - win->dragStartX_;
win->offsetY_ = y - win->dragStartY_;
const u32 MS_BETWEEN_DRAG_REDRAWS = 5;
if (GetTickCount() - win->dragLastUpdate_ > MS_BETWEEN_DRAG_REDRAWS) {
win->Redraw();
}
if (win->ToggleZoom()) {
return 0;
}
break;
case WM_LBUTTONDOWN:
if (win->DragStart(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
return 0;
}
break;
case WM_LBUTTONUP:
if (win->DragEnd(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
return 0;
}
break;
case WM_MOUSEMOVE:
if (win->DragContinue(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
return 0;
}
break;
case WM_PAINT:
win->Redraw();
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);

View file

@ -32,6 +32,7 @@ struct SimpleGLWindow {
FORMAT_FLOAT = 0x10,
FORMAT_16BIT = 0x11,
FORMAT_8BIT = 0x12,
};
enum Flags {
@ -68,6 +69,10 @@ protected:
void CreateProgram();
void GenerateChecker();
void DrawChecker();
bool DragStart(int mouseX, int mouseY);
bool DragContinue(int mouseX, int mouseY);
bool DragEnd(int mouseX, int mouseY);
bool ToggleZoom();
HWND hWnd_;
HDC hDC_;

View file

@ -17,6 +17,8 @@
#include "base/basictypes.h"
#include "Windows/resource.h"
#include "Windows/InputBox.h"
#include "Windows/GEDebugger/GEDebugger.h"
#include "Windows/GEDebugger/TabState.h"
#include "GPU/GPUState.h"
#include "GPU/GeDisasm.h"
@ -54,6 +56,7 @@ enum CmdFormatType {
CMD_FMT_MATERIALUPDATE,
CMD_FMT_STENCILOP,
CMD_FMT_BLENDMODE,
CMD_FMT_FLAG,
};
struct TabStateRow {
@ -66,25 +69,25 @@ struct TabStateRow {
};
static const TabStateRow stateFlagsRows[] = {
{ L"Lighting enable", GE_CMD_LIGHTINGENABLE, CMD_FMT_NUM },
{ L"Light 0 enable", GE_CMD_LIGHTENABLE0, CMD_FMT_NUM },
{ L"Light 1 enable", GE_CMD_LIGHTENABLE1, CMD_FMT_NUM },
{ L"Light 2 enable", GE_CMD_LIGHTENABLE2, CMD_FMT_NUM },
{ L"Light 3 enable", GE_CMD_LIGHTENABLE3, CMD_FMT_NUM },
{ L"Clip enable", GE_CMD_CLIPENABLE, CMD_FMT_NUM },
{ L"Cullface enable", GE_CMD_CULLFACEENABLE, CMD_FMT_NUM },
{ L"Texture map enable", GE_CMD_TEXTUREMAPENABLE, CMD_FMT_NUM },
{ L"Fog enable", GE_CMD_FOGENABLE, CMD_FMT_NUM },
{ L"Dither enable", GE_CMD_DITHERENABLE, CMD_FMT_NUM },
{ L"Alpha blend enable", GE_CMD_ALPHABLENDENABLE, CMD_FMT_NUM },
{ L"Alpha test enable", GE_CMD_ALPHATESTENABLE, CMD_FMT_NUM },
{ L"Depth test enable", GE_CMD_ZTESTENABLE, CMD_FMT_NUM },
{ L"Stencil test enable", GE_CMD_STENCILTESTENABLE, CMD_FMT_NUM },
{ L"Antialias enable", GE_CMD_ANTIALIASENABLE, CMD_FMT_NUM },
{ L"Patch cull enable", GE_CMD_PATCHCULLENABLE, CMD_FMT_NUM },
{ L"Color test enable", GE_CMD_COLORTESTENABLE, CMD_FMT_NUM },
{ L"Logic op enable", GE_CMD_LOGICOPENABLE, CMD_FMT_NUM },
{ L"Depth write disable", GE_CMD_ZWRITEDISABLE, CMD_FMT_NUM },
{ L"Lighting enable", GE_CMD_LIGHTINGENABLE, CMD_FMT_FLAG },
{ L"Light 0 enable", GE_CMD_LIGHTENABLE0, CMD_FMT_FLAG },
{ L"Light 1 enable", GE_CMD_LIGHTENABLE1, CMD_FMT_FLAG },
{ L"Light 2 enable", GE_CMD_LIGHTENABLE2, CMD_FMT_FLAG },
{ L"Light 3 enable", GE_CMD_LIGHTENABLE3, CMD_FMT_FLAG },
{ L"Clip enable", GE_CMD_CLIPENABLE, CMD_FMT_FLAG },
{ L"Cullface enable", GE_CMD_CULLFACEENABLE, CMD_FMT_FLAG },
{ L"Texture map enable", GE_CMD_TEXTUREMAPENABLE, CMD_FMT_FLAG },
{ L"Fog enable", GE_CMD_FOGENABLE, CMD_FMT_FLAG },
{ L"Dither enable", GE_CMD_DITHERENABLE, CMD_FMT_FLAG },
{ L"Alpha blend enable", GE_CMD_ALPHABLENDENABLE, CMD_FMT_FLAG },
{ L"Alpha test enable", GE_CMD_ALPHATESTENABLE, CMD_FMT_FLAG },
{ L"Depth test enable", GE_CMD_ZTESTENABLE, CMD_FMT_FLAG },
{ L"Stencil test enable", GE_CMD_STENCILTESTENABLE, CMD_FMT_FLAG },
{ L"Antialias enable", GE_CMD_ANTIALIASENABLE, CMD_FMT_FLAG },
{ L"Patch cull enable", GE_CMD_PATCHCULLENABLE, CMD_FMT_FLAG },
{ L"Color test enable", GE_CMD_COLORTESTENABLE, CMD_FMT_FLAG },
{ L"Logic op enable", GE_CMD_LOGICOPENABLE, CMD_FMT_FLAG },
{ L"Depth write disable", GE_CMD_ZWRITEDISABLE, CMD_FMT_FLAG },
};
static const TabStateRow stateLightingRows[] = {
@ -97,7 +100,7 @@ static const TabStateRow stateLightingRows[] = {
{ L"Material alpha", GE_CMD_MATERIALALPHA, CMD_FMT_HEX },
{ L"Material specular", GE_CMD_MATERIALSPECULAR, CMD_FMT_HEX },
{ L"Mat. specular coef", GE_CMD_MATERIALSPECULARCOEF, CMD_FMT_FLOAT24 },
{ L"Reverse normals", GE_CMD_REVERSENORMAL, CMD_FMT_NUM },
{ L"Reverse normals", GE_CMD_REVERSENORMAL, CMD_FMT_FLAG },
// TODO: Format?
{ L"Shade model", GE_CMD_SHADEMODE, CMD_FMT_NUM },
// TODO: Format?
@ -484,6 +487,14 @@ void FormatStateRow(wchar_t *dest, const TabStateRow &info, u32 value, bool enab
}
break;
case CMD_FMT_FLAG:
if ((value & ~1) == 0) {
swprintf(dest, L"%d", value);
} else {
swprintf(dest, L"%06x", value);
}
break;
default:
swprintf(dest, L"BAD FORMAT %06x", value);
}
@ -518,7 +529,48 @@ void CtrlStateValues::GetColumnText(wchar_t *dest, int row, int col) {
break;
}
}
}
void CtrlStateValues::OnDoubleClick(int row, int column) {
if (gpuDebug == NULL) {
return;
}
const auto info = rows_[row];
switch (info.fmt) {
case CMD_FMT_FLAG:
{
const auto state = gpuDebug->GetGState();
u32 newValue = state.cmdmem[info.cmd] ^ 1;
SetCmdValue(newValue);
}
break;
default:
{
// TODO: Floats/etc., and things with multiple cmds.
const auto state = gpuDebug->GetGState();
u32 newValue = state.cmdmem[info.cmd] & 0x00FFFFFF;
if (InputBox_GetHex(GetModuleHandle(NULL), GetHandle(), L"New value", newValue, newValue)) {
newValue |= state.cmdmem[info.cmd] & 0xFF000000;
SetCmdValue(newValue);
}
}
break;
}
}
void CtrlStateValues::OnRightClick(int row, int column, const POINT& point) {
if (gpuDebug == NULL) {
return;
}
// TODO: Copy, break, watch... enable?
}
void CtrlStateValues::SetCmdValue(u32 op) {
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_SETCMDWPARAM, op, NULL);
Update();
}
TabStateValues::TabStateValues(const TabStateRow *rows, int rowCount, LPCSTR dialogID, HINSTANCE _hInstance, HWND _hParent)

View file

@ -30,8 +30,12 @@ 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 rowCount_; }
virtual void OnDoubleClick(int row, int column);
virtual void OnRightClick(int row, int column, const POINT& point);
private:
void SetCmdValue(u32 op);
const TabStateRow *rows_;
int rowCount_;
};

View file

@ -117,8 +117,11 @@ bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t *title, u32 de
if (value == IDOK)
{
wscanf(out.c_str(),"%08x",&outvalue);
return true;
if (swscanf(out.c_str(), L"0x%08x", &outvalue) == 1)
return true;
if (swscanf(out.c_str(), L"%08x", &outvalue) == 1)
return true;
return false;
}
else
{

View file

@ -6,7 +6,8 @@
const DWORD tabControlStyleMask = ~(WS_POPUP | WS_TILEDWINDOW);
TabControl::TabControl(HWND handle): hwnd(handle), showTabTitles(true),currentTab(0),ignoreBottomMargin(false)
TabControl::TabControl(HWND handle, bool noDisplayArea)
: hwnd(handle), showTabTitles(true), currentTab(0), ignoreBottomMargin(false), noDisplayArea_(noDisplayArea)
{
SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)this);
oldProc = (WNDPROC) SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)wndProc);
@ -60,26 +61,29 @@ void TabControl::AddTab(HWND handle, wchar_t* title)
if (showTabTitles)
AppendPageToControl(title);
int index = tabs.size();
RECT tabRect;
GetWindowRect(hwnd,&tabRect);
MapWindowPoints(HWND_DESKTOP,GetParent(hwnd),(LPPOINT)&tabRect,2);
TabCtrl_AdjustRect(hwnd, FALSE, &tabRect);
SetParent(handle,GetParent(hwnd));
DWORD style = (GetWindowLong(handle,GWL_STYLE) | WS_CHILD);
TabInfo info;
info.hasBorder = (style & WS_BORDER) != 0;
info.hasClientEdge = (GetWindowLong(handle,GWL_EXSTYLE) & WS_EX_CLIENTEDGE) != 0;
if (hasButtons == false)
TabInfo info = {0};
if (!noDisplayArea_)
{
style &= (~WS_BORDER);
SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle,GWL_EXSTYLE) & (~WS_EX_CLIENTEDGE));
}
RECT tabRect;
GetWindowRect(hwnd,&tabRect);
MapWindowPoints(HWND_DESKTOP,GetParent(hwnd),(LPPOINT)&tabRect,2);
TabCtrl_AdjustRect(hwnd, FALSE, &tabRect);
SetWindowLong(handle, GWL_STYLE, style & tabControlStyleMask);
MoveWindow(handle,tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE);
SetParent(handle,GetParent(hwnd));
DWORD style = (GetWindowLong(handle,GWL_STYLE) | WS_CHILD);
info.hasBorder = (style & WS_BORDER) != 0;
info.hasClientEdge = (GetWindowLong(handle,GWL_EXSTYLE) & WS_EX_CLIENTEDGE) != 0;
if (hasButtons == false)
{
style &= (~WS_BORDER);
SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle,GWL_EXSTYLE) & (~WS_EX_CLIENTEDGE));
}
SetWindowLong(handle, GWL_STYLE, style & tabControlStyleMask);
MoveWindow(handle,tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE);
}
info.lastFocus = handle;
info.pageHandle = handle;
@ -133,7 +137,8 @@ void TabControl::ShowTab(int index, bool setControlIndex)
{
if (oldFocus && i == index)
SetFocus(tabs[i].lastFocus);
ShowWindow(tabs[i].pageHandle,i == index ? SW_NORMAL : SW_HIDE);
if (!noDisplayArea_)
ShowWindow(tabs[i].pageHandle,i == index ? SW_NORMAL : SW_HIDE);
}
if (setControlIndex && showTabTitles)
@ -156,7 +161,8 @@ void TabControl::ShowTab(HWND pageHandle)
if (oldFocus)
SetFocus(tabs[i].lastFocus);
}
ShowWindow(tabs[i].pageHandle,tabs[i].pageHandle == pageHandle ? SW_NORMAL : SW_HIDE);
if (!noDisplayArea_)
ShowWindow(tabs[i].pageHandle,tabs[i].pageHandle == pageHandle ? SW_NORMAL : SW_HIDE);
}
}
@ -176,7 +182,7 @@ void TabControl::SetShowTabTitles(bool enabled)
{
AppendPageToControl(tabs[i].title);
if (hasButtons == false)
if (hasButtons == false && !noDisplayArea_)
{
DWORD style = GetWindowLong(tabs[i].pageHandle,GWL_STYLE) & (~WS_BORDER);
SetWindowLong(tabs[i].pageHandle,GWL_STYLE,style);
@ -186,7 +192,7 @@ void TabControl::SetShowTabTitles(bool enabled)
}
}
TabCtrl_SetCurSel(hwnd,CurrentTabIndex());
} else if (hasButtons == false)
} else if (hasButtons == false && !noDisplayArea_)
{
for (int i = 0; i < (int) tabs.size(); i++)
{
@ -207,6 +213,11 @@ void TabControl::SetShowTabTitles(bool enabled)
OnResize();
}
void TabControl::SetMinTabWidth(int w)
{
TabCtrl_SetMinTabWidth(hwnd, w);
}
void TabControl::NextTab(bool cycle)
{
int index = CurrentTabIndex()+1;
@ -265,15 +276,18 @@ void TabControl::OnResize()
int current = CurrentTabIndex();
for (size_t i = 0; i < tabs.size(); i++)
if (!noDisplayArea_)
{
InvalidateRect(tabs[i].pageHandle,NULL,FALSE);
MoveWindow(tabs[i].pageHandle,tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE);
if (i == current)
for (size_t i = 0; i < tabs.size(); i++)
{
InvalidateRect(tabs[i].pageHandle,NULL,TRUE);
UpdateWindow(tabs[i].pageHandle);
InvalidateRect(tabs[i].pageHandle,NULL,FALSE);
MoveWindow(tabs[i].pageHandle,tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE);
if (i == current)
{
InvalidateRect(tabs[i].pageHandle,NULL,TRUE);
UpdateWindow(tabs[i].pageHandle);
}
}
}
}

View file

@ -7,7 +7,7 @@ class Dialog;
class TabControl
{
public:
TabControl(HWND handle);
TabControl(HWND handle, bool noDisplayArea = false);
void HandleNotify(LPARAM lParam);
HWND AddTabWindow(wchar_t* className, wchar_t* title, DWORD style = 0);
void AddTabDialog(Dialog* dialog, wchar_t* title);
@ -21,6 +21,8 @@ public:
void SetShowTabTitles(bool enabled);
void SetIgnoreBottomMargin(bool enabled) { ignoreBottomMargin = enabled; };
bool GetShowTabTitles() { return showTabTitles; };
void SetMinTabWidth(int w);
private:
static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void OnResize();
@ -42,4 +44,5 @@ private:
bool ignoreBottomMargin;
int currentTab;
bool hasButtons;
bool noDisplayArea_;
};

View file

@ -178,7 +178,10 @@ BEGIN
PUSHBUTTON "Resume",IDC_GEDBG_RESUME,104,0,48,14
CONTROL "",IDC_GEDBG_TEX,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,10,20,128,128
CONTROL "",IDC_GEDBG_FRAME,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,148,20,256,136
CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER ,10,216,480,180
CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,480,180
EDITTEXT IDC_GEDBG_FRAMEBUFADDR,148,192,128,12,ES_READONLY | NOT WS_BORDER
EDITTEXT IDC_GEDBG_TEXADDR,10,152,128,12,ES_READONLY | NOT WS_BORDER
CONTROL "",IDC_GEDBG_FBTABS,"SysTabControl32",TCS_BUTTONS | TCS_FOCUSNEVER,384,192,110,12
END
@ -505,7 +508,7 @@ BEGIN
MENUITEM "Copy Instruction (Disasm)", ID_DISASM_COPYINSTRUCTIONDISASM
MENUITEM "Disassemble to File", ID_DISASM_DISASSEMBLETOFILE
MENUITEM SEPARATOR
MENUITEM "Assemble Ppcode", ID_DISASM_ASSEMBLE
MENUITEM "Assemble Opcode", ID_DISASM_ASSEMBLE
MENUITEM SEPARATOR
MENUITEM "Run to Cursor", ID_DISASM_RUNTOHERE
MENUITEM "Jump to Cursor", ID_DISASM_SETPCTOHERE
@ -558,9 +561,11 @@ BEGIN
MENUITEM SEPARATOR
MENUITEM "Run to Cursor", ID_DISASM_RUNTOHERE
MENUITEM "Jump to Cursor", ID_DISASM_SETPCTOHERE
MENUITEM "Set Stall" IDC_DEBUG_LIST_SETSTALL
MENUITEM "Set Stall" ID_GEDBG_SETSTALLADDR
MENUITEM "Toggle Breakpoint", ID_DISASM_TOGGLEBREAKPOINT
MENUITEM SEPARATOR
MENUITEM "Go to Displaylist PC", ID_GEDBG_GOTOPC
MENUITEM "Go to Address...", ID_GEDBG_GOTOADDR
MENUITEM "Go to in Memory View", ID_DISASM_GOTOINMEMORYVIEW
END
END

View file

@ -155,6 +155,9 @@
#define IDC_DUMP_SIZE 1188
#define IDC_DUMP_FILENAME 1189
#define IDC_DUMP_BROWSEFILENAME 1190
#define IDC_GEDBG_FRAMEBUFADDR 1191
#define IDC_GEDBG_TEXADDR 1192
#define IDC_GEDBG_FBTABS 1193
// Don't define anything else in the 3000 range.
// It's reserved for languages.
@ -284,7 +287,9 @@
#define IDC_DEBUG_BOTTOMTABS 40127
#define ID_DEBUG_HIDEBOTTOMTABS 40128
#define ID_DEBUG_TOGGLEBOTTOMTABTITLES 40129
#define IDC_DEBUG_LIST_SETSTALL 40130
#define ID_GEDBG_SETSTALLADDR 40130
#define ID_GEDBG_GOTOPC 40131
#define ID_GEDBG_GOTOADDR 40132
// Dummy option to let the buffered rendering hotkey cycle through all the options.
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
@ -297,8 +302,8 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 254
#define _APS_NEXT_COMMAND_VALUE 40131
#define _APS_NEXT_CONTROL_VALUE 1191
#define _APS_NEXT_COMMAND_VALUE 40133
#define _APS_NEXT_CONTROL_VALUE 1193
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif