mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-29 17:33:56 +00:00
Breakpoints on full-speed.
BRK # [ON|OFF] BRKOP ##
This commit is contained in:
parent
38de33eb77
commit
d26aa82dd1
110
source/CPU.cpp
110
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;
|
||||
}
|
||||
|
||||
//
|
||||
|
153
source/Debug.cpp
153
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
|
||||
|
@ -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 ();
|
||||
|
@ -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);
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user