2012-09-07 21:44:07 +00:00
//EmulationStation, a graphical front-end for ROM browsing. Created by Alec "Aloshi" Lofquist.
2013-06-02 21:05:29 +00:00
//http://www.aloshi.com
2012-09-07 21:44:07 +00:00
2013-05-13 19:53:28 +00:00
# include <SDL.h>
2012-07-19 01:14:17 +00:00
# include <iostream>
2013-05-29 18:22:02 +00:00
# include <iomanip>
2012-07-19 01:14:17 +00:00
# include "Renderer.h"
2012-07-20 16:14:09 +00:00
# include "components/GuiGameList.h"
# include "SystemData.h"
2012-07-23 23:53:33 +00:00
# include <boost/filesystem.hpp>
2013-04-09 18:13:47 +00:00
# include "components/GuiDetectDevice.h"
2012-10-13 18:29:53 +00:00
# include "AudioManager.h"
2012-09-10 18:10:59 +00:00
# include "platform.h"
2013-01-04 23:31:51 +00:00
# include "Log.h"
2013-04-08 16:52:40 +00:00
# include "Window.h"
2013-06-02 16:17:13 +00:00
# include "EmulationStation.h"
2013-06-17 19:01:03 +00:00
# include "Settings.h"
2012-09-10 18:10:59 +00:00
# ifdef _RPI_
# include <bcm_host.h>
# endif
2012-09-07 21:44:07 +00:00
# include <sstream>
2012-08-08 00:50:45 +00:00
2012-08-12 14:43:09 +00:00
namespace fs = boost : : filesystem ;
2013-07-09 10:37:37 +00:00
bool parseArgs ( int argc , char * argv [ ] , unsigned int * width , unsigned int * height )
2012-07-19 01:14:17 +00:00
{
2012-07-27 22:35:45 +00:00
if ( argc > 1 )
{
for ( int i = 1 ; i < argc ; i + + )
{
if ( strcmp ( argv [ i ] , " -w " ) = = 0 )
{
2013-07-09 10:37:37 +00:00
* width = atoi ( argv [ i + 1 ] ) ;
2013-05-13 19:53:28 +00:00
i + + ; //skip the argument value
2012-07-27 22:35:45 +00:00
} else if ( strcmp ( argv [ i ] , " -h " ) = = 0 )
{
2013-07-09 10:37:37 +00:00
* height = atoi ( argv [ i + 1 ] ) ;
2013-05-13 19:53:28 +00:00
i + + ; //skip the argument value
2012-08-08 00:50:45 +00:00
} else if ( strcmp ( argv [ i ] , " --gamelist-only " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " PARSEGAMELISTONLY " , true ) ;
2012-08-11 04:17:52 +00:00
} else if ( strcmp ( argv [ i ] , " --ignore-gamelist " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " IGNOREGAMELIST " , true ) ;
2012-09-07 21:44:07 +00:00
} else if ( strcmp ( argv [ i ] , " --draw-framerate " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " DRAWFRAMERATE " , true ) ;
2012-12-18 15:20:13 +00:00
} else if ( strcmp ( argv [ i ] , " --no-exit " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " DONTSHOWEXIT " , true ) ;
2012-12-20 18:29:05 +00:00
} else if ( strcmp ( argv [ i ] , " --debug " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " DEBUG " , true ) ;
2013-01-06 20:33:50 +00:00
Log : : setReportingLevel ( LogDebug ) ;
2013-03-19 14:29:44 +00:00
} else if ( strcmp ( argv [ i ] , " --dimtime " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setInt ( " DIMTIME " , atoi ( argv [ i + 1 ] ) * 1000 ) ;
2013-05-13 19:53:28 +00:00
i + + ; //skip the argument value
} else if ( strcmp ( argv [ i ] , " --windowed " ) = = 0 )
{
2013-06-17 19:01:03 +00:00
Settings : : getInstance ( ) - > setBool ( " WINDOWED " , true ) ;
2012-10-31 14:46:06 +00:00
} else if ( strcmp ( argv [ i ] , " --help " ) = = 0 )
2012-09-07 21:44:07 +00:00
{
std : : cout < < " EmulationStation, a graphical front-end for ROM browsing. \n " ;
std : : cout < < " Command line arguments: \n " ;
2012-09-07 21:53:27 +00:00
std : : cout < < " -w [width in pixels] set screen width \n " ;
std : : cout < < " -h [height in pixels] set screen height \n " ;
std : : cout < < " --gamelist-only skip automatic game detection, only read from gamelist.xml \n " ;
2012-09-07 21:44:07 +00:00
std : : cout < < " --ignore-gamelist ignore the gamelist (useful for troubleshooting) \n " ;
std : : cout < < " --draw-framerate display the framerate \n " ;
2012-12-18 15:20:13 +00:00
std : : cout < < " --no-exit don't show the exit option in the menu \n " ;
2013-01-04 23:31:51 +00:00
std : : cout < < " --debug even more logging \n " ;
2013-03-19 14:29:44 +00:00
std : : cout < < " --dimtime [seconds] time to wait before dimming the screen (default 30, use 0 for never) \n " ;
2013-05-13 19:53:28 +00:00
2013-06-02 21:05:29 +00:00
# ifdef USE_OPENGL_DESKTOP
2013-05-13 19:53:28 +00:00
std : : cout < < " --windowed not fullscreen \n " ;
# endif
2012-09-07 21:53:27 +00:00
std : : cout < < " --help summon a sentient, angry tuba \n \n " ;
2012-09-07 21:44:07 +00:00
std : : cout < < " More information available in README.md. \n " ;
2013-07-09 10:37:37 +00:00
return false ; //exit after printing help
2012-07-27 22:35:45 +00:00
}
}
}
2013-07-09 10:37:37 +00:00
return true ;
}
2012-09-07 21:53:27 +00:00
2013-07-09 10:37:37 +00:00
bool verifyHomeFolderExists ( )
{
2013-01-08 02:24:59 +00:00
//make sure the config directory exists
2013-05-13 19:53:28 +00:00
std : : string home = getHomePath ( ) ;
2013-01-08 02:24:59 +00:00
std : : string configDir = home + " /.emulationstation " ;
if ( ! fs : : exists ( configDir ) )
{
std : : cout < < " Creating config directory \" " < < configDir < < " \" \n " ;
fs : : create_directory ( configDir ) ;
2013-07-09 10:37:37 +00:00
if ( ! fs : : exists ( configDir ) )
{
std : : cerr < < " Config directory could not be created! \n " ;
return false ;
}
2013-01-08 02:24:59 +00:00
}
2013-07-09 10:37:37 +00:00
return true ;
}
//called on exit, assuming we get far enough to have the log initialized
void onExit ( )
{
Log : : close ( ) ;
# ifdef _RPI_
bcm_host_deinit ( ) ;
# endif
}
int main ( int argc , char * argv [ ] )
{
unsigned int width = 0 ;
unsigned int height = 0 ;
if ( ! parseArgs ( argc , argv , & width , & height ) )
return 0 ;
//if ~/.emulationstation doesn't exist and cannot be created, bail
if ( ! verifyHomeFolderExists ( ) )
return 1 ;
# ifdef _RPI_
bcm_host_init ( ) ;
# endif
2013-01-08 02:24:59 +00:00
//start the logger
Log : : open ( ) ;
2013-06-02 16:17:13 +00:00
LOG ( LogInfo ) < < " EmulationStation - " < < PROGRAM_VERSION_STRING ;
2013-01-08 02:24:59 +00:00
2013-07-09 10:37:37 +00:00
//always close the log and deinit the BCM library on exit
atexit ( & onExit ) ;
Window window ;
if ( ! window . init ( width , height ) )
2012-07-19 16:13:27 +00:00
{
2013-07-09 10:37:37 +00:00
LOG ( LogError ) < < " Window failed to initialize! " ;
2012-07-19 16:13:27 +00:00
return 1 ;
}
2013-08-09 00:15:50 +00:00
//dont generate joystick events while we're loading (hopefully fixes "automatically started emulator" bug)
SDL_JoystickEventState ( SDL_DISABLE ) ;
2012-08-08 00:50:45 +00:00
//try loading the system config file
2013-07-09 10:37:37 +00:00
if ( ! SystemData : : loadConfig ( SystemData : : getConfigPath ( ) , true ) )
2012-07-23 23:53:33 +00:00
{
2013-07-09 10:37:37 +00:00
LOG ( LogError ) < < " Error parsing system config file! " ;
return 1 ;
}
2012-07-19 16:13:27 +00:00
2013-07-09 10:37:37 +00:00
//make sure it wasn't empty
if ( SystemData : : sSystemVector . size ( ) = = 0 )
{
2013-08-13 06:56:10 +00:00
LOG ( LogError ) < < " No systems found! Does at least one system have a game present? (check that extensions match!) \n (Also, make sure you've updated your es_systems.cfg for XML!) " ;
2013-07-09 10:37:37 +00:00
return 1 ;
}
//choose which GUI to open depending on if an input configuration already exists
if ( fs : : exists ( InputManager : : getConfigPath ( ) ) )
{
GuiGameList : : create ( & window ) ;
} else {
window . pushGui ( new GuiDetectDevice ( & window ) ) ;
2012-07-23 23:53:33 +00:00
}
2012-07-22 21:15:55 +00:00
2013-08-09 00:15:50 +00:00
//generate joystick events since we're done loading
SDL_JoystickEventState ( SDL_ENABLE ) ;
2013-03-19 14:29:44 +00:00
bool sleeping = false ;
unsigned int timeSinceLastEvent = 0 ;
2012-08-02 01:43:55 +00:00
int lastTime = 0 ;
2013-07-09 10:37:37 +00:00
bool running = true ;
2012-07-19 16:13:27 +00:00
while ( running )
{
SDL_Event event ;
while ( SDL_PollEvent ( & event ) )
{
switch ( event . type )
{
2012-07-24 02:10:05 +00:00
case SDL_JOYHATMOTION :
2012-07-22 21:15:55 +00:00
case SDL_JOYBUTTONDOWN :
case SDL_JOYBUTTONUP :
2012-07-19 16:13:27 +00:00
case SDL_KEYDOWN :
2012-07-20 01:08:29 +00:00
case SDL_KEYUP :
2013-03-19 14:29:44 +00:00
case SDL_JOYAXISMOTION :
2013-04-08 16:52:40 +00:00
if ( window . getInputManager ( ) - > parseEvent ( event ) )
2013-03-25 13:16:54 +00:00
{
sleeping = false ;
timeSinceLastEvent = 0 ;
}
2012-07-19 16:13:27 +00:00
break ;
2013-06-27 08:26:56 +00:00
case SDL_USEREVENT :
2013-05-24 11:44:40 +00:00
//try to poll input devices, but do not necessarily wake up...
window . getInputManager ( ) - > parseEvent ( event ) ;
break ;
2012-07-19 16:13:27 +00:00
case SDL_QUIT :
running = false ;
break ;
}
}
2013-03-19 14:29:44 +00:00
if ( sleeping )
{
lastTime = SDL_GetTicks ( ) ;
2013-06-27 08:26:56 +00:00
SDL_Delay ( 1 ) ; //this doesn't need to be accurate
2013-03-19 14:29:44 +00:00
continue ;
}
2012-08-02 01:43:55 +00:00
int curTime = SDL_GetTicks ( ) ;
int deltaTime = curTime - lastTime ;
lastTime = curTime ;
2013-08-07 03:46:25 +00:00
//cap deltaTime at 1000
if ( deltaTime > 1000 | | deltaTime < 0 )
deltaTime = 1000 ;
2013-04-08 16:52:40 +00:00
window . update ( deltaTime ) ;
2013-06-20 00:56:45 +00:00
Renderer : : swapBuffers ( ) ; //swap here so we can read the last screen state during updates (see ImageComponent::copyScreen())
2013-04-08 16:52:40 +00:00
window . render ( ) ;
2012-09-07 21:44:07 +00:00
2013-03-19 14:29:44 +00:00
//sleep if we're past our threshold
//sleeping entails setting a flag to start skipping frames
//and initially drawing a black semi-transparent rect to dim the screen
timeSinceLastEvent + = deltaTime ;
2013-06-17 19:01:03 +00:00
if ( timeSinceLastEvent > = ( unsigned int ) Settings : : getInstance ( ) - > getInt ( " DIMTIME " ) & & Settings : : getInstance ( ) - > getInt ( " DIMTIME " ) ! = 0 )
2013-03-19 14:29:44 +00:00
{
sleeping = true ;
timeSinceLastEvent = 0 ;
Renderer : : drawRect ( 0 , 0 , Renderer : : getScreenWidth ( ) , Renderer : : getScreenHeight ( ) , 0x000000A0 ) ;
2013-06-20 00:56:45 +00:00
Renderer : : swapBuffers ( ) ;
2013-03-19 14:29:44 +00:00
}
2012-09-07 21:44:07 +00:00
2013-01-04 23:31:51 +00:00
Log : : flush ( ) ;
2012-07-19 16:13:27 +00:00
}
2012-08-29 18:53:53 +00:00
Renderer : : deinit ( ) ;
2012-07-21 20:57:53 +00:00
SystemData : : deleteSystems ( ) ;
2012-07-19 01:14:17 +00:00
2012-07-20 01:08:29 +00:00
std : : cout < < " EmulationStation cleanly shutting down... \n " ;
2012-07-19 01:14:17 +00:00
return 0 ;
}