Support for #384:

. Debug 'G(o)' cmd now defaults to normal speed (and precise video updates)
. New debug 'GG' cmd enables full speed (and periodic video updates)
. Single-stepping (normal or full speed) now routed through ContinueExecution()
. Removed Cpu6502()/Cpu65C02() check for debug breakpoints
. Removed the (undocumented) SHIFT+F7 feature to exit debugger for 'normal speed breakpoints'
. Removed the g_bDebugNormalSpeedBreakpoints variable
This commit is contained in:
tomcw 2017-02-25 22:32:46 +00:00
parent 1193cfd10f
commit 0b6c5bbb91
17 changed files with 204 additions and 201 deletions

View File

@ -207,8 +207,12 @@ void SetPriorityNormal(void)
//---------------------------------------------------------------------------
void ContinueExecution(void)
static UINT g_uModeStepping_Cycles = 0;
static void ContinueExecution(void)
{
_ASSERT(g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING);
const double fUsecPerSec = 1.e6;
#if 1
const UINT nExecutionPeriodUsec = 1000; // 1.0ms
@ -226,9 +230,10 @@ void ContinueExecution(void)
: (GetKeyState(VK_SCROLL) < 0);
const bool bWasFullSpeed = g_bFullSpeed;
g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) ||
g_bFullSpeed = (g_dwSpeed == SPEED_MAX) ||
bScrollLock_FullSpeed ||
(DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );
(DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) ||
IsDebugSteppingAtFullSpeed();
if (g_bFullSpeed)
{
@ -269,18 +274,43 @@ void ContinueExecution(void)
if (nCyclesToExecute < 0)
nCyclesToExecute = 0;
const DWORD uActualCyclesExecuted = CpuExecute(nCyclesToExecute);
if (g_nAppMode == MODE_STEPPING)
nCyclesToExecute = 0;
const bool bVideoUpdate = !g_bFullSpeed;
const DWORD uActualCyclesExecuted = CpuExecute(nCyclesToExecute, bVideoUpdate);
g_dwCyclesThisFrame += uActualCyclesExecuted;
DiskUpdatePosition(uActualCyclesExecuted);
JoyUpdateButtonLatch(nExecutionPeriodUsec); // Button latch time is independent of CPU clock frequency
SpkrUpdate(uActualCyclesExecuted);
sg_SSC.CommUpdate(uActualCyclesExecuted);
PrintUpdate(uActualCyclesExecuted);
//
DWORD uSpkrActualCyclesExecuted = uActualCyclesExecuted;
bool bModeStepping_WaitTimer = false;
if (g_nAppMode == MODE_STEPPING && !IsDebugSteppingAtFullSpeed())
{
g_uModeStepping_Cycles += uActualCyclesExecuted;
if (g_uModeStepping_Cycles >= fExecutionPeriodClks)
{
uSpkrActualCyclesExecuted = g_uModeStepping_Cycles;
g_uModeStepping_Cycles -= (UINT)fExecutionPeriodClks;
bModeStepping_WaitTimer = true;
}
}
// For MODE_STEPPING: do this speaker update periodically
// - Otherwise kills performance due to sound-buffer lock/unlock for every 6502 opcode!
if (g_nAppMode == MODE_RUNNING || bModeStepping_WaitTimer)
SpkrUpdate(uSpkrActualCyclesExecuted);
//
if (g_dwCyclesThisFrame >= dwClksPerFrame)
{
g_dwCyclesThisFrame -= dwClksPerFrame;
@ -293,12 +323,17 @@ void ContinueExecution(void)
MB_EndOfVideoFrame();
}
if (!g_bFullSpeed)
if ((g_nAppMode == MODE_RUNNING && !g_bFullSpeed) || bModeStepping_WaitTimer)
{
SysClk_WaitTimer();
}
}
void SingleStep(void)
{
ContinueExecution();
}
//===========================================================================
void SetCurrentCLK6502(void)

View File

@ -19,6 +19,8 @@ extern eApple2Type g_Apple2Type;
eApple2Type GetApple2Type(void);
void SetApple2Type(eApple2Type type);
void SingleStep(void);
extern bool g_bFullSpeed;
//===========================================

View File

