2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2001-11-04 19:34:28 +00:00
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
File: StepMania.cpp
|
|
|
|
|
|
2002-07-23 01:41:40 +00:00
|
|
|
Desc: Entry point for program.
|
2001-11-04 19:34:28 +00:00
|
|
|
|
2002-05-19 01:59:48 +00:00
|
|
|
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
2002-07-23 01:41:40 +00:00
|
|
|
Chris Danford
|
2001-11-04 19:34:28 +00:00
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
*/
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-01-24 23:09:31 +00:00
|
|
|
#include "StepMania.h"
|
|
|
|
|
|
2002-07-27 19:29:51 +00:00
|
|
|
//
|
|
|
|
|
// Rage global classes
|
|
|
|
|
//
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "RageTextureManager.h"
|
2002-12-15 10:35:39 +00:00
|
|
|
#include "RageSoundManager.h"
|
2003-07-26 22:47:55 +00:00
|
|
|
#include "RageSounds.h"
|
2002-07-27 19:29:51 +00:00
|
|
|
#include "RageInput.h"
|
|
|
|
|
#include "RageTimer.h"
|
|
|
|
|
#include "RageException.h"
|
2002-10-28 05:30:45 +00:00
|
|
|
#include "RageMath.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "RageDisplay.h"
|
2002-07-27 19:29:51 +00:00
|
|
|
|
2002-11-17 09:13:35 +00:00
|
|
|
#include "arch/arch.h"
|
2002-11-18 21:37:58 +00:00
|
|
|
#include "arch/LoadingWindow/LoadingWindow.h"
|
2004-04-05 05:22:32 +00:00
|
|
|
#include <ctime>
|
2002-11-17 09:13:35 +00:00
|
|
|
|
2004-03-04 04:27:55 +00:00
|
|
|
#include "ProductInfo.h"
|
|
|
|
|
|
2003-02-14 06:31:09 +00:00
|
|
|
#include "SDL_utils.h"
|
2002-10-24 03:56:46 +00:00
|
|
|
|
2004-02-19 03:20:11 +00:00
|
|
|
#include "Screen.h"
|
2004-02-12 09:44:16 +00:00
|
|
|
#include "CodeDetector.h"
|
|
|
|
|
|
2002-04-16 17:31:00 +00:00
|
|
|
//
|
|
|
|
|
// StepMania global classes
|
|
|
|
|
//
|
2002-11-11 04:53:31 +00:00
|
|
|
#include "ThemeManager.h"
|
2003-02-06 07:32:57 +00:00
|
|
|
#include "NoteSkinManager.h"
|
2002-02-28 19:40:40 +00:00
|
|
|
#include "PrefsManager.h"
|
|
|
|
|
#include "SongManager.h"
|
2002-07-23 01:41:40 +00:00
|
|
|
#include "GameState.h"
|
2002-05-19 01:59:48 +00:00
|
|
|
#include "AnnouncerManager.h"
|
2003-09-08 03:26:58 +00:00
|
|
|
#include "ProfileManager.h"
|
2003-12-15 07:35:40 +00:00
|
|
|
#include "MemoryCardManager.h"
|
2002-05-19 01:59:48 +00:00
|
|
|
#include "ScreenManager.h"
|
2002-03-19 07:09:49 +00:00
|
|
|
#include "GameManager.h"
|
2002-03-30 20:00:13 +00:00
|
|
|
#include "FontManager.h"
|
2002-04-16 17:31:00 +00:00
|
|
|
#include "InputFilter.h"
|
|
|
|
|
#include "InputMapper.h"
|
2002-05-19 01:59:48 +00:00
|
|
|
#include "InputQueue.h"
|
2002-08-21 02:13:08 +00:00
|
|
|
#include "SongCacheIndex.h"
|
2003-06-04 22:42:17 +00:00
|
|
|
#include "BannerCache.h"
|
2003-07-07 22:21:31 +00:00
|
|
|
#include "UnlockSystem.h"
|
2003-07-11 03:15:28 +00:00
|
|
|
#include "arch/ArchHooks/ArchHooks.h"
|
2003-12-04 08:25:59 +00:00
|
|
|
#include "RageFileManager.h"
|
2003-10-13 08:33:39 +00:00
|
|
|
#include "Bookkeeper.h"
|
2003-11-16 04:45:12 +00:00
|
|
|
#include "LightsManager.h"
|
2004-02-08 09:04:23 +00:00
|
|
|
#include "ModelManager.h"
|
2004-02-15 05:45:18 +00:00
|
|
|
#include "CryptManager.h"
|
2004-03-16 22:10:45 +00:00
|
|
|
#include "NetworkSyncManager.h"
|
2003-07-22 07:47:27 +00:00
|
|
|
|
|
|
|
|
#if defined(_XBOX)
|
2003-11-13 00:39:36 +00:00
|
|
|
#include "custom_launch_params.h"
|
|
|
|
|
#ifdef _DEBUG
|
2003-10-04 06:41:17 +00:00
|
|
|
#pragma comment(lib, "SDL-1.2.6/lib/xboxSDLmaind.lib")
|
2003-07-22 07:47:27 +00:00
|
|
|
#else
|
2003-10-04 06:41:17 +00:00
|
|
|
#pragma comment(lib, "SDL-1.2.6/lib/xboxSDLmain.lib")
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
|
|
|
|
#elif defined(_WINDOWS)
|
|
|
|
|
#ifdef DEBUG
|
2003-10-04 06:41:17 +00:00
|
|
|
#pragma comment(lib, "SDL-1.2.6/lib/SDLmaind.lib")
|
2003-07-22 07:47:27 +00:00
|
|
|
#else
|
2003-10-04 06:41:17 +00:00
|
|
|
#pragma comment(lib, "SDL-1.2.6/lib/SDLmain.lib")
|
2003-07-22 07:47:27 +00:00
|
|
|
#endif
|
2002-11-11 04:53:31 +00:00
|
|
|
#endif
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-12-10 08:55:20 +00:00
|
|
|
#define ZIPS_DIR "Packages/"
|
|
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
#ifdef _WINDOWS
|
2002-12-03 00:35:34 +00:00
|
|
|
HWND g_hWndMain = NULL;
|
|
|
|
|
#endif
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-07-15 00:47:53 +00:00
|
|
|
int g_argc = 0;
|
|
|
|
|
char **g_argv = NULL;
|
2003-07-06 22:13:56 +00:00
|
|
|
|
2003-01-19 11:00:53 +00:00
|
|
|
static bool g_bHasFocus = true;
|
2003-04-12 16:06:06 +00:00
|
|
|
static bool g_bQuitting = false;
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2004-01-13 22:34:55 +00:00
|
|
|
void UpdateHWnd()
|
|
|
|
|
{
|
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
|
/* Grab the window manager specific information */
|
|
|
|
|
SDL_SysWMinfo info;
|
|
|
|
|
SDL_VERSION(&info.version);
|
|
|
|
|
if ( SDL_GetWMInfo(&info) < 0 )
|
|
|
|
|
RageException::Throw( "SDL_GetWMInfo failed" );
|
|
|
|
|
|
|
|
|
|
g_hWndMain = info.window;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-12 18:50:42 +00:00
|
|
|
static RageDisplay::VideoModeParams GetCurVideoModeParams()
|
|
|
|
|
{
|
|
|
|
|
return RageDisplay::VideoModeParams(
|
2003-06-05 19:29:27 +00:00
|
|
|
PREFSMAN->m_bWindowed,
|
|
|
|
|
PREFSMAN->m_iDisplayWidth,
|
|
|
|
|
PREFSMAN->m_iDisplayHeight,
|
|
|
|
|
PREFSMAN->m_iDisplayColorDepth,
|
|
|
|
|
PREFSMAN->m_iRefreshRate,
|
|
|
|
|
PREFSMAN->m_bVsync,
|
2003-08-12 19:08:07 +00:00
|
|
|
PREFSMAN->m_bInterlaced,
|
2003-12-20 21:29:55 +00:00
|
|
|
PREFSMAN->m_bSmoothLines,
|
2004-05-18 09:05:21 +00:00
|
|
|
PREFSMAN->m_bTrilinearFiltering,
|
2004-05-18 08:43:21 +00:00
|
|
|
PREFSMAN->m_bAnisotropicFiltering,
|
2003-06-05 19:29:27 +00:00
|
|
|
THEME->GetMetric("Common","WindowTitle"),
|
2004-05-23 23:24:44 +00:00
|
|
|
THEME->GetPathToG("Common window icon"),
|
|
|
|
|
PREFSMAN->m_bPAL
|
2003-08-12 18:50:42 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-15 07:52:58 +00:00
|
|
|
static void StoreActualGraphicOptions( bool initial )
|
|
|
|
|
{
|
|
|
|
|
// find out what we actually have
|
|
|
|
|
PREFSMAN->m_bWindowed = DISPLAY->GetVideoModeParams().windowed;
|
|
|
|
|
PREFSMAN->m_iDisplayWidth = DISPLAY->GetVideoModeParams().width;
|
|
|
|
|
PREFSMAN->m_iDisplayHeight = DISPLAY->GetVideoModeParams().height;
|
|
|
|
|
PREFSMAN->m_iDisplayColorDepth = DISPLAY->GetVideoModeParams().bpp;
|
|
|
|
|
PREFSMAN->m_iRefreshRate = DISPLAY->GetVideoModeParams().rate;
|
|
|
|
|
PREFSMAN->m_bVsync = DISPLAY->GetVideoModeParams().vsync;
|
|
|
|
|
|
|
|
|
|
CString log = ssprintf("%s %dx%d %d color %d texture %dHz %s %s",
|
|
|
|
|
PREFSMAN->m_bWindowed ? "Windowed" : "Fullscreen",
|
|
|
|
|
PREFSMAN->m_iDisplayWidth,
|
|
|
|
|
PREFSMAN->m_iDisplayHeight,
|
|
|
|
|
PREFSMAN->m_iDisplayColorDepth,
|
|
|
|
|
PREFSMAN->m_iTextureColorDepth,
|
|
|
|
|
PREFSMAN->m_iRefreshRate,
|
|
|
|
|
PREFSMAN->m_bVsync ? "Vsync" : "NoVsync",
|
2003-12-20 21:29:55 +00:00
|
|
|
PREFSMAN->m_bSmoothLines? "AA" : "NoAA" );
|
2003-09-15 07:52:58 +00:00
|
|
|
if( initial )
|
|
|
|
|
LOG->Info( "%s", log.c_str() );
|
|
|
|
|
else
|
|
|
|
|
SCREENMAN->SystemMessage( log );
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-12 18:50:42 +00:00
|
|
|
void ApplyGraphicOptions()
|
|
|
|
|
{
|
|
|
|
|
bool bNeedReload = false;
|
|
|
|
|
|
|
|
|
|
bNeedReload |= DISPLAY->SetVideoMode( GetCurVideoModeParams() );
|
|
|
|
|
|
2003-10-11 07:47:34 +00:00
|
|
|
DISPLAY->ChangeCentering(
|
|
|
|
|
PREFSMAN->m_iCenterImageTranslateX,
|
|
|
|
|
PREFSMAN->m_iCenterImageTranslateY,
|
|
|
|
|
PREFSMAN->m_fCenterImageScaleX,
|
|
|
|
|
PREFSMAN->m_fCenterImageScaleY );
|
|
|
|
|
|
2003-02-02 09:09:29 +00:00
|
|
|
bNeedReload |= TEXTUREMAN->SetPrefs(
|
2003-02-02 02:01:28 +00:00
|
|
|
PREFSMAN->m_iTextureColorDepth,
|
2003-07-09 02:28:56 +00:00
|
|
|
PREFSMAN->m_iMovieColorDepth,
|
2003-04-18 23:55:20 +00:00
|
|
|
PREFSMAN->m_bDelayedTextureDelete,
|
2003-02-02 02:01:28 +00:00
|
|
|
PREFSMAN->m_iMaxTextureResolution );
|
2002-11-12 09:31:08 +00:00
|
|
|
|
2003-02-02 09:09:29 +00:00
|
|
|
if( bNeedReload )
|
2003-05-26 09:18:44 +00:00
|
|
|
TEXTUREMAN->ReloadAll();
|
|
|
|
|
|
2003-09-15 07:52:58 +00:00
|
|
|
StoreActualGraphicOptions( false );
|
2003-06-18 05:43:12 +00:00
|
|
|
|
2004-01-13 22:34:55 +00:00
|
|
|
/* Recreating the window changes the hwnd. */
|
|
|
|
|
UpdateHWnd();
|
|
|
|
|
|
2003-06-18 05:43:12 +00:00
|
|
|
/* Give the input handlers a chance to re-open devices as necessary. */
|
|
|
|
|
INPUTMAN->WindowReset();
|
2002-11-11 04:53:31 +00:00
|
|
|
}
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2004-05-06 09:06:24 +00:00
|
|
|
void HandleException( CString error )
|
|
|
|
|
{
|
|
|
|
|
if( g_bAutoRestart )
|
|
|
|
|
HOOKS->RestartProgram();
|
|
|
|
|
|
|
|
|
|
HOOKS->MessageBoxError( error ); // throw up a pretty error dialog
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-19 04:44:22 +00:00
|
|
|
void ExitGame()
|
2003-01-10 02:22:07 +00:00
|
|
|
{
|
2003-04-12 16:06:06 +00:00
|
|
|
g_bQuitting = true;
|
2003-01-10 02:22:07 +00:00
|
|
|
}
|
|
|
|
|
|
2003-09-25 06:05:19 +00:00
|
|
|
void ResetGame( bool ReturnToFirstScreen )
|
2003-01-10 02:22:07 +00:00
|
|
|
{
|
|
|
|
|
GAMESTATE->Reset();
|
2003-10-02 01:39:23 +00:00
|
|
|
ReadGamePrefsFromDisk();
|
2003-01-10 02:22:07 +00:00
|
|
|
INPUTMAPPER->ReadMappingsFromDisk();
|
|
|
|
|
|
2003-06-25 05:22:58 +00:00
|
|
|
NOTESKIN->RefreshNoteSkinData( GAMESTATE->m_CurGame );
|
|
|
|
|
|
2003-04-21 23:43:51 +00:00
|
|
|
/*
|
|
|
|
|
GameState::Reset() will switch the NoteSkin
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-01-10 02:22:07 +00:00
|
|
|
{
|
2003-02-17 12:19:42 +00:00
|
|
|
PlayerNumber pn = (PlayerNumber)p;
|
|
|
|
|
if( !NOTESKIN->DoesNoteSkinExist( NOTESKIN->GetCurNoteSkinName(pn) ) )
|
|
|
|
|
{
|
|
|
|
|
CStringArray asNoteSkinNames;
|
|
|
|
|
NOTESKIN->GetNoteSkinNames( asNoteSkinNames );
|
|
|
|
|
NOTESKIN->SwitchNoteSkin( pn, asNoteSkinNames[0] );
|
|
|
|
|
}
|
2003-01-10 02:22:07 +00:00
|
|
|
}
|
2003-04-21 23:43:51 +00:00
|
|
|
*/
|
2003-01-10 02:22:07 +00:00
|
|
|
if( !THEME->DoesThemeExist( THEME->GetCurThemeName() ) )
|
|
|
|
|
{
|
|
|
|
|
CString sGameName = GAMESTATE->GetCurrentGameDef()->m_szName;
|
|
|
|
|
if( THEME->DoesThemeExist( sGameName ) )
|
2003-08-19 08:01:15 +00:00
|
|
|
THEME->SwitchThemeAndLanguage( sGameName, THEME->GetCurLanguage() );
|
2003-01-10 02:22:07 +00:00
|
|
|
else
|
2003-08-19 08:01:15 +00:00
|
|
|
THEME->SwitchThemeAndLanguage( "default", THEME->GetCurLanguage() );
|
2003-04-18 23:55:20 +00:00
|
|
|
TEXTUREMAN->DoDelayedDelete();
|
2003-01-10 02:22:07 +00:00
|
|
|
}
|
2003-10-02 01:39:23 +00:00
|
|
|
SaveGamePrefsToDisk();
|
2003-01-10 02:22:07 +00:00
|
|
|
|
2003-10-03 03:20:50 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// update last seen joysticks
|
|
|
|
|
//
|
|
|
|
|
vector<InputDevice> vDevices;
|
|
|
|
|
vector<CString> vDescriptions;
|
|
|
|
|
INPUTMAN->GetDevicesAndDescriptions(vDevices,vDescriptions);
|
|
|
|
|
CString sInputDevices = join( ",", vDescriptions );
|
|
|
|
|
|
|
|
|
|
if( PREFSMAN->m_sLastSeenInputDevices != sInputDevices )
|
|
|
|
|
{
|
|
|
|
|
LOG->Info( "Input devices changed from '%s' to '%s'.", PREFSMAN->m_sLastSeenInputDevices.c_str(), sInputDevices.c_str() );
|
|
|
|
|
|
|
|
|
|
if( PREFSMAN->m_bAutoMapOnJoyChange )
|
|
|
|
|
{
|
|
|
|
|
LOG->Info( "Remapping joysticks." );
|
|
|
|
|
INPUTMAPPER->AutoMapJoysticksForCurrentGame();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PREFSMAN->m_sLastSeenInputDevices = sInputDevices;
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-25 06:05:19 +00:00
|
|
|
|
|
|
|
|
if( ReturnToFirstScreen )
|
2004-04-18 21:48:12 +00:00
|
|
|
{
|
|
|
|
|
if( PREFSMAN->m_bFirstRun )
|
|
|
|
|
SCREENMAN->SetNewScreen( THEME->GetMetric("Common","FirstRunInitialScreen") );
|
|
|
|
|
else
|
|
|
|
|
SCREENMAN->SetNewScreen( THEME->GetMetric("Common","InitialScreen") );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PREFSMAN->m_bFirstRun = false;
|
2003-01-10 02:22:07 +00:00
|
|
|
}
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2002-12-19 23:26:50 +00:00
|
|
|
static void GameLoop();
|
2002-11-14 23:54:40 +00:00
|
|
|
|
2003-01-19 11:00:53 +00:00
|
|
|
static bool ChangeAppPri()
|
2003-01-18 04:27:33 +00:00
|
|
|
{
|
|
|
|
|
if(PREFSMAN->m_iBoostAppPriority == 0)
|
2003-01-19 11:00:53 +00:00
|
|
|
return false;
|
2003-01-18 04:27:33 +00:00
|
|
|
|
2003-10-12 17:53:35 +00:00
|
|
|
// if using NTPAD don't boost or else input is laggy
|
|
|
|
|
if(PREFSMAN->m_iBoostAppPriority == -1)
|
|
|
|
|
{ vector<InputDevice> vDevices;
|
|
|
|
|
vector<CString> vDescriptions;
|
|
|
|
|
INPUTMAN->GetDevicesAndDescriptions(vDevices,vDescriptions);
|
|
|
|
|
CString sInputDevices = join( ",", vDescriptions );
|
|
|
|
|
if( sInputDevices.Find("NTPAD") != -1 )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Using NTPAD. Don't boost priority." );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-18 04:27:33 +00:00
|
|
|
/* If -1 and this is a debug build, don't. It makes the debugger sluggish. */
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
if(PREFSMAN->m_iBoostAppPriority == -1)
|
2003-01-19 11:00:53 +00:00
|
|
|
return false;
|
2003-01-18 04:27:33 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-01-19 11:00:53 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void BoostAppPri()
|
|
|
|
|
{
|
|
|
|
|
if(!ChangeAppPri())
|
|
|
|
|
return;
|
|
|
|
|
|
2003-07-11 03:15:28 +00:00
|
|
|
#ifdef _WINDOWS
|
2003-01-18 04:27:33 +00:00
|
|
|
/* We just want a slight boost, so we don't skip needlessly if something happens
|
|
|
|
|
* in the background. We don't really want to be high-priority--above normal should
|
|
|
|
|
* be enough. However, ABOVE_NORMAL_PRIORITY_CLASS is only supported in Win2000
|
|
|
|
|
* and later. */
|
|
|
|
|
OSVERSIONINFO version;
|
|
|
|
|
version.dwOSVersionInfoSize=sizeof(version);
|
|
|
|
|
if(!GetVersionEx(&version))
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn(werr_ssprintf(GetLastError(), "GetVersionEx failed"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-19 21:05:03 +00:00
|
|
|
#ifndef ABOVE_NORMAL_PRIORITY_CLASS
|
|
|
|
|
#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-01-18 04:27:33 +00:00
|
|
|
DWORD pri = HIGH_PRIORITY_CLASS;
|
|
|
|
|
if(version.dwMajorVersion >= 5)
|
|
|
|
|
pri = ABOVE_NORMAL_PRIORITY_CLASS;
|
|
|
|
|
|
|
|
|
|
/* Be sure to boost the app, not the thread, to make sure the
|
|
|
|
|
* sound thread stays higher priority than the main thread. */
|
|
|
|
|
SetPriorityClass(GetCurrentProcess(), pri);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-10 23:50:31 +00:00
|
|
|
static void CheckSettings()
|
|
|
|
|
{
|
|
|
|
|
#if defined(WIN32)
|
|
|
|
|
/* Has the amount of memory changed? */
|
|
|
|
|
MEMORYSTATUS mem;
|
|
|
|
|
GlobalMemoryStatus(&mem);
|
|
|
|
|
|
|
|
|
|
const int Memory = mem.dwTotalPhys / 1048576;
|
|
|
|
|
|
|
|
|
|
if( PREFSMAN->m_iLastSeenMemory == Memory )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "Memory changed from %i to %i; settings changed", PREFSMAN->m_iLastSeenMemory, Memory );
|
|
|
|
|
PREFSMAN->m_iLastSeenMemory = Memory;
|
|
|
|
|
|
|
|
|
|
/* Let's consider 128-meg systems low-memory, and 256-meg systems high-memory.
|
|
|
|
|
* Cut off at 192. This is somewhat conservative; many 128-meg systems can
|
|
|
|
|
* deal with higher memory profile settings, but some can't.
|
|
|
|
|
*
|
|
|
|
|
* Actually, Windows lops off a meg or two; cut off a little lower to treat
|
|
|
|
|
* 192-meg systems as high-memory. */
|
|
|
|
|
const bool HighMemory = (Memory >= 190);
|
2003-06-11 02:58:13 +00:00
|
|
|
const bool LowMemory = (Memory < 100); /* 64 and 96-meg systems */
|
2003-06-10 23:50:31 +00:00
|
|
|
|
|
|
|
|
/* Two memory-consuming features that we can disable are texture caching and
|
|
|
|
|
* preloaded banners. Texture caching can use a lot of memory; disable it for
|
|
|
|
|
* low-memory systems. */
|
|
|
|
|
PREFSMAN->m_bDelayedTextureDelete = HighMemory;
|
|
|
|
|
|
2003-06-11 02:58:13 +00:00
|
|
|
/* Preloaded banners takes about 9k per song. Although it's smaller than the
|
|
|
|
|
* actual song data, it still adds up with a lot of songs. Disable it for 64-meg
|
|
|
|
|
* systems. */
|
2003-11-25 22:56:48 +00:00
|
|
|
PREFSMAN->m_BannerCache = LowMemory? PrefsManager::BNCACHE_OFF:PrefsManager::BNCACHE_LOW_RES;
|
2003-06-10 23:50:31 +00:00
|
|
|
|
|
|
|
|
PREFSMAN->SaveGlobalPrefsToDisk();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 23:33:37 +00:00
|
|
|
#if defined(WIN32)
|
|
|
|
|
#include "RageDisplay_D3D.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if !defined(_XBOX)
|
|
|
|
|
#include "RageDisplay_OGL.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-03-24 08:31:29 +00:00
|
|
|
#include "RageDisplay_Null.h"
|
|
|
|
|
|
2003-05-26 23:33:37 +00:00
|
|
|
#include "archutils/Win32/VideoDriverInfo.h"
|
2003-05-28 05:58:24 +00:00
|
|
|
|
2003-06-22 17:45:19 +00:00
|
|
|
static const CString D3DURL = "http://search.microsoft.com/gomsuri.asp?n=1&c=rp_BestBets&siteid=us&target=http://www.microsoft.com/downloads/details.aspx?FamilyID=a19bed22-0b25-4e5d-a584-6389d8a3dad0&displaylang=en";
|
|
|
|
|
|
2003-07-22 07:47:27 +00:00
|
|
|
|
2003-10-02 04:35:29 +00:00
|
|
|
struct VideoCardDefaults
|
|
|
|
|
{
|
2003-10-12 17:44:33 +00:00
|
|
|
char *szDriverRegex;
|
|
|
|
|
char *szVideoRenderers;
|
2003-10-02 04:35:29 +00:00
|
|
|
int iWidth;
|
|
|
|
|
int iHeight;
|
|
|
|
|
int iDisplayColor;
|
|
|
|
|
int iTextureColor;
|
2003-10-07 08:18:28 +00:00
|
|
|
int iMovieColor;
|
2003-10-08 03:58:16 +00:00
|
|
|
int iTextureSize;
|
2003-12-20 21:29:55 +00:00
|
|
|
bool bSmoothLines;
|
2003-10-02 04:35:29 +00:00
|
|
|
} const g_VideoCardDefaults[] =
|
2003-08-28 04:38:01 +00:00
|
|
|
{
|
2004-03-05 02:54:46 +00:00
|
|
|
{
|
|
|
|
|
"Xbox",
|
|
|
|
|
"d3d,opengl",
|
|
|
|
|
600,400,
|
|
|
|
|
32,32,32,
|
|
|
|
|
2048,
|
|
|
|
|
true
|
|
|
|
|
},
|
2003-12-20 21:23:29 +00:00
|
|
|
{
|
2004-01-01 02:25:18 +00:00
|
|
|
"Voodoo *5",
|
2004-02-17 22:29:59 +00:00
|
|
|
"d3d,opengl", // received 3 reports of opengl crashing. -Chris
|
2003-12-20 21:23:29 +00:00
|
|
|
640,480,
|
|
|
|
|
32,32,32,
|
|
|
|
|
2048,
|
|
|
|
|
true // accelerated
|
|
|
|
|
},
|
2004-01-17 23:17:08 +00:00
|
|
|
{
|
2004-03-26 02:59:40 +00:00
|
|
|
"Voodoo|3dfx", /* all other Voodoos: some drivers don't identify which one */
|
2004-01-17 23:17:08 +00:00
|
|
|
"d3d,opengl",
|
|
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
|
|
|
|
256,
|
|
|
|
|
false // broken, causes black screen
|
|
|
|
|
},
|
2003-10-07 08:18:28 +00:00
|
|
|
{
|
2004-02-27 01:13:08 +00:00
|
|
|
"Radeon.* 7|Wonder 7500|ArcadeVGA", // Radeon 7xxx, RADEON Mobility 7500
|
2003-11-29 11:17:53 +00:00
|
|
|
"d3d,opengl", // movie texture performance is terrible in OpenGL, but fine in D3D.
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
true // accelerated
|
2003-10-07 08:18:28 +00:00
|
|
|
},
|
2003-10-02 04:35:29 +00:00
|
|
|
{
|
2003-12-02 18:11:14 +00:00
|
|
|
"GeForce|Radeon|Wonder 9",
|
2003-10-02 04:35:29 +00:00
|
|
|
"opengl,d3d",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
32,32,32, // 32 bit textures are faster to load
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
true // hardware accelerated
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"TNT|Vanta|M64",
|
|
|
|
|
"opengl,d3d",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
2003-10-08 03:58:16 +00:00
|
|
|
16,16,16, // Athlon 1.2+TNT demonstration w/ movies: 70fps w/ 32bit textures, 86fps w/ 16bit textures
|
|
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
true // hardware accelerated
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"G200|G250|G400",
|
|
|
|
|
"d3d,opengl",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
false // broken, causes black screen
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Savage",
|
|
|
|
|
"d3d",
|
|
|
|
|
// OpenGL is unusable on my Savage IV with even the latest drivers.
|
|
|
|
|
// It draws 30 frames of gibberish then crashes. This happens even with
|
|
|
|
|
// simple NeHe demos. -Chris
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-10-02 04:35:29 +00:00
|
|
|
false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"XPERT@PLAY|IIC|RAGE PRO|RAGE LT PRO", // Rage Pro chip, Rage IIC chip
|
|
|
|
|
"d3d",
|
|
|
|
|
// OpenGL is not hardware accelerated, despite the fact that the
|
|
|
|
|
// drivers come with an ICD. Also, the WinXP driver performance
|
|
|
|
|
// is terrible and supports only 640. The ATI driver is usable.
|
|
|
|
|
// -Chris
|
2003-10-08 07:13:21 +00:00
|
|
|
320,240, // lower resolution for 60fps. In-box WinXP driver doesn't support 400x300.
|
2003-10-07 08:18:28 +00:00
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
256,
|
2003-11-29 18:02:31 +00:00
|
|
|
false
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"RAGE MOBILITY-M1",
|
|
|
|
|
"d3d,opengl", // Vertex alpha is broken in OpenGL, but not D3D. -Chris
|
2003-10-07 08:18:28 +00:00
|
|
|
400,300, // lower resolution for 60fps
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
256,
|
2003-11-29 18:02:31 +00:00
|
|
|
false
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Intel.*82810|Intel.*82815",
|
|
|
|
|
"opengl,d3d",// OpenGL is 50%+ faster than D3D w/ latest Intel drivers. -Chris
|
2003-10-07 08:18:28 +00:00
|
|
|
512,384, // lower resolution for 60fps
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
512,
|
2003-11-29 18:02:31 +00:00
|
|
|
false
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
2003-11-15 06:05:58 +00:00
|
|
|
{
|
|
|
|
|
"Intel*Extreme Graphics",
|
|
|
|
|
"d3d", // OpenGL blue screens w/ XP drivers from 6-21-2002
|
|
|
|
|
640,480,
|
|
|
|
|
16,16,16, // slow at 32bpp
|
|
|
|
|
1024,
|
2003-11-29 18:02:31 +00:00
|
|
|
false
|
2003-11-15 06:05:58 +00:00
|
|
|
},
|
2004-02-27 01:13:08 +00:00
|
|
|
{
|
|
|
|
|
"Intel.*", /* fallback: all unknown Intel cards to D3D, since Intel is notoriously bad at OpenGL */
|
|
|
|
|
"d3d,opengl",
|
|
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
|
|
|
|
1024,
|
|
|
|
|
false
|
|
|
|
|
},
|
2003-10-02 04:35:29 +00:00
|
|
|
{
|
|
|
|
|
// Cards that have problems with OpenGL:
|
|
|
|
|
// ASSERT fail somewhere in RageDisplay_OpenGL "Trident Video Accelerator CyberBlade"
|
|
|
|
|
// bug 764499: ASSERT fail after glDeleteTextures for "SiS 650_651_740"
|
|
|
|
|
// bug 764830: ASSERT fail after glDeleteTextures for "VIA Tech VT8361/VT8601 Graphics Controller"
|
|
|
|
|
// bug 791950: AV in glsis630!DrvSwapBuffers for "SiS 630/730"
|
|
|
|
|
"Trident Video Accelerator CyberBlade|VIA.*VT|SiS 6*",
|
|
|
|
|
"d3d,opengl",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
false
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"OpenGL", // This matches all drivers in Mac and Linux. -Chris
|
|
|
|
|
"opengl",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
true // Right now, they've got to have NVidia or ATi Cards anyway..
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
// Default graphics settings used for all cards that don't match above.
|
|
|
|
|
// This must be the very last entry!
|
|
|
|
|
"",
|
|
|
|
|
"opengl,d3d",
|
2003-10-07 08:18:28 +00:00
|
|
|
640,480,
|
|
|
|
|
16,16,16,
|
2003-10-08 03:58:16 +00:00
|
|
|
2048,
|
2003-11-29 18:02:31 +00:00
|
|
|
false // AA is slow on some cards, so let's selectively enable HW accelerated cards.
|
2003-10-02 04:35:29 +00:00
|
|
|
},
|
|
|
|
|
};
|
2003-08-28 04:38:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static CString GetVideoDriverName()
|
|
|
|
|
{
|
|
|
|
|
#if defined(_WINDOWS)
|
|
|
|
|
return GetPrimaryVideoDriverName();
|
2003-12-02 18:11:14 +00:00
|
|
|
#elif defined(_XBOX)
|
|
|
|
|
return "Xbox";
|
2003-08-28 04:38:01 +00:00
|
|
|
#else
|
|
|
|
|
return "OpenGL";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void CheckVideoDefaultSettings()
|
|
|
|
|
{
|
|
|
|
|
// Video card changed since last run
|
|
|
|
|
CString sVideoDriver = GetVideoDriverName();
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "Last seen video driver: " + PREFSMAN->m_sLastSeenVideoDriver );
|
|
|
|
|
|
2003-10-02 04:35:29 +00:00
|
|
|
const VideoCardDefaults* pDefaults = NULL;
|
|
|
|
|
|
2003-10-07 06:39:16 +00:00
|
|
|
for( unsigned i=0; i<ARRAYSIZE(g_VideoCardDefaults); i++ )
|
2003-10-02 04:35:29 +00:00
|
|
|
{
|
|
|
|
|
pDefaults = &g_VideoCardDefaults[i];
|
|
|
|
|
|
|
|
|
|
CString sDriverRegex = pDefaults->szDriverRegex;
|
|
|
|
|
Regex regex( sDriverRegex );
|
|
|
|
|
if( regex.Compare(sVideoDriver) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Card matches '%s'.", sDriverRegex.size()? sDriverRegex.c_str():"(unknown card)" );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-08-28 04:38:01 +00:00
|
|
|
|
2003-10-02 04:35:29 +00:00
|
|
|
ASSERT( pDefaults ); // we must have matched at least one
|
2003-08-28 04:38:01 +00:00
|
|
|
|
2003-10-02 04:35:29 +00:00
|
|
|
CString sVideoRenderers = pDefaults->szVideoRenderers;
|
2003-08-28 04:38:01 +00:00
|
|
|
|
|
|
|
|
bool SetDefaultVideoParams=false;
|
|
|
|
|
if( PREFSMAN->m_sVideoRenderers == "" )
|
|
|
|
|
{
|
2003-10-02 04:35:29 +00:00
|
|
|
SetDefaultVideoParams = true;
|
2003-09-25 00:55:00 +00:00
|
|
|
LOG->Trace( "Applying defaults for %s.", sVideoDriver.c_str() );
|
2003-10-02 04:35:29 +00:00
|
|
|
}
|
|
|
|
|
else if( PREFSMAN->m_sLastSeenVideoDriver != sVideoDriver )
|
|
|
|
|
{
|
|
|
|
|
SetDefaultVideoParams = true;
|
2003-08-28 04:38:01 +00:00
|
|
|
LOG->Trace( "Video card has changed from %s to %s. Applying new defaults.", PREFSMAN->m_sLastSeenVideoDriver.c_str(), sVideoDriver.c_str() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( SetDefaultVideoParams )
|
|
|
|
|
{
|
2003-10-02 04:35:29 +00:00
|
|
|
PREFSMAN->m_sVideoRenderers = pDefaults->szVideoRenderers;
|
|
|
|
|
PREFSMAN->m_iDisplayWidth = pDefaults->iWidth;
|
|
|
|
|
PREFSMAN->m_iDisplayHeight = pDefaults->iHeight;
|
|
|
|
|
PREFSMAN->m_iDisplayColorDepth = pDefaults->iDisplayColor;
|
|
|
|
|
PREFSMAN->m_iTextureColorDepth = pDefaults->iTextureColor;
|
2003-10-07 08:18:28 +00:00
|
|
|
PREFSMAN->m_iMovieColorDepth = pDefaults->iMovieColor;
|
2003-10-08 03:58:16 +00:00
|
|
|
PREFSMAN->m_iMaxTextureResolution = pDefaults->iTextureSize;
|
2003-12-20 21:29:55 +00:00
|
|
|
PREFSMAN->m_bSmoothLines = pDefaults->bSmoothLines;
|
2003-08-28 04:38:01 +00:00
|
|
|
|
|
|
|
|
// Update last seen video card
|
|
|
|
|
PREFSMAN->m_sLastSeenVideoDriver = GetVideoDriverName();
|
2003-10-02 04:35:29 +00:00
|
|
|
}
|
|
|
|
|
else if( PREFSMAN->m_sVideoRenderers.CompareNoCase(sVideoRenderers) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn("Video renderer list has been changed from '%s' to '%s'",
|
2003-08-28 04:38:01 +00:00
|
|
|
sVideoRenderers.c_str(), PREFSMAN->m_sVideoRenderers.c_str() );
|
2004-02-27 09:54:06 +00:00
|
|
|
return;
|
2003-08-28 04:38:01 +00:00
|
|
|
}
|
2004-02-27 09:54:06 +00:00
|
|
|
|
|
|
|
|
LOG->Info( "Video renderers: '%s'", PREFSMAN->m_sVideoRenderers.c_str() );
|
2003-08-28 04:38:01 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 23:33:37 +00:00
|
|
|
RageDisplay *CreateDisplay()
|
|
|
|
|
{
|
|
|
|
|
/* We never want to bother users with having to decide which API to use.
|
|
|
|
|
*
|
|
|
|
|
* Some cards simply are too troublesome with OpenGL to ever use it, eg. Voodoos.
|
|
|
|
|
* If D3D8 isn't installed on those, complain and refuse to run (by default).
|
|
|
|
|
* For others, always use OpenGL. Allow forcing to D3D as an advanced option.
|
|
|
|
|
*
|
|
|
|
|
* If we're missing acceleration when we load D3D8 due to a card being in the
|
|
|
|
|
* D3D list, it means we need drivers and that they do exist.
|
|
|
|
|
*
|
|
|
|
|
* If we try to load OpenGL and we're missing acceleration, it may mean:
|
|
|
|
|
* 1. We're missing drivers, and they just need upgrading.
|
|
|
|
|
* 2. The card doesn't have drivers, and it should be using D3D8. In other words,
|
|
|
|
|
* it needs an entry in this table.
|
|
|
|
|
* 3. The card doesn't have drivers for either. (Sorry, no S3 868s.) Can't play.
|
|
|
|
|
*
|
|
|
|
|
* In this case, fail to load; don't silently fall back on D3D. We don't want
|
|
|
|
|
* people unknowingly using D3D8 with old drivers (and reporting obscure bugs
|
|
|
|
|
* due to driver problems). We'll probably get bug reports for all three types.
|
|
|
|
|
* #2 is the only case that's actually a bug.
|
|
|
|
|
*
|
2003-05-28 05:58:24 +00:00
|
|
|
* Actually, right now we're falling back. I'm not sure which behavior is better.
|
2003-05-26 23:33:37 +00:00
|
|
|
*/
|
2003-05-31 21:34:07 +00:00
|
|
|
|
2003-08-28 04:38:01 +00:00
|
|
|
CheckVideoDefaultSettings();
|
2003-05-27 01:03:21 +00:00
|
|
|
|
2003-08-12 18:50:42 +00:00
|
|
|
RageDisplay::VideoModeParams params(GetCurVideoModeParams());
|
2003-06-05 19:29:27 +00:00
|
|
|
|
2003-05-31 21:34:07 +00:00
|
|
|
CString error = "There was an error while initializing your video card.\n\n"
|
|
|
|
|
" PLEASE DO NOT FILE THIS ERROR AS A BUG!\n\n"
|
2003-08-28 04:38:01 +00:00
|
|
|
"Video Driver: "+GetVideoDriverName()+"\n\n";
|
2003-05-28 05:58:24 +00:00
|
|
|
|
2003-05-31 21:34:07 +00:00
|
|
|
CStringArray asRenderers;
|
|
|
|
|
split( PREFSMAN->m_sVideoRenderers, ",", asRenderers, true );
|
2003-06-12 01:35:54 +00:00
|
|
|
|
|
|
|
|
if( asRenderers.empty() )
|
|
|
|
|
RageException::Throw("No video renderers attempted.");
|
|
|
|
|
|
2003-06-01 00:34:15 +00:00
|
|
|
for( unsigned i=0; i<asRenderers.size(); i++ )
|
2003-05-26 23:33:37 +00:00
|
|
|
{
|
2003-05-31 21:34:07 +00:00
|
|
|
CString sRenderer = asRenderers[i];
|
|
|
|
|
|
|
|
|
|
if( sRenderer.CompareNoCase("opengl")==0 )
|
|
|
|
|
{
|
2003-07-23 21:20:12 +00:00
|
|
|
#if defined(SUPPORT_OPENGL)
|
2003-05-31 21:34:07 +00:00
|
|
|
error += "Initializing OpenGL...\n";
|
2003-06-25 20:44:49 +00:00
|
|
|
try {
|
|
|
|
|
return new RageDisplay_OGL( params, PREFSMAN->m_bAllowUnacceleratedRenderer );
|
|
|
|
|
} catch(RageException e) {
|
|
|
|
|
error += CString(e.what()) + "\n";
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2003-06-05 19:29:27 +00:00
|
|
|
#endif
|
2003-05-31 21:34:07 +00:00
|
|
|
}
|
|
|
|
|
else if( sRenderer.CompareNoCase("d3d")==0 )
|
|
|
|
|
{
|
2003-07-23 21:20:12 +00:00
|
|
|
#if defined(SUPPORT_D3D)
|
2003-05-31 21:34:07 +00:00
|
|
|
error += "Initializing Direct3D...\n";
|
|
|
|
|
try {
|
2003-06-05 19:29:27 +00:00
|
|
|
return new RageDisplay_D3D( params );
|
2003-07-23 20:19:22 +00:00
|
|
|
} catch( const exception &e ) {
|
2003-06-25 20:44:49 +00:00
|
|
|
error += CString(e.what()) + "\n";
|
2003-05-31 21:34:07 +00:00
|
|
|
};
|
2003-06-05 19:29:27 +00:00
|
|
|
#endif
|
2003-05-31 21:34:07 +00:00
|
|
|
}
|
2004-03-24 08:31:29 +00:00
|
|
|
else if( sRenderer.CompareNoCase("null")==0 )
|
2004-03-25 02:59:01 +00:00
|
|
|
return new RageDisplay_Null( params );
|
2003-05-31 21:34:07 +00:00
|
|
|
else
|
|
|
|
|
RageException::Throw("Unknown video renderer value: %s", sRenderer.c_str() );
|
2003-05-26 23:33:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-28 05:58:24 +00:00
|
|
|
RageException::Throw( error );
|
2003-05-26 19:42:04 +00:00
|
|
|
}
|
|
|
|
|
|
2003-09-21 07:00:01 +00:00
|
|
|
static void CheckSDLVersion( int major, int minor, int patch )
|
|
|
|
|
{
|
|
|
|
|
const SDL_version *ver = SDL_Linked_Version();
|
|
|
|
|
if( ver->major > major ||
|
|
|
|
|
(ver->major == major && ver->minor > minor) ||
|
|
|
|
|
(ver->major == major && ver->minor == minor && ver->patch >= patch))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
RageException::Throw( "SDL %i.%i.%i is required, but you only appear to "
|
|
|
|
|
"have SDL %i.%i.%i installed. Please upgrade your installation of SDL or download "
|
|
|
|
|
"it from:\n\n\thttp://www.libsdl.org/",
|
|
|
|
|
major, minor, patch, ver->major, ver->minor, ver->patch );
|
|
|
|
|
}
|
2003-05-26 23:33:37 +00:00
|
|
|
|
2003-01-19 11:00:53 +00:00
|
|
|
static void RestoreAppPri()
|
|
|
|
|
{
|
|
|
|
|
if(!ChangeAppPri())
|
|
|
|
|
return;
|
|
|
|
|
|
2003-07-11 03:15:28 +00:00
|
|
|
#ifdef _WINDOWS
|
2003-01-19 11:00:53 +00:00
|
|
|
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
2003-02-15 00:11:12 +00:00
|
|
|
#endif
|
2003-01-19 11:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2003-12-10 09:02:55 +00:00
|
|
|
#define GAMEPREFS_INI_PATH "Data/GamePrefs.ini"
|
|
|
|
|
#define STATIC_INI_PATH "Data/Static.ini"
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2003-10-02 03:06:20 +00:00
|
|
|
void ChangeCurrentGame( Game g )
|
|
|
|
|
{
|
2004-01-14 08:05:19 +00:00
|
|
|
ASSERT( g >= 0 && g < NUM_GAMES );
|
|
|
|
|
|
2003-10-02 03:06:20 +00:00
|
|
|
SaveGamePrefsToDisk();
|
|
|
|
|
INPUTMAPPER->SaveMappingsToDisk(); // save mappings before switching the game
|
|
|
|
|
|
|
|
|
|
GAMESTATE->m_CurGame = g;
|
|
|
|
|
|
|
|
|
|
ReadGamePrefsFromDisk( false );
|
|
|
|
|
INPUTMAPPER->ReadMappingsFromDisk();
|
|
|
|
|
|
|
|
|
|
/* Save the newly-selected game. */
|
|
|
|
|
SaveGamePrefsToDisk();
|
|
|
|
|
}
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2003-10-02 03:06:20 +00:00
|
|
|
void ReadGamePrefsFromDisk( bool bSwitchToLastPlayedGame )
|
2003-10-02 01:39:23 +00:00
|
|
|
{
|
2003-10-10 03:17:08 +00:00
|
|
|
ASSERT( GAMESTATE );
|
|
|
|
|
ASSERT( ANNOUNCER );
|
|
|
|
|
ASSERT( THEME );
|
2003-10-02 01:39:23 +00:00
|
|
|
|
|
|
|
|
CString sGameName = GAMESTATE->GetCurrentGameDef()->m_szName;
|
|
|
|
|
IniFile ini;
|
2004-05-23 02:27:51 +00:00
|
|
|
ini.ReadFile( GAMEPREFS_INI_PATH ); // it's OK if this fails
|
|
|
|
|
ini.ReadFile( STATIC_INI_PATH ); // it's OK if this fails, too
|
2003-10-08 08:06:42 +00:00
|
|
|
|
2003-10-02 01:39:23 +00:00
|
|
|
CString sAnnouncer = sGameName, sTheme = sGameName, sNoteSkin = sGameName;
|
|
|
|
|
|
|
|
|
|
// if these calls fail, the three strings will keep the initial values set above.
|
|
|
|
|
ini.GetValue( sGameName, "Announcer", sAnnouncer );
|
|
|
|
|
ini.GetValue( sGameName, "Theme", sTheme );
|
|
|
|
|
ini.GetValue( sGameName, "DefaultModifiers", PREFSMAN->m_sDefaultModifiers );
|
|
|
|
|
|
|
|
|
|
// it's OK to call these functions with names that don't exist.
|
|
|
|
|
ANNOUNCER->SwitchAnnouncer( sAnnouncer );
|
|
|
|
|
THEME->SwitchThemeAndLanguage( sTheme, PREFSMAN->m_sLanguage );
|
|
|
|
|
|
|
|
|
|
// NOTESKIN->SwitchNoteSkin( sNoteSkin );
|
2003-10-02 03:06:20 +00:00
|
|
|
|
|
|
|
|
if( bSwitchToLastPlayedGame )
|
|
|
|
|
{
|
2004-04-19 23:34:11 +00:00
|
|
|
CString sGame;
|
|
|
|
|
if( ini.GetValue("Options", "Game", sGame) )
|
2004-01-14 08:05:19 +00:00
|
|
|
{
|
2004-04-19 23:34:11 +00:00
|
|
|
GAMESTATE->m_CurGame = GAMEMAN->StringToGameType( sGame );
|
|
|
|
|
if( GAMESTATE->m_CurGame == GAME_INVALID )
|
|
|
|
|
GAMESTATE->m_CurGame = (Game)0;
|
2004-01-14 08:05:19 +00:00
|
|
|
}
|
2003-10-02 03:06:20 +00:00
|
|
|
}
|
2003-10-02 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
2003-10-02 03:06:20 +00:00
|
|
|
|
2003-10-02 01:39:23 +00:00
|
|
|
void SaveGamePrefsToDisk()
|
|
|
|
|
{
|
|
|
|
|
if( !GAMESTATE )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CString sGameName = GAMESTATE->GetCurrentGameDef()->m_szName;
|
|
|
|
|
IniFile ini;
|
2004-05-23 02:27:51 +00:00
|
|
|
ini.ReadFile( GAMEPREFS_INI_PATH ); // it's OK if this fails
|
2003-10-02 01:39:23 +00:00
|
|
|
|
|
|
|
|
ini.SetValue( sGameName, "Announcer", ANNOUNCER->GetCurAnnouncerName() );
|
|
|
|
|
ini.SetValue( sGameName, "Theme", THEME->GetCurThemeName() );
|
|
|
|
|
ini.SetValue( sGameName, "DefaultModifiers", PREFSMAN->m_sDefaultModifiers );
|
2004-04-19 23:34:11 +00:00
|
|
|
ini.SetValue( "Options", "Game", (CString)GAMESTATE->GetCurrentGameDef()->m_szName );
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2004-05-23 02:27:51 +00:00
|
|
|
ini.WriteFile( GAMEPREFS_INI_PATH );
|
2003-10-02 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-14 20:47:50 +00:00
|
|
|
static void OnFirstRun()
|
|
|
|
|
{
|
|
|
|
|
// TODO: generate a machine keypair here
|
|
|
|
|
}
|
|
|
|
|
|
2003-12-10 08:55:20 +00:00
|
|
|
static void MountTreeOfZips( const CString &dir )
|
|
|
|
|
{
|
|
|
|
|
vector<CString> dirs;
|
|
|
|
|
dirs.push_back( dir );
|
|
|
|
|
|
|
|
|
|
while( dirs.size() )
|
|
|
|
|
{
|
|
|
|
|
CString path = dirs.back();
|
|
|
|
|
dirs.pop_back();
|
|
|
|
|
|
|
|
|
|
if( !IsADirectory(path) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
vector<CString> zips;
|
|
|
|
|
GetDirListing( path + "/*.zip", zips, false, true );
|
|
|
|
|
GetDirListing( path + "/*.smzip", zips, false, true );
|
|
|
|
|
|
|
|
|
|
for( unsigned i = 0; i < zips.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if( !IsAFile(zips[i]) )
|
|
|
|
|
continue;
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2003-12-10 08:55:20 +00:00
|
|
|
LOG->Trace( "VFS: found %s", zips[i].c_str() );
|
|
|
|
|
FILEMAN->Mount( "zip", zips[i], "" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetDirListing( path + "/*", dirs, true, true );
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-10-02 01:39:23 +00:00
|
|
|
|
2003-11-13 00:39:36 +00:00
|
|
|
#ifdef _XBOX
|
2004-02-01 01:11:41 +00:00
|
|
|
/*
|
|
|
|
|
extern int SDL_main(int argc, char *argv[]);
|
|
|
|
|
|
|
|
|
|
void __cdecl main()
|
|
|
|
|
{
|
|
|
|
|
SDL_main(0, NULL);
|
|
|
|
|
}
|
|
|
|
|
*/
|
2003-11-25 22:56:48 +00:00
|
|
|
char *xboxargv[] = { "d:\\default.xbe" };
|
2003-11-13 00:39:36 +00:00
|
|
|
extern RageDisplay::VideoModeParams g_CurrentParams;
|
2004-02-01 01:11:41 +00:00
|
|
|
/*
|
|
|
|
|
void __cdecl main()
|
|
|
|
|
{
|
|
|
|
|
main(0, xboxargv);
|
|
|
|
|
}
|
|
|
|
|
*/
|
2003-11-13 00:39:36 +00:00
|
|
|
#endif
|
2003-07-22 07:47:27 +00:00
|
|
|
|
2004-03-04 04:27:55 +00:00
|
|
|
#if defined(HAVE_VERSION_INFO)
|
|
|
|
|
extern unsigned long version_num;
|
|
|
|
|
extern const char *version_time;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void WriteLogHeader()
|
|
|
|
|
{
|
|
|
|
|
LOG->Info( PRODUCT_NAME_VER );
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_VERSION_INFO)
|
|
|
|
|
LOG->Info( "Compiled %s (build %lu)", version_time, version_num );
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
time_t cur_time;
|
|
|
|
|
time(&cur_time);
|
|
|
|
|
struct tm now;
|
|
|
|
|
localtime_r( &cur_time, &now );
|
|
|
|
|
|
|
|
|
|
LOG->Info( "Log starting %.4d-%.2d-%.2d %.2d:%.2d:%.2d",
|
|
|
|
|
1900+now.tm_year, now.tm_mon+1, now.tm_mday, now.tm_hour+1, now.tm_min, now.tm_sec );
|
|
|
|
|
LOG->Trace( " " );
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-25 08:25:30 +00:00
|
|
|
static void ApplyLogPreferences()
|
|
|
|
|
{
|
|
|
|
|
LOG->SetShowLogOutput( PREFSMAN->m_bShowLogOutput );
|
|
|
|
|
LOG->SetLogToDisk( PREFSMAN->m_bLogToDisk );
|
|
|
|
|
LOG->SetInfoToDisk( true );
|
|
|
|
|
LOG->SetFlushing( PREFSMAN->m_bForceLogFlush );
|
|
|
|
|
Checkpoints::LogCheckpoints( PREFSMAN->m_bLogCheckpoints );
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
/* Search for the commandline argument given; eg. "test" searches for
|
|
|
|
|
* the option "--test". All commandline arguments are getopt_long style:
|
|
|
|
|
* --foo; short arguments (-x) are not supported. (As commandline arguments
|
|
|
|
|
* are not intended for common, general use, having short options isn't
|
|
|
|
|
* needed.) If argument is non-NULL, accept an argument. */
|
2004-04-30 07:24:29 +00:00
|
|
|
bool GetCommandlineArgument( const CString &option, CString *argument, int iIndex )
|
2004-04-15 19:31:45 +00:00
|
|
|
{
|
2004-04-15 20:10:40 +00:00
|
|
|
const CString optstr = "--" + option;
|
|
|
|
|
|
|
|
|
|
for( int arg = 1; arg < g_argc; ++arg )
|
2004-04-15 19:31:45 +00:00
|
|
|
{
|
2004-04-15 20:10:40 +00:00
|
|
|
const CString CurArgument = g_argv[arg];
|
2004-04-15 19:31:45 +00:00
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
const unsigned i = CurArgument.find( "=" );
|
|
|
|
|
CString CurOption = CurArgument.substr(0,i);
|
|
|
|
|
if( CurOption.CompareNoCase(optstr) )
|
|
|
|
|
continue; /* no match */
|
2004-04-15 19:31:45 +00:00
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
/* Found it. */
|
2004-04-30 07:24:29 +00:00
|
|
|
if( iIndex )
|
|
|
|
|
{
|
|
|
|
|
--iIndex;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
if( argument )
|
|
|
|
|
{
|
|
|
|
|
if( i != CString::npos )
|
|
|
|
|
*argument = CurArgument.substr( i+1 );
|
|
|
|
|
else
|
|
|
|
|
*argument = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2004-04-15 19:31:45 +00:00
|
|
|
}
|
2004-04-15 20:10:40 +00:00
|
|
|
|
|
|
|
|
return false;
|
2004-04-15 19:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
//Process args first, put command line options that
|
|
|
|
|
//have to run before the SM window loads here
|
|
|
|
|
static void ProcessArgsFirst()
|
2004-04-15 19:31:45 +00:00
|
|
|
{
|
2004-04-15 20:10:40 +00:00
|
|
|
CString Argument;
|
|
|
|
|
if( GetCommandlineArgument( "test", &Argument ) )
|
|
|
|
|
LOG->Info ("Test: \"%s\"", Argument.c_str() );
|
2004-04-17 22:26:37 +00:00
|
|
|
|
|
|
|
|
//--LogSongs
|
|
|
|
|
if( GetCommandlineArgument( "sendsongs" ) )
|
|
|
|
|
NSMAN->SendSongs();
|
2004-04-15 20:10:40 +00:00
|
|
|
}
|
2004-04-15 19:31:45 +00:00
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
static void ProcessArgsSecond()
|
|
|
|
|
{
|
2004-04-17 22:26:37 +00:00
|
|
|
CString Argument;
|
2004-04-15 20:10:40 +00:00
|
|
|
if( GetCommandlineArgument( "test2" ) )
|
2004-04-17 22:26:37 +00:00
|
|
|
LOG->Info ("Test2");
|
|
|
|
|
|
2004-04-29 01:03:28 +00:00
|
|
|
if( GetCommandlineArgument( "netip" ) )
|
|
|
|
|
NSMAN->DisplayStartupStatus(); //If we're using networking show what happend
|
2004-04-15 19:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-11 04:53:31 +00:00
|
|
|
int main(int argc, char* argv[])
|
|
|
|
|
{
|
2003-11-13 00:39:36 +00:00
|
|
|
#ifdef _XBOX
|
2003-11-25 22:56:48 +00:00
|
|
|
argc = 1;
|
|
|
|
|
argv = xboxargv;
|
|
|
|
|
XGetCustomLaunchData();
|
2003-11-13 00:39:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-07-12 19:51:40 +00:00
|
|
|
g_argc = argc;
|
|
|
|
|
g_argv = argv;
|
|
|
|
|
|
2003-01-24 23:09:31 +00:00
|
|
|
/* Set up arch hooks first. This may set up crash handling. */
|
|
|
|
|
HOOKS = MakeArchHooks();
|
|
|
|
|
|
2003-08-05 01:28:11 +00:00
|
|
|
CString g_sErrorString = "";
|
|
|
|
|
|
2004-01-04 03:28:00 +00:00
|
|
|
#if !defined(DEBUG)
|
|
|
|
|
/* Always catch RageExceptions; they should always have distinct strings. */
|
2003-12-21 09:14:05 +00:00
|
|
|
try { /* RageException */
|
2004-01-04 03:28:00 +00:00
|
|
|
|
|
|
|
|
/* Tricky: for other exceptions, we want a backtrace. To do this in Windows,
|
|
|
|
|
* we need to catch the exception and force a crash. The call stack is still
|
|
|
|
|
* there, and gets picked up by the crash handler. (If we don't catch it, we'll
|
2004-04-10 21:00:38 +00:00
|
|
|
* get a generic, useless "abnormal termination" dialog.) In Linux, if we do this
|
2004-01-04 03:28:00 +00:00
|
|
|
* we'll only get main() on the stack, but if we don't catch the exception, it'll
|
2004-02-13 22:25:08 +00:00
|
|
|
* just work. So, only catch generic exceptions in Windows. */
|
2004-01-04 03:28:00 +00:00
|
|
|
#if defined(_WINDOWS)
|
2003-12-21 09:14:05 +00:00
|
|
|
try { /* exception */
|
2004-01-04 03:28:00 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-08-05 01:28:11 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-12-12 08:22:03 +00:00
|
|
|
/* Almost everything uses this to read and write files. Load this early. */
|
2004-03-04 00:19:42 +00:00
|
|
|
FILEMAN = new RageFileManager( argv[0] );
|
2004-03-04 01:16:52 +00:00
|
|
|
FILEMAN->MountInitialFilesystems();
|
2003-12-12 08:22:03 +00:00
|
|
|
|
2004-03-04 00:19:42 +00:00
|
|
|
/* Set this up next. Do this early, since it's needed for RageException::Throw. */
|
2003-01-27 01:05:19 +00:00
|
|
|
LOG = new RageLog();
|
2003-04-25 05:43:48 +00:00
|
|
|
|
2003-01-27 01:05:19 +00:00
|
|
|
/* Whew--we should be able to crash safely now! */
|
|
|
|
|
|
2004-02-19 08:45:17 +00:00
|
|
|
//
|
|
|
|
|
// load preferences and mount any alternative trees.
|
|
|
|
|
//
|
|
|
|
|
PREFSMAN = new PrefsManager;
|
|
|
|
|
|
2004-03-25 08:25:30 +00:00
|
|
|
ApplyLogPreferences();
|
2004-03-04 22:25:30 +00:00
|
|
|
|
|
|
|
|
WriteLogHeader();
|
|
|
|
|
|
2004-02-19 08:45:17 +00:00
|
|
|
/* Set up alternative filesystem trees. */
|
|
|
|
|
if( PREFSMAN->m_sAdditionalFolders != "" )
|
|
|
|
|
{
|
|
|
|
|
CStringArray dirs;
|
|
|
|
|
split( PREFSMAN->m_sAdditionalFolders, ",", dirs, true );
|
|
|
|
|
for( unsigned i=0; i < dirs.size(); i++)
|
|
|
|
|
FILEMAN->Mount( "dir", dirs[i], "" );
|
|
|
|
|
}
|
|
|
|
|
if( PREFSMAN->m_sAdditionalSongFolders != "" )
|
|
|
|
|
{
|
|
|
|
|
CStringArray dirs;
|
|
|
|
|
split( PREFSMAN->m_sAdditionalSongFolders, ",", dirs, true );
|
|
|
|
|
for( unsigned i=0; i < dirs.size(); i++)
|
|
|
|
|
FILEMAN->Mount( "dir", dirs[i], "Songs" );
|
|
|
|
|
}
|
2003-12-10 08:55:20 +00:00
|
|
|
MountTreeOfZips( ZIPS_DIR );
|
|
|
|
|
|
2004-03-25 08:25:30 +00:00
|
|
|
/* One of the above filesystems might contain files that affect preferences, eg Data/Static.ini.
|
|
|
|
|
* Re-read preferences. */
|
|
|
|
|
PREFSMAN->ReadGlobalPrefsFromDisk();
|
|
|
|
|
ApplyLogPreferences();
|
|
|
|
|
|
2003-01-27 01:05:19 +00:00
|
|
|
atexit(SDL_Quit); /* Clean up on exit */
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-04-25 05:43:48 +00:00
|
|
|
/* Fire up the SDL, but don't actually start any subsystems.
|
|
|
|
|
* We use our own error handlers. */
|
2003-09-16 02:38:18 +00:00
|
|
|
SDL_Init( SDL_INIT_NOPARACHUTE );
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2002-03-19 07:09:49 +00:00
|
|
|
//
|
2002-01-24 08:01:24 +00:00
|
|
|
// Create game objects
|
2002-03-19 07:09:49 +00:00
|
|
|
//
|
2002-07-23 01:41:40 +00:00
|
|
|
GAMESTATE = new GameState;
|
2003-07-18 08:05:39 +00:00
|
|
|
|
2004-02-15 22:56:51 +00:00
|
|
|
/* This requires PREFSMAN, for PREFSMAN->m_bShowLoadingWindow. */
|
|
|
|
|
LoadingWindow *loading_window = MakeLoadingWindow();
|
|
|
|
|
if( loading_window == NULL )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace("Couldn't open any loading windows.");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading_window->Paint();
|
|
|
|
|
|
|
|
|
|
srand( time(NULL) ); // seed number generator
|
|
|
|
|
|
2003-09-21 07:00:01 +00:00
|
|
|
CheckSDLVersion( 1,2,6 );
|
|
|
|
|
|
2004-02-14 20:47:50 +00:00
|
|
|
if( PREFSMAN->m_bFirstRun )
|
|
|
|
|
OnFirstRun();
|
|
|
|
|
|
2003-08-14 23:02:55 +00:00
|
|
|
/* This should be done after PREFSMAN is set up, so it can use HOOKS->MessageBoxOK,
|
|
|
|
|
* but before we do more complex things that might crash. */
|
|
|
|
|
HOOKS->DumpDebugInfo();
|
|
|
|
|
|
2003-06-11 02:58:13 +00:00
|
|
|
CheckSettings();
|
|
|
|
|
|
2002-06-14 22:25:22 +00:00
|
|
|
GAMEMAN = new GameManager;
|
|
|
|
|
THEME = new ThemeManager;
|
2003-10-10 03:23:36 +00:00
|
|
|
ANNOUNCER = new AnnouncerManager;
|
|
|
|
|
|
|
|
|
|
/* Set up the theme and announcer. */
|
|
|
|
|
ReadGamePrefsFromDisk();
|
|
|
|
|
|
2003-02-06 07:32:57 +00:00
|
|
|
NOTESKIN = new NoteSkinManager;
|
2003-12-02 20:52:26 +00:00
|
|
|
if( PREFSMAN->m_iSoundWriteAhead )
|
|
|
|
|
LOG->Info( "Sound writeahead has been overridden to %i", PREFSMAN->m_iSoundWriteAhead );
|
2004-05-23 21:13:19 +00:00
|
|
|
SOUNDMAN = new RageSoundManager;
|
|
|
|
|
SOUNDMAN->Init( PREFSMAN->m_sSoundDrivers );
|
|
|
|
|
SOUNDMAN->SetPrefs( PREFSMAN->m_fSoundVolume );
|
2003-07-26 22:47:55 +00:00
|
|
|
SOUND = new RageSounds;
|
2003-10-13 08:33:39 +00:00
|
|
|
BOOKKEEPER = new Bookkeeper;
|
2003-11-16 04:45:12 +00:00
|
|
|
LIGHTSMAN = new LightsManager(PREFSMAN->m_sLightsDriver);
|
2002-11-11 04:53:31 +00:00
|
|
|
INPUTFILTER = new InputFilter;
|
|
|
|
|
INPUTMAPPER = new InputMapper;
|
|
|
|
|
INPUTQUEUE = new InputQueue;
|
|
|
|
|
SONGINDEX = new SongCacheIndex;
|
2003-06-04 22:42:17 +00:00
|
|
|
BANNERCACHE = new BannerCache;
|
2003-06-11 00:23:24 +00:00
|
|
|
|
2002-08-21 02:13:08 +00:00
|
|
|
/* depends on SONGINDEX: */
|
2002-11-17 09:13:35 +00:00
|
|
|
SONGMAN = new SongManager( loading_window ); // this takes a long time to load
|
2004-02-15 05:45:18 +00:00
|
|
|
CRYPTMAN = new CryptManager; // need to do this before ProfileMan
|
2003-12-15 07:35:40 +00:00
|
|
|
MEMCARDMAN = new MemoryCardManager;
|
2003-12-07 08:19:10 +00:00
|
|
|
PROFILEMAN = new ProfileManager; // must load after SONGMAN
|
2004-02-21 01:51:16 +00:00
|
|
|
UNLOCKMAN = new UnlockSystem;
|
2004-02-08 09:04:23 +00:00
|
|
|
MODELMAN = new ModelManager;
|
2002-11-17 09:13:35 +00:00
|
|
|
delete loading_window; // destroy this before init'ing Display
|
2004-03-17 06:05:52 +00:00
|
|
|
|
2004-04-15 15:31:59 +00:00
|
|
|
NSMAN = new NetworkSyncManager;
|
|
|
|
|
//Load Network Sync manager, but do not connect
|
|
|
|
|
|
2004-04-15 20:10:40 +00:00
|
|
|
ProcessArgsFirst();
|
2004-04-15 15:31:59 +00:00
|
|
|
|
|
|
|
|
|
2002-07-31 19:40:40 +00:00
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
DISPLAY = CreateDisplay();
|
2003-10-11 07:47:34 +00:00
|
|
|
|
|
|
|
|
DISPLAY->ChangeCentering(
|
|
|
|
|
PREFSMAN->m_iCenterImageTranslateX,
|
|
|
|
|
PREFSMAN->m_iCenterImageTranslateY,
|
|
|
|
|
PREFSMAN->m_fCenterImageScaleX,
|
|
|
|
|
PREFSMAN->m_fCenterImageScaleY );
|
|
|
|
|
|
2003-04-18 23:55:20 +00:00
|
|
|
TEXTUREMAN = new RageTextureManager();
|
|
|
|
|
TEXTUREMAN->SetPrefs(
|
|
|
|
|
PREFSMAN->m_iTextureColorDepth,
|
2003-07-09 02:28:56 +00:00
|
|
|
PREFSMAN->m_iMovieColorDepth,
|
2003-04-18 23:55:20 +00:00
|
|
|
PREFSMAN->m_bDelayedTextureDelete,
|
|
|
|
|
PREFSMAN->m_iMaxTextureResolution );
|
2002-03-30 20:00:13 +00:00
|
|
|
|
2003-09-15 07:52:58 +00:00
|
|
|
StoreActualGraphicOptions( true );
|
|
|
|
|
|
2003-04-12 16:06:06 +00:00
|
|
|
/* Now that we've started DISPLAY, we can set up event masks. */
|
2003-05-26 01:48:48 +00:00
|
|
|
mySDL_EventState(SDL_QUIT, SDL_ENABLE);
|
|
|
|
|
mySDL_EventState(SDL_ACTIVEEVENT, SDL_ENABLE);
|
2003-04-12 16:06:06 +00:00
|
|
|
|
2004-01-13 22:34:55 +00:00
|
|
|
UpdateHWnd();
|
2002-09-21 16:29:14 +00:00
|
|
|
|
2003-11-25 22:56:48 +00:00
|
|
|
SONGMAN->PreloadSongImages();
|
|
|
|
|
|
2003-04-12 16:06:06 +00:00
|
|
|
/* This initializes objects that change the SDL event mask, and has other
|
|
|
|
|
* dependencies on the SDL video subsystem, so it must be initialized after
|
|
|
|
|
* DISPLAY and setting the default SDL event mask. */
|
2003-04-25 05:43:48 +00:00
|
|
|
INPUTMAN = new RageInput;
|
2002-07-27 19:29:51 +00:00
|
|
|
|
2002-07-23 01:41:40 +00:00
|
|
|
// These things depend on the TextureManager, so do them after!
|
2002-05-28 20:01:22 +00:00
|
|
|
FONT = new FontManager;
|
|
|
|
|
SCREENMAN = new ScreenManager;
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-01-18 04:27:33 +00:00
|
|
|
/* People may want to do something else while songs are loading, so do
|
|
|
|
|
* this after loading songs. */
|
|
|
|
|
BoostAppPri();
|
|
|
|
|
|
2003-01-19 04:44:22 +00:00
|
|
|
ResetGame();
|
2002-11-08 08:17:59 +00:00
|
|
|
|
2004-02-12 09:44:16 +00:00
|
|
|
CodeDetector::RefreshCacheItems();
|
|
|
|
|
|
2003-08-04 09:18:26 +00:00
|
|
|
/* Initialize which courses are ranking courses here. */
|
|
|
|
|
SONGMAN->UpdateRankingCourses();
|
|
|
|
|
|
2004-04-15 15:31:59 +00:00
|
|
|
/* Run the second argcheck, you can do your other options here */
|
2004-04-15 20:10:40 +00:00
|
|
|
ProcessArgsSecond();
|
2004-04-15 15:31:59 +00:00
|
|
|
|
2002-11-14 23:54:40 +00:00
|
|
|
/* Run the main loop. */
|
|
|
|
|
GameLoop();
|
|
|
|
|
|
2002-12-09 22:31:21 +00:00
|
|
|
PREFSMAN->SaveGlobalPrefsToDisk();
|
2003-10-02 01:39:23 +00:00
|
|
|
SaveGamePrefsToDisk();
|
2002-12-09 22:31:21 +00:00
|
|
|
|
2003-02-15 05:15:24 +00:00
|
|
|
#ifndef DEBUG
|
2002-11-14 23:54:40 +00:00
|
|
|
}
|
2003-08-13 17:45:47 +00:00
|
|
|
catch( const RageException &e )
|
2002-11-14 23:54:40 +00:00
|
|
|
{
|
2003-12-21 09:14:05 +00:00
|
|
|
/* Gracefully shut down. */
|
2002-11-14 23:54:40 +00:00
|
|
|
g_sErrorString = e.what();
|
2003-09-22 23:37:33 +00:00
|
|
|
}
|
2002-11-14 23:54:40 +00:00
|
|
|
#endif
|
2001-12-19 14:56:22 +00:00
|
|
|
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( SCREENMAN );
|
2004-03-20 18:14:26 +00:00
|
|
|
SAFE_DELETE( NSMAN );
|
2003-07-14 06:23:15 +00:00
|
|
|
/* Delete INPUTMAN before the other INPUTFILTER handlers, or an input
|
|
|
|
|
* driver may try to send a message to INPUTFILTER after we delete it. */
|
|
|
|
|
SAFE_DELETE( INPUTMAN );
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( INPUTQUEUE );
|
|
|
|
|
SAFE_DELETE( INPUTMAPPER );
|
|
|
|
|
SAFE_DELETE( INPUTFILTER );
|
2004-02-08 09:04:23 +00:00
|
|
|
SAFE_DELETE( MODELMAN );
|
2003-12-07 07:09:13 +00:00
|
|
|
SAFE_DELETE( PROFILEMAN ); // PROFILEMAN needs the songs still loaded
|
2004-02-22 08:33:14 +00:00
|
|
|
SAFE_DELETE( UNLOCKMAN );
|
2004-02-15 05:45:18 +00:00
|
|
|
SAFE_DELETE( CRYPTMAN );
|
2003-12-15 07:35:40 +00:00
|
|
|
SAFE_DELETE( MEMCARDMAN );
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( SONGMAN );
|
2003-06-04 22:42:17 +00:00
|
|
|
SAFE_DELETE( BANNERCACHE );
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( SONGINDEX );
|
2004-05-08 21:11:02 +00:00
|
|
|
SAFE_DELETE( SOUND ); /* uses GAMESTATE, PREFSMAN */
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( PREFSMAN );
|
|
|
|
|
SAFE_DELETE( GAMESTATE );
|
|
|
|
|
SAFE_DELETE( GAMEMAN );
|
2003-02-06 07:32:57 +00:00
|
|
|
SAFE_DELETE( NOTESKIN );
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( THEME );
|
|
|
|
|
SAFE_DELETE( ANNOUNCER );
|
2003-10-13 08:33:39 +00:00
|
|
|
SAFE_DELETE( BOOKKEEPER );
|
2003-11-16 04:45:12 +00:00
|
|
|
SAFE_DELETE( LIGHTSMAN );
|
2002-12-15 10:35:39 +00:00
|
|
|
SAFE_DELETE( SOUNDMAN );
|
2002-11-14 23:54:40 +00:00
|
|
|
SAFE_DELETE( FONT );
|
|
|
|
|
SAFE_DELETE( TEXTUREMAN );
|
|
|
|
|
SAFE_DELETE( DISPLAY );
|
|
|
|
|
SAFE_DELETE( LOG );
|
2004-01-15 00:43:32 +00:00
|
|
|
SAFE_DELETE( FILEMAN );
|
2003-12-21 09:14:05 +00:00
|
|
|
|
2004-01-04 03:28:00 +00:00
|
|
|
#if !defined(DEBUG) && defined(_WINDOWS)
|
2003-12-21 09:14:05 +00:00
|
|
|
}
|
|
|
|
|
catch( const exception &e )
|
|
|
|
|
{
|
|
|
|
|
/* This can be things like calling std::string::reserve(-1), or out of memory.
|
2003-12-28 22:27:51 +00:00
|
|
|
* This can also happen if we throw a RageException during a ctor, in which case
|
|
|
|
|
* we want a crash dump. */
|
2004-03-13 10:22:03 +00:00
|
|
|
FAIL_M( e.what() );
|
2003-12-21 09:14:05 +00:00
|
|
|
}
|
|
|
|
|
#endif
|
2003-01-24 23:09:31 +00:00
|
|
|
|
2002-11-14 23:54:40 +00:00
|
|
|
if( g_sErrorString != "" )
|
2004-05-06 09:06:24 +00:00
|
|
|
HandleException( g_sErrorString );
|
2003-09-23 05:06:13 +00:00
|
|
|
|
|
|
|
|
SAFE_DELETE( HOOKS );
|
2002-11-14 23:54:40 +00:00
|
|
|
|
2003-11-13 00:39:36 +00:00
|
|
|
#ifdef _XBOX
|
2004-03-06 07:23:46 +00:00
|
|
|
XReturnToLaunchingXBE();
|
2003-11-13 00:39:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
2002-11-14 23:54:40 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 05:04:11 +00:00
|
|
|
CString SaveScreenshot( CString sDir, bool bSaveCompressed, bool bMakeSignature, int iIndex )
|
2004-02-12 09:44:16 +00:00
|
|
|
{
|
2004-02-14 20:47:50 +00:00
|
|
|
//
|
|
|
|
|
// Find a file name for the screenshot
|
|
|
|
|
//
|
2004-02-12 09:44:16 +00:00
|
|
|
FlushDirCache();
|
|
|
|
|
|
2004-02-15 03:09:28 +00:00
|
|
|
vector<CString> files;
|
|
|
|
|
GetDirListing( sDir + "screen*", files, false, false );
|
|
|
|
|
sort( files.begin(), files.end() );
|
|
|
|
|
|
|
|
|
|
/* Files should be of the form "screen######.xxx". Ignore the extension; find
|
|
|
|
|
* the last file of this form, and use the next number. This way, we don't
|
2004-02-22 05:04:11 +00:00
|
|
|
* write the same screenshot number for different formats (screen00011.bmp,
|
|
|
|
|
* screen00011.jpg), and we always increase from the end, so if screen00003.jpg
|
2004-02-15 03:09:28 +00:00
|
|
|
* is deleted, we won't fill in the hole (which makes screenshots hard to find). */
|
2004-02-22 05:04:11 +00:00
|
|
|
if( iIndex == -1 )
|
|
|
|
|
{
|
2004-02-25 01:51:31 +00:00
|
|
|
iIndex = 0;
|
|
|
|
|
|
2004-02-22 05:04:11 +00:00
|
|
|
for( int i = files.size()-1; i >= 0; --i )
|
2004-02-25 01:51:31 +00:00
|
|
|
{
|
|
|
|
|
static Regex re( "^screen([0-9]{5})\\....$" );
|
|
|
|
|
vector<CString> matches;
|
|
|
|
|
if( !re.Compare( files[i], matches ) )
|
|
|
|
|
continue;
|
2004-02-15 03:09:28 +00:00
|
|
|
|
2004-02-25 01:51:31 +00:00
|
|
|
ASSERT( matches.size() == 1 );
|
|
|
|
|
iIndex = atoi( matches[0] )+1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-02-22 05:04:11 +00:00
|
|
|
}
|
2004-02-14 20:47:50 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Save the screenshot
|
|
|
|
|
//
|
2004-03-23 22:35:30 +00:00
|
|
|
/* If writing lossy to a memcard, use SAVE_LOSSY_LOW_QUAL, so we don't eat up
|
|
|
|
|
* lots of space with screenshots. */
|
|
|
|
|
RageDisplay::GraphicsFileFormat fmt;
|
|
|
|
|
if( bSaveCompressed && MEMCARDMAN->PathIsMemCard(sDir) )
|
|
|
|
|
fmt = RageDisplay::SAVE_LOSSY_LOW_QUAL;
|
|
|
|
|
else if( bSaveCompressed )
|
|
|
|
|
fmt = RageDisplay::SAVE_LOSSY_HIGH_QUAL;
|
|
|
|
|
else
|
|
|
|
|
fmt = RageDisplay::SAVE_LOSSLESS;
|
|
|
|
|
|
2004-02-22 05:04:11 +00:00
|
|
|
CString sFileName = ssprintf( "screen%05d.%s",iIndex,bSaveCompressed ? "jpg" : "bmp" );
|
2004-02-17 01:16:57 +00:00
|
|
|
CString sPath = sDir+sFileName;
|
2004-03-23 22:35:30 +00:00
|
|
|
bool bResult = DISPLAY->SaveScreenshot( sPath, fmt );
|
2004-02-16 09:23:34 +00:00
|
|
|
if( !bResult )
|
2004-02-14 20:47:50 +00:00
|
|
|
{
|
2004-03-23 23:56:38 +00:00
|
|
|
SCREENMAN->PlayInvalidSound();
|
2004-02-17 01:16:57 +00:00
|
|
|
return "";
|
2004-02-14 20:47:50 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-23 23:56:38 +00:00
|
|
|
SCREENMAN->PlayScreenshotSound();
|
2004-02-16 09:23:34 +00:00
|
|
|
|
|
|
|
|
// We wrote a new file, and SignFile won't pick it up unless we invalidate
|
|
|
|
|
// the Dir cache. There's got to be a better way of doing this than
|
|
|
|
|
// thowing out all the cache. -Chris
|
|
|
|
|
FlushDirCache();
|
|
|
|
|
|
2004-02-22 04:48:39 +00:00
|
|
|
if( PREFSMAN->m_bSignProfileData && bMakeSignature )
|
2004-02-22 02:15:34 +00:00
|
|
|
CryptManager::SignFileToFile( sPath );
|
2004-02-14 20:47:50 +00:00
|
|
|
|
2004-02-17 01:16:57 +00:00
|
|
|
return sFileName;
|
2004-02-12 09:44:16 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
/* Returns true if the key has been handled and should be discarded, false if
|
|
|
|
|
* the key should be sent on to screens. */
|
|
|
|
|
bool HandleGlobalInputs( DeviceInput DeviceI, InputEventType type, GameInput GameI, MenuInput MenuI, StyleInput StyleI )
|
2002-12-15 20:16:14 +00:00
|
|
|
{
|
2003-03-09 00:55:49 +00:00
|
|
|
/* None of the globals keys act on types other than FIRST_PRESS */
|
2003-03-09 03:28:34 +00:00
|
|
|
if( type != IET_FIRST_PRESS )
|
2003-03-09 00:55:49 +00:00
|
|
|
return false;
|
|
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
switch( MenuI.button )
|
2002-12-15 20:16:14 +00:00
|
|
|
{
|
2003-02-12 17:36:54 +00:00
|
|
|
case MENU_BUTTON_OPERATOR:
|
2003-02-12 11:43:08 +00:00
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
/* Global operator key, to get quick access to the options menu. Don't
|
|
|
|
|
* do this if we're on a "system menu", which includes the editor
|
|
|
|
|
* (to prevent quitting without storing changes). */
|
|
|
|
|
if( !GAMESTATE->m_bIsOnSystemMenu )
|
|
|
|
|
{
|
|
|
|
|
SCREENMAN->SystemMessage( "OPERATOR" );
|
2003-10-13 08:33:39 +00:00
|
|
|
GAMESTATE->Reset();
|
2003-02-12 17:36:54 +00:00
|
|
|
SCREENMAN->SetNewScreen( "ScreenOptionsMenu" );
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2003-02-12 11:43:08 +00:00
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
case MENU_BUTTON_COIN:
|
|
|
|
|
/* Handle a coin insertion. */
|
2003-03-09 00:55:49 +00:00
|
|
|
if( GAMESTATE->m_bEditing ) // no coins while editing
|
2003-10-18 21:01:04 +00:00
|
|
|
{
|
|
|
|
|
LOG->Trace( "Ignored coin insertion (editing)" );
|
2003-02-19 05:46:09 +00:00
|
|
|
break;
|
2003-10-18 21:01:04 +00:00
|
|
|
}
|
|
|
|
|
|
2003-03-09 00:55:49 +00:00
|
|
|
GAMESTATE->m_iCoins++;
|
2003-10-18 21:01:04 +00:00
|
|
|
LOG->Trace("%i coins inserted, %i needed to play", GAMESTATE->m_iCoins, PREFSMAN->m_iCoinsPerCredit);
|
2003-10-13 08:33:39 +00:00
|
|
|
BOOKKEEPER->CoinInserted();
|
2003-03-09 00:55:49 +00:00
|
|
|
SCREENMAN->RefreshCreditsMessages();
|
2004-03-23 23:56:38 +00:00
|
|
|
SCREENMAN->PlayCoinSound();
|
2003-03-09 00:55:49 +00:00
|
|
|
return false; // Attract need to know because they go to TitleMenu on > 1 credit
|
2003-02-12 17:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-17 11:48:12 +00:00
|
|
|
if(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_F2))
|
|
|
|
|
{
|
2004-04-18 20:37:18 +00:00
|
|
|
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT) ) )
|
|
|
|
|
{
|
|
|
|
|
// HACK: Also save bookkeeping and profile info for debugging
|
|
|
|
|
// so we don't have to play through a whole song to get new output.
|
|
|
|
|
BOOKKEEPER->WriteToDisk();
|
|
|
|
|
PROFILEMAN->SaveMachineProfile();
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2004-04-18 20:37:18 +00:00
|
|
|
if( PROFILEMAN->IsUsingProfile((PlayerNumber)p) )
|
|
|
|
|
PROFILEMAN->SaveProfile( (PlayerNumber)p );
|
|
|
|
|
SCREENMAN->SystemMessage( "Stats saved" );
|
|
|
|
|
}
|
2003-12-18 21:16:43 +00:00
|
|
|
else
|
2004-04-18 20:37:18 +00:00
|
|
|
{
|
|
|
|
|
THEME->ReloadMetrics();
|
|
|
|
|
TEXTUREMAN->ReloadAll();
|
|
|
|
|
SCREENMAN->ReloadCreditsText();
|
|
|
|
|
NOTESKIN->RefreshNoteSkinData( GAMESTATE->m_CurGame );
|
|
|
|
|
CodeDetector::RefreshCacheItems();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* If we're in screen test mode, reload the screen. */
|
|
|
|
|
if( PREFSMAN->m_bScreenTestMode )
|
|
|
|
|
ResetGame( true );
|
|
|
|
|
else
|
|
|
|
|
SCREENMAN->SystemMessage( "Reloaded metrics and textures" );
|
|
|
|
|
}
|
2003-12-18 21:16:43 +00:00
|
|
|
|
2003-11-17 11:48:12 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2003-06-18 09:33:22 +00:00
|
|
|
#ifndef DARWIN
|
2003-02-12 17:36:54 +00:00
|
|
|
if(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_F4))
|
|
|
|
|
{
|
2003-02-16 01:35:48 +00:00
|
|
|
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_RALT)) ||
|
|
|
|
|
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_LALT)) )
|
2002-12-15 20:16:14 +00:00
|
|
|
{
|
2003-02-12 17:36:54 +00:00
|
|
|
// pressed Alt+F4
|
2003-04-12 16:06:06 +00:00
|
|
|
ExitGame();
|
2003-02-12 17:36:54 +00:00
|
|
|
return true;
|
2002-12-15 20:16:14 +00:00
|
|
|
}
|
2003-02-12 17:36:54 +00:00
|
|
|
}
|
2003-06-18 09:33:22 +00:00
|
|
|
#else
|
2003-07-09 06:36:00 +00:00
|
|
|
if(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_q))
|
|
|
|
|
{
|
|
|
|
|
if(INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RMETA)) ||
|
|
|
|
|
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LMETA)))
|
|
|
|
|
{
|
|
|
|
|
// pressed CMD-Q
|
|
|
|
|
ExitGame();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-06-18 09:33:22 +00:00
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2003-09-26 05:45:24 +00:00
|
|
|
/* The default Windows message handler will capture the desktop window upon
|
|
|
|
|
* pressing PrntScrn, or will capture the foregroud with focus upon pressing
|
|
|
|
|
* Alt+PrntScrn. Windows will do this whether or not we save a screenshot
|
|
|
|
|
* ourself by dumping the frame buffer. */
|
2003-10-09 00:25:06 +00:00
|
|
|
/* Pressing F13 on an Apple keyboard sends SDLK_PRINT.
|
|
|
|
|
* However, notebooks don't have F13. Use cmd-F12 then*/
|
2003-09-26 05:45:24 +00:00
|
|
|
// "if pressing PrintScreen and not pressing Alt"
|
2003-10-09 00:25:06 +00:00
|
|
|
if( (DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_PRINT) &&
|
|
|
|
|
!INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_RALT)) &&
|
|
|
|
|
!INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_LALT))) ||
|
|
|
|
|
(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_F12) &&
|
|
|
|
|
(INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_RMETA)) ||
|
|
|
|
|
INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_LMETA)))))
|
2003-07-09 06:36:00 +00:00
|
|
|
{
|
2004-02-14 20:47:50 +00:00
|
|
|
// If holding LShift save uncompressed, else save compressed
|
|
|
|
|
bool bSaveCompressed = !INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_LSHIFT) );
|
|
|
|
|
SaveScreenshot( "Screenshots/", bSaveCompressed, false );
|
2004-02-12 06:49:13 +00:00
|
|
|
return true; // handled
|
2003-02-12 17:36:54 +00:00
|
|
|
}
|
2002-12-15 20:16:14 +00:00
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
if(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_RETURN))
|
|
|
|
|
{
|
2003-02-16 01:35:48 +00:00
|
|
|
if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_RALT)) ||
|
|
|
|
|
INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, SDLK_LALT)) )
|
2002-12-15 20:16:14 +00:00
|
|
|
{
|
2003-02-12 17:36:54 +00:00
|
|
|
/* alt-enter */
|
|
|
|
|
PREFSMAN->m_bWindowed = !PREFSMAN->m_bWindowed;
|
|
|
|
|
ApplyGraphicOptions();
|
|
|
|
|
return true;
|
2002-12-15 20:16:14 +00:00
|
|
|
}
|
2003-02-12 17:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-17 20:14:59 +00:00
|
|
|
if(DeviceI == DeviceInput(DEVICE_KEYBOARD, SDLK_PAUSE))
|
|
|
|
|
{
|
|
|
|
|
static bool bMute = false;
|
|
|
|
|
bMute = !bMute;
|
|
|
|
|
SOUNDMAN->SetPrefs( bMute ? 0 : PREFSMAN->m_fSoundVolume );
|
|
|
|
|
SCREENMAN->SystemMessage( bMute ? "Mute on" : "Mute off" );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2002-12-15 20:16:14 +00:00
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
static void HandleInputEvents(float fDeltaTime)
|
|
|
|
|
{
|
2003-02-16 01:35:48 +00:00
|
|
|
INPUTFILTER->Update( fDeltaTime );
|
|
|
|
|
|
2004-02-19 03:20:11 +00:00
|
|
|
/* Hack: If the topmost screen hasn't been updated yet, don't process input, since
|
|
|
|
|
* we must not send inputs to a screen that hasn't at least had one update yet. (The
|
|
|
|
|
* first Update should be the very first thing a screen gets.) We'll process it next
|
|
|
|
|
* time. Do call Update above, so the inputs are read and timestamped. */
|
|
|
|
|
if( SCREENMAN->GetTopScreen()->IsFirstUpdate() )
|
|
|
|
|
return;
|
|
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
static InputEventArray ieArray;
|
|
|
|
|
ieArray.clear(); // empty the array
|
2003-02-16 01:35:48 +00:00
|
|
|
INPUTFILTER->GetInputEvents( ieArray );
|
2003-07-14 20:09:50 +00:00
|
|
|
|
|
|
|
|
/* If we don't have focus, discard input. */
|
|
|
|
|
if( !g_bHasFocus )
|
|
|
|
|
return;
|
|
|
|
|
|
2003-02-12 17:36:54 +00:00
|
|
|
for( unsigned i=0; i<ieArray.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
DeviceInput DeviceI = (DeviceInput)ieArray[i];
|
|
|
|
|
InputEventType type = ieArray[i].type;
|
2002-12-15 20:16:14 +00:00
|
|
|
GameInput GameI;
|
|
|
|
|
MenuInput MenuI;
|
|
|
|
|
StyleInput StyleI;
|
|
|
|
|
|
|
|
|
|
INPUTMAPPER->DeviceToGame( DeviceI, GameI );
|
|
|
|
|
|
|
|
|
|
if( GameI.IsValid() && type == IET_FIRST_PRESS )
|
|
|
|
|
INPUTQUEUE->RememberInput( GameI );
|
|
|
|
|
if( GameI.IsValid() )
|
|
|
|
|
{
|
|
|
|
|
INPUTMAPPER->GameToMenu( GameI, MenuI );
|
|
|
|
|
INPUTMAPPER->GameToStyle( GameI, StyleI );
|
|
|
|
|
}
|
2003-02-12 17:36:54 +00:00
|
|
|
|
|
|
|
|
// HACK: Numlock is read is being pressed if the NumLock light is on.
|
|
|
|
|
// Filter out all NumLock repeat messages
|
2003-12-06 08:50:54 +00:00
|
|
|
/* XXX: Is this still needed? If so, it should probably be done in the
|
|
|
|
|
* affected input driver. */
|
2003-02-12 17:36:54 +00:00
|
|
|
if( DeviceI.device == DEVICE_KEYBOARD && DeviceI.button == SDLK_NUMLOCK && type != IET_FIRST_PRESS )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
if( HandleGlobalInputs(DeviceI, type, GameI, MenuI, StyleI ) )
|
|
|
|
|
continue; // skip
|
2003-02-12 11:43:08 +00:00
|
|
|
|
2002-12-15 20:16:14 +00:00
|
|
|
SCREENMAN->Input( DeviceI, type, GameI, MenuI, StyleI );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-12 16:06:06 +00:00
|
|
|
static void HandleSDLEvents()
|
2002-11-14 23:54:40 +00:00
|
|
|
{
|
2003-03-17 06:20:57 +00:00
|
|
|
// process all queued events
|
|
|
|
|
SDL_Event event;
|
2003-04-12 19:03:02 +00:00
|
|
|
while(SDL_GetEvent(event, SDL_QUITMASK|SDL_ACTIVEEVENTMASK))
|
2002-10-28 05:30:45 +00:00
|
|
|
{
|
2003-03-17 06:20:57 +00:00
|
|
|
switch(event.type)
|
|
|
|
|
{
|
|
|
|
|
case SDL_QUIT:
|
|
|
|
|
LOG->Trace("SDL_QUIT: shutting down");
|
2003-04-12 16:06:06 +00:00
|
|
|
ExitGame();
|
2003-03-17 06:20:57 +00:00
|
|
|
break;
|
2003-04-12 16:06:06 +00:00
|
|
|
|
2003-03-17 06:20:57 +00:00
|
|
|
case SDL_ACTIVEEVENT:
|
2003-05-26 09:18:44 +00:00
|
|
|
{
|
|
|
|
|
/* We don't care about mouse focus. */
|
|
|
|
|
if(event.active.state == SDL_APPMOUSEFOCUS)
|
|
|
|
|
break;
|
|
|
|
|
|
2004-05-11 21:14:13 +00:00
|
|
|
uint8_t i = SDL_GetAppState();
|
2003-05-26 09:18:44 +00:00
|
|
|
|
|
|
|
|
g_bHasFocus = i&SDL_APPINPUTFOCUS && i&SDL_APPACTIVE;
|
|
|
|
|
LOG->Trace("App %s focus (%i%i)", g_bHasFocus? "has":"doesn't have",
|
|
|
|
|
i&SDL_APPINPUTFOCUS, i&SDL_APPACTIVE);
|
|
|
|
|
|
2004-01-26 04:00:52 +00:00
|
|
|
/* If we lose focus, we may lose input events, especially key releases. */
|
|
|
|
|
INPUTFILTER->Reset();
|
|
|
|
|
|
2003-05-26 09:18:44 +00:00
|
|
|
if(g_bHasFocus)
|
|
|
|
|
BoostAppPri();
|
|
|
|
|
else
|
|
|
|
|
RestoreAppPri();
|
|
|
|
|
}
|
2002-10-28 05:30:45 +00:00
|
|
|
}
|
2003-03-17 06:20:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-01 08:04:17 +00:00
|
|
|
static void CheckSkips( float fDeltaTime )
|
|
|
|
|
{
|
|
|
|
|
if( !PREFSMAN->m_bLogSkips )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
static int iLastFPS = 0;
|
|
|
|
|
int iThisFPS = DISPLAY->GetFPS();
|
|
|
|
|
|
|
|
|
|
/* If vsync is on, and we have a solid framerate (vsync == refresh and we've sustained this
|
|
|
|
|
* for at least one frame), we expect the amount of time for the last frame to be 1/FPS. */
|
|
|
|
|
|
|
|
|
|
if( iThisFPS != DISPLAY->GetVideoModeParams().rate || iThisFPS != iLastFPS )
|
|
|
|
|
{
|
|
|
|
|
iLastFPS = iThisFPS;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const float fExpectedTime = 1.0f / iThisFPS;
|
|
|
|
|
const float fDifference = fDeltaTime - fExpectedTime;
|
|
|
|
|
if( fabsf(fDifference) > 0.002f && fabsf(fDifference) < 0.100f )
|
|
|
|
|
LOG->Trace("GameLoop timer skip: %i FPS, expected %.3f, got %.3f (%.3f difference)",
|
|
|
|
|
iThisFPS, fExpectedTime, fDeltaTime, fDifference );
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-17 06:20:57 +00:00
|
|
|
static void GameLoop()
|
|
|
|
|
{
|
|
|
|
|
RageTimer timer;
|
2003-04-12 16:06:06 +00:00
|
|
|
while(!g_bQuitting)
|
2003-03-17 06:20:57 +00:00
|
|
|
{
|
2003-04-12 16:06:06 +00:00
|
|
|
/* This needs to be called before anything that handles SDL events. */
|
|
|
|
|
SDL_PumpEvents();
|
|
|
|
|
HandleSDLEvents();
|
2001-12-19 01:50:57 +00:00
|
|
|
|
2002-11-01 20:01:59 +00:00
|
|
|
/*
|
2002-11-11 04:53:31 +00:00
|
|
|
* Update
|
|
|
|
|
*/
|
2002-12-19 23:13:52 +00:00
|
|
|
float fDeltaTime = timer.GetDeltaTime();
|
2002-11-11 04:53:31 +00:00
|
|
|
|
2004-03-01 08:04:17 +00:00
|
|
|
CheckSkips( fDeltaTime );
|
|
|
|
|
|
2003-02-16 01:35:48 +00:00
|
|
|
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_TAB) ) ) {
|
|
|
|
|
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_BACKQUOTE) ) )
|
2002-11-11 08:52:07 +00:00
|
|
|
fDeltaTime = 0; /* both; stop time */
|
|
|
|
|
else
|
|
|
|
|
fDeltaTime *= 4;
|
2003-08-07 06:09:14 +00:00
|
|
|
}
|
|
|
|
|
else if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD, SDLK_BACKQUOTE) ) )
|
|
|
|
|
{
|
|
|
|
|
fDeltaTime /= 4;
|
|
|
|
|
}
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-04-12 16:06:06 +00:00
|
|
|
DISPLAY->Update( fDeltaTime );
|
2004-01-20 06:08:56 +00:00
|
|
|
|
2004-05-08 02:18:27 +00:00
|
|
|
/* Update SOUNDMAN early (before any RageSound::GetPosition calls), to flush position data. */
|
|
|
|
|
SOUNDMAN->Update( fDeltaTime );
|
|
|
|
|
|
2004-01-20 06:08:56 +00:00
|
|
|
/* Update song beat information -before- calling update on all the classes that
|
|
|
|
|
* depend on it. If you don't do this first, the classes are all acting on old
|
|
|
|
|
* information and will lag. (but no longer fatally, due to timestamping -glenn) */
|
2003-12-18 08:53:38 +00:00
|
|
|
SOUND->Update( fDeltaTime );
|
2002-11-28 20:48:00 +00:00
|
|
|
TEXTUREMAN->Update( fDeltaTime );
|
2003-02-26 23:26:57 +00:00
|
|
|
GAMESTATE->Update( fDeltaTime );
|
2002-11-11 04:53:31 +00:00
|
|
|
SCREENMAN->Update( fDeltaTime );
|
2003-12-15 07:35:40 +00:00
|
|
|
MEMCARDMAN->Update( fDeltaTime );
|
2001-11-03 10:52:42 +00:00
|
|
|
|
2003-03-17 06:20:57 +00:00
|
|
|
/* Important: Process input AFTER updating game logic, or input will be acting on song beat from last frame */
|
2003-02-17 02:45:30 +00:00
|
|
|
HandleInputEvents( fDeltaTime );
|
|
|
|
|
|
2003-11-20 11:55:45 +00:00
|
|
|
LIGHTSMAN->Update( fDeltaTime );
|
|
|
|
|
|
2003-08-04 11:18:55 +00:00
|
|
|
HOOKS->Update( fDeltaTime );
|
|
|
|
|
|
2002-11-11 04:53:31 +00:00
|
|
|
/*
|
|
|
|
|
* Render
|
|
|
|
|
*/
|
2003-03-17 06:20:57 +00:00
|
|
|
SCREENMAN->Draw();
|
2002-09-18 20:42:33 +00:00
|
|
|
|
2003-08-29 04:44:03 +00:00
|
|
|
/* If we don't have focus, give up lots of CPU. */
|
|
|
|
|
if( !g_bHasFocus )
|
2004-05-23 02:27:51 +00:00
|
|
|
usleep( 10000 );// give some time to other processes and threads
|
2003-08-29 04:44:03 +00:00
|
|
|
#if defined(_WINDOWS)
|
|
|
|
|
/* In Windows, we want to give up some CPU for other threads. Most OS's do
|
|
|
|
|
* this more intelligently. */
|
|
|
|
|
else
|
2004-05-23 02:27:51 +00:00
|
|
|
usleep( 1000 ); // give some time to other processes and threads
|
2003-07-28 10:39:15 +00:00
|
|
|
#endif
|
2002-11-11 04:53:31 +00:00
|
|
|
}
|
2003-02-15 00:11:46 +00:00
|
|
|
}
|
2004-04-15 15:31:59 +00:00
|
|
|
|