emu48-mirror/sources/Emu48/DEBUGGER.C

1476 lines
39 KiB
C
Raw Normal View History

2024-03-19 22:25:45 +01:00
/*
* debugger.c
*
* This file is part of Emu48
*
* Copyright (C) 1999 Christoph Gie<EFBFBD>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;
}