diff --git a/CMakeLists.txt b/CMakeLists.txt index 175196914f..13eb3d71b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1008,6 +1008,8 @@ if(WIN32) Windows/DSoundStream.cpp Windows/DSoundStream.h Windows/Debugger/CPURegsInterface.h + Windows/Debugger/BreakpointWindow.cpp + Windows/Debugger/BreakpointWindow.h Windows/Debugger/CtrlDisAsmView.cpp Windows/Debugger/CtrlDisAsmView.h Windows/Debugger/CtrlMemView.cpp diff --git a/Windows/Debugger/BreakpointWindow.cpp b/Windows/Debugger/BreakpointWindow.cpp new file mode 100644 index 0000000000..5ff772f1b4 --- /dev/null +++ b/Windows/Debugger/BreakpointWindow.cpp @@ -0,0 +1,280 @@ +#include "BreakpointWindow.h" +#include "../resource.h" +#include + +BreakpointWindow* BreakpointWindow::bp; + +INT_PTR CALLBACK BreakpointWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + char str[128]; + + switch (iMsg) + { + case WM_INITDIALOG: + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_EXECUTE),BM_SETCHECK,bp->memory ? BST_UNCHECKED : BST_CHECKED,0); + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_MEMORY),BM_SETCHECK,bp->memory ? BST_CHECKED : BST_UNCHECKED,0); + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),BM_SETCHECK, bp->read ? BST_CHECKED : BST_UNCHECKED,0); + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),BM_SETCHECK, bp->write ? BST_CHECKED : BST_UNCHECKED,0); + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_ENABLED),BM_SETCHECK, bp->enabled ? BST_CHECKED : BST_UNCHECKED,0); + SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),BM_SETCHECK, bp->log ? BST_CHECKED : BST_UNCHECKED,0); + + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory); + + if (bp->address != -1) + { + sprintf(str,"0x%08X",bp->address); + SetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str); + } + + sprintf(str,"0x%08X",bp->size); + SetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),str); + + SetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),bp->condition); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_BREAKPOINT_EXECUTE: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + bp->memory = false; + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory); + break; + } + break; + case IDC_BREAKPOINT_MEMORY: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + bp->memory = true; + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory); + EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory); + break; + } + break; + case IDC_BREAKPOINT_OK: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + if (bp->fetchDialogData(hwnd)) + { + EndDialog(hwnd,true); + } + break; + }; + break; + case IDC_BREAKPOINT_CANCEL: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + EndDialog(hwnd,false); + break; + }; + break; + case IDOK: + if (bp->fetchDialogData(hwnd)) + { + EndDialog(hwnd,true); + } + break; + case IDCANCEL: + EndDialog(hwnd,false); + break; + } + + case WM_KEYDOWN: + + break; + } + + return FALSE; +} + +bool BreakpointWindow::fetchDialogData(HWND hwnd) +{ + char str[256],errorMessage[512]; + PostfixExpression exp; + + memory = (bool) SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_MEMORY),BM_GETCHECK,0,0); + read = (bool) SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),BM_GETCHECK,0,0); + write = (bool) SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),BM_GETCHECK,0,0); + enabled = (bool) SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_ENABLED),BM_GETCHECK,0,0); + log = (bool) SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),BM_GETCHECK,0,0); + + // parse address + GetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str,256); + if (cpu->initExpression(str,exp) == false) + { + sprintf(errorMessage,"Invalid expression \"%s\".",str); + MessageBox(hwnd,errorMessage,"Error",MB_OK); + return false; + } + + if (cpu->parseExpression(exp,address) == false) + { + sprintf(errorMessage,"Invalid expression \"%s\".",str); + MessageBox(hwnd,errorMessage,"Error",MB_OK); + return false; + } + + if (memory) + { + // parse size + GetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),str,256); + if (cpu->initExpression(str,exp) == false) + { + sprintf(errorMessage,"Invalid expression \"%s\".",str); + MessageBox(hwnd,errorMessage,"Error",MB_OK); + return false; + } + + if (cpu->parseExpression(exp,size) == false) + { + sprintf(errorMessage,"Invalid expression \"%s\".",str); + MessageBox(hwnd,errorMessage,"Error",MB_OK); + return false; + } + } + + // condition + GetWindowText(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),condition,128); + compiledCondition.clear(); + if (condition[0] != 0) + { + if (cpu->initExpression(condition,compiledCondition) == false) + { + sprintf(errorMessage,"Invalid expression \"%s\".",str); + MessageBox(hwnd,errorMessage,"Error",MB_OK); + return false; + } + } + + return true; +} + +bool BreakpointWindow::exec() +{ + bp = this; + bool result = (bool) DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_BREAKPOINT),parentHwnd,dlgFunc,(LPARAM)this); + return result; +} + +void BreakpointWindow::addMemcheck() +{ + MemCheckCondition cond; + if (read && write) cond = MEMCHECK_READWRITE; + else if (read) cond = MEMCHECK_READ; + else cond = MEMCHECK_WRITE; + + MemCheckResult result; + if (log && enabled) result = MEMCHECK_BOTH; + else if (log) result = MEMCHECK_LOG; + else if (enabled) result = MEMCHECK_BREAK; + else result = MEMCHECK_IGNORE; + + CBreakPoints::AddMemCheck(address,address+size,cond,result); +} + +void BreakpointWindow::addBreakpoint() +{ + // todo: condition, enabled + CBreakPoints::AddBreakPoint(address,false); +} + +void BreakpointWindow::editMemcheck(MemCheck& memcheck) +{ + MemCheckCondition cond; + if (read && write) cond = MEMCHECK_READWRITE; + else if (read) cond = MEMCHECK_READ; + else cond = MEMCHECK_WRITE; + + MemCheckResult result; + if (log && enabled) result = MEMCHECK_BOTH; + else if (log) result = MEMCHECK_LOG; + else if (enabled) result = MEMCHECK_BREAK; + else result = MEMCHECK_IGNORE; + + memcheck.cond = cond; + memcheck.result = result; + memcheck.start = address; + memcheck.end = address+size; + CBreakPoints::Update(); +} + +void BreakpointWindow::editBreakpoint(BreakPoint& memcheck) +{ + memcheck.addr = address; + memcheck.enabled = enabled; + + // todo + memcheck.hasCond = false; + CBreakPoints::Update(); +} + +void BreakpointWindow::loadFromMemcheck(MemCheck& memcheck) +{ + memory = true; + + switch (memcheck.cond) + { + case MEMCHECK_READWRITE: + read = write = true; + break; + case MEMCHECK_READ: + read = true; + write = false; + break; + case MEMCHECK_WRITE: + read = false; + write = true; + break; + default: + read = write = false; + break; + } + + switch (memcheck.result) + { + case MEMCHECK_BOTH: + log = enabled = true; + break; + case MEMCHECK_LOG: + log = true; + enabled = false; + break; + case MEMCHECK_BREAK: + log = false; + enabled = true; + break; + case MEMCHECK_IGNORE: + log = enabled = false; + break; + } + + address = memcheck.start; + size = memcheck.end-address; +} + +void BreakpointWindow::loadFromBreakpoint(BreakPoint& memcheck) +{ + memory = false; + + address = memcheck.addr; + enabled = memcheck.enabled; + size = 1; + + // todo: cond + condition[0] = 0; +} diff --git a/Windows/Debugger/BreakpointWindow.h b/Windows/Debugger/BreakpointWindow.h new file mode 100644 index 0000000000..0180d74052 --- /dev/null +++ b/Windows/Debugger/BreakpointWindow.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include "Common/CommonTypes.h" +#include "../../Core/Debugger/DebugInterface.h" +#include "Core/Debugger/Breakpoints.h" + +class BreakpointWindow +{ + HWND parentHwnd; + DebugInterface* cpu; + bool ctrlDown; + + bool memory; + bool read; + bool write; + bool enabled; + bool log; + u32 address; + u32 size; + char condition[128]; + PostfixExpression compiledCondition; + + static BreakpointWindow* bp; + bool fetchDialogData(HWND hwnd); +public: + BreakpointWindow(HWND parent, DebugInterface* cpu): cpu(cpu) + { + parentHwnd = parent; + memory = false; + read = write = true; + enabled = log = true; + address = -1; + size = 1; + condition[0] = 0; + + ctrlDown = false; + }; + + + static INT_PTR CALLBACK dlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + bool exec(); + bool isMemoryBreakpoint() { return memory; }; + + void addMemcheck(); + void addBreakpoint(); + void editMemcheck(MemCheck& memcheck); + void editBreakpoint(BreakPoint& memcheck); + void loadFromMemcheck(MemCheck& memcheck); + void loadFromBreakpoint(BreakPoint& memcheck); + +}; \ No newline at end of file diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index bbdf91b7a5..7ffadf18cb 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -11,6 +11,7 @@ #include "Debugger_Disasm.h" #include "Debugger_VFPUDlg.h" #include "DebuggerShared.h" +#include "BreakpointWindow.h" #include "../main.h" #include "CtrlRegisterList.h" @@ -655,9 +656,16 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) Core_WaitInactive(200); } - u32 start; - if (executeExpressionWindow(m_hDlg,cpu,start)) - CBreakPoints::AddMemCheck(start, 0, MEMCHECK_READWRITE, MEMCHECK_BOTH); + BreakpointWindow bpw(m_hDlg,cpu); + if (bpw.exec()) + { + if (bpw.isMemoryBreakpoint()) + { + bpw.addMemcheck(); + } else { + bpw.addBreakpoint(); + } + } if (isRunning) { diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 007be1cb93..6c9f49467c 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -260,6 +260,7 @@ + @@ -299,6 +300,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index b4e8382b38..17c8355afb 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -104,6 +104,9 @@ Windows\Debugger + + Windows\Debugger + @@ -185,6 +188,9 @@ Windows\Debugger + + Windows\Debugger + diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 4b9127cd75..0f9cefef38 100644 Binary files a/Windows/ppsspp.rc and b/Windows/ppsspp.rc differ diff --git a/Windows/resource.h b/Windows/resource.h index e8fc59248d..df8d02f0bf 100644 Binary files a/Windows/resource.h and b/Windows/resource.h differ