#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_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),bp->memory); if (bp->address != -1) { sprintf(str,"0x%08X",bp->address); SetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str); } sprintf(str,"0x%08X",bp->size); SetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),str); SetWindowTextA(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_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),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); 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 = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_MEMORY),BM_GETCHECK,0,0) != 0; read = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_READ),BM_GETCHECK,0,0) != 0; write = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_WRITE),BM_GETCHECK,0,0) != 0; enabled = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_ENABLED),BM_GETCHECK,0,0) != 0; log = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),BM_GETCHECK,0,0) != 0; onChange = SendMessage(GetDlgItem(hwnd,IDC_BREAKPOINT_ONCHANGE),BM_GETCHECK,0,0) != 0; // parse address GetWindowTextA(GetDlgItem(hwnd,IDC_BREAKPOINT_ADDRESS),str,256); if (cpu->initExpression(str,exp) == false) { sprintf(errorMessage,"Invalid expression \"%s\".",str); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (cpu->parseExpression(exp,address) == false) { sprintf(errorMessage,"Invalid expression \"%s\".",str); 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) { sprintf(errorMessage,"Invalid expression \"%s\".",str); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } if (cpu->parseExpression(exp,size) == false) { sprintf(errorMessage,"Invalid expression \"%s\".",exp); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } // condition GetWindowTextA(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); MessageBoxA(hwnd,errorMessage,"Error",MB_OK); return false; } } return true; } bool BreakpointWindow::exec() { bp = this; bool result = DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(IDD_BREAKPOINT),parentHwnd,dlgFunc,(LPARAM)this) != 0; return result; } void BreakpointWindow::addBreakpoint() { if (memory) { // add 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; CBreakPoints::AddMemCheck(address,address+size,cond,result); } else { // add breakpoint CBreakPoints::AddBreakPoint(address,false); if (condition[0] != 0) { BreakPointCond cond; cond.debug = cpu; strcpy(cond.expressionString,condition); cond.expression = compiledCondition; CBreakPoints::ChangeBreakPointAddCond(address,cond); } if (enabled == false) { CBreakPoints::ChangeBreakPoint(address,false); } } } 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& breakpoint) { memory = false; enabled = breakpoint.enabled; address = breakpoint.addr; size = 1; if (breakpoint.hasCond) { strcpy(condition,breakpoint.cond.expressionString); } else { condition[0] = 0; } } void BreakpointWindow::initBreakpoint(u32 _address) { memory = false; enabled = true; address = _address; size = 1; condition[0] = 0; }