From 86f36b30d579b2c9618c7779dafaec5482f044ae Mon Sep 17 00:00:00 2001 From: avolkov Date: Thu, 2 Jul 2009 01:44:31 +0000 Subject: [PATCH] First steps towards clean exit; bug #52 git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3167 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/sc2code/comm/starbas/starbas.c | 3 +- sc2/src/sc2code/confirm.c | 26 +++++------- sc2/src/sc2code/controls.h | 1 - sc2/src/sc2code/encount.c | 8 ++-- sc2/src/sc2code/gameinp.c | 4 -- sc2/src/sc2code/libs/graphics/cmap.c | 4 ++ .../sc2code/libs/graphics/sdl/sdl_common.c | 11 ++--- sc2/src/sc2code/libs/inplib.h | 1 + sc2/src/sc2code/libs/sound/audiocore.c | 9 +++++ sc2/src/sc2code/libs/sound/sound.c | 10 ++++- sc2/src/sc2code/starcon.c | 25 ++++++++---- sc2/src/sc2code/starcon.h | 3 ++ sc2/src/sc2code/util.c | 6 +-- sc2/src/starcon2.c | 40 ++++++++++++++++--- 15 files changed, 101 insertions(+), 51 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 8098a0b3f..2fcb9d990 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.7: +- Game attempts to exit cleanly under normal circustances (bug #52) - Alex - Fixed Mmrnmhrm's X-Form transformation without energy use (bug #1004) - Alex - Added missing sleeps in DoInput() functions (bug #893) - Alex - Starmap unit conversion corrections; fixes bug #970 - Alex diff --git a/sc2/src/sc2code/comm/starbas/starbas.c b/sc2/src/sc2code/comm/starbas/starbas.c index bf20a8908..9eb28feed 100644 --- a/sc2/src/sc2code/comm/starbas/starbas.c +++ b/sc2/src/sc2code/comm/starbas/starbas.c @@ -1753,7 +1753,8 @@ SellMinerals (RESPONSE_REF R) total += amount * GLOBAL (ElementWorth[i]); do { - if (!Sleepy || AnyButtonPress (TRUE)) + if (!Sleepy || AnyButtonPress (TRUE) || + (GLOBAL (CurrentActivity) & CHECK_ABORT)) { Sleepy = FALSE; GLOBAL_SIS (ElementAmounts[i]) = 0; diff --git a/sc2/src/sc2code/confirm.c b/sc2/src/sc2code/confirm.c index b93ac0d4b..8f0199730 100644 --- a/sc2/src/sc2code/confirm.c +++ b/sc2/src/sc2code/confirm.c @@ -84,7 +84,7 @@ BOOLEAN DoConfirmExit (void) { BOOLEAN result; - static BOOLEAN in_confirm = FALSE; + if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE && !(LastActivity & CHECK_RESTART)) @@ -93,12 +93,6 @@ DoConfirmExit (void) PauseTrack (); LockMutex (GraphicsLock); - if (in_confirm) - { - result = FALSE; - ExitRequested = FALSE; - } - else { RECT r; STAMP s; @@ -107,7 +101,6 @@ DoConfirmExit (void) RECT oldRect; BOOLEAN response = FALSE, done; - in_confirm = TRUE; oldContext = SetContext (ScreenContext); GetContextClipRect (&oldRect); SetContextClipRect (NULL); @@ -130,16 +123,20 @@ DoConfirmExit (void) FlushGraphics (); //LockMutex (GraphicsLock); - GLOBAL (CurrentActivity) |= CHECK_ABORT; FlushInput (); done = FALSE; - + do { // Forbid recursive calls or pausing here! ExitRequested = FALSE; GamePaused = FALSE; UpdateInputState (); - if (PulsedInputState.menu[KEY_MENU_SELECT]) + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + { // something else triggered an exit + done = TRUE; + response = TRUE; + } + else if (PulsedInputState.menu[KEY_MENU_SELECT]) { done = TRUE; PlayMenuSound (MENU_SOUND_SUCCESS); @@ -155,21 +152,21 @@ DoConfirmExit (void) DrawConfirmationWindow (response); PlayMenuSound (MENU_SOUND_MOVE); } - TaskSwitch (); + SleepThread (ONE_SECOND / 30); } while (!done); s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); ClearSystemRect (); - if (response) + if (response || (GLOBAL (CurrentActivity) & CHECK_ABORT)) { result = TRUE; + GLOBAL (CurrentActivity) |= CHECK_ABORT; } else { result = FALSE; - GLOBAL (CurrentActivity) &= ~CHECK_ABORT; } ExitRequested = FALSE; GamePaused = FALSE; @@ -190,7 +187,6 @@ DoConfirmExit (void) do_subtitles ((void *)~0); } - in_confirm = FALSE; return (result); } diff --git a/sc2/src/sc2code/controls.h b/sc2/src/sc2code/controls.h index c4ad4774f..536c707ad 100644 --- a/sc2/src/sc2code/controls.h +++ b/sc2/src/sc2code/controls.h @@ -102,7 +102,6 @@ void SetDefaultMenuRepeatDelay (void); void ResetKeyRepeat (void); BOOLEAN PauseGame (void); BOOLEAN DoConfirmExit (void); -void TFB_Abort (void); BOOLEAN WaitAnyButtonOrQuit (BOOLEAN CheckSpecial); void WaitForNoInput (SIZE Duration); BOOLEAN ConfirmExit (void); diff --git a/sc2/src/sc2code/encount.c b/sc2/src/sc2code/encount.c index 11d6fa82e..958544ed4 100644 --- a/sc2/src/sc2code/encount.c +++ b/sc2/src/sc2code/encount.c @@ -201,8 +201,7 @@ InitEncounter (void) PlayMusic (MR, FALSE, 1); SegueFrame = CaptureDrawable (LoadGraphic (SEGUE_PMAP_ANIM)); UnlockMutex (GraphicsLock); - while (PLRPlaying (MR)) - TaskSwitch (); + WaitForSoundEnd (TFBSOUND_WAIT_ALL); StopMusic (); DestroyMusic (MR); LockMutex (GraphicsLock); @@ -622,7 +621,8 @@ UninitEncounter (void) for (j = 0; j < NUM_SHIP_FADES; ++j) { UnlockMutex (GraphicsLock); - Sleepy = (BOOLEAN)!AnyButtonPress (TRUE); + Sleepy = (BOOLEAN)!AnyButtonPress (TRUE) && + !(GLOBAL (CurrentActivity) & CHECK_ABORT); LockMutex (GraphicsLock); if (!Sleepy) break; @@ -658,6 +658,7 @@ UninitEncounter (void) FlushInput (); Time = GetTimeCounter () + (ONE_SECOND * 3); UnlockMutex (GraphicsLock); + // TODO: handle rapid quit while (!(AnyButtonPress (TRUE)) && GetTimeCounter () < Time) TaskSwitch (); LockMutex (GraphicsLock); @@ -688,6 +689,7 @@ UninitEncounter (void) DrawFadeText (str1, str2, TRUE, &scavenge_r); Time = GetTimeCounter () + ONE_SECOND * 2; UnlockMutex (GraphicsLock); + // TODO: handle rapid quit while (!(AnyButtonPress (TRUE)) && GetTimeCounter () < Time) TaskSwitch (); diff --git a/sc2/src/sc2code/gameinp.c b/sc2/src/sc2code/gameinp.c index 45af9c8d6..78c6bb4a6 100644 --- a/sc2/src/sc2code/gameinp.c +++ b/sc2/src/sc2code/gameinp.c @@ -60,7 +60,6 @@ static DWORD GestaltRepeatDelay, GestaltTime; static BOOLEAN OldGestalt, CachedGestalt; static DWORD _max_accel, _min_accel, _step_accel; static BOOLEAN _gestalt_keys; -int ExitState; static MENU_SOUND_FLAGS sound_0, sound_1; @@ -353,9 +352,6 @@ DoInput (void *pInputState, BOOLEAN resetInput) #endif /* CREATE_JOURNAL */ } - if (CurrentInputState.menu[KEY_EXIT]) - ExitState = ConfirmExit (); - soundFlags = MenuKeysToSoundFlags (&PulsedInputState); if (MenuSounds diff --git a/sc2/src/sc2code/libs/graphics/cmap.c b/sc2/src/sc2code/libs/graphics/cmap.c index b320bba60..9ba94be11 100644 --- a/sc2/src/sc2code/libs/graphics/cmap.c +++ b/sc2/src/sc2code/libs/graphics/cmap.c @@ -18,6 +18,7 @@ #include "gfx_common.h" #include "libs/tasklib.h" +#include "libs/inplib.h" #include "libs/log.h" #include @@ -606,6 +607,9 @@ XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) if (!ColorMapPtr) return (0); + if (QuitPosted) // Don't make users wait for fades + TimeInterval = 0; + what = *ColorMapPtr; if (what >= (int)FadeAllToWhite && what <= (int)FadeSomeToColor) return XFormFade (ColorMapPtr, TimeInterval); diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c index 6430b981c..a9df62104 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c @@ -56,11 +56,7 @@ TFB_GRAPHICS_BACKEND *graphics_backend = NULL; #define FPS_PERIOD 100 int RenderedFrames = 0; -void -TFB_Abort (void) -{ - abortFlag = TRUE; -} +volatile int QuitPosted = 0; void TFB_PreInit (void) @@ -208,8 +204,7 @@ TFB_ProcessEvents () // TODO break; case SDL_QUIT: - log_showBox (false, false); - exit (EXIT_SUCCESS); + QuitPosted = 1; break; case SDL_VIDEORESIZE: /* User resized video mode */ // TODO @@ -222,7 +217,7 @@ TFB_ProcessEvents () } } - if (ImmediateInputState.menu[KEY_ABORT] || abortFlag) + if (ImmediateInputState.menu[KEY_ABORT]) { log_showBox (false, false); exit (EXIT_SUCCESS); diff --git a/sc2/src/sc2code/libs/inplib.h b/sc2/src/sc2code/libs/inplib.h index 15a1fd529..d97c7e38b 100644 --- a/sc2/src/sc2code/libs/inplib.h +++ b/sc2/src/sc2code/libs/inplib.h @@ -39,6 +39,7 @@ extern BYTE LocateMouse (SWORD *px, SWORD *py); */ extern volatile int MouseButtonDown; +extern volatile int QuitPosted; /* Functions for dealing with Character Mode */ diff --git a/sc2/src/sc2code/libs/sound/audiocore.c b/sc2/src/sc2code/libs/sound/audiocore.c index 1b5aed998..c74d87e86 100644 --- a/sc2/src/sc2code/libs/sound/audiocore.c +++ b/sc2/src/sc2code/libs/sound/audiocore.c @@ -27,6 +27,8 @@ static audio_Driver audiodrv; /* The globals that control the sound drivers. */ int snddriver, soundflags; +volatile bool audio_inited = false; + /* * Declarations for driver init funcs */ @@ -74,12 +76,19 @@ initAudio (sint32 driver, sint32 flags) "NOTICE: Try running UQM with '--sound=none' option"); exit (EXIT_FAILURE); } + + audio_inited = true; + return ret; } void unInitAudio (void) { + if (!audio_inited) + return; + + audio_inited = false; audiodrv.Uninitialize (); } diff --git a/sc2/src/sc2code/libs/sound/sound.c b/sc2/src/sc2code/libs/sound/sound.c index 4d0d54812..4249b224f 100644 --- a/sc2/src/sc2code/libs/sound/sound.c +++ b/sc2/src/sc2code/libs/sound/sound.c @@ -17,8 +17,9 @@ */ #include "sound.h" -#include "../compiler.h" -#include "../tasklib.h" +#include "libs/compiler.h" +#include "libs/tasklib.h" +#include "libs/inplib.h" static Task FadeTask; static SIZE TTotal; @@ -118,6 +119,8 @@ WaitForSoundEnd (COUNT Channel) SoundPlaying () : ChannelPlaying (Channel)) { SleepThread (ONE_SECOND / 20); + if (QuitPosted) // Don't make users wait for sounds to end + break; } } @@ -184,6 +187,9 @@ FadeMusic (BYTE end_vol, SIZE TimeInterval) { DWORD TimeOut; + if (QuitPosted) // Don't make users wait for fades + TimeInterval = 0; + if (FadeTask) { volume_end = musicVolume; diff --git a/sc2/src/sc2code/starcon.c b/sc2/src/sc2code/starcon.c index da6e5e531..a82e43dbc 100644 --- a/sc2/src/sc2code/starcon.c +++ b/sc2/src/sc2code/starcon.c @@ -39,6 +39,8 @@ #include "uqmversion.h" #include "options.h" +volatile int MainExited = FALSE; + // Open or close the periodically occuring QuasiSpace portal. // A seperate thread is always inside this function when the player // is in hyperspace. This thread awakens every BATTLE_FRAME_RATE seconds. @@ -96,6 +98,13 @@ BackgroundInitKernel (DWORD TimeOut) } } +void +SignalStopMainThread (void) +{ + GamePaused = FALSE; + GLOBAL (CurrentActivity) |= CHECK_ABORT; +} + /* TODO: Remove these declarations once threading is gone. */ extern int snddriver, soundflags; @@ -125,11 +134,13 @@ while (--ac > 0) } #endif // CREATE_JOURNAL - /* TODO: Put initAudio back in main where it belongs once threading - * is gone. - */ - extern sint32 initAudio (sint32 driver, sint32 flags); - initAudio (snddriver, soundflags); + { + /* TODO: Put initAudio back in main where it belongs once threading + * is gone. + */ + extern sint32 initAudio (sint32 driver, sint32 flags); + initAudio (snddriver, soundflags); + } if (!LoadKernel (0,0)) { @@ -258,9 +269,7 @@ while (--ac > 0) FreeGameData (); FreeKernel (); - // XXX: the abort can now be changed to something cleaner; - // something to terminate the for(;;) loop in main() - TFB_Abort (); + MainExited = TRUE; (void) threadArg; /* Satisfying compiler (unused parameter) */ return 0; diff --git a/sc2/src/sc2code/starcon.h b/sc2/src/sc2code/starcon.h index 62048cd96..995119b8c 100644 --- a/sc2/src/sc2code/starcon.h +++ b/sc2/src/sc2code/starcon.h @@ -17,6 +17,9 @@ #ifndef _STARCON_H #define _STARCON_H +extern volatile int MainExited; +extern void SignalStopMainThread (void); + extern int Starcon2Main (void *threadArg); extern void FreeGameData (void); diff --git a/sc2/src/sc2code/util.c b/sc2/src/sc2code/util.c index 9b97e6f1a..8f47a5b27 100644 --- a/sc2/src/sc2code/util.c +++ b/sc2/src/sc2code/util.c @@ -188,19 +188,19 @@ PauseGame (void) FlushGraphics (); //LockMutex (GraphicsLock); - while (ImmediateInputState.menu[KEY_PAUSE]) + while (ImmediateInputState.menu[KEY_PAUSE] && GamePaused) { BeginInputFrame (); TaskSwitch (); } - while (!ImmediateInputState.menu[KEY_PAUSE]) + while (!ImmediateInputState.menu[KEY_PAUSE] && GamePaused) { BeginInputFrame (); TaskSwitch (); } - while (ImmediateInputState.menu[KEY_PAUSE]) + while (ImmediateInputState.menu[KEY_PAUSE] && GamePaused) { BeginInputFrame (); TaskSwitch (); diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c index 4943fa6d5..0a9b85c47 100644 --- a/sc2/src/starcon2.c +++ b/sc2/src/starcon2.c @@ -29,6 +29,7 @@ #include "libs/graphics/gfx_common.h" #include "libs/sound/sound.h" #include "libs/input/input_common.h" +#include "libs/inplib.h" #include "libs/tasklib.h" #include "controls.h" #include "element.h" @@ -146,6 +147,7 @@ main (int argc, char *argv[]) /* .speechVolumeScale = */ 1.0f, }; int optionsResult; + int i; log_init (15); @@ -476,21 +478,47 @@ main (int argc, char *argv[]) StartThread (Starcon2Main, NULL, 1024, "Starcon2Main"); - for (;;) + for (i = 0; i < 2000 && !MainExited; ) { + if (QuitPosted) + { /* Try to stop the main thread, but limited number of times */ + SignalStopMainThread (); + ++i; + } + TFB_ProcessEvents (); ProcessThreadLifecycles (); TFB_FlushGraphics (); } -#if 0 - unInitTempDir (); -#endif - uninitIO (); + /* Currently, we use atexit() callbacks everywhere, so we + * cannot simply call unInitAudio() and the like, because other + * tasks might still be using it */ + if (MainExited) + { + // Not yet: TFB_UninitInput (); + unInitAudio (); + uninit_communication (); + UninitColorMaps (); + // Not yet: TFB_UninitGraphics (); #ifdef NETPLAY - Network_uninit (); + NetManager_uninit (); + Alarm_uninit (); + Network_uninit (); #endif + + // Not yet: CleanupTaskSystem (); + UnInitTimeSystem (); +#if 0 + unInitTempDir (); +#endif + uninitIO (); + UnInitThreadSystem (); + mem_uninit (); + } + + log_showBox (false, false); return EXIT_SUCCESS; }