1476 lines
39 KiB
C
1476 lines
39 KiB
C
|
/*
|
|||
|
* 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;
|
|||
|
}
|