From bf6138c2560086445f1c8adaa161e5851216141c Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 17 Mar 2002 19:37:00 +0000 Subject: [PATCH] Finally implemented pause functionality. It is only enabled in X11 and SDL versions for now, but can easily be used in other ports. Press the PAUSE button to activate and deactivate. It is started by calling Console.mediaSource().pause(bool state), where state is either true or false and will enable/disable the pause, respectively. When pause is enabled, a mute is sent to the Sound device, so other ports must have coded this Sound::mute method. While pause is on, all calls to Console.mediaSource().update() will do nothing. Only by calling pause() again can the emulator proceed. Other ports will probably require a minor rewrite of their main loop, since the calculation of frames per second will now have to be done differently. Previously, FPS was based on the time entering the main loop and the time leaving. This difference was the total time used in calculating FPS. Now, since pause can be on for an indefinite amount of time, the total time must be incremented *per frame* instead of over the whole loop. Similarly, the total number of frames drawn is no longer how many times you pass through the loop, but how many times you pass through the loop *while not paused*. See ui/sdl/mainSDL.cxx or ui/x11/mainX11.cxx for more info. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@47 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/build/makefile | 4 +- stella/src/emucore/MediaSrc.hxx | 14 ++++-- stella/src/emucore/TIA.cxx | 21 ++++++++- stella/src/emucore/TIA.hxx | 17 ++++++-- stella/src/ui/sdl/mainSDL.cxx | 75 +++++++++++++++++++++------------ stella/src/ui/x11/mainX11.cxx | 71 ++++++++++++++++++++----------- 6 files changed, 142 insertions(+), 60 deletions(-) diff --git a/stella/src/build/makefile b/stella/src/build/makefile index 45f2d5ed9..ea856dd07 100644 --- a/stella/src/build/makefile +++ b/stella/src/build/makefile @@ -13,7 +13,7 @@ ## See the file "license" for information on usage and redistribution of ## this file, and for a DISCLAIMER OF ALL WARRANTIES. ## -## $Id: makefile,v 1.10 2002-03-10 01:29:54 stephena Exp $ +## $Id: makefile,v 1.11 2002-03-17 19:37:00 stephena Exp $ ##============================================================================ ##============================================================================ @@ -34,7 +34,7 @@ OPTIMIZATIONS = # -funroll-loops -fstrength-reduce -fomit-frame-pointer -ffast-math \ # -malign-functions=2 -malign-jumps=2 -malign-loops=2 ### to get full optimization under gcc/x Athlon based OS's.. -# OPTIMIZATIONS = -O3 -march=athlon -Wall -Wno-unused \ +# OPTIMIZATIONS = -O3 -mcpu=athlon -march=athlon -Wall -Wno-unused \ # -funroll-loops -fstrength-reduce -fomit-frame-pointer -ffast-math \ # -malign-functions=2 -malign-jumps=2 -malign-loops=2 diff --git a/stella/src/emucore/MediaSrc.hxx b/stella/src/emucore/MediaSrc.hxx index 660970bf1..0ce28a583 100644 --- a/stella/src/emucore/MediaSrc.hxx +++ b/stella/src/emucore/MediaSrc.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: MediaSrc.hxx,v 1.1.1.1 2001-12-27 19:54:22 bwmott Exp $ +// $Id: MediaSrc.hxx,v 1.2 2002-03-17 19:37:00 stephena Exp $ //============================================================================ #ifndef MEDIASOURCE_HXX @@ -27,7 +27,7 @@ class MediaSource; This class provides an interface for accessing graphics data. @author Bradford W. Mott - @version $Id: MediaSrc.hxx,v 1.1.1.1 2001-12-27 19:54:22 bwmott Exp $ + @version $Id: MediaSrc.hxx,v 1.2 2002-03-17 19:37:00 stephena Exp $ */ class MediaSource { @@ -49,6 +49,15 @@ class MediaSource */ virtual void update() = 0; + /** + This method should be called to cause further calls to 'update' + to be ignored until an unpause is given. Will also send a mute to + the Sound device. + + @return Status of the pause, success (true) or failure (false) + */ + virtual bool pause(bool state) = 0; + /** Answers the current frame buffer @@ -102,4 +111,3 @@ class MediaSource MediaSource& operator = (const MediaSource&); }; #endif - diff --git a/stella/src/emucore/TIA.cxx b/stella/src/emucore/TIA.cxx index 1661ca105..426c2c636 100644 --- a/stella/src/emucore/TIA.cxx +++ b/stella/src/emucore/TIA.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TIA.cxx,v 1.6 2002-01-27 02:10:04 stephena Exp $ +// $Id: TIA.cxx,v 1.7 2002-03-17 19:37:00 stephena Exp $ //============================================================================ #include @@ -262,6 +262,10 @@ void TIA::install(System& system) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIA::update() { + // Don't do an update if the emulator is paused + if(pauseState) + return; + uInt8* tmp = myCurrentFrameBuffer; myCurrentFrameBuffer = myPreviousFrameBuffer; myPreviousFrameBuffer = tmp; @@ -295,6 +299,21 @@ void TIA::update() myScanlineCountForFrame = totalClocks / 228; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool TIA::pause(bool state) +{ + // Ignore multiple calls to do the same thing + if(pauseState == state) + return false; + + pauseState = state; + + // Now pause the Sound device + mySound.mute(pauseState); + + return true; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const uInt32* TIA::palette() const { diff --git a/stella/src/emucore/TIA.hxx b/stella/src/emucore/TIA.hxx index f1b06f4ce..8f05e528a 100644 --- a/stella/src/emucore/TIA.hxx +++ b/stella/src/emucore/TIA.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TIA.hxx,v 1.1.1.1 2001-12-27 19:54:25 bwmott Exp $ +// $Id: TIA.hxx,v 1.2 2002-03-17 19:37:00 stephena Exp $ //============================================================================ #ifndef TIA_HXX @@ -38,7 +38,7 @@ class System; be displayed on screen. @author Bradford W. Mott - @version $Id: TIA.hxx,v 1.1.1.1 2001-12-27 19:54:25 bwmott Exp $ + @version $Id: TIA.hxx,v 1.2 2002-03-17 19:37:00 stephena Exp $ */ class TIA : public Device , public MediaSource { @@ -106,6 +106,15 @@ class TIA : public Device , public MediaSource */ virtual void update(); + /** + This method should be called to cause further calls to 'update' + to be ignored until an unpause is given. Will also send a mute to + the Sound device. + + @return Status of the pause, success (true) or failure (false) + */ + virtual bool pause(bool state); + /** Answers the current frame buffer @@ -417,6 +426,8 @@ class TIA : public Device , public MediaSource // Assignment operator isn't supported by this class so make it private TIA& operator = (const TIA&); + + // Indicates whether the current emulation cycle should is paused + bool pauseState; }; #endif - diff --git a/stella/src/ui/sdl/mainSDL.cxx b/stella/src/ui/sdl/mainSDL.cxx index e13513a2e..eb87615c7 100644 --- a/stella/src/ui/sdl/mainSDL.cxx +++ b/stella/src/ui/sdl/mainSDL.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: mainSDL.cxx,v 1.12 2002-03-10 01:29:55 stephena Exp $ +// $Id: mainSDL.cxx,v 1.13 2002-03-17 19:37:00 stephena Exp $ //============================================================================ #include @@ -49,6 +49,7 @@ #define SDL_DISABLE 0 #endif +#define HAVE_GETTIMEOFDAY SDL_Joystick* theLeftJoystick; SDL_Joystick* theRightJoystick; @@ -73,6 +74,7 @@ void toggleFullscreen(); void takeSnapshot(); void togglePause(); uInt32 maxWindowSizeForScreen(); +uInt32 getTicks(); bool setupProperties(PropertiesSet& set); void handleCommandLineArguments(int ac, char* av[]); @@ -608,8 +610,6 @@ void toggleFullscreen() */ void togglePause() { -// todo: implement pause functionality - if(thePauseIndicator) // emulator is already paused so continue { thePauseIndicator = false; @@ -618,6 +618,8 @@ void togglePause() { thePauseIndicator = true; } + + theConsole->mediaSource().pause(thePauseIndicator); } @@ -961,8 +963,7 @@ void handleEvents() { if(!thePauseIndicator) { - // togglePause(); - cerr << "todo: Pause on minimize.\n"; + togglePause(); } } } @@ -1673,13 +1674,13 @@ int main(int argc, char* argv[]) cleanup(); } - // Get the starting time in case we need to print statistics - timeval startingTime; - gettimeofday(&startingTime, 0); + // Set up timing stuff + Uint32 before, delta, frameTime = 0, eventTime = 0; + Uint32 timePerFrame = 1000000 / theDesiredFrameRate; + Uint32 numberOfFrames = 0; - uInt32 numberOfFrames = 0; - uInt32 frameTime = 1000000 / theDesiredFrameRate; - for( ; ; ++numberOfFrames) + // Main game loop + for(;;) { // Exit if the user wants to quit if(theQuitIndicator) @@ -1687,36 +1688,37 @@ int main(int argc, char* argv[]) break; } - // Remember the current time before we start drawing the frame - timeval before; - gettimeofday(&before, 0); + // Call handleEvents here to see if user pressed pause + handleEvents(); + if(thePauseIndicator) + { + updateDisplay(theConsole->mediaSource()); + SDL_Delay(10); + continue; + } + before = getTicks(); theConsole->mediaSource().update(); updateDisplay(theConsole->mediaSource()); handleEvents(); // Now, waste time if we need to so that we are at the desired frame rate - timeval after; for(;;) { - gettimeofday(&after, 0); + delta = getTicks() - before; - uInt32 delta = (uInt32)((after.tv_sec - before.tv_sec) * 1000000 + - (after.tv_usec - before.tv_usec)); - - if(delta > frameTime) + if(delta >= timePerFrame) break; -//else SDL_Delay(1); } + + frameTime += (getTicks() - before); + ++numberOfFrames; } if(theShowInfoFlag) { - timeval endingTime; - gettimeofday(&endingTime, 0); - double executionTime = (endingTime.tv_sec - startingTime.tv_sec) + - ((endingTime.tv_usec - startingTime.tv_usec) / 1000000.0); - double framesPerSecond = numberOfFrames / executionTime; + double executionTime = (double) frameTime / 1000000.0; + double framesPerSecond = (double) numberOfFrames / executionTime; cout << endl; cout << numberOfFrames << " total frames drawn\n"; @@ -1732,3 +1734,24 @@ int main(int argc, char* argv[]) // Cleanup time ... cleanup(); } + + +/** + Returns number of ticks in microseconds +*/ +#ifdef HAVE_GETTIMEOFDAY +inline uInt32 getTicks() +{ + timeval now; + gettimeofday(&now, 0); + + uInt32 ticks = now.tv_sec * 1000000 + now.tv_usec; + + return ticks; +} +#else +inline uInt32 getTicks() +{ + return SDL_GetTicks() * 1000; +} +#endif diff --git a/stella/src/ui/x11/mainX11.cxx b/stella/src/ui/x11/mainX11.cxx index 9a2171c34..fa2a27edc 100644 --- a/stella/src/ui/x11/mainX11.cxx +++ b/stella/src/ui/x11/mainX11.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: mainX11.cxx,v 1.13 2002-03-12 19:27:11 stephena Exp $ +// $Id: mainX11.cxx,v 1.14 2002-03-17 19:37:00 stephena Exp $ //============================================================================ #include @@ -66,6 +66,8 @@ int theRightJoystickFd; #endif +#define HAVE_GETTIMEOFDAY + // Globals for X windows stuff Display* theDisplay; string theDisplayName = ""; @@ -99,6 +101,7 @@ void toggleFullscreen(); void takeSnapshot(); void togglePause(); uInt32 maxWindowSizeForScreen(); +uInt32 getTicks(); bool setupProperties(PropertiesSet& set); void handleCommandLineArguments(int argc, char* argv[]); @@ -686,8 +689,7 @@ void handleEvents() { if(!thePauseIndicator) { - // togglePause(); - cerr << "todo: Pause on minimize.\n"; + togglePause(); } } } @@ -922,8 +924,6 @@ void toggleFullscreen() */ void togglePause() { -// todo: implement pause functionality - if(thePauseIndicator) // emulator is already paused so continue { thePauseIndicator = false; @@ -932,6 +932,8 @@ void togglePause() { thePauseIndicator = true; } + + theConsole->mediaSource().pause(thePauseIndicator); } /** @@ -1574,13 +1576,13 @@ int main(int argc, char* argv[]) cleanup(); } - // Get the starting time in case we need to print statistics - timeval startingTime; - gettimeofday(&startingTime, 0); - + // Set up timing stuff + uInt32 before, delta, frameTime = 0, eventTime = 0; + uInt32 timePerFrame = 1000000 / theDesiredFrameRate; uInt32 numberOfFrames = 0; - uInt32 frameTime = 1000000 / theDesiredFrameRate; - for( ; ; ++numberOfFrames) + + // Main game loop + for(;;) { // Exit if the user wants to quit if(theQuitIndicator) @@ -1588,35 +1590,37 @@ int main(int argc, char* argv[]) break; } - // Remember the current time before we start drawing the frame - timeval before; - gettimeofday(&before, 0); + // Call handleEvents here to see if user pressed pause + handleEvents(); + if(thePauseIndicator) + { + updateDisplay(theConsole->mediaSource()); + usleep(10000); + continue; + } + before = getTicks(); theConsole->mediaSource().update(); updateDisplay(theConsole->mediaSource()); handleEvents(); // Now, waste time if we need to so that we are at the desired frame rate - timeval after; for(;;) { - gettimeofday(&after, 0); + delta = getTicks() - before; - uInt32 delta = (uInt32)((after.tv_sec - before.tv_sec) * 1000000 + - (after.tv_usec - before.tv_usec)); - - if(delta > frameTime) + if(delta > timePerFrame) break; } + + frameTime += (getTicks() - before); + ++numberOfFrames; } if(theShowInfoFlag) { - timeval endingTime; - gettimeofday(&endingTime, 0); - double executionTime = (endingTime.tv_sec - startingTime.tv_sec) + - ((endingTime.tv_usec - startingTime.tv_usec) / 1000000.0); - double framesPerSecond = numberOfFrames / executionTime; + double executionTime = (double) frameTime / 1000000.0; + double framesPerSecond = (double) numberOfFrames / executionTime; cout << endl; cout << numberOfFrames << " total frames drawn\n"; @@ -1633,3 +1637,20 @@ int main(int argc, char* argv[]) cleanup(); return 0; } + +/** + Returns number of ticks in microseconds +*/ +#ifdef HAVE_GETTIMEOFDAY +inline uInt32 getTicks() +{ + timeval now; + gettimeofday(&now, 0); + + uInt32 ticks = now.tv_sec * 1000000 + now.tv_usec; + + return ticks; +} +#else +#error "We need gettimeofday for the X11 version" +#endif