- More cleanup

- Split the mainloop into several (run) subfunctions
- start/stop functions for (de)initialization. This replaces the !Restart part
- removed necessity of several variables
- This is the last step before the event based mainloop


git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@1622 4a71c877-e1ca-e34f-864e-861f7616d084
master
Dennis Schridde 2007-05-12 21:47:06 +00:00
parent 50ea035570
commit f5439cfa16
3 changed files with 293 additions and 337 deletions

View File

@ -60,15 +60,7 @@ static FPSmanager wzFPSmanager;
static UWORD currentCursorResID = UWORD_MAX;
SDL_Cursor *aCursors[MAX_CURSORS];
typedef enum _focus_state
{
FOCUS_OUT, // Window does not have the focus
FOCUS_SET, // Just received WM_SETFOCUS
FOCUS_IN, // Window has got the focus
FOCUS_KILL, // Just received WM_KILLFOCUS
} FOCUS_STATE;
FOCUS_STATE focusState, focusLast;
FOCUS_STATE focusState = FOCUS_IN;
/************************************************************************************
*
@ -225,7 +217,7 @@ BOOL frameInitialise(
BOOL fullScreen // Whether to start full screen or windowed
)
{
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CDROM) != 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
{
debug( LOG_ERROR, "Error: Could not initialise SDL (%s).\n", SDL_GetError() );
return FALSE;
@ -233,9 +225,6 @@ BOOL frameInitialise(
SDL_WM_SetCaption(pWindowName, NULL);
focusState = FOCUS_IN;
focusLast = FOCUS_IN;
/* Initialise the trig stuff */
if (!trigInitialise())
{
@ -265,6 +254,7 @@ BOOL frameInitialise(
return TRUE;
}
/*
* frameUpdate
*
@ -273,105 +263,19 @@ BOOL frameInitialise(
*
* Returns FRAME_STATUS.
*/
FRAME_STATUS frameUpdate(void)
void frameUpdate(void)
{
SDL_Event event;
FRAME_STATUS retVal = FRAME_OK;
BOOL wzQuit = FALSE;
/* Tell the input system about the start of another frame */
inputNewFrame();
/* Deal with any windows messages */
while ( SDL_PollEvent( &event ) != 0)
{
switch (event.type)
{
case SDL_QUIT:
wzQuit = TRUE;
break;
case SDL_ACTIVEEVENT:
// Ignore focus loss through SDL_APPMOUSEFOCUS, since it mostly happens accidentialy
// active.state is a bitflag! Mixed events (eg. APPACTIVE|APPMOUSEFOCUS) will thus not be ignored.
if ( event.active.state != SDL_APPMOUSEFOCUS )
{
if ( event.active.gain == 1 )
{
debug( LOG_NEVER, "WM_SETFOCUS\n");
if (focusState != FOCUS_IN)
{
debug( LOG_NEVER, "FOCUS_SET\n");
focusState = FOCUS_SET;
}
}
else
{
debug( LOG_NEVER, "WM_KILLFOCUS\n");
if (focusState != FOCUS_OUT)
{
debug( LOG_NEVER, "FOCUS_KILL\n");
focusState = FOCUS_KILL;
}
/* Have to tell the input system that we've lost focus */
inputLooseFocus();
}
}
break;
case SDL_KEYUP:
case SDL_KEYDOWN:
inputHandleKeyEvent(&event);
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
inputHandleMouseButtonEvent(&event);
break;
case SDL_MOUSEMOTION:
inputHandleMouseMotionEvent(&event);
break;
default:
break;
}
}
/* Now figure out what to return */
if (wzQuit)
{
retVal = FRAME_QUIT;
}
else if (focusState == FOCUS_SET && focusLast == FOCUS_OUT)
{
debug( LOG_NEVER, "frameUpdate: Returning SETFOCUS\n");
focusState = FOCUS_IN;
retVal = FRAME_SETFOCUS;
}
else if (focusState == FOCUS_KILL && focusLast == FOCUS_IN)
{
debug( LOG_NEVER, "frameUpdate: Returning KILLFOCUS\n");
focusState = FOCUS_OUT;
retVal = FRAME_KILLFOCUS;
}
if (focusState == FOCUS_SET || focusState == FOCUS_KILL)
{
/* Got a SET or KILL when we were already in or out of
focus respectively */
focusState = focusLast;
}
else if (focusLast != focusState)
{
debug( LOG_NEVER, "focusLast changing from %d to %d\n", focusLast, focusState);
focusLast = focusState;
}
/* If things are running normally update the framerate */
if (!wzQuit && focusState == FOCUS_IN)
if (focusState == FOCUS_IN)
{
/* Update the frame rate stuff */
MaintainFrameStuff();
SDL_framerateDelay( &wzFPSmanager );
}
return retVal;
SDL_framerateDelay(&wzFPSmanager);
}
@ -534,7 +438,6 @@ BOOL loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bu
}
/* next four used in HashPJW */
#define BITS_IN_int 32
#define THREE_QUARTERS ((UDWORD) ((BITS_IN_int * 3) / 4))
@ -542,9 +445,6 @@ BOOL loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bu
#define HIGH_BITS ( ~((UDWORD)(~0) >> ONE_EIGHTH ))
///////////////////////////////////////////////////////////////////
/***************************************************************************/
/*
* HashString

View File

@ -74,21 +74,20 @@ extern BOOL frameInitialise(
*/
extern void frameShutDown(void);
/* The current status of the framework */
typedef enum _frame_status
typedef enum _focus_state
{
FRAME_OK, // Everything normal
FRAME_KILLFOCUS, // The main app window has lost focus (might well want to pause)
FRAME_SETFOCUS, // The main app window has focus back
FRAME_QUIT, // The main app window has been told to quit
} FRAME_STATUS;
FOCUS_OUT, // Window does not have the focus
FOCUS_IN, // Window has got the focus
} FOCUS_STATE;
/* Call this each cycle to allow the framework to deal with
* windows messages, and do general house keeping.
*
* Returns FRAME_STATUS.
*/
extern FRAME_STATUS frameUpdate(void);
extern void frameUpdate(void);
/* Set the current cursor from a Resource ID
* This is the same as calling:

View File

@ -37,6 +37,7 @@
#endif // WZ_OS_WIN
#include "lib/framework/configfile.h"
#include "lib/framework/input.h"
#include "lib/gamelib/gtime.h"
#include "lib/ivis_common/piestate.h"
#include "lib/ivis_common/rendmode.h"
@ -100,6 +101,9 @@ char MultiPlayersPath[MAX_PATH];
char KeyMapPath[MAX_PATH];
char UserMusicPath[MAX_PATH];
static int gameLoopStatus = 0;
extern FOCUS_STATE focusState;
extern void debug_callback_stderr( void**, const char * );
extern void debug_callback_win32debug( void**, const char * );
@ -384,17 +388,271 @@ static void make_dir(char *dest, const char *dirname, const char *subdir)
if ( !PHYSFS_mkdir(dest) ) {
debug(LOG_ERROR, "Unable to create directory \"%s\" in write dir \"%s\"!",
dest, PHYSFS_getWriteDir());
exit(1);
exit(EXIT_FAILURE);
}
}
static void startTitleLoop(void)
{
screen_RestartBackDrop();
if (!frontendInitialise("wrf/frontend.wrf"))
{
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
frontendInitialised = TRUE;
frontendInitVars();
}
static void stopTitleLoop(void)
{
if (!frontendShutdown())
{
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
frontendInitialised = FALSE;
}
static void startGameLoop(void)
{
if (!levLoadData(pLevelName, NULL, 0))
{
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
//after data is loaded check the research stats are valid
if (!checkResearchStats())
{
debug( LOG_ERROR, "Invalid Research Stats" );
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
//and check the structure stats are valid
if (!checkStructureStats())
{
debug( LOG_ERROR, "Invalid Structure Stats" );
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
//set a flag for the trigger/event system to indicate initialisation is complete
gameInitialised = TRUE;
screen_StopBackDrop();
}
static void stopGameLoop(void)
{
if (gameLoopStatus != GAMECODE_NEWLEVEL)
{
initLoadingScreen(TRUE); // returning to f.e. do a loader.render not active
pie_EnableFog(FALSE); // dont let the normal loop code set status on
fogStatus = 0;
if (gameLoopStatus != GAMECODE_LOADGAME)
{
levReleaseAll();
}
}
gameInitialised = FALSE;
}
static void initSaveGameLoad(void)
{
screen_RestartBackDrop();
// load up a save game
if (!loadGameInit(saveGameName))
{
debug( LOG_ERROR, "Shutting down after failure" );
exit(EXIT_FAILURE);
}
screen_StopBackDrop();
SetGameMode(GS_NORMAL);
}
static void runGameLoop(void)
{
gameLoopStatus = gameLoop();
switch (gameLoopStatus)
{
case GAMECODE_CONTINUE:
case GAMECODE_PLAYVIDEO:
break;
case GAMECODE_QUITGAME:
debug(LOG_MAIN, "GAMECODE_QUITGAME");
stopGameLoop();
SetGameMode(GS_TITLE_SCREEN);
startTitleLoop();
break;
case GAMECODE_LOADGAME:
debug(LOG_MAIN, "GAMECODE_LOADGAME");
stopGameLoop();
SetGameMode(GS_SAVEGAMELOAD);
startTitleLoop();
break;
case GAMECODE_NEWLEVEL:
debug(LOG_MAIN, "GAMECODE_NEWLEVEL");
stopGameLoop();
startGameLoop();
break;
// Never trown:
case GAMECODE_FASTEXIT:
case GAMECODE_RESTARTGAME:
break;
default:
debug(LOG_ERROR, "Unknown code returned by gameLoop");
break;
}
}
static void runTitleLoop(void)
{
switch (titleLoop())
{
case TITLECODE_CONTINUE:
break;
case TITLECODE_QUITGAME:
debug(LOG_MAIN, "TITLECODE_QUITGAME");
stopTitleLoop();
{
// Create a quit event to halt game loop.
SDL_Event quitEvent;
quitEvent.type = SDL_QUIT;
SDL_PushEvent(&quitEvent);
}
break;
case TITLECODE_SAVEGAMELOAD:
debug(LOG_MAIN, "TITLECODE_SAVEGAMELOAD");
stopTitleLoop();
SetGameMode(GS_SAVEGAMELOAD);
initSaveGameLoad();
break;
case TITLECODE_STARTGAME:
debug(LOG_MAIN, "TITLECODE_STARTGAME");
stopTitleLoop();
SetGameMode(GS_NORMAL);
startGameLoop();
break;
case TITLECODE_SHOWINTRO:
debug(LOG_MAIN, "TITLECODE_SHOWINTRO");
seq_ClearSeqList();
seq_AddSeqToList("eidos-logo.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("pumpkin.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("titles.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("devastation.rpl", NULL, "devastation.txa", FALSE);
seq_StartNextFullScreenVideo();
break;
default:
debug(LOG_ERROR, "Unknown code returned by titleLoop");
break;
}
}
static void handleActiveEvent(SDL_Event * event)
{
// Ignore focus loss through SDL_APPMOUSEFOCUS, since it mostly happens accidentialy
// active.state is a bitflag! Mixed events (eg. APPACTIVE|APPMOUSEFOCUS) will thus not be ignored.
if ( event->active.state != SDL_APPMOUSEFOCUS )
{
if ( event->active.gain == 1 )
{
debug( LOG_NEVER, "WM_SETFOCUS\n");
if (focusState != FOCUS_IN)
{
focusState = FOCUS_IN;
gameTimeStart();
// Should be: audio_ResumeAll();
}
}
else
{
debug( LOG_NEVER, "WM_KILLFOCUS\n");
if (focusState != FOCUS_OUT)
{
focusState = FOCUS_OUT;
gameTimeStop();
// Should be: audio_PauseAll();
audio_StopAll();
}
/* Have to tell the input system that we've lost focus */
inputLooseFocus();
}
}
}
static void mainLoop(void)
{
SDL_Event event;
while (TRUE)
{
/* Deal with any windows messages */
while (SDL_PollEvent(&event))
{
switch (event.type)
{
if (focusState == FOCUS_IN)
{
case SDL_KEYUP:
case SDL_KEYDOWN:
inputHandleKeyEvent(&event);
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
inputHandleMouseButtonEvent(&event);
break;
case SDL_MOUSEMOTION:
inputHandleMouseMotionEvent(&event);
break;
}
case SDL_ACTIVEEVENT:
handleActiveEvent(&event);
break;
case SDL_QUIT:
return;
default:
break;
}
}
if (focusState == FOCUS_IN)
{
gameTimeUpdate();
if(loop_GetVideoStatus())
videoLoop();
else switch (GetGameMode())
{
case GS_NORMAL:
runGameLoop();
break;
case GS_TITLE_SCREEN:
runTitleLoop();
break;
default:
break;
}
frameUpdate(); // General housekeeping
}
}
}
int main(int argc, char *argv[])
{
BOOL quit = FALSE;
BOOL Restart = FALSE;
BOOL lostFocus = FALSE;
int loopStatus = 0;
iColour* psPaletteBuffer = NULL;
UDWORD pSize = 0;
@ -520,227 +778,26 @@ int main(int argc, char *argv[])
//set all the pause states to false
setAllPauseStates(FALSE);
while (!quit)
{
// Do the game mode specific initialisation.
switch(gameStatus)
switch(GetGameMode())
{
case GS_TITLE_SCREEN:
screen_RestartBackDrop();
if (!frontendInitialise("wrf/frontend.wrf"))
{
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
frontendInitialised = TRUE;
frontendInitVars();
startTitleLoop();
break;
case GS_SAVEGAMELOAD:
screen_RestartBackDrop();
SetGameMode(GS_NORMAL);
// load up a save game
if (!loadGameInit(saveGameName))
{
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
screen_StopBackDrop();
initSaveGameLoad();
break;
case GS_NORMAL:
if (!levLoadData(pLevelName, NULL, 0))
{
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
//after data is loaded check the research stats are valid
if (!checkResearchStats())
{
debug( LOG_ERROR, "Invalid Research Stats" );
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
//and check the structure stats are valid
if (!checkStructureStats())
{
debug( LOG_ERROR, "Invalid Structure Stats" );
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
//set a flag for the trigger/event system to indicate initialisation is complete
gameInitialised = TRUE;
screen_StopBackDrop();
startGameLoop();
break;
default:
debug( LOG_ERROR, "Unknown game status on shutdown!" );
}
debug(LOG_MAIN, "Entering main loop");
Restart = FALSE;
while (!Restart)
{
// Event handling, etc.
switch (frameUpdate())
{
case FRAME_KILLFOCUS:
lostFocus = TRUE;
gameTimeStop();
audio_StopAll();
break;
case FRAME_SETFOCUS:
lostFocus = FALSE;
gameTimeStart();
break;
case FRAME_QUIT:
debug(LOG_MAIN, "frame quit");
quit = TRUE;
Restart = TRUE;
break;
default:
break;
}
lastStatus = gameStatus;
if (!lostFocus && !quit)
{
if (loop_GetVideoStatus())
{
videoLoop();
}
else switch(gameStatus)
{
case GS_TITLE_SCREEN:
switch(titleLoop()) {
case TITLECODE_QUITGAME:
debug(LOG_MAIN, "TITLECODE_QUITGAME");
Restart = TRUE;
quit = TRUE;
break;
case TITLECODE_SAVEGAMELOAD:
debug(LOG_MAIN, "TITLECODE_SAVEGAMELOAD");
gameStatus = GS_SAVEGAMELOAD;
Restart = TRUE;
break;
case TITLECODE_STARTGAME:
debug(LOG_MAIN, "TITLECODE_STARTGAME");
SetGameMode(GS_NORMAL);
Restart = TRUE;
break;
case TITLECODE_SHOWINTRO:
debug(LOG_MAIN, "TITLECODE_SHOWINTRO");
seq_ClearSeqList();
seq_AddSeqToList("eidos-logo.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("pumpkin.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("titles.rpl", NULL, NULL, FALSE);
seq_AddSeqToList("devastation.rpl", NULL, "devastation.txa", FALSE);
seq_StartNextFullScreenVideo();
break;
case TITLECODE_CONTINUE:
break;
default:
debug(LOG_ERROR, "Unknown code returned by titleLoop");
}
break;
case GS_NORMAL:
loopStatus = gameLoop();
switch(loopStatus) {
case GAMECODE_QUITGAME:
debug(LOG_MAIN, "GAMECODE_QUITGAME");
SetGameMode(GS_TITLE_SCREEN);
Restart = TRUE;
if(NetPlay.bLobbyLaunched)
{
quit = TRUE;
}
break;
case GAMECODE_FASTEXIT:
debug(LOG_MAIN, "GAMECODE_FASTEXIT");
Restart = TRUE;
quit = TRUE;
break;
case GAMECODE_LOADGAME:
debug(LOG_MAIN, "GAMECODE_LOADGAME");
Restart = TRUE;
gameStatus = GS_SAVEGAMELOAD;
break;
case GAMECODE_PLAYVIDEO:
debug(LOG_MAIN, "GAMECODE_PLAYVIDEO");
Restart = FALSE;
break;
case GAMECODE_NEWLEVEL:
case GAMECODE_RESTARTGAME:
debug(LOG_MAIN, "GAMECODE_RESTARTGAME");
Restart = TRUE;
break;
case GAMECODE_CONTINUE:
break;
default:
debug(LOG_ERROR, "Unknown code returned by gameLoop");
}
break;
default:
debug(LOG_ERROR, "Weirdy game status, I'm afraid!!");
break;
}
gameTimeUpdate();
} // !lostFocus && !quit
else if (lostFocus && !quit)
{
// Prevent CPU hogging when we've lost focus
SDL_Delay(1);
}
} // End of !Restart loop.
debug(LOG_MAIN, "Entering main loop");
debug(LOG_MAIN, "Preparing for shutdown/restart");
// Do game mode specific shutdown.
switch(lastStatus)
{
case GS_TITLE_SCREEN:
if (!frontendShutdown())
{
debug(LOG_ERROR, "Shutting down after failure");
exit(EXIT_FAILURE);
}
frontendInitialised = FALSE;
break;
case GS_NORMAL:
if (loopStatus != GAMECODE_NEWLEVEL)
{
initLoadingScreen(TRUE); // returning to f.e. do a loader.render not active
pie_EnableFog(FALSE);//dont let the normal loop code set status on
fogStatus = 0;
if (loopStatus != GAMECODE_LOADGAME)
{
levReleaseAll();
}
}
gameInitialised = FALSE;
break;
default:
debug(LOG_ERROR, "Unknown game status on shutdown!");
break;
}
} // End of !quit loop.
mainLoop();
debug(LOG_MAIN, "Shutting down Warzone 2100");