diff --git a/source/Applewin.cpp b/source/Applewin.cpp index 6b2cffce..91bc4e5c 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -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) diff --git a/source/Applewin.h b/source/Applewin.h index b9af8c1b..e7ea04ff 100644 --- a/source/Applewin.h +++ b/source/Applewin.h @@ -19,6 +19,8 @@ extern eApple2Type g_Apple2Type; eApple2Type GetApple2Type(void); void SetApple2Type(eApple2Type type); +void SingleStep(void); + extern bool g_bFullSpeed; //=========================================== diff --git a/source/CPU.cpp b/source/CPU.cpp index c9c32e88..104ce158 100644 --- a/source/CPU.cpp +++ b/source/CPU.cpp @@ -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); diff --git a/source/CPU.h b/source/CPU.h index 8fb02e3a..e0fcc722 100644 --- a/source/CPU.h +++ b/source/CPU.h @@ -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 (); diff --git a/source/CPU/cpu6502.h b/source/CPU/cpu6502.h index 64b89f56..6451c1cf 100644 --- a/source/CPU/cpu6502.h +++ b/source/CPU/cpu6502.h @@ -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 diff --git a/source/CPU/cpu65C02.h b/source/CPU/cpu65C02.h index eb08c471..92106513 100644 --- a/source/CPU/cpu65C02.h +++ b/source/CPU/cpu65C02.h @@ -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 diff --git a/source/CPU/cpu65d02.h b/source/CPU/cpu65d02.h index 44962aef..9f83f88c 100644 --- a/source/CPU/cpu65d02.h +++ b/source/CPU/cpu65d02.h @@ -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 diff --git a/source/Common.h b/source/Common.h index c1db33e1..6095c769 100644 --- a/source/Common.h +++ b/source/Common.h @@ -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 diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 10a181ba..225473c5 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -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; +} diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h index c05f897c..db9e6c21 100644 --- a/source/Debugger/Debug.h +++ b/source/Debugger/Debug.h @@ -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 ); - \ No newline at end of file + + bool IsDebugSteppingAtFullSpeed(void); diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp index fe678cbd..c01e068a 100644 --- a/source/Debugger/Debugger_Commands.cpp +++ b/source/Debugger/Debugger_Commands.cpp @@ -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" }, diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index bc9651e1..552c91f6 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -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) diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp index 94be3f6d..b912b8b1 100644 --- a/source/Debugger/Debugger_Help.cpp +++ b/source/Debugger/Debugger_Help.cpp @@ -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]" diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h index a59259cb..4ca264a0 100644 --- a/source/Debugger/Debugger_Types.h +++ b/source/Debugger/Debugger_Types.h @@ -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); diff --git a/source/Frame.cpp b/source/Frame.cpp index db8aafce..cf6459aa 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -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 } diff --git a/source/Video.cpp b/source/Video.cpp index 13209396..23e6129b 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -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); diff --git a/test/TestCPU6502/TestCPU6502.cpp b/test/TestCPU6502/TestCPU6502.cpp index 747a5511..8514f1a7 100644 --- a/test/TestCPU6502/TestCPU6502.cpp +++ b/test/TestCPU6502/TestCPU6502.cpp @@ -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)