@ -457,12 +457,12 @@ static __forceinline void CheckInterruptSources(ULONG uExecutedCycles)
//===========================================================================
static DWORD InternalCpuExecute (DWORD uTotalCycles)
static DWORD InternalCpuExecute(const DWORD uTotalCycles, const bool bVideoUpdate)
{
if (GetMainCpu() == CPU_6502)
return Cpu6502(uTotalCycles); // Apple ][, ][+, //e, Clones
return Cpu6502(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
else
return Cpu65C02(uTotalCycles); // Enhanced Apple //e
return Cpu65C02(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
}
//
@ -549,7 +549,7 @@ DWORD CpuGetEmulationTime_ms(void)
//===========================================================================
DWORD CpuExecute(const DWORD uCycles)
DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate)
{
g_nCyclesExecuted = 0;
@ -558,7 +558,7 @@ DWORD CpuExecute(const DWORD uCycles)
// uCycles:
// =0 : Do single step
// >0 : Do multi-opcode emulation
const DWORD uExecutedCycles = InternalCpuExecute(uCycles);
const DWORD uExecutedCycles = InternalCpuExecute(uCycles, bVideoUpdate);
MB_UpdateCycles(uExecutedCycles); // Update 6522s (NB. Do this before updating g_nCumulativeCycles below)
UpdateEmulationTime(uExecutedCycles);

View File

@ -16,7 +16,7 @@ extern unsigned __int64 g_nCumulativeCycles;
void CpuDestroy ();
void CpuCalcCycles(ULONG nExecutedCycles);
DWORD CpuExecute (DWORD);
DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate);
ULONG CpuGetCyclesThisVideoFrame(ULONG nExecutedCycles);
void CpuInitialize ();
void CpuSetupBenchmark ();

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//===========================================================================
static DWORD Cpu6502 (DWORD uTotalCycles)
static DWORD Cpu6502(DWORD uTotalCycles, const bool bVideoUpdate)
{
WORD addr;
BOOL flagc; // must always be 0 or 1, no other values allowed
@ -324,15 +324,13 @@ static DWORD Cpu6502 (DWORD uTotalCycles)
IRQ(uExecutedCycles, flagc, flagn, flagv, flagz);
// NTSC_BEGIN
if (!g_bFullSpeed)
if (bVideoUpdate)
{
ULONG uElapsedCycles = uExecutedCycles - uPreviousCycles;
NTSC_VideoUpdateCycles( uElapsedCycles );
}
// NTSC_END
if ( IsDebugBreakpointHit() )
break;
} while (uExecutedCycles < uTotalCycles);
EF_TO_AF

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//===========================================================================
static DWORD Cpu65C02 (DWORD uTotalCycles)
static DWORD Cpu65C02(DWORD uTotalCycles, const bool bVideoUpdate)
{
// Optimisation:
// . Copy the global /regs/ vars to stack-based local vars
@ -327,16 +327,13 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
IRQ(uExecutedCycles, flagc, flagn, flagv, flagz);
// NTSC_BEGIN
if (!g_bFullSpeed)
if ( bVideoUpdate )
{
ULONG uElapsedCycles = uExecutedCycles - uPreviousCycles;
NTSC_VideoUpdateCycles( uElapsedCycles );
}
// NTSC_END
if( IsDebugBreakpointHit() )
break;
} while (uExecutedCycles < uTotalCycles);
EF_TO_AF // Emulator Flags to Apple Flags

View File

@ -97,7 +97,7 @@ inline u8 ReadByte( u16 addr, int uExecutedCycles )
// Michael's Real-Time Debugger/Visualizer CPU
// Based on Modified 65C02
static DWORD Cpu65D02 (DWORD uTotalCycles)
static DWORD Cpu65D02(DWORD uTotalCycles, const bool bVideoUpdate)
{
// Optimisation:
// . Copy the global /regs/ vars to stack-based local vars
@ -412,16 +412,13 @@ static DWORD Cpu65D02 (DWORD uTotalCycles)
IRQ(uExecutedCycles, flagc, flagn, flagv, flagz);
// NTSC_BEGIN
if (!g_bFullSpeed)
if (bVideoUpdate)
{
ULONG uElapsedCycles = uExecutedCycles - uPreviousCycles;
NTSC_VideoUpdateCycles( uElapsedCycles );
}
// NTSC_END
if( IsDebugBreakpointHit() )
break;
} while (uExecutedCycles < uTotalCycles);
EF_TO_AF // Emulator Flags to Apple Flags

View File

@ -29,9 +29,9 @@ enum AppMode_e
{
MODE_LOGO = 0
, MODE_PAUSED
, MODE_RUNNING // 6502 is running at normal speed (Debugger breakpoints may or may not be active)
, MODE_RUNNING // 6502 is running at normal/full speed (Debugger breakpoints may or may not be active)
, MODE_DEBUG // 6502 is paused
, MODE_STEPPING // 6502 is running at full speed (Debugger breakpoints always active)
, MODE_STEPPING // 6502 is running at normal/full speed (Debugger breakpoints always active)
};
#define SPEED_MIN 0

View File

@ -41,6 +41,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "..\Keyboard.h"
#include "..\Memory.h"
#include "..\NTSC.h"
#include "..\SoundCore.h" // SoundCore_SetFade()
#include "..\Video.h"
// #define DEBUG_COMMAND_HELP 1
@ -62,12 +63,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Breakpoints ________________________________________________________________
// MODE_RUNNING // Normal Speed Breakpoints: Shift-F7 exit debugger, keep breakpoints active, enter run state at NORMAL speed
bool g_bDebugNormalSpeedBreakpoints = 0;
// MODE_STEPPING // Full Speed Breakpoints
// Any Speed Breakpoints
int g_nDebugBreakOnInvalid = 0; // Bit Flags of Invalid Opcode to break on: // iOpcodeType = AM_IMPLIED (BRK), AM_1, AM_2, AM_3
int g_iDebugBreakOnOpcode = 0;
@ -75,7 +70,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bool g_bDebugBreakDelayCheck = false; // If exiting the debugger, allow at least one instruction to execute so we don't trigger on the same invalid opcode
int g_bDebugBreakpointHit = 0; // See: BreakpointHit_t
int g_nBreakpoints = 0;
int g_nBreakpoints = 0;
Breakpoint_t g_aBreakpoints[ MAX_BREAKPOINTS ];
// NOTE: Breakpoint_Source_t and g_aBreakpointSource must match!
@ -205,6 +200,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
MemoryTextFile_t g_ConfigState;
static bool g_bDebugFullSpeed = false;
static bool g_bLastGoCmdWasFullSpeed = false;
// Display ____________________________________________________________________
void UpdateDisplay( Update_t bUpdate );
@ -296,7 +294,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bool g_bBenchmarking = false;
BOOL fulldisp = 0;
WORD lastpc = 0;
BOOL g_bProfiling = 0;
int g_nDebugSteps = 0;
@ -319,6 +316,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Prototypes _______________________________________________________________
static void DebugEnd ();
static int ParseInput ( LPTSTR pConsoleInput, bool bCook = true );
static Update_t ExecuteCommand ( int nArgs );
@ -372,8 +370,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
void _CursorMoveUpAligned( int nDelta );
void DisasmCalcTopFromCurAddress( bool bUpdateTop = true );
bool InternalSingleStep ();
void DisasmCalcCurFromTopAddress();
void DisasmCalcBotFromTopAddress();
void DisasmCalcTopBotAddress ();
@ -747,17 +743,6 @@ Update_t CmdBookmarkSave (int nArgs)
//===========================================================================
BOOL CheckJump (WORD targetaddress)
{
WORD savedpc = regs.pc;
InternalSingleStep();
BOOL result = (regs.pc == targetaddress);
regs.pc = savedpc;
return result;
}
// Benchmark ______________________________________________________________________________________
//===========================================================================
@ -1836,7 +1821,7 @@ Update_t CmdAssemble (int nArgs)
// CPU Step, Trace ________________________________________________________________________________
//===========================================================================
Update_t CmdGo (int nArgs)
static Update_t CmdGo (int nArgs, const bool bFullSpeed)
{
// G StopAddress [SkipAddress,Length]
// Example:
@ -1844,6 +1829,8 @@ Update_t CmdGo (int nArgs)
// TODO: G addr1,len addr3,len
// TODO: G addr1:addr2 addr3:addr4
const int kCmdGo = !bFullSpeed ? CMD_GO_NORMAL_SPEED : CMD_GO_FULL_SPEED;
g_nDebugSteps = -1;
g_nDebugStepCycles = 0;
g_nDebugStepStart = regs.pc;
@ -1852,7 +1839,7 @@ Update_t CmdGo (int nArgs)
g_nDebugSkipLen = -1;
if (nArgs > 4)
return Help_Arg_1( CMD_GO );
return Help_Arg_1( kCmdGo );
// G StopAddress [SkipAddress,Len]
// Old 1 2 2
@ -1882,7 +1869,7 @@ Update_t CmdGo (int nArgs)
}
else
{
return Help_Arg_1( CMD_GO );
return Help_Arg_1( kCmdGo );
}
}
else
@ -1891,10 +1878,10 @@ Update_t CmdGo (int nArgs)
nEnd = g_aArgs[ iArg + 2 ].nValue + 1;
}
else
return Help_Arg_1( CMD_GO );
return Help_Arg_1( kCmdGo );
}
else
return Help_Arg_1( CMD_GO );
return Help_Arg_1( kCmdGo );
nLen = nEnd - g_nDebugSkipStart;
if (nLen < 0)
@ -1919,10 +1906,26 @@ Update_t CmdGo (int nArgs)
// g_nDebugStepUntil = GetAddress(g_aArgs[1].sArg);
g_bDebuggerEatKey = true;
g_bDebugFullSpeed = bFullSpeed;
g_bLastGoCmdWasFullSpeed = bFullSpeed;
g_nAppMode = MODE_STEPPING;
FrameRefreshStatus(DRAW_TITLE);
return UPDATE_CONSOLE_DISPLAY; // TODO: Verify // 0;
SoundCore_SetFade(FADE_IN);
return UPDATE_CONSOLE_DISPLAY;
}
Update_t CmdGoNormalSpeed (int nArgs)
{
return CmdGo(nArgs, false);
}
Update_t CmdGoFullSpeed (int nArgs)
{
return CmdGo(nArgs, true);
}
//===========================================================================
@ -1963,7 +1966,7 @@ Update_t CmdStepOut (int nArgs)
{
nArgs = _Arg_1( nAddress );
g_aArgs[1].sArg[0] = 0;
CmdGo( 1 );
CmdGo( 1, true );
}
return UPDATE_ALL;
@ -3396,7 +3399,7 @@ Update_t CmdCursorJumpRetAddr (int nArgs)
Update_t CmdCursorRunUntil (int nArgs)
{
nArgs = _Arg_1( g_nDisasmCurAddress );
return CmdGo( nArgs );
return CmdGo( nArgs, true );
}
@ -4093,6 +4096,7 @@ Update_t CmdConfigSetDebugDir (int nArgs)
return ConsoleUpdate();
}
//===========================================================================
#if 0 // Original
Update_t CmdMemoryLoad (int nArgs)
@ -6005,12 +6009,6 @@ Update_t CmdMemorySearchHex (int nArgs)
//===========================================================================
Update_t CmdRegisterSet (int nArgs)
{
if ((nArgs == 2) &&
(g_aArgs[1].sArg[0] == TEXT('P')) && (g_aArgs[2].sArg[0] == TEXT('L'))) //HACK: TODO/FIXME: undocumented hard-coded command?!?!
{
regs.pc = lastpc;
}
else
if (nArgs < 2) // || ((g_aArgs[2].sArg[0] != TEXT('0')) && !g_aArgs[2].nValue))
{
return Help_Arg_1( CMD_REGISTER_SET );
@ -7970,42 +7968,6 @@ Update_t ExecuteCommand (int nArgs)
//===========================================================================
bool InternalSingleStep ()
{
bool bResult = false;
_try
{
BYTE nOpcode = *(mem+regs.pc);
int nOpmode = g_aOpcodes[ nOpcode ].nAddressMode;
g_aProfileOpcodes[ nOpcode ].m_nCount++;
g_aProfileOpmodes[ nOpmode ].m_nCount++;
// Like ContinueExecution()
{
DWORD dwExecutedCycles = CpuExecute(g_nDebugStepCycles);
g_dwCyclesThisFrame += dwExecutedCycles;
if (g_dwCyclesThisFrame >= dwClksPerFrame)
{
g_dwCyclesThisFrame -= dwClksPerFrame;
}
}
bResult = true;
}
_except (EXCEPTION_EXECUTE_HANDLER)
{
bResult = false;
}
return bResult;
}
//===========================================================================
void OutputTraceLine ()
{
DisasmLine_t line;
@ -8487,6 +8449,23 @@ void DebugBegin ()
#endif
}
//===========================================================================
void DebugExitDebugger ()
{
if (g_nBreakpoints == 0)
{
DebugEnd();
return;
}
// Still have some BPs set, so continue single-stepping
if (!g_bLastGoCmdWasFullSpeed)
CmdGoNormalSpeed(0);
else
CmdGoFullSpeed(0);
}
//===========================================================================
void DebugContinueStepping ()
{
@ -8512,11 +8491,19 @@ void DebugContinueStepping ()
{
if (g_hTraceFile)
OutputTraceLine();
lastpc = regs.pc;
InternalSingleStep();
// Update profiling stats
{
BYTE nOpcode = *(mem+regs.pc);
int nOpmode = g_aOpcodes[ nOpcode ].nAddressMode;
_IsDebugBreakpointHit(); // Updates g_bDebugBreakpointHit
g_aProfileOpcodes[ nOpcode ].m_nCount++;
g_aProfileOpmodes[ nOpmode ].m_nCount++;
}
SingleStep();
g_bDebugBreakpointHit |= CheckBreakpointsIO() || CheckBreakpointsReg();
if ((regs.pc == g_nDebugStepUntil) || g_bDebugBreakpointHit)
g_nDebugSteps = 0;
@ -8524,14 +8511,7 @@ void DebugContinueStepping ()
g_nDebugSteps--;
}
if (g_nDebugSteps)
{
if (!((++nStepsTaken) & 0xFFFF)) // Arbitrary: redraw screen every 0x10000 steps
{
VideoRedrawScreen();
}
}
else
if (!g_nDebugSteps)
{
g_nAppMode = MODE_DEBUG;
FrameRefreshStatus(DRAW_TITLE);
@ -8577,7 +8557,7 @@ void DebugDestroy ()
//===========================================================================
void DebugEnd ()
static void DebugEnd ()
{
// Stepping ... calls us when key hit?! FrameWndProc() ProcessButtonClick() DebugEnd()
if (g_bProfiling)
@ -9662,3 +9642,9 @@ void DebuggerMouseClick( int x, int y )
}
}
}
//===========================================================================
bool IsDebugSteppingAtFullSpeed(void)
{
return (g_nAppMode == MODE_STEPPING) && g_bDebugFullSpeed;
}

View File

@ -42,11 +42,6 @@
extern const char *g_aBreakpointSource [ NUM_BREAKPOINT_SOURCES ];
extern const TCHAR *g_aBreakpointSymbols[ NUM_BREAKPOINT_OPERATORS ];
// MODE_RUNNING // Normal Speed Breakpoints
extern bool g_bDebugNormalSpeedBreakpoints;
// MODE_STEPPING // Full Speed Breakpoints
// Any Speed Breakpoints
extern int g_nDebugBreakOnInvalid ;
extern int g_iDebugBreakOnOpcode ;
@ -149,12 +144,6 @@
bool GetBreakpointInfo ( WORD nOffset, bool & bBreakpointActive_, bool & bBreakpointEnable_ );
inline int _IsDebugBreakpointHit()
{
g_bDebugBreakpointHit |= CheckBreakpointsIO() || CheckBreakpointsReg();
return g_bDebugBreakpointHit;
}
inline int _IsDebugBreakOnOpcode( int iOpcode )
{
if (g_iDebugBreakOnOpcode == iOpcode)
@ -200,13 +189,6 @@
return g_bDebugBreakpointHit;
}
//
inline int IsDebugBreakpointHit()
{
if ( !g_bDebugNormalSpeedBreakpoints )
return false;
return _IsDebugBreakpointHit();
}
// Source Level Debugging
int FindSourceLine( WORD nAddress );
@ -238,10 +220,10 @@
bool DebugGetVideoMode(UINT* pVideoMode);
void DebugBegin ();
void DebugExitDebugger ();
void DebugContinueStepping ();
void DebugDestroy ();
void DebugDisplay (BOOL);
void DebugEnd ();
void DebugInitialize ();
// void DebugProcessChar (TCHAR);
void DebuggerInputConsoleChar( TCHAR ch );
@ -252,4 +234,5 @@
void DebuggerCursorNext();
void DebuggerMouseClick( int x, int y );
bool IsDebugSteppingAtFullSpeed(void);

View File

@ -45,9 +45,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// CPU (Main)
{TEXT(".") , CmdCursorJumpPC , CMD_CURSOR_JUMP_PC , "Locate the cursor in the disasm window" }, // centered
{TEXT("=") , CmdCursorSetPC , CMD_CURSOR_SET_PC , "Sets the PC to the current instruction" },
// {TEXT("g") , CmdGoNormalSpeed , CMD_GO_NORMAL , "Run @ normal speed [until PC == address]" },
// {TEXT("G") , CmdGoFullSpeed , CMD_GO_FULL , "Run @ full speed [until PC == address]" },
{TEXT("G") , CmdGo , CMD_GO , "Run @ full speed [until PC == address]" },
{TEXT("G") , CmdGoNormalSpeed , CMD_GO_NORMAL_SPEED , "Run at normal speed [until PC == address]" },
{TEXT("GG") , CmdGoFullSpeed , CMD_GO_FULL_SPEED , "Run at full speed [until PC == address]" },
{TEXT("IN") , CmdIn , CMD_IN , "Input byte from IO $C0xx" },
{TEXT("KEY") , CmdKey , CMD_INPUT_KEY , "Feed key into emulator" },
{TEXT("JSR") , CmdJSR , CMD_JSR , "Call sub-routine" },

View File

@ -1405,7 +1405,6 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
sprintf( line_.sTargetValue, "%04X", nTarget & 0xFFFF );
// Always show branch indicators
// if ((nBaseAddress == regs.pc) && CheckJump(nAddress))
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
if (nTarget < nBaseAddress)

View File

@ -567,7 +567,7 @@ Update_t CmdHelpSpecific (int nArgs)
{
case PARAM_CAT_BOOKMARKS : iCmdBegin = CMD_BOOKMARK ; iCmdEnd = CMD_BOOKMARK_SAVE ; break;
case PARAM_CAT_BREAKPOINTS: iCmdBegin = CMD_BREAK_INVALID ; iCmdEnd = CMD_BREAKPOINT_SAVE ; break;
case PARAM_CAT_CONFIG : iCmdBegin = CMD_BENCHMARK ; iCmdEnd = CMD_CONFIG_SAVE ; break;
case PARAM_CAT_CONFIG : iCmdBegin = CMD_BENCHMARK ; iCmdEnd = CMD_CONFIG_SET_DEBUG_DIR; break;
case PARAM_CAT_CPU : iCmdBegin = CMD_ASSEMBLE ; iCmdEnd = CMD_UNASSEMBLE ; break;
case PARAM_CAT_FLAGS :
nFound = FindCommand( g_aArgs[iArg].sArg, pFunction, & iCommand ); // check if we have an exact command match first
@ -727,7 +727,7 @@ Update_t CmdHelpSpecific (int nArgs)
if (iCmd <= CMD_BREAKPOINT_SAVE)
wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName );
else
if (iCmd <= CMD_CONFIG_SAVE)
if (iCmd <= CMD_CONFIG_SET_DEBUG_DIR)
wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_CONFIG ].m_sName );
else
if (iCmd <= CMD_CURSOR_PAGE_DOWN_4K)
@ -833,7 +833,8 @@ Update_t CmdHelpSpecific (int nArgs)
ConsoleColorizePrint( sText, " Usage: [address | symbol]" );
ConsoleBufferPush( " Disassembles memory." );
break;
case CMD_GO:
case CMD_GO_NORMAL_SPEED:
case CMD_GO_FULL_SPEED:
ConsoleColorizePrint( sText, " Usage: address | symbol [Skip,Length]" );
ConsoleColorizePrint( sText, " Usage: address | symbol [Start:End]" );
ConsoleBufferPush( " Skip : Start address to skip stepping" );
@ -842,8 +843,8 @@ Update_t CmdHelpSpecific (int nArgs)
ConsoleBufferPush( " If the Program Counter is outside the skip range, resumes single-stepping." );
ConsoleBufferPush( " Can be used to skip ROM/OS/user code." );
Help_Examples();
ConsolePrintFormat( sText, "%s G C600 FA00,600" , CHC_EXAMPLE );
ConsolePrintFormat( sText, "%s G C600 F000:FFFF", CHC_EXAMPLE );
ConsolePrintFormat( sText, "%s G[G] C600 FA00,600" , CHC_EXAMPLE );
ConsolePrintFormat( sText, "%s G[G] C600 F000:FFFF", CHC_EXAMPLE );
break;
case CMD_JSR:
ConsoleColorizePrint( sText, " %sUsage%s: %s[symbol | address]" );
@ -854,7 +855,7 @@ Update_t CmdHelpSpecific (int nArgs)
break;
case CMD_OUT:
ConsoleColorizePrint( sText, " Usage: [address8 | address16 | symbol] ## [##]" );
ConsoleBufferPush( TEXT(" Ouput a byte or word to the IO address $C0xx" ) );
ConsoleBufferPush( TEXT(" Output a byte or word to the IO address $C0xx" ) );
break;
case CMD_PROFILE:
ConsoleColorizePrintFormat( sTemp, sText, " Usage: [%s | %s | %s]"

View File

@ -280,7 +280,8 @@
// CPU
, CMD_CURSOR_JUMP_PC // Shift
, CMD_CURSOR_SET_PC // Ctrl
, CMD_GO
, CMD_GO_NORMAL_SPEED
, CMD_GO_FULL_SPEED
, CMD_IN
, CMD_INPUT_KEY
, CMD_JSR
@ -582,7 +583,8 @@
Update_t CmdCursorSetPC (int nArgs);
Update_t CmdBreakInvalid (int nArgs); // Breakpoint IFF Full-speed!
Update_t CmdBreakOpcode (int nArgs); // Breakpoint IFF Full-speed!
Update_t CmdGo (int nArgs);
Update_t CmdGoNormalSpeed (int nArgs);
Update_t CmdGoFullSpeed (int nArgs);
Update_t CmdIn (int nArgs);
Update_t CmdKey (int nArgs);
Update_t CmdJSR (int nArgs);

View File

@ -1860,11 +1860,8 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
{
if (ConfirmReboot(bFromButtonUI))
{
// If any breakpoints active and we are not running at normal speed
if (g_nBreakpoints && !g_bDebugNormalSpeedBreakpoints)
CmdGo(0); // 6502 runs at full speed, switch to MODE_STEPPING
else
DebugEnd(); // 6502 runs at normal speed, switch to MODE_RUNNING
DebugExitDebugger();
// Post: g_nAppMode = MODE_RUNNING or MODE_STEPPING
}
}
DrawStatusArea((HDC)0,DRAW_TITLE);
@ -1901,11 +1898,6 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
else
if (g_nAppMode == MODE_DEBUG)
{
if (KeybGetShiftStatus())
g_bDebugNormalSpeedBreakpoints = true; // MODE_RUNNING // Normal Speed Breakpoints: Shift-F7 exit debugger, keep breakpoints active, enter run state at NORMAL speed
else
g_bDebugNormalSpeedBreakpoints = false; // MODE_STEPPING // Full Speed Breakpoints
g_bDebugBreakDelayCheck = true;
ProcessButtonClick(BTN_RUN); // Exit debugger, switch to MODE_RUNNING or MODE_STEPPING
}

View File

@ -711,7 +711,7 @@ void VideoBenchmark () {
milliseconds = GetTickCount();
cycle = 0;
do {
CpuExecute(100000);
CpuExecute(100000, true);
totalmhz10++;
} while (GetTickCount() - milliseconds < 1000);
@ -729,7 +729,7 @@ void VideoBenchmark () {
int loop = 0;
while ((loop < 10000) && !error) {
CpuSetupBenchmark();
CpuExecute(loop);
CpuExecute(loop, true);
if ((regs.pc < 0x300) || (regs.pc > 0x400))
error = 1;
else {
@ -777,7 +777,7 @@ void VideoBenchmark () {
if (realisticfps < 10) {
int cycles = 100000;
while (cycles > 0) {
DWORD executedcycles = CpuExecute(103);
DWORD executedcycles = CpuExecute(103, true);
cycles -= executedcycles;
DiskUpdatePosition(executedcycles);
JoyUpdateButtonLatch(executedcycles);

View File

@ -134,6 +134,18 @@ void reset(void)
//-------------------------------------
DWORD TestCpu6502(DWORD uTotalCycles)
{
return Cpu6502(uTotalCycles, true);
}
DWORD TestCpu65C02(DWORD uTotalCycles)
{
return Cpu65C02(uTotalCycles, true);
}
//-------------------------------------
int GH264_test(void)
{
// No page-cross
@ -147,12 +159,12 @@ int GH264_test(void)
mem[regs.pc+3] = dst&0xff;
mem[regs.pc+4] = dst>>8;
DWORD cycles = Cpu6502(0);
DWORD cycles = TestCpu6502(0);
if (cycles != 5) return 1;
if (regs.pc != dst) return 1;
reset();
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (cycles != 6) return 1;
if (regs.pc != dst) return 1;
@ -167,14 +179,14 @@ int GH264_test(void)
mem[regs.pc+3] = dst&0xff;
mem[regs.pc+4] = mem[regs.pc & ~0xff] = dst>>8; // Allow for bug in 6502
cycles = Cpu6502(0);
cycles = TestCpu6502(0);
if (cycles != 5) return 1;
if (regs.pc != dst) return 1;
reset();
regs.pc = 0x3fc;
mem[regs.pc & ~0xff] = 0; // Test that 65C02 fixes the bug in the 6502
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (cycles != 7) return 1; // todo: is this 6 or 7?
if (regs.pc != dst) return 1;
@ -231,11 +243,11 @@ int GH271_test(void)
const BYTE x = 0;
ASL_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d<<1)&0xff)) return 1;
ASL_ABSX(x, base, d);
if (Cpu65C02(0) != 6) return 1; // Non-PX case is optimised on 65C02
if (TestCpu65C02(0) != 6) return 1; // Non-PX case is optimised on 65C02
if (mem[base+x] != ((d<<1)&0xff)) return 1;
}
@ -244,11 +256,11 @@ int GH271_test(void)
const BYTE x = 1;
ASL_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d<<1)&0xff)) return 1;
ASL_ABSX(x, base, d);
if (Cpu65C02(0) != 7) return 1;
if (TestCpu65C02(0) != 7) return 1;
if (mem[base+x] != ((d<<1)&0xff)) return 1;
}
}
@ -263,11 +275,11 @@ int GH271_test(void)
const BYTE x = 0;
DEC_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d-1)&0xff)) return 1;
DEC_ABSX(x, base, d);
if (Cpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
if (TestCpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
if (mem[base+x] != ((d-1)&0xff)) return 1;
}
@ -276,11 +288,11 @@ int GH271_test(void)
const BYTE x = 1;
DEC_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d-1)&0xff)) return 1;
DEC_ABSX(x, base, d);
if (Cpu65C02(0) != 7) return 1;
if (TestCpu65C02(0) != 7) return 1;
if (mem[base+x] != ((d-1)&0xff)) return 1;
}
}
@ -295,11 +307,11 @@ int GH271_test(void)
const BYTE x = 0;
INC_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d+1)&0xff)) return 1;
INC_ABSX(x, base, d);
if (Cpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
if (TestCpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
if (mem[base+x] != ((d+1)&0xff)) return 1;
}
@ -308,11 +320,11 @@ int GH271_test(void)
const BYTE x = 1;
INC_ABSX(x, base, d);
if (Cpu6502(0) != 7) return 1;
if (TestCpu6502(0) != 7) return 1;
if (mem[base+x] != ((d+1)&0xff)) return 1;
INC_ABSX(x, base, d);
if (Cpu65C02(0) != 7) return 1;
if (TestCpu65C02(0) != 7) return 1;
if (mem[base+x] != ((d+1)&0xff)) return 1;
}
}
@ -599,13 +611,13 @@ int GH278_Bcc_Sub(BYTE op, BYTE ps_not_taken, BYTE ps_taken, WORD pc)
reset();
regs.pc = pc;
regs.ps = ps_not_taken;
if (Cpu6502(0) != 2) return 1;
if (TestCpu6502(0) != 2) return 1;
if (regs.pc != dst_not_taken) return 1;
reset();
regs.pc = pc;
regs.ps = ps_taken;
if (Cpu6502(0) != 3+pagecross) return 1;
if (TestCpu6502(0) != 3+pagecross) return 1;
if (regs.pc != dst_taken) return 1;
// 65C02
@ -613,13 +625,13 @@ int GH278_Bcc_Sub(BYTE op, BYTE ps_not_taken, BYTE ps_taken, WORD pc)
reset();
regs.pc = pc;
regs.ps = ps_not_taken;
if (Cpu65C02(0) != 2) return 1;
if (TestCpu65C02(0) != 2) return 1;
if (regs.pc != dst_not_taken) return 1;
reset();
regs.pc = pc;
regs.ps = ps_taken;
if (Cpu65C02(0) != 3+pagecross) return 1;
if (TestCpu65C02(0) != 3+pagecross) return 1;
if (regs.pc != dst_taken) return 1;
return 0;
@ -644,7 +656,7 @@ int GH278_BRA(void)
reset();
regs.pc = pc;
if (Cpu65C02(0) != 3) return 1;
if (TestCpu65C02(0) != 3) return 1;
if (regs.pc != dst_taken) return 1;
}
@ -657,7 +669,7 @@ int GH278_BRA(void)
reset();
regs.pc = pc;
if (Cpu65C02(0) != 4) return 1;
if (TestCpu65C02(0) != 4) return 1;
if (regs.pc != dst_taken) return 1;
}
@ -677,7 +689,7 @@ int GH278_JMP_INDX(void)
mem[regs.pc+3] = dst&0xff;
mem[regs.pc+4] = dst>>8;
DWORD cycles = Cpu65C02(0);
DWORD cycles = TestCpu65C02(0);
if (cycles != 6) return 1;
if (regs.pc != dst) return 1;
@ -692,7 +704,7 @@ int GH278_JMP_INDX(void)
mem[regs.pc+3] = dst&0xff;
mem[regs.pc+4] = dst>>8;
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (cycles != 6) return 1; // todo: is this 6 or 7?
if (regs.pc != dst) return 1;
@ -709,7 +721,7 @@ int GH278_JMP_INDX(void)
mem[regs.pc+4] = dst&0xff;
mem[regs.pc+5] = dst>>8;
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (cycles != 6) return 1; // todo: is this 6 or 7?
if (regs.pc != dst) return 1;
@ -728,12 +740,12 @@ int GH278_ADC_SBC(UINT op)
// No page-cross
reset();
regs.ps = AF_DECIMAL;
DWORD cycles = Cpu6502(0);
DWORD cycles = TestCpu6502(0);
if (g_OpcodeTimings[op][CYC_6502] != cycles) return 1;
reset();
regs.ps = AF_DECIMAL;
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (g_OpcodeTimings[op][CYC_65C02]+1 != cycles) return 1; // CMOS is +1 cycles in decimal mode
// Page-cross
@ -741,14 +753,14 @@ int GH278_ADC_SBC(UINT op)
regs.ps = AF_DECIMAL;
regs.x = 1;
regs.y = 1;
cycles = Cpu6502(0);
cycles = TestCpu6502(0);
if (g_OpcodeTimings[op][CYC_6502_PX] != cycles) return 1;
reset();
regs.ps = AF_DECIMAL;
regs.x = 1;
regs.y = 1;
cycles = Cpu65C02(0);
cycles = TestCpu65C02(0);
if (g_OpcodeTimings[op][CYC_65C02_PX]+1 != cycles) return 1; // CMOS is +1 cycles in decimal mode
return 0;
@ -794,7 +806,7 @@ int GH278_test(void)
mem[regs.pc+0] = op;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
DWORD cycles = Cpu6502(0);
DWORD cycles = TestCpu6502(0);
if (g_OpcodeTimings[op][variant] != cycles) return 1;
}
@ -811,7 +823,7 @@ int GH278_test(void)
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
mem[0xff] = 0xff; mem[0x00] = 0x00; // For: OPCODE (zp),Y
DWORD cycles = Cpu6502(0);
DWORD cycles = TestCpu6502(0);
if (g_OpcodeTimings[op][variant] != cycles) return 1;
}
@ -829,7 +841,7 @@ int GH278_test(void)
mem[regs.pc+0] = op;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
DWORD cycles = Cpu65C02(0);
DWORD cycles = TestCpu65C02(0);
if (g_OpcodeTimings[op][variant] != cycles) return 1;
}
@ -846,7 +858,7 @@ int GH278_test(void)
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
mem[0xff] = 0xff; mem[0x00] = 0x00; // For: OPCODE (zp),Y
DWORD cycles = Cpu65C02(0);
DWORD cycles = TestCpu65C02(0);
if (g_OpcodeTimings[op][variant] != cycles) return 1;
}
@ -893,7 +905,7 @@ DWORD AXA_ZPY(BYTE a, BYTE x, BYTE y, WORD base)
regs.y = y;
mem[regs.pc+0] = 0x93;
mem[regs.pc+1] = 0xfe;
return Cpu6502(0);
return TestCpu6502(0);
}
DWORD AXA_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
@ -905,7 +917,7 @@ DWORD AXA_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
mem[regs.pc+0] = 0x9f;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
return Cpu6502(0);
return TestCpu6502(0);
}
DWORD SAY_ABSX(BYTE a, BYTE x, BYTE y, WORD base)
@ -917,7 +929,7 @@ DWORD SAY_ABSX(BYTE a, BYTE x, BYTE y, WORD base)
mem[regs.pc+0] = 0x9c;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
return Cpu6502(0);
return TestCpu6502(0);
}
DWORD TAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
@ -929,7 +941,7 @@ DWORD TAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
mem[regs.pc+0] = 0x9b;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
return Cpu6502(0);
return TestCpu6502(0);
}
DWORD XAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
@ -941,7 +953,7 @@ DWORD XAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
mem[regs.pc+0] = 0x9e;
mem[regs.pc+1] = base&0xff;
mem[regs.pc+2] = base>>8;
return Cpu6502(0);
return TestCpu6502(0);
}
int GH282_test(void)
@ -1077,10 +1089,10 @@ int GH292_test(void)
reset();
WORD base=regs.pc;
mem[regs.pc] = op+0x03; if (Cpu65C02(0) != 1 || regs.pc != base+1) return 1;
mem[regs.pc] = op+0x07; if (Cpu65C02(0) != 1 || regs.pc != base+2) return 1;
mem[regs.pc] = op+0x0B; if (Cpu65C02(0) != 1 || regs.pc != base+3) return 1;
mem[regs.pc] = op+0x0F; if (Cpu65C02(0) != 1 || regs.pc != base+4) return 1;
mem[regs.pc] = op+0x03; if (TestCpu65C02(0) != 1 || regs.pc != base+1) return 1;
mem[regs.pc] = op+0x07; if (TestCpu65C02(0) != 1 || regs.pc != base+2) return 1;
mem[regs.pc] = op+0x0B; if (TestCpu65C02(0) != 1 || regs.pc != base+3) return 1;
mem[regs.pc] = op+0x0F; if (TestCpu65C02(0) != 1 || regs.pc != base+4) return 1;
}
//
@ -1093,14 +1105,14 @@ int GH292_test(void)
mem[regs.pc+0] = 0xDC;
mem[regs.pc+1] = 0x00;
mem[regs.pc+2] = 0xC0;
if (Cpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 1 || regs.a != 0) return 1;
if (TestCpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 1 || regs.a != 0) return 1;
reset();
base = regs.pc;
mem[regs.pc+0] = 0xFC;
mem[regs.pc+1] = 0x00;
mem[regs.pc+2] = 0xC0;
if (Cpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 2 || regs.a != 0) return 1;
if (TestCpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 2 || regs.a != 0) return 1;
IORead[0] = NULL;
@ -1240,7 +1252,7 @@ int GH321_test()
g_dwCyclesThisFrame = startCycle;
regs.pc = org;
ULONG uExecutedCycles = Cpu65C02(2 * kNTSCScanLines * kHClocks);
ULONG uExecutedCycles = TestCpu65C02(2 * kNTSCScanLines * kHClocks);
res[startCycle] = mem[0x000a];
//if (mem[0x000a] == 0)