#include #include "Common/Data/Encoding/Utf8.h" #include "Common/Math/expression_parser.h" #include "BreakpointWindow.h" #include "../resource.h" 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_ONCHANGE),BM_SETCHECK, bp->onChange ? 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_ONCHANGE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG_FORMAT), bp->log); if (bp->address != -1) { snprintf(str, sizeof(str), "0x%08X", bp->address); SetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str); } snprintf(str, sizeof(str), "0x%08X", bp->size); SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE),str); SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(bp->condition).c_str()); SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), ConvertUTF8ToWString(bp->logFormat).c_str()); 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_ONCHANGE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!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_ONCHANGE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory); EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory); break; } break; case IDC_BREAKPOINT_LOG: switch (HIWORD(wParam)) { case BN_CLICKED: EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), bp->GetCheckState(hwnd, IDC_BREAKPOINT_LOG)); 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 = GetCheckState(hwnd, IDC_BREAKPOINT_MEMORY); read = GetCheckState(hwnd, IDC_BREAKPOINT_READ); write = GetCheckState(hwnd, IDC_BREAKPOINT_WRITE); enabled = GetCheckState(hwnd, IDC_BREAKPOINT_ENABLED); log = GetCheckState(hwnd, IDC_BREAKPOINT_LOG); onChange = GetCheckState(hwnd, IDC_BREAKPOINT_ONCHANGE); // parse address GetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str,256); if (cpu->initExpression(str,exp) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (cpu->parseExpression(exp,address) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (memory) { // parse size GetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),str,256); if (cpu->initExpression(str,exp) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (cpu->parseExpression(exp,size) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError()); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } // condition wchar_t tempCond[512]; GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), tempCond, 512); condition = ConvertWStringToUTF8(tempCond); compiledCondition.clear(); if (!condition.empty()) { if (cpu->initExpression(condition.c_str(), compiledCondition) == false) { snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", condition.c_str(), getExpressionError()); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } wchar_t tempLogFormat[512]; GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), tempLogFormat, 512); logFormat = ConvertWStringToUTF8(tempLogFormat); if (!CBreakPoints::ValidateLogFormat(cpu, logFormat)) { snprintf(errorMessage, sizeof(errorMessage), "Invalid log format (example: \"{a1}\")."); MessageBoxA(hwnd, errorMessage, "Error", MB_OK); return false; } return true; } bool BreakpointWindow::GetCheckState(HWND hwnd, int dlgItem) { return SendMessage(GetDlgItem(hwnd, dlgItem), BM_GETCHECK, 0, 0) != 0; } bool BreakpointWindow::exec() { bp = this; bool result = DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_BREAKPOINT),parentHwnd,dlgFunc,(LPARAM)this) != 0; return result; } void BreakpointWindow::addBreakpoint() { BreakAction result = BREAK_ACTION_IGNORE; if (log) result |= BREAK_ACTION_LOG; if (enabled) result |= BREAK_ACTION_PAUSE; if (memory) { // add memcheck int cond = 0; if (read) cond |= MEMCHECK_READ; if (write) cond |= MEMCHECK_WRITE; if (onChange) cond |= MEMCHECK_WRITE_ONCHANGE; CBreakPoints::AddMemCheck(address, address + size, (MemCheckCondition)cond, result); CBreakPoints::ChangeMemCheckLogFormat(address, address + size, logFormat); } else { // add breakpoint CBreakPoints::AddBreakPoint(address,false); if (!condition.empty()) { BreakPointCond cond; cond.debug = cpu; cond.expressionString = condition; cond.expression = compiledCondition; CBreakPoints::ChangeBreakPointAddCond(address,cond); } CBreakPoints::ChangeBreakPoint(address, result); CBreakPoints::ChangeBreakPointLogFormat(address, logFormat); } } void BreakpointWindow::loadFromMemcheck(MemCheck& memcheck) { memory = true; read = (memcheck.cond & MEMCHECK_READ) != 0; write = (memcheck.cond & MEMCHECK_WRITE) != 0; onChange = (memcheck.cond & MEMCHECK_WRITE_ONCHANGE) != 0; log = (memcheck.result & BREAK_ACTION_LOG) != 0; enabled = (memcheck.result & BREAK_ACTION_PAUSE) != 0; address = memcheck.start; size = memcheck.end-address; logFormat = memcheck.logFormat; } void BreakpointWindow::loadFromBreakpoint(BreakPoint& breakpoint) { memory = false; log = (breakpoint.result & BREAK_ACTION_LOG) != 0; enabled = (breakpoint.result & BREAK_ACTION_PAUSE) != 0; address = breakpoint.addr; size = 1; if (breakpoint.hasCond) { condition = breakpoint.cond.expressionString; } else { condition.clear(); } logFormat = breakpoint.logFormat; } void BreakpointWindow::initBreakpoint(u32 _address) { memory = false; enabled = true; address = _address; size = 1; condition.clear(); }