2011-03-17 01:47:30 -04:00
# include "global.h"
# include "StepMania.h"
// Rage global classes
# include "RageLog.h"
# include "RageTextureManager.h"
# include "RageSoundManager.h"
# include "GameSoundManager.h"
# include "RageInput.h"
# include "RageTimer.h"
# include "RageMath.h"
# include "RageDisplay.h"
# include "RageThreads.h"
# include "LocalizedString.h"
# include "arch/ArchHooks/ArchHooks.h"
# include "arch/LoadingWindow/LoadingWindow.h"
# include "arch/Dialog/Dialog.h"
# include <ctime>
# include "ProductInfo.h"
# include "Screen.h"
# include "InputEventPlus.h"
# include "ScreenDimensions.h"
# include "CodeDetector.h"
# include "CommonMetrics.h"
# include "Game.h"
# include "RageSurface.h"
# include "RageSurface_Load.h"
# include "CommandLineActions.h"
# if !defined(SUPPORT_OPENGL) && !defined(SUPPORT_D3D)
# define SUPPORT_OPENGL
# endif
// StepMania global classes
# include "ThemeManager.h"
# include "NoteSkinManager.h"
# include "PrefsManager.h"
# include "SongManager.h"
# include "CharacterManager.h"
# include "GameState.h"
# include "AnnouncerManager.h"
# include "ProfileManager.h"
# include "MemoryCardManager.h"
# include "ScreenManager.h"
# include "LuaManager.h"
# include "GameManager.h"
# include "FontManager.h"
# include "InputFilter.h"
# include "InputMapper.h"
# include "InputQueue.h"
# include "SongCacheIndex.h"
# include "BannerCache.h"
//#include "BackgroundCache.h"
# include "UnlockManager.h"
# include "RageFileManager.h"
# include "Bookkeeper.h"
# include "LightsManager.h"
# include "ModelManager.h"
# include "CryptManager.h"
# include "NetworkSyncManager.h"
# include "MessageManager.h"
# include "StatsManager.h"
# include "GameLoop.h"
# include "SpecialFiles.h"
# include "Profile.h"
2011-05-02 20:11:26 -05:00
# if defined(XBOX)
# include "Archutils/Xbox/VirtualMemory.h"
# endif
# if defined(WIN32) && !defined(XBOX)
2011-03-17 01:47:30 -04:00
# include <windows.h>
# endif
2011-05-02 20:11:26 -05:00
// since the XBOX SDK only works with VS.Net 2003, this doesn't exist yet.
// see http://old.nabble.com/Linking-Error-with-MSVC%2B%2B-6.0-td21608559.html
// for more information. -aj
# if defined(XBOX)
extern " C "
{
int _get_output_format ( void ) { return 0 ; }
}
# endif
2011-03-17 01:47:30 -04:00
static Preference < bool > g_bAllowMultipleInstances ( " AllowMultipleInstances " , false ) ;
2011-05-02 20:11:26 -05:00
2011-03-17 01:47:30 -04:00
void StepMania : : GetPreferredVideoModeParams ( VideoModeParams & paramsOut )
{
/* We can't rely on there being full-screen video modes that give us square
* pixels at non-4:3 aspects. The lowest non-4:3 resolution my new laptop
* with Radeon supports is 1280x720. In most cases, we'll using a 4:3
* resolution when full-screen let the monitor stretch to the correct aspect.
* When windowed (no monitor stretching), we will tweak the width so that
* we get square pixels.
* -Chris */
int iWidth = PREFSMAN - > m_iDisplayWidth ;
if ( PREFSMAN - > m_bWindowed )
{
//float fRatio = PREFSMAN->m_iDisplayWidth / PREFSMAN->m_iDisplayHeight;
//iWidth = PREFSMAN->m_iDisplayHeight * fRatio;
iWidth = static_cast < int > ( ceilf ( PREFSMAN - > m_iDisplayHeight * PREFSMAN - > m_fDisplayAspectRatio ) ) ;
}
// todo: allow for PRODUCT_ID + "-" + CommonMetrics::WINDOW_TITLE as
// a theme option (Midi requested it, AJ had the idea for making it optional)
paramsOut = VideoModeParams (
PREFSMAN - > m_bWindowed ,
iWidth ,
PREFSMAN - > m_iDisplayHeight ,
PREFSMAN - > m_iDisplayColorDepth ,
PREFSMAN - > m_iRefreshRate ,
PREFSMAN - > m_bVsync ,
PREFSMAN - > m_bInterlaced ,
PREFSMAN - > m_bSmoothLines ,
PREFSMAN - > m_bTrilinearFiltering ,
PREFSMAN - > m_bAnisotropicFiltering ,
CommonMetrics : : WINDOW_TITLE ,
THEME - > GetPathG ( " Common " , " window icon " ) ,
PREFSMAN - > m_bPAL ,
PREFSMAN - > m_fDisplayAspectRatio
) ;
}
static LocalizedString COLOR ( " StepMania " , " color " ) ;
static LocalizedString TEXTURE ( " StepMania " , " texture " ) ;
static LocalizedString WINDOWED ( " StepMania " , " Windowed " ) ;
static LocalizedString FULLSCREEN ( " StepMania " , " Fullscreen " ) ;
static LocalizedString ANNOUNCER_ ( " StepMania " , " Announcer " ) ;
static LocalizedString VSYNC ( " StepMania " , " Vsync " ) ;
static LocalizedString NO_VSYNC ( " StepMania " , " NoVsync " ) ;
static LocalizedString SMOOTH_LINES ( " StepMania " , " SmoothLines " ) ;
static LocalizedString NO_SMOOTH_LINES ( " StepMania " , " NoSmoothLines " ) ;
static RString GetActualGraphicOptionsString ( )
{
const VideoModeParams & params = DISPLAY - > GetActualVideoModeParams ( ) ;
RString sFormat = " %s %s %dx%d %d " + COLOR . GetValue ( ) + " %d " + TEXTURE . GetValue ( ) + " %dHz %s %s " ;
RString sLog = ssprintf ( sFormat ,
DISPLAY - > GetApiDescription ( ) . c_str ( ) ,
( params . windowed ? WINDOWED : FULLSCREEN ) . GetValue ( ) . c_str ( ) ,
( int ) params . width ,
( int ) params . height ,
( int ) params . bpp ,
( int ) PREFSMAN - > m_iTextureColorDepth ,
( int ) params . rate ,
( params . vsync ? VSYNC : NO_VSYNC ) . GetValue ( ) . c_str ( ) ,
( PREFSMAN - > m_bSmoothLines ? SMOOTH_LINES : NO_SMOOTH_LINES ) . GetValue ( ) . c_str ( ) ) ;
return sLog ;
}
static void StoreActualGraphicOptions ( )
{
/* Store the settings that RageDisplay was actually able to use so that
* we don't go through the process of auto-detecting a usable video mode
* every time. */
const VideoModeParams & params = DISPLAY - > GetActualVideoModeParams ( ) ;
PREFSMAN - > m_bWindowed . Set ( params . windowed ) ;
/* If we're windowed, we may have tweaked the width based on the aspect ratio.
* Don't save this new value over the preferred value. */
if ( ! PREFSMAN - > m_bWindowed )
{
PREFSMAN - > m_iDisplayWidth . Set ( params . width ) ;
PREFSMAN - > m_iDisplayHeight . Set ( params . height ) ;
}
PREFSMAN - > m_iDisplayColorDepth . Set ( params . bpp ) ;
if ( PREFSMAN - > m_iRefreshRate ! = REFRESH_DEFAULT )
PREFSMAN - > m_iRefreshRate . Set ( params . rate ) ;
PREFSMAN - > m_bVsync . Set ( params . vsync ) ;
Dialog : : SetWindowed ( params . windowed ) ;
}
static RageDisplay * CreateDisplay ( ) ;
bool StepMania : : GetHighResolutionTextures ( )
{
switch ( PREFSMAN - > m_HighResolutionTextures )
{
default :
case HighResolutionTextures_Auto :
{
int height = PREFSMAN - > m_iDisplayHeight ;
return height > 480 ;
}
case HighResolutionTextures_ForceOn :
return true ;
case HighResolutionTextures_ForceOff :
return false ;
}
}
static void StartDisplay ( )
{
if ( DISPLAY ! = NULL )
return ; // already started
DISPLAY = CreateDisplay ( ) ;
DISPLAY - > ChangeCentering (
PREFSMAN - > m_iCenterImageTranslateX ,
PREFSMAN - > m_iCenterImageTranslateY ,
PREFSMAN - > m_fCenterImageAddWidth ,
PREFSMAN - > m_fCenterImageAddHeight ) ;
TEXTUREMAN = new RageTextureManager ;
TEXTUREMAN - > SetPrefs (
RageTextureManagerPrefs (
PREFSMAN - > m_iTextureColorDepth ,
PREFSMAN - > m_iMovieColorDepth ,
PREFSMAN - > m_bDelayedTextureDelete ,
PREFSMAN - > m_iMaxTextureResolution ,
StepMania : : GetHighResolutionTextures ( ) ,
PREFSMAN - > m_bForceMipMaps
)
) ;
MODELMAN = new ModelManager ;
MODELMAN - > SetPrefs (
ModelManagerPrefs (
PREFSMAN - > m_bDelayedModelDelete
)
) ;
}
void StepMania : : ApplyGraphicOptions ( )
{
bool bNeedReload = false ;
VideoModeParams params ;
GetPreferredVideoModeParams ( params ) ;
RString sError = DISPLAY - > SetVideoMode ( params , bNeedReload ) ;
if ( sError ! = " " )
RageException : : Throw ( " %s " , sError . c_str ( ) ) ;
DISPLAY - > ChangeCentering (
PREFSMAN - > m_iCenterImageTranslateX ,
PREFSMAN - > m_iCenterImageTranslateY ,
PREFSMAN - > m_fCenterImageAddWidth ,
PREFSMAN - > m_fCenterImageAddHeight ) ;
bNeedReload | = TEXTUREMAN - > SetPrefs (
RageTextureManagerPrefs (
PREFSMAN - > m_iTextureColorDepth ,
PREFSMAN - > m_iMovieColorDepth ,
PREFSMAN - > m_bDelayedTextureDelete ,
PREFSMAN - > m_iMaxTextureResolution ,
StepMania : : GetHighResolutionTextures ( ) ,
PREFSMAN - > m_bForceMipMaps
)
) ;
bNeedReload | = MODELMAN - > SetPrefs (
ModelManagerPrefs (
PREFSMAN - > m_bDelayedModelDelete
)
) ;
if ( bNeedReload )
TEXTUREMAN - > ReloadAll ( ) ;
StoreActualGraphicOptions ( ) ;
if ( SCREENMAN )
SCREENMAN - > SystemMessage ( GetActualGraphicOptionsString ( ) ) ;
// Give the input handlers a chance to re-open devices as necessary.
INPUTMAN - > WindowReset ( ) ;
}
static bool CheckVideoDefaultSettings ( ) ;
void StepMania : : ResetPreferences ( )
{
PREFSMAN - > ResetToFactoryDefaults ( ) ;
SOUNDMAN - > SetMixVolume ( ) ;
CheckVideoDefaultSettings ( ) ;
ApplyGraphicOptions ( ) ;
}
/* Shutdown all global singletons. Note that this may be called partway through
* initialization, due to an object failing to initialize, in which case some of
* these may still be NULL. */
void ShutdownGame ( )
{
/* First, tell SOUNDMAN that we're shutting down. This signals sound drivers to
* stop sounds, which we want to do before any threads that may have started sounds
* are closed; this prevents annoying DirectSound glitches and delays. */
if ( SOUNDMAN )
SOUNDMAN - > Shutdown ( ) ;
SAFE_DELETE ( SCREENMAN ) ;
SAFE_DELETE ( STATSMAN ) ;
SAFE_DELETE ( MESSAGEMAN ) ;
SAFE_DELETE ( NSMAN ) ;
/* 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 ) ;
SAFE_DELETE ( INPUTQUEUE ) ;
SAFE_DELETE ( INPUTMAPPER ) ;
SAFE_DELETE ( INPUTFILTER ) ;
SAFE_DELETE ( MODELMAN ) ;
SAFE_DELETE ( PROFILEMAN ) ; // PROFILEMAN needs the songs still loaded
SAFE_DELETE ( CHARMAN ) ;
SAFE_DELETE ( UNLOCKMAN ) ;
SAFE_DELETE ( CRYPTMAN ) ;
SAFE_DELETE ( MEMCARDMAN ) ;
SAFE_DELETE ( SONGMAN ) ;
SAFE_DELETE ( BANNERCACHE ) ;
//SAFE_DELETE( BACKGROUNDCACHE );
SAFE_DELETE ( SONGINDEX ) ;
SAFE_DELETE ( SOUND ) ; // uses GAMESTATE, PREFSMAN
SAFE_DELETE ( PREFSMAN ) ;
SAFE_DELETE ( GAMESTATE ) ;
SAFE_DELETE ( GAMEMAN ) ;
SAFE_DELETE ( NOTESKIN ) ;
SAFE_DELETE ( THEME ) ;
SAFE_DELETE ( ANNOUNCER ) ;
SAFE_DELETE ( BOOKKEEPER ) ;
SAFE_DELETE ( LIGHTSMAN ) ;
SAFE_DELETE ( SOUNDMAN ) ;
SAFE_DELETE ( FONT ) ;
SAFE_DELETE ( TEXTUREMAN ) ;
SAFE_DELETE ( DISPLAY ) ;
Dialog : : Shutdown ( ) ;
SAFE_DELETE ( LOG ) ;
SAFE_DELETE ( FILEMAN ) ;
SAFE_DELETE ( LUA ) ;
SAFE_DELETE ( HOOKS ) ;
}
static void HandleException ( const RString & sError )
{
if ( g_bAutoRestart )
HOOKS - > RestartProgram ( ) ;
// Shut down first, so we exit graphics mode before trying to open a dialog.
ShutdownGame ( ) ;
// Throw up a pretty error dialog.
Dialog : : Error ( sError ) ;
Dialog : : Shutdown ( ) ; // Shut it back down.
}
void StepMania : : ResetGame ( )
{
GAMESTATE - > Reset ( ) ;
if ( ! THEME - > DoesThemeExist ( THEME - > GetCurThemeName ( ) ) )
{
RString sGameName = GAMESTATE - > GetCurrentGame ( ) - > m_szName ;
if ( ! THEME - > DoesThemeExist ( sGameName ) )
sGameName = PREFSMAN - > m_sDefaultTheme ; // was previously "default" -aj
THEME - > SwitchThemeAndLanguage ( sGameName , THEME - > GetCurLanguage ( ) , PREFSMAN - > m_bPseudoLocalize ) ;
TEXTUREMAN - > DoDelayedDelete ( ) ;
}
PREFSMAN - > SavePrefsToDisk ( ) ;
}
ThemeMetric < RString > INITIAL_SCREEN ( " Common " , " InitialScreen " ) ;
RString StepMania : : GetInitialScreen ( )
{
if ( PREFSMAN - > m_sTestInitialScreen . Get ( ) ! = " " )
return PREFSMAN - > m_sTestInitialScreen ;
return INITIAL_SCREEN . GetValue ( ) ;
}
ThemeMetric < RString > SELECT_MUSIC_SCREEN ( " Common " , " SelectMusicScreen " ) ;
RString StepMania : : GetSelectMusicScreen ( )
{
return SELECT_MUSIC_SCREEN . GetValue ( ) ;
}
# if defined(WIN32)
static Preference < int > g_iLastSeenMemory ( " LastSeenMemory " , 0 ) ;
# endif
static void AdjustForChangedSystemCapabilities ( )
{
# if defined(WIN32)
// Has the amount of memory changed?
MEMORYSTATUS mem ;
GlobalMemoryStatus ( & mem ) ;
const int Memory = mem . dwTotalPhys / ( 1024 * 1024 ) ;
if ( g_iLastSeenMemory = = Memory )
return ;
LOG - > Trace ( " Memory changed from %i to %i; settings changed " , g_iLastSeenMemory . Get ( ) , Memory ) ;
g_iLastSeenMemory . Set ( Memory ) ;
// is this assumption outdated? -aj
/* Let's consider 128-meg systems low-memory, and 256-meg systems high-memory.
* Cut off at 192. This is pretty 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 ) ;
const bool LowMemory = ( Memory < 100 ) ; // 64 and 96-meg systems
/* 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 . Set ( HighMemory ) ;
/* 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. */
PREFSMAN - > m_BannerCache . Set ( LowMemory ? BNCACHE_OFF : BNCACHE_LOW_RES_PRELOAD ) ;
// might wanna do this for backgrounds, too... -aj
//PREFSMAN->m_BackgroundCache.Set( LowMemory ? BGCACHE_OFF:BGCACHE_LOW_RES_PRELOAD );
PREFSMAN - > SavePrefsToDisk ( ) ;
# endif
}
# if defined(WIN32)
2011-05-02 20:11:26 -05:00
//#include "RageDisplay_D3D.h"
2011-03-17 01:47:30 -04:00
# include "archutils/Win32/VideoDriverInfo.h"
# endif
# if defined(SUPPORT_OPENGL)
# include "RageDisplay_OGL.h"
# endif
# include "RageDisplay_Null.h"
struct VideoCardDefaults
{
RString sDriverRegex ;
RString sVideoRenderers ;
int iWidth ;
int iHeight ;
int iDisplayColor ;
int iTextureColor ;
int iMovieColor ;
int iTextureSize ;
bool bSmoothLines ;
VideoCardDefaults ( ) { }
VideoCardDefaults (
RString sDriverRegex_ ,
RString sVideoRenderers_ ,
int iWidth_ ,
int iHeight_ ,
int iDisplayColor_ ,
int iTextureColor_ ,
int iMovieColor_ ,
int iTextureSize_ ,
bool bSmoothLines_
)
{
sDriverRegex = sDriverRegex_ ;
sVideoRenderers = sVideoRenderers_ ;
iWidth = iWidth_ ;
iHeight = iHeight_ ;
iDisplayColor = iDisplayColor_ ;
iTextureColor = iTextureColor_ ;
iMovieColor = iMovieColor_ ;
iTextureSize = iTextureSize_ ;
bSmoothLines = bSmoothLines_ ;
}
} const g_VideoCardDefaults [ ] =
{
2011-05-02 20:11:26 -05:00
VideoCardDefaults (
" Xbox " ,
" d3d " ,
600 , 400 ,
32 , 32 , 32 ,
2048 ,
true
) ,
2011-03-17 01:47:30 -04:00
VideoCardDefaults (
" Voodoo *5 " ,
" d3d,opengl " , // received 3 reports of opengl crashing. -Chris
640 , 480 ,
32 , 32 , 32 ,
2048 ,
true // accelerated
) ,
VideoCardDefaults (
" Voodoo|3dfx " , // all other Voodoos: some drivers don't identify which one
" d3d,opengl " ,
640 , 480 ,
16 , 16 , 16 ,
256 ,
false // broken, causes black screen
) ,
VideoCardDefaults (
" Radeon.* 7|Wonder 7500|ArcadeVGA " , // Radeon 7xxx, RADEON Mobility 7500
" d3d,opengl " , // movie texture performance is terrible in OpenGL, but fine in D3D.
640 , 480 ,
16 , 16 , 16 ,
2048 ,
true // accelerated
) ,
VideoCardDefaults (
" GeForce|Radeon|Wonder 9|Quadro " ,
" opengl,d3d " ,
640 , 480 ,
32 , 32 , 32 , // 32 bit textures are faster to load
2048 ,
true // hardware accelerated
) ,
VideoCardDefaults (
" TNT|Vanta|M64 " ,
" opengl,d3d " ,
640 , 480 ,
16 , 16 , 16 , // Athlon 1.2+TNT demonstration w/ movies: 70fps w/ 32bit textures, 86fps w/ 16bit textures
2048 ,
true // hardware accelerated
) ,
VideoCardDefaults (
" G200|G250|G400 " ,
" d3d,opengl " ,
640 , 480 ,
16 , 16 , 16 ,
2048 ,
false // broken, causes black screen
) ,
VideoCardDefaults (
" 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
640 , 480 ,
16 , 16 , 16 ,
2048 ,
false
) ,
VideoCardDefaults (
" 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
320 , 240 , // lower resolution for 60fps. In-box WinXP driver doesn't support 400x300.
16 , 16 , 16 ,
256 ,
false
) ,
VideoCardDefaults (
" RAGE MOBILITY-M1 " ,
" d3d,opengl " , // Vertex alpha is broken in OpenGL, but not D3D. -Chris
400 , 300 , // lower resolution for 60fps
16 , 16 , 16 ,
256 ,
false
) ,
VideoCardDefaults (
" Mobility M3 " , // ATI Rage Mobility 128 (AKA "M3")
" d3d,opengl " , // bad movie texture performance in opengl
640 , 480 ,
16 , 16 , 16 ,
1024 ,
false
) ,
VideoCardDefaults (
" Intel.*82810|Intel.*82815 " ,
" opengl,d3d " , // OpenGL is 50%+ faster than D3D w/ latest Intel drivers. -Chris
512 , 384 , // lower resolution for 60fps
16 , 16 , 16 ,
512 ,
false
) ,
VideoCardDefaults (
" Intel*Extreme Graphics " ,
" d3d " , // OpenGL blue screens w/ XP drivers from 6-21-2002
640 , 480 ,
16 , 16 , 16 , // slow at 32bpp
1024 ,
false
) ,
VideoCardDefaults (
" Intel.* " , /* fallback: all unknown Intel cards to D3D, since Intel is notoriously bad at OpenGL */
" d3d,opengl " ,
640 , 480 ,
16 , 16 , 16 ,
2048 ,
false
) ,
VideoCardDefaults (
// 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 " ,
640 , 480 ,
16 , 16 , 16 ,
2048 ,
false
) ,
VideoCardDefaults (
/* Unconfirmed texture problems on this; let's try D3D, since it's
* a VIA/S3 chipset. */
" VIA/S3G KM400/KN400 " ,
" d3d,opengl " ,
640 , 480 ,
16 , 16 , 16 ,
2048 ,
false
) ,
VideoCardDefaults (
" OpenGL " , // This matches all drivers in Mac and Linux. -Chris
" opengl " ,
640 , 480 ,
16 , 16 , 16 ,
2048 ,
true // Right now, they've got to have NVidia or ATi Cards anyway..
) ,
VideoCardDefaults (
// Default graphics settings used for all cards that don't match above.
// This must be the very last entry!
" " ,
" opengl,d3d " ,
640 , 480 ,
32 , 32 , 32 ,
2048 ,
false // AA is slow on some cards, so let's selectively enable HW accelerated cards.
) ,
} ;
static RString GetVideoDriverName ( )
{
# if defined(_WINDOWS)
return GetPrimaryVideoDriverName ( ) ;
2011-05-02 20:11:26 -05:00
# elif defined(_XBOX)
return " Xbox " ;
2011-03-17 01:47:30 -04:00
# else
return " OpenGL " ;
# endif
}
bool CheckVideoDefaultSettings ( )
{
// Video card changed since last run
RString sVideoDriver = GetVideoDriverName ( ) ;
LOG - > Trace ( " Last seen video driver: %s " , PREFSMAN - > m_sLastSeenVideoDriver . Get ( ) . c_str ( ) ) ;
VideoCardDefaults defaults ;
for ( unsigned i = 0 ; i < ARRAYLEN ( g_VideoCardDefaults ) ; i + + )
{
defaults = g_VideoCardDefaults [ i ] ;
RString sDriverRegex = defaults . sDriverRegex ;
Regex regex ( sDriverRegex ) ;
if ( regex . Compare ( sVideoDriver ) )
{
LOG - > Trace ( " Card matches '%s'. " , sDriverRegex . size ( ) ? sDriverRegex . c_str ( ) : " (unknown card) " ) ;
goto found_defaults ;
}
}
ASSERT ( 0 ) ; // we must have matched at least one above
found_defaults :
bool bSetDefaultVideoParams = false ;
if ( PREFSMAN - > m_sVideoRenderers . Get ( ) = = " " )
{
bSetDefaultVideoParams = true ;
LOG - > Trace ( " Applying defaults for %s. " , sVideoDriver . c_str ( ) ) ;
}
else if ( PREFSMAN - > m_sLastSeenVideoDriver . Get ( ) ! = sVideoDriver )
{
bSetDefaultVideoParams = true ;
LOG - > Trace ( " Video card has changed from %s to %s. Applying new defaults. " , PREFSMAN - > m_sLastSeenVideoDriver . Get ( ) . c_str ( ) , sVideoDriver . c_str ( ) ) ;
}
if ( bSetDefaultVideoParams )
{
PREFSMAN - > m_sVideoRenderers . Set ( defaults . sVideoRenderers ) ;
PREFSMAN - > m_iDisplayWidth . Set ( defaults . iWidth ) ;
PREFSMAN - > m_iDisplayHeight . Set ( defaults . iHeight ) ;
PREFSMAN - > m_iDisplayColorDepth . Set ( defaults . iDisplayColor ) ;
PREFSMAN - > m_iTextureColorDepth . Set ( defaults . iTextureColor ) ;
PREFSMAN - > m_iMovieColorDepth . Set ( defaults . iMovieColor ) ;
PREFSMAN - > m_iMaxTextureResolution . Set ( defaults . iTextureSize ) ;
PREFSMAN - > m_bSmoothLines . Set ( defaults . bSmoothLines ) ;
PREFSMAN - > m_fDisplayAspectRatio . Set ( HOOKS - > GetDisplayAspectRatio ( ) ) ;
// Update last seen video card
PREFSMAN - > m_sLastSeenVideoDriver . Set ( GetVideoDriverName ( ) ) ;
}
else if ( PREFSMAN - > m_sVideoRenderers . Get ( ) . CompareNoCase ( defaults . sVideoRenderers ) )
{
LOG - > Warn ( " Video renderer list has been changed from '%s' to '%s' " ,
defaults . sVideoRenderers . c_str ( ) , PREFSMAN - > m_sVideoRenderers . Get ( ) . c_str ( ) ) ;
}
LOG - > Info ( " Video renderers: '%s' " , PREFSMAN - > m_sVideoRenderers . Get ( ) . c_str ( ) ) ;
return bSetDefaultVideoParams ;
}
static LocalizedString ERROR_INITIALIZING_CARD ( " StepMania " , " There was an error while initializing your video card. " ) ;
static LocalizedString ERROR_DONT_FILE_BUG ( " StepMania " , " Please do not file this error as a bug! Use the web page below to troubleshoot this problem. " ) ;
static LocalizedString ERROR_VIDEO_DRIVER ( " StepMania " , " Video Driver: %s " ) ;
static LocalizedString ERROR_NO_VIDEO_RENDERERS ( " StepMania " , " No video renderers attempted. " ) ;
static LocalizedString ERROR_INITIALIZING ( " StepMania " , " Initializing %s... " ) ;
static LocalizedString ERROR_UNKNOWN_VIDEO_RENDERER ( " StepMania " , " Unknown video renderer value: %s " ) ;
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.
*
* Actually, right now we're falling back. I'm not sure which behavior is better.
*/
//bool bAppliedDefaults = CheckVideoDefaultSettings();
CheckVideoDefaultSettings ( ) ;
VideoModeParams params ;
StepMania : : GetPreferredVideoModeParams ( params ) ;
RString error = ERROR_INITIALIZING_CARD . GetValue ( ) + " \n \n " +
ERROR_DONT_FILE_BUG . GetValue ( ) + " \n \n "
VIDEO_TROUBLESHOOTING_URL " \n \n " +
ssprintf ( ERROR_VIDEO_DRIVER . GetValue ( ) , GetVideoDriverName ( ) . c_str ( ) ) + " \n \n " ;
vector < RString > asRenderers ;
split ( PREFSMAN - > m_sVideoRenderers , " , " , asRenderers , true ) ;
if ( asRenderers . empty ( ) )
RageException : : Throw ( " %s " , ERROR_NO_VIDEO_RENDERERS . GetValue ( ) . c_str ( ) ) ;
RageDisplay * pRet = NULL ;
for ( unsigned i = 0 ; i < asRenderers . size ( ) ; i + + )
{
RString sRenderer = asRenderers [ i ] ;
if ( sRenderer . CompareNoCase ( " opengl " ) = = 0 )
{
# if defined(SUPPORT_OPENGL)
2011-05-02 20:11:26 -05:00
pRet = new RageDisplay_Legacy ;
2011-03-17 01:47:30 -04:00
# endif
}
else if ( sRenderer . CompareNoCase ( " d3d " ) = = 0 )
{
2011-05-02 20:11:26 -05:00
// TODO: ANGLE/RageDisplay_Modern
//#if defined(SUPPORT_D3D)
// pRet = new RageDisplay_D3D;
//#endif
2011-03-17 01:47:30 -04:00
}
else if ( sRenderer . CompareNoCase ( " null " ) = = 0 )
{
return new RageDisplay_Null ;
}
else
{
RageException : : Throw ( ERROR_UNKNOWN_VIDEO_RENDERER . GetValue ( ) , sRenderer . c_str ( ) ) ;
}
if ( pRet = = NULL )
continue ;
RString sError = pRet - > Init ( params , PREFSMAN - > m_bAllowUnacceleratedRenderer ) ;
if ( ! sError . empty ( ) )
{
error + = ssprintf ( ERROR_INITIALIZING . GetValue ( ) , sRenderer . c_str ( ) ) + " \n " + sError ;
SAFE_DELETE ( pRet ) ;
error + = " \n \n \n " ;
continue ;
}
break ; // the display is ready to go
}
if ( pRet = = NULL )
RageException : : Throw ( " %s " , error . c_str ( ) ) ;
return pRet ;
}
static void SwitchToLastPlayedGame ( )
{
const Game * pGame = GAMEMAN - > StringToGame ( PREFSMAN - > GetCurrentGame ( ) ) ;
// If the active game type isn't actually available, revert to the default.
if ( pGame = = NULL )
pGame = GAMEMAN - > GetDefaultGame ( ) ;
if ( ! GAMEMAN - > IsGameEnabled ( pGame ) & & pGame ! = GAMEMAN - > GetDefaultGame ( ) )
{
pGame = GAMEMAN - > GetDefaultGame ( ) ;
LOG - > Warn ( " Default NoteSkin for \" %s \" missing, reverting to \" %s \" " ,
pGame - > m_szName , GAMEMAN - > GetDefaultGame ( ) - > m_szName ) ;
}
ASSERT ( GAMEMAN - > IsGameEnabled ( pGame ) ) ;
StepMania : : ChangeCurrentGame ( pGame ) ;
}
void StepMania : : ChangeCurrentGame ( const Game * g )
{
ASSERT ( g ) ;
ASSERT ( GAMESTATE ) ;
ASSERT ( ANNOUNCER ) ;
ASSERT ( THEME ) ;
GAMESTATE - > SetCurGame ( g ) ;
RString sAnnouncer = PREFSMAN - > m_sAnnouncer ;
RString sTheme = PREFSMAN - > m_sTheme ;
RString sLanguage = PREFSMAN - > m_sLanguage ;
if ( sAnnouncer . empty ( ) )
sAnnouncer = GAMESTATE - > GetCurrentGame ( ) - > m_szName ;
if ( sTheme . empty ( ) )
sTheme = GAMESTATE - > GetCurrentGame ( ) - > m_szName ;
// process theme and language command line arguments;
// these change the preferences in order for transparent loading -aj
RString argTheme ;
if ( GetCommandlineArgument ( " theme " , & argTheme ) & & argTheme ! = sTheme )
{
sTheme = argTheme ;
// set theme in preferences too for correct behavior -aj
PREFSMAN - > m_sTheme . Set ( sTheme ) ;
}
RString argLanguage ;
if ( GetCommandlineArgument ( " language " , & argLanguage ) )
{
sLanguage = argLanguage ;
// set language in preferences too for correct behavior -aj
PREFSMAN - > m_sLanguage . Set ( sLanguage ) ;
}
// it's OK to call these functions with names that don't exist.
ANNOUNCER - > SwitchAnnouncer ( sAnnouncer ) ;
THEME - > SwitchThemeAndLanguage ( sTheme , sLanguage , PREFSMAN - > m_bPseudoLocalize ) ;
// Set the input scheme for the new game, and load keymaps.
if ( INPUTMAPPER )
{
INPUTMAPPER - > SetInputScheme ( & g - > m_InputScheme ) ;
INPUTMAPPER - > ReadMappingsFromDisk ( ) ;
}
}
static void MountTreeOfZips ( const RString & dir )
{
vector < RString > dirs ;
dirs . push_back ( dir ) ;
while ( dirs . size ( ) )
{
RString path = dirs . back ( ) ;
dirs . pop_back ( ) ;
2011-05-02 20:11:26 -05:00
# if !defined(XBOX)
// Xbox doesn't detect directories properly, so we'll ignore this
2011-03-17 01:47:30 -04:00
if ( ! IsADirectory ( path ) )
continue ;
2011-05-02 20:11:26 -05:00
# endif
2011-03-17 01:47:30 -04:00
vector < RString > 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 ;
LOG - > Trace ( " VFS: found %s " , zips [ i ] . c_str ( ) ) ;
FILEMAN - > Mount ( " zip " , zips [ i ] , " / " ) ;
}
GetDirListing ( path + " /* " , dirs , true , true ) ;
}
}
# if defined(HAVE_VERSION_INFO)
extern unsigned long version_num ;
extern const char * const version_date ;
extern const char * const version_time ;
# endif
static void WriteLogHeader ( )
{
LOG - > Info ( PRODUCT_ID_VER ) ;
# if defined(HAVE_VERSION_INFO)
LOG - > Info ( " Compiled %s @ %s (build %lu) " , version_date , version_time , version_num ) ;
# endif
// this code should only be enabled in distributed builds
//LOG->Info("sm-ssc is Copyright � 2009 the spinal shark collective, all rights reserved. Commercial use of this binary is prohibited by law and will be prosecuted to the fullest extent of the law.");
// end limited code
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 , now . tm_min , now . tm_sec ) ;
LOG - > Trace ( " " ) ;
if ( g_argc > 1 )
{
RString args ;
for ( int i = 1 ; i < g_argc ; + + i )
{
if ( i > 1 )
args + = " " ;
// surround all params with some marker, as they might have whitespace.
// using [[ and ]], as they are not likely to be in the params.
args + = ssprintf ( " [[%s]] " , g_argv [ i ] ) ;
}
LOG - > Info ( " Command line args (count=%d): %s " , ( g_argc - 1 ) , args . c_str ( ) ) ;
}
}
static void ApplyLogPreferences ( )
{
LOG - > SetShowLogOutput ( PREFSMAN - > m_bShowLogOutput ) ;
LOG - > SetLogToDisk ( PREFSMAN - > m_bLogToDisk ) ;
LOG - > SetInfoToDisk ( true ) ;
LOG - > SetUserLogToDisk ( true ) ;
LOG - > SetFlushing ( PREFSMAN - > m_bForceLogFlush ) ;
Checkpoints : : LogCheckpoints ( PREFSMAN - > m_bLogCheckpoints ) ;
}
static LocalizedString COULDNT_OPEN_LOADING_WINDOW ( " StepMania " , " Couldn't open any loading windows. " ) ;
int main ( int argc , char * argv [ ] )
{
RageThreadRegister thread ( " Main thread " ) ;
RageException : : SetCleanupHandler ( HandleException ) ;
SetCommandlineArguments ( argc , argv ) ;
// Set up arch hooks first. This may set up crash handling.
HOOKS = ArchHooks : : Create ( ) ;
HOOKS - > Init ( ) ;
LUA = new LuaManager ;
// Almost everything uses this to read and write files. Load this early.
FILEMAN = new RageFileManager ( argv [ 0 ] ) ;
FILEMAN - > MountInitialFilesystems ( ) ;
bool bPortable = DoesFileExist ( " Portable.ini " ) ;
if ( ! bPortable )
FILEMAN - > MountUserFilesystems ( ) ;
// Set this up next. Do this early, since it's needed for RageException::Throw.
LOG = new RageLog ;
// Whew--we should be able to crash safely now!
// load preferences and mount any alternative trees.
PREFSMAN = new PrefsManager ;
/* Allow HOOKS to check for multiple instances. We need to do this after PREFS is initialized,
* so ArchHooks can use a preference to turn this off. We want to do this before ApplyLogPreferences,
* so if we exit because of another instance, we don't try to clobber its log. We also want to
* do this before opening the loading window, so if we give focus away, we don't flash the window. */
if ( ! g_bAllowMultipleInstances . Get ( ) & & HOOKS - > CheckForMultipleInstances ( argc , argv ) )
{
ShutdownGame ( ) ;
return 0 ;
}
ApplyLogPreferences ( ) ;
2011-05-02 20:11:26 -05:00
# if defined(XBOX)
vmem_Manager . Init ( ) ;
# endif
2011-03-17 01:47:30 -04:00
WriteLogHeader ( ) ;
// Set up alternative filesystem trees.
if ( PREFSMAN - > m_sAdditionalFolders . Get ( ) ! = " " )
{
vector < RString > dirs ;
split ( PREFSMAN - > m_sAdditionalFolders , " , " , dirs , true ) ;
for ( unsigned i = 0 ; i < dirs . size ( ) ; i + + )
FILEMAN - > Mount ( " dir " , dirs [ i ] , " / " ) ;
}
if ( PREFSMAN - > m_sAdditionalSongFolders . Get ( ) ! = " " )
{
vector < RString > dirs ;
split ( PREFSMAN - > m_sAdditionalSongFolders , " , " , dirs , true ) ;
for ( unsigned i = 0 ; i < dirs . size ( ) ; i + + )
FILEMAN - > Mount ( " dir " , dirs [ i ] , " /AdditionalSongs " ) ;
}
if ( PREFSMAN - > m_sAdditionalCourseFolders . Get ( ) ! = " " )
{
vector < RString > dirs ;
split ( PREFSMAN - > m_sAdditionalCourseFolders , " , " , dirs , true ) ;
for ( unsigned i = 0 ; i < dirs . size ( ) ; i + + )
FILEMAN - > Mount ( " dir " , dirs [ i ] , " /AdditionalCourses " ) ;
}
MountTreeOfZips ( SpecialFiles : : PACKAGES_DIR ) ;
MountTreeOfZips ( SpecialFiles : : USER_PACKAGES_DIR ) ;
/* One of the above filesystems might contain files that affect preferences
* (e.g. Data/Static.ini). Re-read preferences. */
PREFSMAN - > ReadPrefsFromDisk ( ) ;
ApplyLogPreferences ( ) ;
// This needs PREFSMAN.
Dialog : : Init ( ) ;
// Create game objects
GAMESTATE = new GameState ;
// This requires PREFSMAN, for PREFSMAN->m_bShowLoadingWindow.
LoadingWindow * pLoadingWindow = LoadingWindow : : Create ( ) ;
if ( pLoadingWindow = = NULL )
RageException : : Throw ( " %s " , COULDNT_OPEN_LOADING_WINDOW . GetValue ( ) . c_str ( ) ) ;
srand ( time ( NULL ) ) ; // seed number generator
/* Do this early, so we have debugging output if anything else fails. LOG and
* Dialog must be set up first. It shouldn't take long, but it might take a
* little time; do this after the LoadingWindow is shown, since we don't want
* that to appear delayed. */
HOOKS - > DumpDebugInfo ( ) ;
# if defined(HAVE_TLS)
LOG - > Info ( " TLS is %savailable " , RageThread : : GetSupportsTLS ( ) ? " " : " not " ) ;
# endif
AdjustForChangedSystemCapabilities ( ) ;
GAMEMAN = new GameManager ;
THEME = new ThemeManager ;
ANNOUNCER = new AnnouncerManager ;
NOTESKIN = new NoteSkinManager ;
// Switch to the last used game type, and set up the theme and announcer.
SwitchToLastPlayedGame ( ) ;
CommandLineActions : : Handle ( pLoadingWindow ) ;
if ( GetCommandlineArgument ( " dopefish " ) )
GAMESTATE - > m_bDopefish = true ;
{
/* Now that THEME is loaded, load the icon for the current theme into
* the loading window. */
RString sError ;
RageSurface * pIcon = RageSurfaceUtils : : LoadFile ( THEME - > GetPathG ( " Common " , " window icon " ) , sError ) ;
if ( pIcon )
pLoadingWindow - > SetIcon ( pIcon ) ;
delete pIcon ;
}
if ( PREFSMAN - > m_iSoundWriteAhead )
LOG - > Info ( " Sound writeahead has been overridden to %i " , PREFSMAN - > m_iSoundWriteAhead . Get ( ) ) ;
SOUNDMAN = new RageSoundManager ;
SOUNDMAN - > Init ( ) ;
SOUNDMAN - > SetMixVolume ( ) ;
SOUND = new GameSoundManager ;
BOOKKEEPER = new Bookkeeper ;
LIGHTSMAN = new LightsManager ;
INPUTFILTER = new InputFilter ;
INPUTMAPPER = new InputMapper ;
StepMania : : ChangeCurrentGame ( GAMESTATE - > GetCurrentGame ( ) ) ;
INPUTQUEUE = new InputQueue ;
SONGINDEX = new SongCacheIndex ;
BANNERCACHE = new BannerCache ;
//BACKGROUNDCACHE = new BackgroundCache;
// depends on SONGINDEX:
SONGMAN = new SongManager ;
SONGMAN - > InitAll ( pLoadingWindow ) ; // this takes a long time
CRYPTMAN = new CryptManager ; // need to do this before ProfileMan
if ( PREFSMAN - > m_bSignProfileData )
CRYPTMAN - > GenerateGlobalKeys ( ) ;
MEMCARDMAN = new MemoryCardManager ;
CHARMAN = new CharacterManager ;
PROFILEMAN = new ProfileManager ;
PROFILEMAN - > Init ( ) ; // must load after SONGMAN
UNLOCKMAN = new UnlockManager ;
SONGMAN - > UpdatePopular ( ) ;
SONGMAN - > UpdatePreferredSort ( ) ;
NSMAN = new NetworkSyncManager ( pLoadingWindow ) ;
MESSAGEMAN = new MessageManager ;
STATSMAN = new StatsManager ;
SAFE_DELETE ( pLoadingWindow ) ; // destroy this before init'ing Display
/* If the user has tried to quit during the loading, do it before creating
* the main window. This prevents going to full screen just to quit. */
if ( ArchHooks : : UserQuit ( ) )
{
ShutdownGame ( ) ;
return 0 ;
}
StartDisplay ( ) ;
StoreActualGraphicOptions ( ) ;
LOG - > Info ( " %s " , GetActualGraphicOptionsString ( ) . c_str ( ) ) ;
SONGMAN - > PreloadSongImages ( ) ;
/* Input handlers can have dependences on the video system so
* INPUTMAN must be initialized after DISPLAY. */
INPUTMAN = new RageInput ;
// These things depend on the TextureManager, so do them after!
FONT = new FontManager ;
SCREENMAN = new ScreenManager ;
StepMania : : ResetGame ( ) ;
/* Now that GAMESTATE is reset, tell SCREENMAN to update the theme (load
* overlay screens and global sounds), and load the initial screen. */
SCREENMAN - > ThemeChanged ( ) ;
SCREENMAN - > SetNewScreen ( StepMania : : GetInitialScreen ( ) ) ;
// Do this after ThemeChanged so that we can show a system message
RString sMessage ;
if ( INPUTMAPPER - > CheckForChangedInputDevicesAndRemap ( sMessage ) )
SCREENMAN - > SystemMessage ( sMessage ) ;
CodeDetector : : RefreshCacheItems ( ) ;
// Initialize which courses are ranking courses here.
SONGMAN - > UpdateRankingCourses ( ) ;
if ( GetCommandlineArgument ( " netip " ) )
NSMAN - > DisplayStartupStatus ( ) ; // If we're using networking show what happened
// Run the main loop.
GameLoop : : RunGameLoop ( ) ;
PREFSMAN - > SavePrefsToDisk ( ) ;
ShutdownGame ( ) ;
return 0 ;
}
RString StepMania : : SaveScreenshot ( RString sDir , bool bSaveCompressed , bool bMakeSignature , int iIndex )
{
/* As of sm-ssc v1.0 rc2, screenshots are no longer named by an arbitrary
* index. This was causing naming issues for some unknown reason, so we have
* changed the screenshot names to a non-blocking format: date and time.
* As before, we ignore the extension. -aj */
RString sFileNameNoExtension = DateTime : : GetNowDateTime ( ) . GetString ( ) ;
// replace space with underscore.
sFileNameNoExtension . Replace ( " " , " _ " ) ;
// colons are illegal in filenames.
sFileNameNoExtension . Replace ( " : " , " " ) ;
// Save the screenshot. If writing lossy to a memcard, use
// SAVE_LOSSY_LOW_QUAL, so we don't eat up lots of space.
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_SENSIBLE ;
RString sFileName = sFileNameNoExtension + " . " + ( bSaveCompressed ? " jpg " : " png " ) ;
RString sPath = sDir + sFileName ;
bool bResult = DISPLAY - > SaveScreenshot ( sPath , fmt ) ;
if ( ! bResult )
{
SCREENMAN - > PlayInvalidSound ( ) ;
return RString ( ) ;
}
SCREENMAN - > PlayScreenshotSound ( ) ;
if ( PREFSMAN - > m_bSignProfileData & & bMakeSignature )
CryptManager : : SignFileToFile ( sPath ) ;
return sFileName ;
}
void StepMania : : InsertCoin ( int iNum , bool bCountInBookkeeping )
{
if ( bCountInBookkeeping )
{
LIGHTSMAN - > PulseCoinCounter ( ) ;
BOOKKEEPER - > CoinInserted ( ) ;
}
int iNumCoinsOld = GAMESTATE - > m_iCoins ;
GAMESTATE - > m_iCoins . Set ( GAMESTATE - > m_iCoins + iNum ) ;
int iCredits = GAMESTATE - > m_iCoins / PREFSMAN - > m_iCoinsPerCredit ;
bool bMaxCredits = iCredits > = MAX_NUM_CREDITS ;
if ( bMaxCredits )
GAMESTATE - > m_iCoins . Set ( MAX_NUM_CREDITS * PREFSMAN - > m_iCoinsPerCredit ) ;
LOG - > Trace ( " %i coins inserted, %i needed to play " , GAMESTATE - > m_iCoins . Get ( ) , PREFSMAN - > m_iCoinsPerCredit . Get ( ) ) ;
if ( iNumCoinsOld ! = GAMESTATE - > m_iCoins )
SCREENMAN - > PlayCoinSound ( ) ;
else
SCREENMAN - > PlayInvalidSound ( ) ;
/* If AutoJoin and a player is already joined, then try to join a player.
* (If no players are joined, they'll join on the first JoinInput.) */
if ( GAMESTATE - > m_bAutoJoin . Get ( ) & & GAMESTATE - > GetNumSidesJoined ( ) > 0 )
{
if ( GAMESTATE - > GetNumSidesJoined ( ) > 0 & & GAMESTATE - > JoinPlayers ( ) )
SCREENMAN - > PlayStartSound ( ) ;
}
// TODO: remove this redundant message and things that depend on it
Message msg ( " CoinInserted " ) ;
// below params are unused
//msg.SetParam( "Coins", GAMESTATE->m_iCoins );
//msg.SetParam( "Inserted", iNum );
//msg.SetParam( "MaxCredits", bMaxCredits );
MESSAGEMAN - > Broadcast ( msg ) ;
}
void StepMania : : InsertCredit ( )
{
InsertCoin ( PREFSMAN - > m_iCoinsPerCredit , false ) ;
}
void StepMania : : ClearCredits ( )
{
LOG - > Trace ( " %i coins cleared " , GAMESTATE - > m_iCoins . Get ( ) ) ;
GAMESTATE - > m_iCoins . Set ( 0 ) ;
SCREENMAN - > PlayInvalidSound ( ) ;
// TODO: remove this redundant message and things that depend on it
Message msg ( " CoinInserted " ) ;
// below params are unused
//msg.SetParam( "Coins", GAMESTATE->m_iCoins );
//msg.SetParam( "Clear", true );
MESSAGEMAN - > Broadcast ( msg ) ;
}
/* Returns true if the key has been handled and should be discarded, false if
* the key should be sent on to screens. */
static LocalizedString SERVICE_SWITCH_PRESSED ( " StepMania " , " Service switch pressed " ) ;
static LocalizedString RELOADED_METRICS ( " ThemeManager " , " Reloaded metrics " ) ;
static LocalizedString RELOADED_METRICS_AND_TEXTURES ( " ThemeManager " , " Reloaded metrics and textures " ) ;
static LocalizedString RELOADED_SCRIPTS ( " ThemeManager " , " Reloaded scripts " ) ;
static LocalizedString RELOADED_OVERLAY_SCREENS ( " ThemeManager " , " Reloaded overlay screens " ) ;
bool HandleGlobalInputs ( const InputEventPlus & input )
{
// None of the globals keys act on types other than FIRST_PRESS
if ( input . type ! = IET_FIRST_PRESS )
return false ;
switch ( input . MenuI )
{
case GAME_BUTTON_OPERATOR :
/* 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 ( SCREENMAN - > AllowOperatorMenuButton ( ) )
{
SCREENMAN - > SystemMessage ( SERVICE_SWITCH_PRESSED ) ;
SCREENMAN - > PopAllScreens ( ) ;
GAMESTATE - > Reset ( ) ;
SCREENMAN - > SetNewScreen ( CommonMetrics : : OPERATOR_MENU_SCREEN ) ;
}
return true ;
case GAME_BUTTON_COIN :
// Handle a coin insertion.
if ( GAMESTATE - > IsEditing ( ) ) // no coins while editing
{
LOG - > Trace ( " Ignored coin insertion (editing) " ) ;
break ;
}
StepMania : : InsertCoin ( ) ;
return false ; // Attract needs to know because it goes to TitleMenu on > 1 credit
}
/* Re-added for StepMania 3.9 theming veterans, plus it's just faster than
* the debug menu. However, in sm-ssc, the Shift button only reloads the
* metrics, unlike in 3.9 (where it saved bookkeeping and machine profile). -aj */
bool bIsShiftHeld = INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LSHIFT ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RSHIFT ) , & input . InputList ) ;
bool bIsCtrlHeld = INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LCTRL ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RCTRL ) , & input . InputList ) ;
if ( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_F2 ) )
{
if ( bIsShiftHeld & & ! bIsCtrlHeld )
{
// Shift+F2: refresh metrics and CodeDetector cache only
THEME - > ReloadMetrics ( ) ;
CodeDetector : : RefreshCacheItems ( ) ;
SCREENMAN - > SystemMessage ( RELOADED_METRICS ) ;
}
else if ( bIsCtrlHeld & & ! bIsShiftHeld )
{
// Ctrl+F2: reload scripts only
THEME - > UpdateLuaGlobals ( ) ;
SCREENMAN - > SystemMessage ( RELOADED_SCRIPTS ) ;
}
else if ( bIsCtrlHeld & & bIsShiftHeld )
{
// Shift+Ctrl+F2: reload overlay screens (and metrics, since themers
// are likely going to do this after changing metrics and be lazy.)
THEME - > ReloadMetrics ( ) ;
SCREENMAN - > ReloadOverlayScreens ( ) ;
SCREENMAN - > SystemMessage ( RELOADED_OVERLAY_SCREENS ) ;
}
else
{
// F2 alone: refresh metrics, textures, noteskins, codedetector cache
THEME - > ReloadMetrics ( ) ;
TEXTUREMAN - > ReloadAll ( ) ;
NOTESKIN - > RefreshNoteSkinData ( GAMESTATE - > m_pCurGame ) ;
CodeDetector : : RefreshCacheItems ( ) ;
SCREENMAN - > SystemMessage ( RELOADED_METRICS_AND_TEXTURES ) ;
}
return true ;
}
if ( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_PAUSE ) )
{
Message msg ( " ToggleConsoleDisplay " ) ;
MESSAGEMAN - > Broadcast ( msg ) ;
return true ;
}
# if !defined(MACOSX)
if ( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_F4 ) )
{
if ( INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RALT ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LALT ) , & input . InputList ) )
{
// pressed Alt+F4
ArchHooks : : SetUserQuit ( ) ;
return true ;
}
}
# else
if ( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_Cq ) & &
( INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LMETA ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RMETA ) , & input . InputList ) ) )
{
/* The user quit is handled by the menu item so we don't need to set it
* here; however, we do want to return that it has been handled since
* this will happen first. */
return true ;
}
# endif
bool bDoScreenshot =
# if defined(MACOSX)
// Notebooks don't have F13. Use cmd-F12 as well.
input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_PRTSC ) | |
input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_F13 ) | |
( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_F12 ) & &
( INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LMETA ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RMETA ) , & input . InputList ) ) ) ;
# else
/* The default Windows message handler will capture the desktop window upon
* pressing PrntScrn, or will capture the foreground with focus upon pressing
* Alt+PrntScrn. Windows will do this whether or not we save a screenshot
* ourself by dumping the frame buffer. */
// "if pressing PrintScreen and not pressing Alt"
input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_PRTSC ) & &
! INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LALT ) , & input . InputList ) & &
! INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RALT ) , & input . InputList ) ;
# endif
if ( bDoScreenshot )
{
// If holding Shift save uncompressed, else save compressed
bool bHoldingShift = ( INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LSHIFT ) )
| | INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RSHIFT ) ) ) ;
bool bSaveCompressed = ! bHoldingShift ;
RageTimer timer ;
StepMania : : SaveScreenshot ( " Screenshots/ " , bSaveCompressed , false , - 1 ) ;
LOG - > Trace ( " Screenshot took %f seconds. " , timer . GetDeltaTime ( ) ) ;
return true ; // handled
}
if ( input . DeviceI = = DeviceInput ( DEVICE_KEYBOARD , KEY_ENTER ) & &
( INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_RALT ) , & input . InputList ) | |
INPUTFILTER - > IsBeingPressed ( DeviceInput ( DEVICE_KEYBOARD , KEY_LALT ) , & input . InputList ) ) )
{
// alt-enter
/* In OS X, this is a menu item and will be handled as such. This will
* happen first and then the lower priority GUI thread will happen second,
* causing the window to toggle twice. Another solution would be to put
* a timer in ArchHooks::SetToggleWindowed() and just not set the bool
* it if it's been less than, say, half a second. */
# if !defined(MACOSX)
ArchHooks : : SetToggleWindowed ( ) ;
# endif
return true ;
}
return false ;
}
void HandleInputEvents ( float fDeltaTime )
{
INPUTFILTER - > Update ( fDeltaTime ) ;
/* 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. Call Update above, so the inputs are
* read and timestamped. */
if ( SCREENMAN - > GetTopScreen ( ) - > IsFirstUpdate ( ) )
return ;
vector < InputEvent > ieArray ;
INPUTFILTER - > GetInputEvents ( ieArray ) ;
// If we don't have focus, discard input.
if ( ! HOOKS - > AppHasFocus ( ) )
return ;
for ( unsigned i = 0 ; i < ieArray . size ( ) ; i + + )
{
InputEventPlus input ;
input . DeviceI = ieArray [ i ] . di ;
input . type = ieArray [ i ] . type ;
swap ( input . InputList , ieArray [ i ] . m_ButtonState ) ;
// hack for testing (MultiPlayer) with only one joystick
/*
if( input.DeviceI.IsJoystick() )
{
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,KEY_LSHIFT) ) )
input.DeviceI.device = (InputDevice)(input.DeviceI.device + 1);
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,KEY_LCTRL) ) )
input.DeviceI.device = (InputDevice)(input.DeviceI.device + 2);
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,KEY_LALT) ) )
input.DeviceI.device = (InputDevice)(input.DeviceI.device + 4);
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,KEY_RALT) ) )
input.DeviceI.device = (InputDevice)(input.DeviceI.device + 8);
if( INPUTFILTER->IsBeingPressed( DeviceInput(DEVICE_KEYBOARD,KEY_RCTRL) ) )
input.DeviceI.device = (InputDevice)(input.DeviceI.device + 16);
}
*/
INPUTMAPPER - > DeviceToGame ( input . DeviceI , input . GameI ) ;
input . mp = MultiPlayer_Invalid ;
{
// Translate input to the appropriate MultiPlayer. Assume that all
// joystick devices are mapped the same as the master player.
if ( input . DeviceI . IsJoystick ( ) )
{
DeviceInput diTemp = input . DeviceI ;
diTemp . device = DEVICE_JOY1 ;
GameInput gi ;
//LOG->Trace( "device %d, %d", diTemp.device, diTemp.button );
if ( INPUTMAPPER - > DeviceToGame ( diTemp , gi ) )
{
if ( GAMESTATE - > m_bMultiplayer )
{
input . GameI = gi ;
//LOG->Trace( "game %d %d", input.GameI.controller, input.GameI.button );
}
input . mp = InputMapper : : InputDeviceToMultiPlayer ( input . DeviceI . device ) ;
//LOG->Trace( "multiplayer %d", input.mp );
ASSERT ( input . mp > = 0 & & input . mp < NUM_MultiPlayer ) ;
}
}
}
if ( input . GameI . IsValid ( ) )
{
input . MenuI = INPUTMAPPER - > GameButtonToMenuButton ( input . GameI . button ) ;
input . pn = INPUTMAPPER - > ControllerToPlayerNumber ( input . GameI . controller ) ;
}
INPUTQUEUE - > RememberInput ( input ) ;
// When a GameButton is pressed, stop repeating other keys on the same controller.
if ( input . type = = IET_FIRST_PRESS & & input . MenuI ! = GameButton_Invalid )
{
FOREACH_ENUM ( GameButton , m )
{
if ( input . MenuI ! = m )
INPUTMAPPER - > RepeatStopKey ( m , input . pn ) ;
}
}
if ( HandleGlobalInputs ( input ) )
continue ; // skip
// check back in event mode
if ( GAMESTATE - > IsEventMode ( ) & &
CodeDetector : : EnteredCode ( input . GameI . controller , CODE_BACK_IN_EVENT_MODE ) )
{
input . pn = PLAYER_1 ;
input . MenuI = GAME_BUTTON_BACK ;
}
SCREENMAN - > Input ( input ) ;
}
if ( ArchHooks : : GetAndClearToggleWindowed ( ) )
{
PREFSMAN - > m_bWindowed . Set ( ! PREFSMAN - > m_bWindowed ) ;
StepMania : : ApplyGraphicOptions ( ) ;
}
}
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/