2014-01-22 17:33:55 +01:00
# include <components/version/version.hpp>
2012-01-21 01:14:35 +01:00
# include <components/files/configurationmanager.hpp>
2019-01-22 10:08:48 +04:00
# include <components/fallback/fallback.hpp>
2016-01-06 12:46:06 +01:00
# include <components/fallback/validate.hpp>
2018-08-03 13:19:12 +04:00
# include <components/debug/debugging.hpp>
2019-02-24 22:41:11 +03:00
# include <components/misc/rng.hpp>
2022-06-01 10:34:53 +03:00
# include <components/platform/platform.hpp>
2011-04-28 09:39:40 +02:00
2022-05-22 02:47:58 +02:00
# include "mwgui/debugwindow.hpp"
2010-06-16 12:13:21 +02:00
# include "engine.hpp"
2021-09-30 03:48:47 +02:00
# include "options.hpp"
2010-02-28 14:51:17 +01:00
2022-06-25 17:51:01 +02:00
# include <boost/program_options/variables_map.hpp>
2014-06-10 02:22:58 +02:00
# if defined(_WIN32)
2022-04-23 19:00:47 +02:00
# include <components/windows.hpp>
2010-09-19 02:01:01 +02:00
// makes __argc and __argv available on windows
2012-07-17 09:44:24 +02:00
# include <cstdlib>
2021-01-18 18:13:57 +00:00
extern " C " __declspec ( dllexport ) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001 ;
2010-09-19 02:01:01 +02:00
# endif
2022-05-28 22:51:32 +02:00
# include <filesystem>
2017-08-06 13:02:22 +02:00
# if (defined(__APPLE__) || defined(__linux) || defined(__unix) || defined(__posix))
# include <unistd.h>
# endif
2013-11-16 15:56:15 +01:00
2012-04-03 01:47:43 +02:00
2016-01-06 12:46:06 +01:00
using namespace Fallback ;
2012-04-03 01:47:43 +02:00
2011-08-19 21:06:09 +02:00
/**
* \ brief Parses application command line and calls \ ref Cfg : : ConfigurationManager
* to parse configuration files .
*
* Results are directly written to \ ref Engine class .
*
* \ retval true - Everything goes OK
* \ retval false - Error
*/
2012-01-21 01:14:35 +01:00
bool parseOptions ( int argc , char * * argv , OMW : : Engine & engine , Files : : ConfigurationManager & cfgMgr )
2010-02-28 14:51:17 +01:00
{
2010-06-27 16:44:15 -07:00
// Create a local alias for brevity
2010-10-05 18:23:53 +02:00
namespace bpo = boost : : program_options ;
2016-07-12 01:06:57 +01:00
typedef std : : vector < std : : string > StringsVector ;
2010-06-27 16:44:15 -07:00
2021-09-30 03:48:47 +02:00
bpo : : options_description desc = OpenMW : : makeOptionsDescription ( ) ;
2011-08-19 21:06:09 +02:00
bpo : : variables_map variables ;
2010-06-11 19:53:00 +02:00
2021-09-30 03:48:47 +02:00
Files : : parseArgs ( argc , argv , variables , desc ) ;
2010-07-04 17:16:57 -04:00
bpo : : notify ( variables ) ;
2010-06-10 10:31:50 +02:00
if ( variables . count ( " help " ) )
{
2020-12-08 22:23:11 +01:00
getRawStdout ( ) < < desc < < std : : endl ;
2015-01-31 18:36:53 +01:00
return false ;
2011-07-08 16:16:20 +02:00
}
2015-07-18 03:01:06 +02:00
if ( variables . count ( " version " ) )
2011-07-08 16:16:20 +02:00
{
2015-07-18 03:01:06 +02:00
cfgMgr . readConfiguration ( variables , desc , true ) ;
2010-06-16 12:21:02 +02:00
2022-06-23 19:13:10 +02:00
Version : : Version v = Version : : getOpenmwVersion ( variables [ " resources " ] . as < Files : : MaybeQuotedPath > ( ) . u8string ( ) ) ; // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
2020-12-08 22:23:11 +01:00
getRawStdout ( ) < < v . describe ( ) < < std : : endl ;
2010-06-16 12:21:02 +02:00
return false ;
2015-07-18 03:01:06 +02:00
}
2011-07-08 16:16:20 +02:00
2013-12-23 23:55:40 +01:00
cfgMgr . readConfiguration ( variables , desc ) ;
2022-05-22 02:47:58 +02:00
Settings : : Manager : : load ( cfgMgr ) ;
2013-12-23 23:55:40 +01:00
2022-06-19 13:28:33 +02:00
setupLogging ( cfgMgr . getLogPath ( ) , " OpenMW " ) ;
2022-05-22 02:47:58 +02:00
MWGui : : DebugWindow : : startLogRecording ( ) ;
2022-01-13 00:20:16 +01:00
2022-06-23 19:13:10 +02:00
Version : : Version v = Version : : getOpenmwVersion ( variables [ " resources " ] . as < Files : : MaybeQuotedPath > ( ) . u8string ( ) ) ; // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
2020-12-08 11:06:30 +04:00
Log ( Debug : : Info ) < < v . describe ( ) ;
2015-11-19 02:56:26 +01:00
2017-03-04 21:36:11 +01:00
engine . setGrabMouse ( ! variables [ " no-grab " ] . as < bool > ( ) ) ;
2013-11-29 20:06:54 +01:00
Added new command line option: "encoding"
Added new command line option: "encoding" which allow to
change font encoding used in game messages.
Currently there are three evailable encodings:
win1250 - Central and Eastern European (languages
that use Latin script, such as Polish,
Czech, Slovak, Hungarian, Slovene, Bosnian,
Croatian, Serbian (Latin script),
Romanian and Albanian)
win1251 - languages that use the Cyrillic alphabet
such as Russian, Bulgarian, Serbian Cyrillic
and others
win1252 - Western European (Latin) - default
Signed-off-by: Lukasz Gromanowski <lgromanowski@gmail.com>
2011-07-17 22:16:50 +02:00
// Font encoding settings
2021-10-09 01:49:08 +01:00
std : : string encoding ( variables [ " encoding " ] . as < std : : string > ( ) ) ;
2020-12-08 11:06:30 +04:00
Log ( Debug : : Info ) < < ToUTF8 : : encodingUsingMessage ( encoding ) ;
2012-12-26 16:19:59 +01:00
engine . setEncoding ( ToUTF8 : : calculateEncoding ( encoding ) ) ;
2010-06-16 12:21:02 +02:00
2011-03-29 13:57:56 +02:00
// directory settings
2011-08-19 21:06:09 +02:00
engine . enableFSStrict ( variables [ " fs-strict " ] . as < bool > ( ) ) ;
2011-05-05 19:56:16 +02:00
2021-11-21 19:51:02 +00:00
Files : : PathContainer dataDirs ( asPathContainer ( variables [ " data " ] . as < Files : : MaybeQuotedPathContainer > ( ) ) ) ;
2011-05-05 19:50:28 +02:00
2022-06-23 19:13:10 +02:00
Files : : PathContainer : : value_type local ( variables [ " data-local " ] . as < Files : : MaybeQuotedPathContainer : : value_type > ( ) . u8string ( ) ) ; // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
2011-05-05 19:50:28 +02:00
if ( ! local . empty ( ) )
2020-10-23 15:34:41 +01:00
dataDirs . push_back ( local ) ;
2011-05-05 19:39:11 +02:00
2022-04-26 22:36:03 +02:00
cfgMgr . filterOutNonExistingPaths ( dataDirs ) ;
2012-02-22 23:56:07 +01:00
2022-06-23 19:13:10 +02:00
engine . setResourceDir ( variables [ " resources " ] . as < Files : : MaybeQuotedPath > ( ) . u8string ( ) ) ; // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
2011-08-19 21:06:09 +02:00
engine . setDataDirs ( dataDirs ) ;
2013-03-09 21:08:08 +01:00
// fallback archives
2021-10-09 01:49:08 +01:00
StringsVector archives = variables [ " fallback-archive " ] . as < StringsVector > ( ) ;
2013-07-31 18:46:32 +02:00
for ( StringsVector : : const_iterator it = archives . begin ( ) ; it ! = archives . end ( ) ; + + it )
2013-03-09 21:08:08 +01:00
{
engine . addArchive ( * it ) ;
}
2021-10-09 01:49:08 +01:00
StringsVector content = variables [ " content " ] . as < StringsVector > ( ) ;
2013-09-29 09:11:57 +02:00
if ( content . empty ( ) )
2011-03-29 13:57:56 +02:00
{
2018-08-14 23:05:43 +04:00
Log ( Debug : : Error ) < < " No content file given (esm/esp, nor omwgame/omwaddon). Aborting... " ;
return false ;
2011-03-29 13:57:56 +02:00
}
2021-08-01 03:04:12 +01:00
std : : set < std : : string > contentDedupe ;
for ( const auto & contentFile : content )
{
if ( ! contentDedupe . insert ( contentFile ) . second )
{
Log ( Debug : : Error ) < < " Content file specified more than once: " < < contentFile < < " . Aborting... " ;
return false ;
}
}
2011-03-29 13:57:56 +02:00
2020-01-12 11:42:47 +04:00
for ( auto & file : content )
{
engine . addContentFile ( file ) ;
}
2021-10-09 01:49:08 +01:00
StringsVector groundcover = variables [ " groundcover " ] . as < StringsVector > ( ) ;
2020-01-12 11:42:47 +04:00
for ( auto & file : groundcover )
2011-08-19 21:06:09 +02:00
{
2020-01-12 11:42:47 +04:00
engine . addGroundcoverFile ( file ) ;
2011-08-19 21:06:09 +02:00
}
2011-03-29 13:57:56 +02:00
2021-09-26 15:21:46 +02:00
if ( variables . count ( " lua-scripts " ) )
{
Log ( Debug : : Warning ) < < " Lua scripts have been specified via the old lua-scripts option and will not be loaded. "
" Please update them to a version which uses the new omwscripts format. " ;
}
2021-02-07 12:44:03 +01:00
2011-03-29 13:57:56 +02:00
// startup-settings
2021-10-09 01:49:08 +01:00
engine . setCell ( variables [ " start " ] . as < std : : string > ( ) ) ;
2014-09-01 11:55:12 +02:00
engine . setSkipMenu ( variables [ " skip-menu " ] . as < bool > ( ) , variables [ " new-game " ] . as < bool > ( ) ) ;
if ( ! variables [ " skip-menu " ] . as < bool > ( ) & & variables [ " new-game " ] . as < bool > ( ) )
2018-08-14 23:05:43 +04:00
Log ( Debug : : Warning ) < < " Warning: new-game used without skip-menu -> ignoring it " ;
2011-03-29 13:57:56 +02:00
2014-07-21 09:34:10 +02:00
// scripts
2011-08-19 21:06:09 +02:00
engine . setCompileAll ( variables [ " script-all " ] . as < bool > ( ) ) ;
2014-12-13 02:47:04 +01:00
engine . setCompileAllDialogue ( variables [ " script-all-dialogue " ] . as < bool > ( ) ) ;
2012-07-30 11:43:28 +02:00
engine . setScriptConsoleMode ( variables [ " script-console " ] . as < bool > ( ) ) ;
2021-10-09 01:49:08 +01:00
engine . setStartupScript ( variables [ " script-run " ] . as < std : : string > ( ) ) ;
2014-02-02 14:09:59 +01:00
engine . setWarningsMode ( variables [ " script-warn " ] . as < int > ( ) ) ;
2021-10-09 01:49:08 +01:00
engine . setScriptBlacklist ( variables [ " script-blacklist " ] . as < StringsVector > ( ) ) ;
2014-07-21 09:34:10 +02:00
engine . setScriptBlacklistUse ( variables [ " script-blacklist-use " ] . as < bool > ( ) ) ;
2022-06-23 19:13:10 +02:00
engine . setSaveGameFile ( variables [ " load-savegame " ] . as < Files : : MaybeQuotedPath > ( ) . u8string ( ) ) ;
2014-07-21 09:34:10 +02:00
// other settings
2019-01-22 10:08:48 +04:00
Fallback : : Map : : init ( variables [ " fallback " ] . as < FallbackMap > ( ) . mMap ) ;
2014-07-21 09:34:10 +02:00
engine . setSoundUsage ( ! variables [ " no-sound " ] . as < bool > ( ) ) ;
engine . setActivationDistanceOverride ( variables [ " activate-dist " ] . as < int > ( ) ) ;
2019-02-24 22:41:11 +03:00
engine . setRandomSeed ( variables [ " random-seed " ] . as < unsigned int > ( ) ) ;
2010-10-06 14:52:53 +02:00
2010-06-22 17:52:17 -07:00
return true ;
2010-06-16 12:21:02 +02:00
}
2020-12-04 11:17:49 +01:00
namespace
{
class OSGLogHandler : public osg : : NotifyHandler
{
void notify ( osg : : NotifySeverity severity , const char * msg ) override
{
// Copy, because osg logging is not thread safe.
std : : string msgCopy ( msg ) ;
if ( msgCopy . empty ( ) )
return ;
Debug : : Level level ;
switch ( severity )
{
case osg : : ALWAYS :
case osg : : FATAL :
level = Debug : : Error ;
break ;
case osg : : WARN :
case osg : : NOTICE :
level = Debug : : Warning ;
break ;
case osg : : INFO :
level = Debug : : Info ;
break ;
case osg : : DEBUG_INFO :
case osg : : DEBUG_FP :
default :
level = Debug : : Debug ;
}
std : : string_view s ( msgCopy ) ;
2021-01-08 23:21:39 +01:00
if ( s . size ( ) < 1024 )
Log ( level ) < < ( s . back ( ) = = ' \n ' ? s . substr ( 0 , s . size ( ) - 1 ) : s ) ;
else
{
while ( ! s . empty ( ) )
{
size_t lineSize = 1 ;
while ( lineSize < s . size ( ) & & s [ lineSize - 1 ] ! = ' \n ' )
lineSize + + ;
Log ( level ) < < s . substr ( 0 , s [ lineSize - 1 ] = = ' \n ' ? lineSize - 1 : lineSize ) ;
s = s . substr ( lineSize ) ;
}
}
2020-12-04 11:17:49 +01:00
}
} ;
}
2018-08-03 15:51:17 +04:00
int runApplication ( int argc , char * argv [ ] )
2010-09-19 02:01:01 +02:00
{
2022-06-01 10:34:53 +03:00
Platform : : init ( ) ;
2018-08-03 15:51:17 +04:00
# ifdef __APPLE__
2022-06-08 15:35:35 +02:00
std : : filesystem : : path binary_path = std : : filesystem : : absolute ( std : : filesystem : : path ( argv [ 0 ] ) ) ;
2022-05-28 22:51:32 +02:00
std : : filesystem : : current_path ( binary_path . parent_path ( ) ) ;
2015-11-12 21:40:59 +01:00
setenv ( " OSG_GL_TEXTURE_STORAGE " , " OFF " , 0 ) ;
# endif
2020-12-04 11:17:49 +01:00
osg : : setNotifyHandler ( new OSGLogHandler ( ) ) ;
2018-08-03 15:51:17 +04:00
Files : : ConfigurationManager cfgMgr ;
2022-05-29 13:24:48 +02:00
std : : unique_ptr < OMW : : Engine > engine = std : : make_unique < OMW : : Engine > ( cfgMgr ) ;
2014-07-26 22:29:04 +02:00
2018-08-03 15:51:17 +04:00
if ( parseOptions ( argc , argv , * engine , cfgMgr ) )
2014-06-10 02:22:58 +02:00
{
2018-08-03 15:51:17 +04:00
engine - > go ( ) ;
2010-09-19 02:01:01 +02:00
}
2014-06-10 02:22:58 +02:00
2018-08-03 15:51:17 +04:00
return 0 ;
}
2014-06-10 02:22:58 +02:00
2018-08-03 15:51:17 +04:00
# ifdef ANDROID
extern " C " int SDL_main ( int argc , char * * argv )
# else
int main ( int argc , char * * argv )
# endif
{
2022-01-13 00:20:16 +01:00
return wrapApplication ( & runApplication , argc , argv , " OpenMW " , false ) ;
2010-09-19 02:01:01 +02:00
}
2014-06-10 02:22:58 +02:00
// Platform specific for Windows when there is no console built into the executable.
// Windows will call the WinMain function instead of main in this case, the normal
// main function is then called with the __argc and __argv parameters.
# if defined(_WIN32) && !defined(_CONSOLE)
int WINAPI WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nShowCmd )
{
return main ( __argc , __argv ) ;
}
2010-09-19 02:01:01 +02:00
# endif