From fb932a8d4fe9da312ece5f4c6b731c5912b2514d Mon Sep 17 00:00:00 2001 From: mpohoreski Date: Sun, 14 May 2006 00:43:19 +0000 Subject: [PATCH] Breakpoints on full-speed. BRK # [ON|OFF] BRKOP ## --- AppleWin/source/CPU.cpp | 110 +++++++++++++++------- AppleWin/source/Debug.cpp | 153 ++++++++++++++++++++++++++++++- AppleWin/source/Debug.h | 23 ++++- AppleWin/source/Debugger_Types.h | 34 ++++--- AppleWin/source/Disk.cpp | 4 +- 5 files changed, 267 insertions(+), 57 deletions(-) diff --git a/AppleWin/source/CPU.cpp b/AppleWin/source/CPU.cpp index 27172c2b..ccd262b6 100644 --- a/AppleWin/source/CPU.cpp +++ b/AppleWin/source/CPU.cpp @@ -427,9 +427,34 @@ static volatile UINT32 g_bmIRQ = 0; #define TXS regs.sp = 0x100 | regs.x; #define TYA regs.a = regs.y; \ SETNZ(regs.a) -#define INVALID1 -#define INVALID2 if (apple2e) ++regs.pc; -#define INVALID3 if (apple2e) regs.pc += 2; + + +void RequestDebugger() +{ + PostMessage( g_hFrameWindow, WM_KEYDOWN, DEBUG_TOGGLE_KEY, 0 ); + PostMessage( g_hFrameWindow, WM_KEYUP , DEBUG_TOGGLE_KEY, 0 ); +} + +bool CheckDebugBreak( int iOpcode ) +{ + // Rnning at full speed? (debugger not running) + if ((mode != MODE_DEBUG) && (mode != MODE_STEPPING)) + { + if (((iOpcode == 0) && IsDebugBreakOnInvalid(0)) || + ((g_iDebugOnOpcode) && (g_iDebugOnOpcode == iOpcode))) // User wants to enter debugger on opcode? + { + RequestDebugger(); + return true; + } + } + + return false; +} + +// Break into debugger on invalid opcodes +#define INVALID1 ; if (IsDebugBreakOnInvalid(1)) { RequestDebugger(); bBreakOnInvalid = true; } +#define INVALID2 if (apple2e) ++regs.pc ; if (IsDebugBreakOnInvalid(2)) { RequestDebugger(); bBreakOnInvalid = true; } +#define INVALID3 if (apple2e) regs.pc += 2; if (IsDebugBreakOnInvalid(3)) { RequestDebugger(); bBreakOnInvalid = true; } /**************************************************************************** * @@ -480,24 +505,33 @@ static inline void DoIrqProfiling(DWORD cycles) //=========================================================================== static DWORD InternalCpuExecute (DWORD totalcycles) { - WORD addr; - BOOL flagc; - BOOL flagn; - BOOL flagv; - BOOL flagz; - WORD temp; - WORD val; - AF_TO_EF - DWORD cycles = 0; - BOOL bWrtMem; // Set if opcode writes to memory (eg. ASL, STA) - WORD base; + WORD addr; + BOOL flagc; + BOOL flagn; + BOOL flagv; + BOOL flagz; + WORD temp; + WORD val; + AF_TO_EF + DWORD cycles = 0; + BOOL bWrtMem; // Set if opcode writes to memory (eg. ASL, STA) + WORD base; - do - { - nInternalCyclesLeft = (totalcycles<<8) - (cycles<<8); - USHORT uExtraCycles = 0; + bool bBreakOnInvalid = false; - switch (*(mem+regs.pc++)) + do + { + nInternalCyclesLeft = (totalcycles<<8) - (cycles<<8); + USHORT uExtraCycles = 0; + + BYTE iOpcode = *(mem+regs.pc); + if (CheckDebugBreak( iOpcode )) + break; + + regs.pc++; + + + switch (iOpcode) { case 0x00: BRK CYC(7) break; case 0x01: INDX ORA CYC(6) break; @@ -759,23 +793,29 @@ static DWORD InternalCpuExecute (DWORD totalcycles) case 0xFF: INVALID1 CYC(1) break; } - if(g_bmIRQ && !(regs.ps & AF_INTERRUPT)) - { - // IRQ signals are deasserted when a specific r/w operation is done on device - g_nCycleIrqStart = g_nCumulativeCycles + cycles; - PUSH(regs.pc >> 8) - PUSH(regs.pc & 0xFF) - EF_TO_AF - regs.ps |= AF_RESERVED; - PUSH(regs.ps) - regs.ps |= AF_INTERRUPT; - regs.pc = * (WORD*) (mem+0xFFFE); - CYC(7) + if(g_bmIRQ && !(regs.ps & AF_INTERRUPT)) + { + // IRQ signals are deasserted when a specific r/w operation is done on device + g_nCycleIrqStart = g_nCumulativeCycles + cycles; + PUSH(regs.pc >> 8) + PUSH(regs.pc & 0xFF) + EF_TO_AF + regs.ps |= AF_RESERVED; + PUSH(regs.ps) + regs.ps |= AF_INTERRUPT; + regs.pc = * (WORD*) (mem+0xFFFE); + CYC(7) + } + + if (bBreakOnInvalid) + break; + } - } - while (cycles < totalcycles); - EF_TO_AF - return cycles; + while (cycles < totalcycles); + + EF_TO_AF + + return cycles; } // diff --git a/AppleWin/source/Debug.cpp b/AppleWin/source/Debug.cpp index 9cce4a44..085fd630 100644 --- a/AppleWin/source/Debug.cpp +++ b/AppleWin/source/Debug.cpp @@ -51,6 +51,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Breakpoints ________________________________________________________________ + // Full-Speed debugging + int g_nDebugOnBreakInvalid = 0; + int g_iDebugOnOpcode = 0; + int g_nBreakpoints = 0; Breakpoint_t g_aBreakpoints[ NUM_BREAKPOINTS ]; @@ -124,6 +128,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // CPU (Main) {TEXT("A") , CmdAssemble , CMD_ASSEMBLE , "Assemble instructions" }, {TEXT("U") , CmdUnassemble , CMD_UNASSEMBLE , "Disassemble instructions" }, + {TEXT("BRK") , CmdBreakInvalid , CMD_BREAK_INVALID , "Enter debugger on BRK or INVALID" }, + {TEXT("BRKOP") , CmdBreakOpcode , CMD_BREAK_OPCODE , "Enter debugger on opcode" }, {TEXT("CALC") , CmdCalculator , CMD_CALC , "Display mini calc result" }, {TEXT("GOTO") , CmdGo , CMD_GO , "Run [until PC = address]" }, {TEXT("I") , CmdInput , CMD_INPUT , "Input from IO $C0xx" }, @@ -832,6 +838,144 @@ LPCTSTR FormatAddress( WORD nAddress, int nBytes ) // Breakpoints ____________________________________________________________________________________ +//=========================================================================== +Update_t CmdBreakInvalid (int nArgs) // Breakpoint IFF Full-speed! +{ + if ((nArgs > 2) || (nArgs == 0)) + goto _Help; + + int iType = 0; // default to BRK + int nActive; + +// if (nArgs == 2) + iType = g_aArgs[ 1 ].nVal1; + + // Cases: + // 0. CMD // display + // 1a. CMD # // display + // 1b. CMD ON | OFF //set + // 1c. CMD ? // error + // 2a. CMD # ON | OFF // set + // 2b. CMD # ? // error + TCHAR sText[ CONSOLE_WIDTH ]; + bool bValidParam = true; + + int iParamArg = nArgs; + int iParam; + int nFound = FindParam( g_aArgs[ iParamArg ].sArg, MATCH_EXACT, iParam, _PARAM_GENERAL_BEGIN, _PARAM_GENERAL_END ); + + if (nFound) + { + if (iParam == PARAM_ON) + nActive = 1; + else + if (iParam == PARAM_OFF) + nActive = 0; + else + bValidParam = false; + } + else + bValidParam = false; + + if (nArgs == 1) + { + if (! nFound) // bValidParam) // case 1a or 1c + { + if ((iType < 0) || (iType > AM_3)) + goto _Help; + + if (IsDebugBreakOnInvalid( iType )) + iParam = PARAM_ON; + else + iParam = PARAM_OFF; + } + else // case 1b + { + SetDebugBreakOnInvalid( iType, nActive ); + } + + if (iType == 0) + wsprintf( sText, TEXT("Enter debugger on BRK opcode: %s"), g_aParameters[ iParam ].m_sName ); + else + wsprintf( sText, TEXT("Enter debugger on INVALID %1X opcode: %s"), iType, g_aParameters[ iParam ].m_sName ); + ConsoleBufferPush( sText ); + return ConsoleUpdate(); + } + else + if (nArgs == 2) + { + if (! bValidParam) // case 2b + { + goto _Help; + } + else // case 2a (or not 2b ;-) + { + if ((iType < 0) || (iType > AM_3)) + goto _Help; + + SetDebugBreakOnInvalid( iType, nActive ); + + if (iType == 0) + wsprintf( sText, TEXT("Enter debugger on BRK opcode: %s"), g_aParameters[ iParam ].m_sName ); + else + wsprintf( sText, TEXT("Enter debugger on INVALID %1X opcode: %s"), iType, g_aParameters[ iParam ].m_sName ); + ConsoleBufferPush( sText ); + return ConsoleUpdate(); + } + } + + return UPDATE_CONSOLE_DISPLAY; + +_Help: + return HelpLastCommand(); +} + + +//=========================================================================== +Update_t CmdBreakOpcode (int nArgs) // Breakpoint IFF Full-speed! +{ + TCHAR sText[ CONSOLE_WIDTH ]; + + if (nArgs > 1) + return HelpLastCommand(); + + TCHAR sAction[ CONSOLE_WIDTH ] = TEXT("Current"); // default to display + + if (nArgs == 1) + { + int iOpcode = g_aArgs[ 1] .nVal1; + g_iDebugOnOpcode = iOpcode & 0xFF; + + _tcscpy( sAction, TEXT("Setting") ); + + if (iOpcode >= NUM_OPCODES) + { + wsprintf( sText, TEXT("Warning: clamping opcode: %02X"), g_iDebugOnOpcode ); + ConsoleBufferPush( sText ); + return ConsoleUpdate(); + } + } + + if (g_iDebugOnOpcode == 0) + // Show what the current break opcode is + wsprintf( sText, TEXT("%s break on opcode: None") + , sAction + , g_iDebugOnOpcode + , g_aOpcodes65C02[ g_iDebugOnOpcode ].sMnemonic + ); + else + // Show what the current break opcode is + wsprintf( sText, TEXT("%s break on opcode: %02X %s") + , sAction + , g_iDebugOnOpcode + , g_aOpcodes65C02[ g_iDebugOnOpcode ].sMnemonic + ); + + ConsoleBufferPush( sText ); + return ConsoleUpdate(); +} + + // bool bBP = g_nBreakpoints && CheckBreakpoint(nOffset,nOffset == regs.pc); //=========================================================================== bool GetBreakpointInfo ( WORD nOffset, bool & bBreakpointActive_, bool & bBreakpointEnable_ ) @@ -1173,6 +1317,7 @@ Update_t CmdCalculator (int nArgs) return ConsoleUpdate(); } + //=========================================================================== Update_t CmdFeedKey (int nArgs) { @@ -2479,7 +2624,7 @@ void DisasmCalcTopFromCurAddress( bool bUpdateTop ) "\tLen: %04X\n" "\tMissed: %04X"), g_nDisasmCurAddress - nLen, nLen, g_nDisasmCurAddress ); - MessageBox( framewindow, sText, "ERROR", MB_OK ); + MessageBox( g_hFrameWindow, sText, "ERROR", MB_OK ); #endif } } @@ -4951,7 +5096,7 @@ void _CmdColorGet( const int iScheme, const int iColor ) { TCHAR sText[ CONSOLE_WIDTH ]; wsprintf( sText, "Color: %d\nOut of range!", iColor ); - MessageBox( framewindow, sText, TEXT("ERROR"), MB_OK ); + MessageBox( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK ); } } @@ -6705,13 +6850,13 @@ void DebugInitialize () if (_tcscmp( g_aCommands[ NUM_COMMANDS ].m_sName, TEXT(__COMMANDS_VERIFY_TXT__))) { wsprintf( sText, "*** ERROR *** Commands mis-matched!" ); - MessageBox( framewindow, sText, TEXT("ERROR"), MB_OK ); + MessageBox( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK ); } if (_tcscmp( g_aParameters[ NUM_PARAMS ].m_sName, TEXT(__PARAMS_VERIFY_TXT__))) { wsprintf( sText, "*** ERROR *** Parameters mis-matched!" ); - MessageBox( framewindow, sText, TEXT("ERROR"), MB_OK ); + MessageBox( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK ); } // Check all summary help to see if it fits within the console diff --git a/AppleWin/source/Debug.h b/AppleWin/source/Debug.h index e0006bb5..254819b5 100644 --- a/AppleWin/source/Debug.h +++ b/AppleWin/source/Debug.h @@ -25,6 +25,10 @@ using namespace std; extern const TCHAR *g_aBreakpointSource [ NUM_BREAKPOINT_SOURCES ]; extern const TCHAR *g_aBreakpointSymbols[ NUM_BREAKPOINT_OPERATORS ]; + // Full-Speed debugging + extern int g_nDebugOnBreakInvalid; + extern int g_iDebugOnOpcode ; + // Commands extern const int NUM_COMMANDS_WITH_ALIASES; // = sizeof(g_aCommands) / sizeof (Command_t); // Determined at compile-time ;-) extern int g_iCommand; // last command @@ -94,6 +98,22 @@ using namespace std; // Breakpoints bool GetBreakpointInfo ( WORD nOffset, bool & bBreakpointActive_, bool & bBreakpointEnable_ ); + // 0 = Brk, 1 = Invalid1, .. 3 = Invalid 3 + inline bool IsDebugBreakOnInvalid( int iOpcodeType ) + { + bool bActive = (g_nDebugOnBreakInvalid >> iOpcodeType) & 1; + return bActive; + } + + inline void SetDebugBreakOnInvalid( int iOpcodeType, int nValue ) + { + if (iOpcodeType <= AM_3) + { + g_nDebugOnBreakInvalid &= ~ ( 1 << iOpcodeType); + g_nDebugOnBreakInvalid |= ((nValue & 1) << iOpcodeType); + } + } + // Color inline COLORREF DebuggerGetColor( int iColor ); @@ -117,7 +137,8 @@ using namespace std; enum { - DEBUG_EXIT_KEY = 0x1B // Escape + DEBUG_EXIT_KEY = 0x1B, // Escape + DEBUG_TOGGLE_KEY = VK_F1 + BTN_DEBUG }; void DebugBegin (); diff --git a/AppleWin/source/Debugger_Types.h b/AppleWin/source/Debugger_Types.h index fe7bbbcc..3375ac03 100644 --- a/AppleWin/source/Debugger_Types.h +++ b/AppleWin/source/Debugger_Types.h @@ -80,7 +80,7 @@ */ enum AddressingMode_e // ADDRESSING_MODES_e { - AM_IMPLIED + AM_IMPLIED // Note: SetDebugBreakOnInvalid() assumes this order of first 4 entries , AM_1 // Invalid 1 Byte , AM_2 // Invalid 2 Bytes , AM_3 // Invalid 3 Bytes @@ -387,6 +387,8 @@ // Main / CPU CMD_ASSEMBLE , CMD_UNASSEMBLE + , CMD_BREAK_INVALID + , CMD_BREAK_OPCODE , CMD_CALC , CMD_GO , CMD_INPUT @@ -590,20 +592,22 @@ // CPU - Update_t CmdAssemble (int nArgs); - Update_t CmdUnassemble (int nArgs); // code dump, aka, Unassemble - Update_t CmdCalculator (int nArgs); - Update_t CmdGo (int nArgs); - Update_t CmdInput (int nArgs); - Update_t CmdJSR (int nArgs); - Update_t CmdNOP (int nArgs); - Update_t CmdOutput (int nArgs); - Update_t CmdFeedKey (int nArgs); - Update_t CmdStepOut (int nArgs); - Update_t CmdStepOver (int nArgs); - Update_t CmdTrace (int nArgs); // alias for CmdStepIn - Update_t CmdTraceFile (int nArgs); - Update_t CmdTraceLine (int nArgs); + Update_t CmdAssemble (int nArgs); + Update_t CmdUnassemble (int nArgs); // code dump, aka, Unassemble + Update_t CmdBreakInvalid(int nArgs); // Breakpoint IFF Full-speed! + Update_t CmdBreakOpcode (int nArgs); // Breakpoint IFF Full-speed! + Update_t CmdCalculator (int nArgs); + Update_t CmdGo (int nArgs); + Update_t CmdInput (int nArgs); + Update_t CmdJSR (int nArgs); + Update_t CmdNOP (int nArgs); + Update_t CmdOutput (int nArgs); + Update_t CmdFeedKey (int nArgs); + Update_t CmdStepOut (int nArgs); + Update_t CmdStepOver (int nArgs); + Update_t CmdTrace (int nArgs); // alias for CmdStepIn + Update_t CmdTraceFile (int nArgs); + Update_t CmdTraceLine (int nArgs); // Breakpoints Update_t CmdBreakpointMenu (int nArgs); diff --git a/AppleWin/source/Disk.cpp b/AppleWin/source/Disk.cpp index 672936a6..aca80504 100644 --- a/AppleWin/source/Disk.cpp +++ b/AppleWin/source/Disk.cpp @@ -400,7 +400,7 @@ void DiskNotifyInvalidImage (LPCTSTR imagefilename,int error) // IGNORE OTHER ERRORS SILENTLY return; } - MessageBox(framewindow, + MessageBox(g_hFrameWindow, buffer, TITLE, MB_ICONEXCLAMATION | MB_SETFOREGROUND); @@ -476,7 +476,7 @@ void DiskSelectImage (int drive, LPSTR pszFilename) OPENFILENAME ofn; ZeroMemory(&ofn,sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = framewindow; + ofn.hwndOwner = g_hFrameWindow; ofn.hInstance = instance; ofn.lpstrFilter = TEXT("All Images\0*.apl;*.bin;*.do;*.dsk;*.iie;*.nib;*.po\0") TEXT("Disk Images (*.bin,*.do,*.dsk,*.iie,*.nib,*.po)\0*.bin;*.do;*.dsk;*.iie;*.nib;*.po\0")