/* * debugger.c * * This file is part of Emu48 * * Copyright (C) 1999 Christoph Gießelink * */ #include "pch.h" #include "resource.h" #include "Emu48.h" #include "Opcodes.h" #include "ops.h" #include "color.h" #include "debugger.h" #define MAXCODELINES 15 // number of lines in code window #define MAXMEMLINES 6 // number of lines in memory window #define MAXMEMITEMS 16 // number of address items in a memory window line #define MAXBREAKPOINTS 256 // max. number of breakpoints #define WM_UPDATE (WM_USER+0x1000) // update debugger dialog box #define MEMWNDMAX (sizeof(nCol) / sizeof(nCol[0])) static CONST int nCol[] = { IDC_DEBUG_MEM_COL0, IDC_DEBUG_MEM_COL1, IDC_DEBUG_MEM_COL2, IDC_DEBUG_MEM_COL3, IDC_DEBUG_MEM_COL4, IDC_DEBUG_MEM_COL5, IDC_DEBUG_MEM_COL6, IDC_DEBUG_MEM_COL7 }; static CONST char cHex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; static WORD wBreakpointCount = 0; // number of breakpoints static DWORD dwBreakpoint[MAXBREAKPOINTS]; // breakpoint table static DWORD dwAdrLine[MAXCODELINES]; // addresses of disassember lines in code window static DWORD dwAdrMem = 0; // start address of memory window static LONG lCharWidth; // width of a character (is a fix font) static HMENU hMenuCode,hMenuMem; // handle of context menues static CHIPSET OldChipset; // 10.11.99 cg, new, old chipset content HWND hDlgDebug = NULL; // handle for debugger dialog HANDLE hEventDebug; // event handle to stop cpu thread BOOL bDbgEnable = FALSE; // debugger mode enable flag INT nDbgState = DBG_RUN; // 13.11.99 cg, new, state of debugger //BOOL bDbgSingle = FALSE; // 13.11.99 cg, removed //BOOL bDbgOver = FALSE; // 13.11.99 cg, removed BOOL bDbgNOP3 = FALSE; // halt on NOP3 (#420 opcode) DWORD dwDbgRstkp; // stack recursion level of step over end DWORD dwDbgRstk; // 13.11.99 cg, new, possible return address // function prototypes static VOID OnNewValue(LPSTR lpszValue); static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue); static BOOL OnEditBreakpoint(HWND hDlg); //################ //# //# Low level subroutines //# //################ // // set/reset breakpoint // static __inline VOID ToggleBreakpoint(DWORD dwAddr) { INT i; for (i = 0; i < wBreakpointCount; ++i) // scan all breakpoints { if (dwBreakpoint[i] == dwAddr) // breakpoint found { // purge breakpoint for (++i; i < wBreakpointCount; ++i) dwBreakpoint[i-1] = dwBreakpoint[i]; --wBreakpointCount; return; } } // breakpoint not found if (wBreakpointCount >= MAXBREAKPOINTS) // breakpoint buffer full { AbortMessage("Reached maximum number of breakpoints !"); return; } dwBreakpoint[wBreakpointCount] = dwAddr; ++wBreakpointCount; return; } // // convert nibble register to string // static LPSTR RegToStr(BYTE *pReg, WORD wNib) { static char szBuffer[32]; WORD i; for (i = 0;i < wNib;++i) szBuffer[i] = cHex[pReg[wNib-i-1]]; szBuffer[i] = 0; return szBuffer; } // // convert string to nibble register // static VOID StrToReg(BYTE *pReg, WORD wNib, LPSTR lpszValue) { int i,nValuelen; nValuelen = strlen(lpszValue); for (i = wNib - 1;i >= 0;--i) { if (i >= nValuelen) // no character in string { pReg[i] = 0; // fill with zero } else { pReg[i] = *lpszValue - '0'; // convert to number if (pReg[i] > 9) pReg[i] -= 7; ++lpszValue; } } return; } // // write code window // static VOID ViewCodeWnd(HWND hWnd, DWORD dwAddress) { INT i,j; char szAddress[64]; SendMessage(hWnd,WM_SETREDRAW,FALSE,0); SendMessage(hWnd,LB_RESETCONTENT,0,0); for (i = 0; i < MAXCODELINES; ++i) { dwAdrLine[i] = dwAddress; j = wsprintf(szAddress,(dwAddress == Chipset.pc) ?"%05lX-> " : "%05lX ",dwAddress); dwAddress = disassemble(dwAddress,&szAddress[j],VIEW_SHORT); SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szAddress); } SendMessage(hWnd,WM_SETREDRAW,TRUE,0); return; } // // write memory window // static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress) { #define TEXTOFF 32 INT i,j,k; char szBuffer[16],szItem[4]; BYTE cChar = 0; szItem[2] = 0; // end of string dwAdrMem = dwAddress; // save start address of memory window // purge all list boxes SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_RESETCONTENT,0,0); SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_RESETCONTENT,0,0); for (j = 0; j < MEMWNDMAX; ++j) SendDlgItemMessage(hDlg,nCol[j],LB_RESETCONTENT,0,0); for (i = 0; i < MAXMEMLINES; ++i) { BYTE byLineData[MAXMEMITEMS]; // 12.11.99 cg, changed, fetch data line Npeek(byLineData, dwAddress, MAXMEMITEMS); wsprintf(szBuffer,"%05lX",dwAddress); SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_ADDSTRING,0,(LPARAM) szBuffer); for (k = 0, j = 0; j < MAXMEMITEMS; ++j) { // 12.11.99 cg, changed, read from fetched data line szItem[j&0x1] = cHex[byLineData[j]]; cChar = (cChar << 4) | byLineData[j]; if ((j&0x1) != 0) { // byte field _ASSERT(j/2 < MEMWNDMAX); SendDlgItemMessage(hDlg,nCol[j/2],LB_ADDSTRING,0,(LPARAM) szItem); // text field szBuffer[j/2] = (isprint(cChar) != 0) ? cChar : '.'; } } szBuffer[j/2] = 0; // end of text string SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_ADDSTRING,0,(LPARAM) szBuffer); dwAddress = (dwAddress + MAXMEMITEMS) & 0xFFFFF; } return; #undef TEXTOFF } // // write stack window // static VOID ViewStackWnd(HWND hDlg) { INT i; char szBuffer[64]; HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_STACK); SendMessage(hWnd,WM_SETREDRAW,FALSE,0); SendMessage(hWnd,LB_RESETCONTENT,0,0); for (i = 1; i <= sizeof(Chipset.rstk) / sizeof(Chipset.rstk[0]); ++i) { wsprintf(szBuffer,"%d: %05X", i, Chipset.rstk[(Chipset.rstkp-i)&7]); SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); } SendMessage(hWnd,WM_SETREDRAW,TRUE,0); return; } //################ //# //# High level Window draw routines //# //################ // // update code window with scrolling // static VOID UpdateCodeWnd(HWND hDlg) { INT i; DWORD dwAddress; char szAddress[256]; HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); // seach for actual address in code area for (i = 0; i < MAXCODELINES; ++i) { // get address SendMessage(hWnd,LB_GETTEXT,i,(LONG) szAddress); sscanf(szAddress,"%X",&dwAddress); if (dwAddress == Chipset.pc) // found new pc address line break; } // redraw code window dwAddress = dwAdrLine[0]; // redraw list box with modified pc if (i == MAXCODELINES) // address not found { dwAddress = Chipset.pc; // begin with actual pc i = 0; // set cursor on top } if (i > 10) // cursor near bottom line { dwAddress = dwAdrLine[i-10]; // move that pc is in line 11 i = 10; // set cursor to actual pc } ViewCodeWnd(hWnd,dwAddress); // init code area SendMessage(hWnd,LB_SETCURSEL,i,0); // set return; } // // update register window // static VOID UpdateRegisterWnd(HWND hDlg) { char szBuffer[64]; wsprintf(szBuffer,"A= %s",RegToStr(Chipset.A,16)); SetDlgItemText(hDlg,IDC_REG_A,szBuffer); wsprintf(szBuffer,"B= %s",RegToStr(Chipset.B,16)); SetDlgItemText(hDlg,IDC_REG_B,szBuffer); wsprintf(szBuffer,"C= %s",RegToStr(Chipset.C,16)); SetDlgItemText(hDlg,IDC_REG_C,szBuffer); wsprintf(szBuffer,"D= %s",RegToStr(Chipset.D,16)); SetDlgItemText(hDlg,IDC_REG_D,szBuffer); wsprintf(szBuffer,"R0=%s",RegToStr(Chipset.R0,16)); SetDlgItemText(hDlg,IDC_REG_R0,szBuffer); wsprintf(szBuffer,"R1=%s",RegToStr(Chipset.R1,16)); SetDlgItemText(hDlg,IDC_REG_R1,szBuffer); wsprintf(szBuffer,"R2=%s",RegToStr(Chipset.R2,16)); SetDlgItemText(hDlg,IDC_REG_R2,szBuffer); wsprintf(szBuffer,"R3=%s",RegToStr(Chipset.R3,16)); SetDlgItemText(hDlg,IDC_REG_R3,szBuffer); wsprintf(szBuffer,"R4=%s",RegToStr(Chipset.R4,16)); SetDlgItemText(hDlg,IDC_REG_R4,szBuffer); wsprintf(szBuffer,"D0=%05X",Chipset.d0); SetDlgItemText(hDlg,IDC_REG_D0,szBuffer); wsprintf(szBuffer,"D1=%05X",Chipset.d1); SetDlgItemText(hDlg,IDC_REG_D1,szBuffer); wsprintf(szBuffer,"P=%X",Chipset.P); SetDlgItemText(hDlg,IDC_REG_P,szBuffer); wsprintf(szBuffer,"PC=%05X",Chipset.pc); SetDlgItemText(hDlg,IDC_REG_PC,szBuffer); wsprintf(szBuffer,"OUT=%03X",Chipset.out); SetDlgItemText(hDlg,IDC_REG_OUT,szBuffer); wsprintf(szBuffer,"IN=%04X",Chipset.in); SetDlgItemText(hDlg,IDC_REG_IN,szBuffer); wsprintf(szBuffer,"ST=%s",RegToStr(Chipset.ST,4)); SetDlgItemText(hDlg,IDC_REG_ST,szBuffer); wsprintf(szBuffer,"CY=%d",Chipset.carry); SetDlgItemText(hDlg,IDC_REG_CY,szBuffer); wsprintf(szBuffer,"Mode=%c",Chipset.mode_dec ? 'D' : 'H'); SetDlgItemText(hDlg,IDC_REG_MODE,szBuffer); wsprintf(szBuffer,"MP=%d",(Chipset.HST & MP) != 0); SetDlgItemText(hDlg,IDC_REG_MP,szBuffer); wsprintf(szBuffer,"SR=%d",(Chipset.HST & SR) != 0); SetDlgItemText(hDlg,IDC_REG_SR,szBuffer); wsprintf(szBuffer,"SB=%d",(Chipset.HST & SB) != 0); SetDlgItemText(hDlg,IDC_REG_SB,szBuffer); wsprintf(szBuffer,"XM=%d",(Chipset.HST & XM) != 0); SetDlgItemText(hDlg,IDC_REG_XM,szBuffer); return; } // // update memory window // static VOID UpdateMemoryWnd(HWND hDlg) { ViewMemWnd(hDlg,dwAdrMem); return; } // // update complete debugger dialog // VOID OnUpdate(HWND hDlg) { nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" // enable debug buttons EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_ENABLED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_ENABLED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_ENABLED); // 12.11.99 cg, new EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_ENABLED); // update windows UpdateCodeWnd(hDlg); // update code window UpdateRegisterWnd(hDlg); // update registers window UpdateMemoryWnd(hDlg); // update memory window ViewStackWnd(hDlg); // update stack window ShowWindow(hDlg,SW_RESTORE); // 15.11.99 cg, moved, pop up if minimized SetFocus(hDlg); // set focus to debugger return; } //################ //# //# Virtual key handler //# //################ // // toggle breakpoint key handler (F2) // static BOOL OnKeyF2(HWND hDlg) { HWND hWnd; RECT rc; LONG i; hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); i = SendMessage(hWnd,LB_GETCURSEL,0,0); // get selected item ToggleBreakpoint(dwAdrLine[i]); // toggle breakpoint at address // update region of toggled item SendMessage(hWnd,LB_GETITEMRECT,i,(LPARAM)&rc); InvalidateRect(hWnd,&rc,TRUE); return -1; // call windows default handler } // // run key handler (F5) // static BOOL OnKeyF5(HWND hDlg) { HWND hWnd; INT i,nPos; char szBuf[64]; if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped { hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); nPos = SendMessage(hWnd,LB_GETCURSEL,0,0); // clear "->" in code window for (i = 0; i < MAXCODELINES; ++i) { SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuf); if (szBuf[5] == '-') // PC in window { szBuf[5] = szBuf[6] = ' '; SendMessage(hWnd,LB_DELETESTRING,i,0); SendMessage(hWnd,LB_INSERTSTRING,i,(LPARAM)(LPSTR)szBuf); break; } } SendMessage(hWnd,LB_SETCURSEL,nPos,0); // disable menu keys EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_GRAYED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_GRAYED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_GRAYED); // 12.11.99 cg, new EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_GRAYED); nDbgState = DBG_RUN; // 13.11.99 cg, changed, state "run" OldChipset = Chipset; // 10.11.99 cg, new, save chipset values SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler UNREFERENCED_PARAMETER(hDlg); } // // step into key handler (F7) // static BOOL OnKeyF7(HWND hDlg) { if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped { nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" OldChipset = Chipset; // 10.11.99 cg, new, save chipset values SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler UNREFERENCED_PARAMETER(hDlg); } // // step over key handler (F8) // static BOOL OnKeyF8(HWND hDlg) { if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped { LPBYTE I = FASTPTR(Chipset.pc); dwDbgRstkp = Chipset.rstkp; // save stack level nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" if (I[0] == 0x7) // GOSUB 7aaa { nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" } if (I[0] == 0x8) // GOSUBL or GOSBVL { if (I[1] == 0xE) // GOSUBL 8Eaaaa { nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" } if (I[1] == 0xF) // GOSBVL 8Eaaaaa { nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" } } OldChipset = Chipset; // 10.11.99 cg, new, save chipset values SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler UNREFERENCED_PARAMETER(hDlg); } // // step out key handler (F9) // // 13.11.99 cg, new static BOOL OnKeyF9(HWND hDlg) { if (nDbgState != DBG_RUN) // emulation stopped { // disable menu keys EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_GRAYED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_GRAYED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_GRAYED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_GRAYED); dwDbgRstkp = (Chipset.rstkp-1)&7; // save stack data dwDbgRstk = Chipset.rstk[dwDbgRstkp]; nDbgState = DBG_STEPOUT; // 13.11.99 cg, changed, state "step out" OldChipset = Chipset; // save chipset values SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler UNREFERENCED_PARAMETER(hDlg); } // // break key handler (F11) // static BOOL OnKeyF11(HWND hDlg) { nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" return -1; // call windows default handler UNREFERENCED_PARAMETER(hDlg); } // // view of given address in disassembler window // static BOOL OnCodeGoAdr(HWND hDlg) { DWORD dwAddress = -1; // no address given OnEnterAddress(hDlg, &dwAddress); if (dwAddress != -1) { HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); ViewCodeWnd(hWnd,dwAddress); SendMessage(hWnd,LB_SETCURSEL,0,0); } return -1; // call windows default handler } // // view pc in disassembler window // static BOOL OnCodeGoPC(HWND hDlg) { UpdateCodeWnd(hDlg); return TRUE; } // // set pc to selction // static BOOL OnCodeSetPcToSelection(HWND hDlg) { Chipset.pc = dwAdrLine[SendDlgItemMessage(hDlg,IDC_DEBUG_CODE,LB_GETCURSEL,0,0)]; return OnCodeGoPC(hDlg); } // // view from address in memory window // static BOOL OnMemGoDx(HWND hDlg, DWORD dwAddress) { HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_MEM_COL0); ViewMemWnd(hDlg, dwAddress); SendMessage(hWnd,LB_SETCURSEL,0,0); SetFocus(hWnd); return -1; // call windows default handler } // // view of given address in memory window // static BOOL OnMemGoAdr(HWND hDlg) { DWORD dwAddress = -1; // no address given OnEnterAddress(hDlg, &dwAddress); if (dwAddress != -1) // not Cancel key OnMemGoDx(hDlg,dwAddress); return -1; // call windows default handler } // // clear all breakpoints // static BOOL OnClearAll(HWND hDlg) // 13.12.99 cg, changed argument { wBreakpointCount = 0; // 13.12.99 cg, changed, redraw code window InvalidateRect(GetDlgItem(hDlg,IDC_DEBUG_CODE),NULL,TRUE); return TRUE; } // // toggle NOP3 breakpoint // static BOOL OnNOP3Break(HWND hDlg) { bDbgNOP3 = !bDbgNOP3; // toggle NOP3 debug flag CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3,bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED); return TRUE; } // // new register setting // static BOOL OnLButtonUp(HWND hDlg, LPARAM lParam) { char szBuffer[64]; POINT pt; HWND hWnd; INT nId; #define BUFLEN (sizeof(szBuffer) / sizeof(szBuffer[0])) POINTSTOPOINT(pt,MAKEPOINTS(lParam)); hWnd = ChildWindowFromPoint(hDlg,pt); // handle of selected window nId = GetDlgCtrlID(hWnd); // control ID of window SendMessage(hWnd,WM_GETTEXT,BUFLEN,(LPARAM)szBuffer); switch (nId) { case IDC_REG_A: // A OnNewValue(&szBuffer[3]); StrToReg(Chipset.A,16,&szBuffer[3]); break; case IDC_REG_B: // B OnNewValue(&szBuffer[3]); StrToReg(Chipset.B,16,&szBuffer[3]); break; case IDC_REG_C: // C OnNewValue(&szBuffer[3]); StrToReg(Chipset.C,16,&szBuffer[3]); break; case IDC_REG_D: // D OnNewValue(&szBuffer[3]); StrToReg(Chipset.D,16,&szBuffer[3]); break; case IDC_REG_R0: // R0 OnNewValue(&szBuffer[3]); StrToReg(Chipset.R0,16,&szBuffer[3]); break; case IDC_REG_R1: // R1 OnNewValue(&szBuffer[3]); StrToReg(Chipset.R1,16,&szBuffer[3]); break; case IDC_REG_R2: // R2 OnNewValue(&szBuffer[3]); StrToReg(Chipset.R2,16,&szBuffer[3]); break; case IDC_REG_R3: // R3 OnNewValue(&szBuffer[3]); StrToReg(Chipset.R3,16,&szBuffer[3]); break; case IDC_REG_R4: // R4 OnNewValue(&szBuffer[3]); StrToReg(Chipset.R4,16,&szBuffer[3]); break; case IDC_REG_D0: // D0 OnNewValue(&szBuffer[3]); sscanf(&szBuffer[3],"%5X",&Chipset.d0); break; case IDC_REG_D1: // D1 OnNewValue(&szBuffer[3]); sscanf(&szBuffer[3],"%5X",&Chipset.d1); break; case IDC_REG_P: // P OnNewValue(&szBuffer[2]); Chipset.P = szBuffer[2] - '0'; if (Chipset.P > 9) Chipset.P -= 7; break; case IDC_REG_PC: // PC OnNewValue(&szBuffer[3]); sscanf(&szBuffer[3],"%5X",&Chipset.pc); break; case IDC_REG_OUT: // OUT OnNewValue(&szBuffer[4]); sscanf(&szBuffer[4],"%3X",&Chipset.out); break; case IDC_REG_IN: // IN OnNewValue(&szBuffer[3]); sscanf(&szBuffer[3],"%4X",&Chipset.in); break; case IDC_REG_ST: // ST OnNewValue(&szBuffer[3]); StrToReg(Chipset.ST,4,&szBuffer[3]); break; case IDC_REG_CY: // CY // if (YesNoMessage("Change Carry flag ?") == IDYES) Chipset.carry = !Chipset.carry; break; case IDC_REG_MODE: // MODE Chipset.mode_dec = !Chipset.mode_dec; break; case IDC_REG_MP: // MP Chipset.HST ^= MP; break; case IDC_REG_SR: // SR Chipset.HST ^= SR; break; case IDC_REG_SB: // SB Chipset.HST ^= SB; break; case IDC_REG_XM: // XM Chipset.HST ^= XM; break; } UpdateRegisterWnd(hDlg); // update register return TRUE; #undef BUFLEN } // // double click in list box area // static BOOL OnDblClick(HWND hWnd, WORD wId) { char szBuffer[4]; BYTE byData; INT i; DWORD dwAddress; for (i = 0; i < MEMWNDMAX; ++i) // scan all Id's if (nCol[i] == wId) // found ID break; if (i == MEMWNDMAX) return FALSE; // not IDC_DEBUG_MEM window, default handler // calculate address of byte dwAddress = i * 2; i = SendMessage(hWnd,LB_GETCARETINDEX,0,0); dwAddress += MAXMEMITEMS * i + dwAdrMem; // enter new value SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer); OnNewValue(szBuffer); sscanf(szBuffer,"%2X", &byData); byData = (byData >> 4) | (byData << 4); // 12.11.99 cg, bugfix, change nibbles for writing Write2(dwAddress, byData); // write data UpdateMemoryWnd(GetParent(hWnd)); // update memory window SendMessage(hWnd,LB_SETCURSEL,i,0); return FALSE; } // // request for context menu // static VOID OnContextMenu(HWND hDlg, LPARAM lParam, WPARAM wParam) { POINT pt; INT nId; POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position nId = GetDlgCtrlID((HWND) wParam); // control ID of window switch(nId) { case IDC_DEBUG_CODE: // handle code window TrackPopupMenu(hMenuCode,0,pt.x,pt.y,0,hDlg,NULL); break; case IDC_DEBUG_MEM_COL0: case IDC_DEBUG_MEM_COL1: case IDC_DEBUG_MEM_COL2: case IDC_DEBUG_MEM_COL3: case IDC_DEBUG_MEM_COL4: case IDC_DEBUG_MEM_COL5: case IDC_DEBUG_MEM_COL6: case IDC_DEBUG_MEM_COL7: // handle memory window TrackPopupMenu(hMenuMem,0,pt.x,pt.y,0,hDlg,NULL); break; } return; } //################ //# //# Dialog handler //# //################ // // handle right/left keys in memory window // static __inline BOOL OnKeyRightLeft(HWND hWnd, WPARAM wParam) { HWND hWndNew; WORD wX, wY; INT nId; nId = GetDlgCtrlID(hWnd); // control ID of window for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's if (nCol[wX] == nId) // found ID break; if (wX == MEMWNDMAX) return -1; // not IDC_DEBUG_MEM window, default handler // delete old focus wY = HIWORD(wParam); SendMessage(hWnd,LB_SETCURSEL,-1,0); // new position wX = (LOWORD(wParam) == VK_RIGHT) ? (wX + 1) : (wX + MEMWNDMAX - 1); wX %= MEMWNDMAX; // set new focus hWndNew = GetDlgItem(GetParent(hWnd),nCol[wX]); SendMessage(hWndNew,LB_SETCURSEL,wY,0); SetFocus(hWndNew); return -2; } // // handle (page) up/down keys in memory window // static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) { INT wX, wY; INT nId; nId = GetDlgCtrlID(hWnd); // control ID of window for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's if (nCol[wX] == nId) // found ID break; if (wX == MEMWNDMAX) return -1; // not IDC_DEBUG_MEM window, default handler wY = HIWORD(wParam); // get old focus switch(LOWORD(wParam)) { case VK_NEXT: dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; UpdateMemoryWnd(GetParent(hWnd)); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; case VK_PRIOR: dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; UpdateMemoryWnd(GetParent(hWnd)); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; case VK_DOWN: if (wY+1 >= MAXMEMLINES) { dwAdrMem = (dwAdrMem + MAXMEMITEMS) & 0xFFFFF; UpdateMemoryWnd(GetParent(hWnd)); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; } break; case VK_UP: if (wY == 0) { dwAdrMem = (dwAdrMem - MAXMEMITEMS) & 0xFFFFF; UpdateMemoryWnd(GetParent(hWnd)); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; } break; } return -1; } // // handle keys in code window // // 13.12.99 cg, changed first argument static __inline BOOL OnKeyCodeWnd(HWND hDlg, WPARAM wParam) { // 13.12.99 cg, new, get handle of code window (was argument) HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); WORD wKey = LOWORD(wParam); WORD wItem = HIWORD(wParam); // down key on last line if ((wKey == VK_DOWN || wKey == VK_NEXT) && wItem == MAXCODELINES - 1) { ViewCodeWnd(hWnd,dwAdrLine[1]); SendMessage(hWnd,LB_SETCURSEL,wItem,0); } // up key on first line if ((wKey == VK_UP || wKey == VK_PRIOR) && wItem == 0) { if (dwAdrLine[0] > 0) ViewCodeWnd(hWnd,dwAdrLine[0]-1); } if (wKey == 'G') return OnCodeGoAdr(GetParent(hWnd)); // goto new address return -1; } // // handle drawing in code window // static __inline BOOL OnDrawCodeWnd(LPDRAWITEMSTRUCT lpdis) { char szBuf[64]; COLORREF crBkColor; COLORREF crTextColor; BOOL bBrk,bPC; if (lpdis->itemID == -1) // no item in list box return TRUE; // get item text SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LONG)(LPSTR)szBuf); bBrk = CheckBreakpoint(dwAdrLine[lpdis->itemID]); // check breakpoint bPC = szBuf[5] == '-'; // check if line of program counter crTextColor = COLOR_WHITE; // standard text color if (lpdis->itemState & ODS_SELECTED) // cursor line { if (bPC) // PC line { crBkColor = bBrk ? COLOR_DKGRAY : COLOR_TEAL; } else // normal line { crBkColor = bBrk ? COLOR_PURPLE : COLOR_NAVY; } } else // not cursor line { if (bPC) // PC line { crBkColor = bBrk ? COLOR_OLIVE : COLOR_GREEN; } else // normal line { if (bBrk) { crBkColor = COLOR_MAROON; } else { crBkColor = COLOR_WHITE; crTextColor = COLOR_BLACK; } } } // write Text crBkColor = SetBkColor(lpdis->hDC,crBkColor); crTextColor = SetTextColor(lpdis->hDC,crTextColor); ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+2,(int)(lpdis->rcItem.top), ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,strlen(szBuf),NULL); SetBkColor(lpdis->hDC,crBkColor); SetTextColor(lpdis->hDC,crTextColor); if (lpdis->itemState & ODS_FOCUS) // redraw focus DrawFocusRect(lpdis->hDC,&lpdis->rcItem); return TRUE; // focus handled here } // // detect changed register // // 10.11.99 cg, new static __inline BOOL OnCtlColorStatic(HWND hWnd) { switch(GetDlgCtrlID(hWnd)) { case IDC_REG_A: // A return memcmp(Chipset.A, OldChipset.A, sizeof(Chipset.A)); case IDC_REG_B: // B return memcmp(Chipset.B, OldChipset.B, sizeof(Chipset.B)); case IDC_REG_C: // C return memcmp(Chipset.C, OldChipset.C, sizeof(Chipset.C)); case IDC_REG_D: // D return memcmp(Chipset.D, OldChipset.D, sizeof(Chipset.D)); case IDC_REG_R0: // R0 return memcmp(Chipset.R0, OldChipset.R0, sizeof(Chipset.R0)); case IDC_REG_R1: // R1 return memcmp(Chipset.R1, OldChipset.R1, sizeof(Chipset.R1)); case IDC_REG_R2: // R2 return memcmp(Chipset.R2, OldChipset.R2, sizeof(Chipset.R2)); case IDC_REG_R3: // R3 return memcmp(Chipset.R3, OldChipset.R3, sizeof(Chipset.R3)); case IDC_REG_R4: // R4 return memcmp(Chipset.R4, OldChipset.R4, sizeof(Chipset.R4)); case IDC_REG_D0: // D0 return Chipset.d0 != OldChipset.d0; case IDC_REG_D1: // D1 return Chipset.d1 != OldChipset.d1; case IDC_REG_P: // P return Chipset.P != OldChipset.P; case IDC_REG_PC: // PC return Chipset.pc != OldChipset.pc; case IDC_REG_OUT: // OUT return Chipset.out != OldChipset.out; case IDC_REG_IN: // IN return Chipset.in != OldChipset.in; case IDC_REG_ST: // ST return memcmp(Chipset.ST, OldChipset.ST, sizeof(Chipset.ST)); case IDC_REG_CY: // CY return Chipset.carry != OldChipset.carry; case IDC_REG_MODE: // MODE return Chipset.mode_dec != OldChipset.mode_dec; case IDC_REG_MP: // MP return (Chipset.HST ^ OldChipset.HST) & MP; case IDC_REG_SR: // SR return (Chipset.HST ^ OldChipset.HST) & SR; case IDC_REG_SB: // SB return (Chipset.HST ^ OldChipset.HST) & SB; case IDC_REG_XM: // XM return (Chipset.HST ^ OldChipset.HST) & XM; } return FALSE; // not changed } //################ //# //# Public functions //# //################ // // check for code breakpoints // BOOL CheckBreakpoint(DWORD dwAddr) { INT i; for (i = 0; i < wBreakpointCount; ++i) // scan all breakpoints { if (dwBreakpoint[i] == dwAddr) // breakpoint found return TRUE; } return FALSE; } // // notify debugger that emulation stopped // VOID NotifyDebugger(VOID) // 10.11.99 cg, new, update registers { _ASSERT(hDlgDebug); // debug dialog box open PostMessage(hDlgDebug,WM_UPDATE,0,0); return; } //################ //# //# Debugger Message loop //# //################ // // ID_TOOL_DEBUG // static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { static HMENU hMenuMainCode,hMenuMainMem; LPDRAWITEMSTRUCT lpdis; LPMEASUREITEMSTRUCT lpmis; TEXTMETRIC tm; HDC hDC; HFONT hFont; INT i; switch (message) { case WM_INITDIALOG: _ASSERT(hWnd); EnableMenuItem(GetMenu(hWnd),ID_TOOL_DEBUG,MF_GRAYED); CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3,bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED); hDlgDebug = hDlg; // handle for debugger dialog // 13.12.99 cg, changed, save handle of base menus hMenuMainCode = LoadMenu(hApp,MAKEINTRESOURCE(IDR_DEBUG_CODE)); _ASSERT(hMenuMainCode); hMenuCode = GetSubMenu(hMenuMainCode, 0); _ASSERT(hMenuCode); hMenuMainMem = LoadMenu(hApp,MAKEINTRESOURCE(IDR_DEBUG_MEM)); _ASSERT(hMenuMainMem); hMenuMem = GetSubMenu(hMenuMainMem, 0); _ASSERT(hMenuMem); // 13.12.99 cg, end of changed part hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL); if (hEventDebug == NULL) { AbortMessage("Event creation failed !"); return TRUE; } // font settings SendDlgItemMessage(hDlg,IDC_STATIC_CODE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_STATIC_REGISTERS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_STATIC_MEMORY, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_STATIC_STACK, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); bDbgEnable = TRUE; // debugger active nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" if (Chipset.Shutdn) // cpu thread stopped SetEvent(hEventShutdn); // goto debug session OldChipset = Chipset; // 10.11.99 cg, new, save chipset values return TRUE; case WM_DESTROY: // SetHP48Time(); // update HP48 time & date hDlgDebug = NULL; // debugger windows closed bDbgEnable = FALSE; // debugger inactive nDbgState = DBG_RUN; // 13.11.99 cg, changed, state of debugger bInterrupt = TRUE; // exit opcode loop SetEvent(hEventDebug); CloseHandle(hEventDebug); DestroyMenu(hMenuMainCode); // 13.12.99 cg, bugfix, used wrong handle DestroyMenu(hMenuMainMem); // 13.12.99 cg, bugfix, used wrong handle _ASSERT(hWnd); EnableMenuItem(GetMenu(hWnd),ID_TOOL_DEBUG,MF_ENABLED); break; case WM_CLOSE: DestroyWindow(hDlg); break; case WM_UPDATE: OnUpdate(hDlg); return TRUE; case WM_COMMAND: switch (HIWORD(wParam)) { case LBN_DBLCLK: return OnDblClick((HWND) lParam, LOWORD(wParam)); case LBN_SETFOCUS: i = SendMessage((HWND) lParam,LB_GETCARETINDEX,0,0); SendMessage((HWND) lParam,LB_SETCURSEL,i,0); return TRUE; case LBN_KILLFOCUS: SendMessage((HWND) lParam,LB_SETCURSEL,-1,0); return TRUE; } switch (LOWORD(wParam)) { case ID_BREAKPOINTS_SETBREAK: return OnKeyF2(hDlg); case ID_DEBUG_RUN: return OnKeyF5(hDlg); case ID_DEBUG_STEP: return OnKeyF7(hDlg); case ID_DEBUG_STEPOVER: return OnKeyF8(hDlg); case ID_DEBUG_STEPOUT: return OnKeyF9(hDlg); case ID_DEBUG_BREAK: return OnKeyF11(hDlg); case ID_DEBUG_CODE_GOADR: return OnCodeGoAdr(hDlg); case ID_DEBUG_CODE_GOPC: return OnCodeGoPC(hDlg); case ID_DEBUG_CODE_SETPCTOSELECT: return OnCodeSetPcToSelection(hDlg); case ID_BREAKPOINTS_CODEEDIT: return OnEditBreakpoint(hDlg); // 13.12.99 cg, changed argument to dialog handle case ID_BREAKPOINTS_CLEARALL: return OnClearAll(hDlg); case ID_BREAKPOINTS_NOP3: return OnNOP3Break(hDlg); case ID_DEBUG_MEM_GOADR: return OnMemGoAdr(hDlg); case ID_DEBUG_MEM_GOPC: return OnMemGoDx(hDlg, Chipset.pc); case ID_DEBUG_MEM_GOD0: return OnMemGoDx(hDlg, Chipset.d0); case ID_DEBUG_MEM_GOD1: return OnMemGoDx(hDlg, Chipset.d1); case ID_DEBUG_MEM_GOSTACK: return OnMemGoDx(hDlg, Chipset.rstk[(Chipset.rstkp-1)&7]); } break; case WM_VKEYTOITEM: switch (LOWORD(wParam)) // always valid { case VK_F2: return OnKeyF2(hDlg); // toggle breakpoint case VK_F5: return OnKeyF5(hDlg); // key run case VK_F7: return OnKeyF7(hDlg); // key step into case VK_F8: return OnKeyF8(hDlg); // key step over case VK_F9: return OnKeyF9(hDlg); // key step out case VK_F11: return OnKeyF11(hDlg); // key break } switch(GetDlgCtrlID((HWND) lParam)) // calling window { // handle code window case IDC_DEBUG_CODE: // 13.12.99 cg, changed first argument to dialog handle return OnKeyCodeWnd(hDlg, wParam); // handle memory window case IDC_DEBUG_MEM_COL0: case IDC_DEBUG_MEM_COL1: case IDC_DEBUG_MEM_COL2: case IDC_DEBUG_MEM_COL3: case IDC_DEBUG_MEM_COL4: case IDC_DEBUG_MEM_COL5: case IDC_DEBUG_MEM_COL6: case IDC_DEBUG_MEM_COL7: switch (LOWORD(wParam)) { case 'G': return OnMemGoAdr(GetParent((HWND) lParam)); case VK_RIGHT: case VK_LEFT: return OnKeyRightLeft((HWND) lParam, wParam); case VK_NEXT: case VK_PRIOR: case VK_DOWN: case VK_UP: return OnKeyUpDown((HWND) lParam, wParam); } break; } return -1; // default action case WM_LBUTTONUP: return OnLButtonUp(hDlg, lParam); case WM_CONTEXTMENU: OnContextMenu(hDlg, lParam, wParam); break; case WM_CTLCOLORSTATIC: // 10.11.99 cg, new, register color highlighting // highlight text? if (OnCtlColorStatic((HWND) lParam)) { SetTextColor((HDC) wParam, COLOR_RED); SetBkColor((HDC) wParam, GetSysColor(COLOR_INACTIVECAPTIONTEXT)); return (BOOL) GetStockObject(NULL_BRUSH); // transparent brush } break; case WM_DRAWITEM: lpdis = (LPDRAWITEMSTRUCT)lParam; // get pointer to the DRAWITEMSTRUCT if (wParam == IDC_DEBUG_CODE) return OnDrawCodeWnd(lpdis); break; case WM_MEASUREITEM: lpmis = (LPMEASUREITEMSTRUCT)lParam; // get pointer to the MEASUREITEMSTRUCT hDC = GetDC(hDlg); // GetTextMetrics from "Courier New 8" font hFont = CreateFont(-MulDiv(8,GetDeviceCaps(hDC, LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,"Courier New"); hFont = SelectObject(hDC,hFont); GetTextMetrics(hDC,&tm); hFont = SelectObject(hDC,hFont); DeleteObject(hFont); lpmis->itemHeight = tm.tmHeight; lCharWidth = tm.tmAveCharWidth; ReleaseDC(hDlg,hDC); return TRUE; } return FALSE; } LRESULT OnToolDebug() // 06.08.99 cg, new, debugger dialogbox call { if ((hDlgDebug = CreateDialog(hApp,MAKEINTRESOURCE(IDD_DEBUG),GetParent(hWnd), (DLGPROC)Debugger)) == NULL) AbortMessage("Debugger Dialog Box Creation Error !"); SetClassLong(hDlgDebug,GCL_HICON,(LONG) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48))); return 0; } //################ //# //# New Value dialog box //# //################ // // enter new value dialog // static BOOL CALLBACK NewValue(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { static LPSTR lpszBuffer; // handle of buffer static int nBufferlen; // length of buffer LONG i; switch (message) { case WM_INITDIALOG: lpszBuffer = (LPSTR) lParam; nBufferlen = strlen(lpszBuffer)+1; // length with zero string terminator SetDlgItemText(hDlg,IDC_NEWVALUE,lpszBuffer); return TRUE; case WM_COMMAND: switch(wParam) { case IDOK: GetDlgItemText(hDlg,IDC_NEWVALUE,lpszBuffer,nBufferlen); // test if valid hex address for (i = 0; i < (LONG) strlen(lpszBuffer); ++i) { if (isxdigit(lpszBuffer[i]) == FALSE) { SendDlgItemMessage(hDlg,IDC_NEWVALUE,EM_SETSEL,0,-1); return FALSE; } } // no break case IDCANCEL: EndDialog(hDlg, wParam); return TRUE; } } return FALSE; UNREFERENCED_PARAMETER(wParam); } static VOID OnNewValue(LPSTR lpszValue) { if (DialogBoxParam(hApp, MAKEINTRESOURCE(IDD_NEWVALUE), hDlgDebug, (DLGPROC)NewValue, (LPARAM)lpszValue) == -1) AbortMessage("Input Dialog Box Creation Error !"); } //################ //# //# Goto Address dialog box //# //################ // // enter goto address dialog // static BOOL CALLBACK EnterAddr(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { static DWORD *dwAddress; char szBuffer[8]; LONG i; switch (message) { case WM_INITDIALOG: dwAddress = (DWORD *) lParam; SetDlgItemText(hDlg,IDC_ENTERADR,""); return TRUE; case WM_COMMAND: switch(wParam) { case IDOK: GetDlgItemText(hDlg,IDC_ENTERADR,szBuffer,8); // test if valid hex address for (i = 0; i < (LONG) strlen(szBuffer); ++i) { if (isxdigit(szBuffer[i]) == FALSE) { SendDlgItemMessage(hDlg,IDC_ENTERADR,EM_SETSEL,0,-1); return FALSE; } } if (*szBuffer) sscanf(szBuffer,"%5X",dwAddress); // no break case IDCANCEL: EndDialog(hDlg, wParam); return TRUE; } } return FALSE; UNREFERENCED_PARAMETER(wParam); } static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue) { if (DialogBoxParam(hApp, MAKEINTRESOURCE(IDD_ENTERADR), hDlg, (DLGPROC)EnterAddr, (LPARAM)dwValue) == -1) AbortMessage("Address Dialog Box Creation Error !"); } //################ //# //# Edit breakpoint dialog box //# //################ // // enter edit breakpoint dialog // static BOOL CALLBACK EditBreakpoint(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { char szBuffer[32]; DWORD dwAddress; INT i; HWND hWnd = GetDlgItem(hDlg,IDC_BREAKEDIT_WND); switch (message) { case WM_INITDIALOG: // font settings SendDlgItemMessage(hDlg,IDC_STATIC_BREAKPOINT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_BREAKEDIT_ADD, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_BREAKEDIT_DELETE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDOK, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendMessage(hWnd,WM_SETREDRAW,FALSE,0); SendMessage(hWnd,LB_RESETCONTENT,0,0); for (i = 0; i < wBreakpointCount; ++i) { wsprintf(szBuffer,"%05X (Code)",dwBreakpoint[i]); SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); } SendMessage(hWnd,WM_SETREDRAW,TRUE,0); return TRUE; case WM_COMMAND: switch(wParam) { case IDC_BREAKEDIT_ADD: dwAddress = -1; // no address given OnEnterAddress(hDlg, &dwAddress); if (dwAddress != -1) { for (i = 0; i < wBreakpointCount; ++i) { if (dwBreakpoint[i] == dwAddress) return FALSE; } wsprintf(szBuffer,"%05X (Code)",dwAddress); SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); dwBreakpoint[wBreakpointCount] = dwAddress; ++wBreakpointCount; } return TRUE; case IDC_BREAKEDIT_DELETE: if ((i = SendMessage(hWnd,LB_GETCURSEL,0,0)) == LB_ERR) return FALSE; SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer); SendMessage(hWnd,LB_DELETESTRING,i,0); sscanf(szBuffer,"%X",&dwAddress); for (i = 0; i < wBreakpointCount; ++i) { if (dwBreakpoint[i] == dwAddress) { // move rest to top for (++i; i < wBreakpointCount; ++i) dwBreakpoint[i-1] = dwBreakpoint[i]; --wBreakpointCount; break; } } return TRUE; case IDOK: case IDCANCEL: EndDialog(hDlg, wParam); return TRUE; } } return FALSE; UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); } static BOOL OnEditBreakpoint(HWND hDlg) { if (DialogBox(hApp, MAKEINTRESOURCE(IDD_BREAKEDIT), hDlg, (DLGPROC)EditBreakpoint) == -1) AbortMessage("Edit Breakpoint Dialog Box Creation Error !"); UpdateCodeWnd(hDlg); // update code window return -1; }