dxx-rebirth/similar/misc/args.cpp

538 lines
14 KiB
C++
Raw Normal View History

2006-03-20 17:12:09 +00:00
/*
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
2006-03-20 17:12:09 +00:00
/*
*
* Functions for accessing arguments.
*
*/
2013-11-10 00:41:38 +00:00
#include <string>
#include <vector>
2006-03-20 17:12:09 +00:00
#include <stdlib.h>
#include <string.h>
2013-06-30 02:22:56 +00:00
#include <SDL_stdinc.h>
2006-03-20 17:12:09 +00:00
#include "physfsx.h"
#include "args.h"
#include "u_mem.h"
#include "strutil.h"
#include "digi.h"
#include "game.h"
#include "console.h"
#include "mission.h"
Add alternative mixer resamplers SDL2_mixer changed how it upsamples sounds, and some users complained about the difference. Add an internal resampler that emulates how SDL_mixer upsamples sounds. Since all Rebirth upsampling is an integer upsample (11Khz -> 44KHz, 22KHz -> 44Khz), this internal emulation is considerably simpler than a general purpose resampler. With this commit, the builder can choose which resamplers to enable. The available resamplers are chosen by preprocessor directive, and presently do not have an SConstruct flag. For each resampler, if no choice is made, then the resampler will be enabled if it is reasonable. At least one of the resamplers must be enabled, or the build will fail with a `#error` message. The user may choose at program start time which of the available resamplers to use for that execution of the program, through passing one of the command line arguments: - `-sdlmixer-resampler=sdl-native` - `-sdlmixer-resampler=emulate-sdl1` - `-sdlmixer-resampler=emulate-soundblaster16` Runtime switching is not supported. If the user does not choose, then the first enabled resampler from the list below will be used. The available resamplers are: - sdl_native (DXX_FEATURE_EXTERNAL_RESAMPLER_SDL_NATIVE) - delegates to SDL_mixer / SDL2_mixer, the way Rebirth has historically done. - emulate_sdl1 (DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SDL1) - an internal resampler that emulates how SDL_mixer worked. This should be equivalent to sdl_native when using SDL_mixer, so by default it is enabled when Rebirth is built to use SDL2_mixer and disabled when Rebirth is built to use SDL_mixer. It can still be enabled manually even when building for SDL_mixer, but this does not seem likely to be useful. - emulate_soundblaster16 (DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SOUNDBLASTER16) - an internal resampler submitted by @raptor in 5165efbc46b9f31a4f36b935322387e86955894a. Some users reported audio quality issues with this resampler, so it is not presently the default.
2023-02-11 10:50:21 +00:00
#if DXX_USE_SDLMIXER
#include "digi_mixer.h"
#endif
#if DXX_USE_UDP
#include "net_udp.h"
#endif
2015-03-22 18:49:20 +00:00
#include "compiler-range_for.h"
#include "partial_range.h"
namespace dcx {
CArg CGameArg;
2006-03-20 17:12:09 +00:00
namespace {
2020-12-26 21:17:29 +00:00
constexpr std::integral_constant<std::size_t, 1000> MAX_ARGS{};
typedef std::vector<std::string> Arglist;
2015-03-22 18:49:21 +00:00
class ini_entry
{
public:
2020-04-26 17:26:23 +00:00
const std::string filename;
2015-03-22 18:49:21 +00:00
ini_entry(std::string &&f) :
2020-04-26 17:26:23 +00:00
filename(std::move(f))
2015-03-22 18:49:21 +00:00
{
}
};
typedef std::vector<ini_entry> Inilist;
2006-03-20 17:12:09 +00:00
2013-11-10 18:31:52 +00:00
class argument_exception
{
public:
2015-03-22 18:49:21 +00:00
const std::string arg;
argument_exception(std::string &&a) :
arg(std::move(a))
{
}
2013-11-10 18:31:52 +00:00
};
2013-11-10 18:31:52 +00:00
class missing_parameter : public argument_exception
2006-03-20 17:12:09 +00:00
{
2013-11-10 18:31:52 +00:00
public:
2020-04-26 17:26:23 +00:00
using argument_exception::argument_exception;
2013-11-10 18:31:52 +00:00
};
2006-03-20 17:12:09 +00:00
2013-11-10 18:31:52 +00:00
class unhandled_argument : public argument_exception
{
public:
2020-04-26 17:26:23 +00:00
using argument_exception::argument_exception;
2013-11-10 18:31:52 +00:00
};
class conversion_failure : public argument_exception
{
public:
2015-03-22 18:49:21 +00:00
const std::string value;
conversion_failure(std::string &&a, std::string &&v) :
argument_exception(std::move(a)), value(std::move(v))
{
}
2013-11-10 18:31:52 +00:00
};
2015-03-22 18:49:21 +00:00
class nesting_depth_exceeded
{
2013-11-10 18:31:52 +00:00
};
2015-03-22 18:49:21 +00:00
static void AppendIniArgs(const char *filename, Arglist &Args)
{
if (auto f = PHYSFSX_openReadBuffered(filename).first)
{
2014-09-07 19:48:10 +00:00
PHYSFSX_gets_line_t<1024> line;
while (Args.size() < MAX_ARGS && PHYSFSX_fgets(line, f))
{
2016-05-12 13:15:26 +00:00
const auto separator = " \t";
2013-08-03 15:50:56 +00:00
for(char *token = strtok(line, separator); token != NULL; token = strtok(NULL, separator))
2014-05-24 23:03:19 +00:00
{
if (*token == ';')
break;
2013-11-10 00:41:38 +00:00
Args.push_back(token);
2014-05-24 23:03:19 +00:00
}
}
}
}
2015-03-22 18:49:20 +00:00
static std::string &&arg_string(Arglist::iterator &pp, Arglist::const_iterator end)
2013-11-10 18:31:52 +00:00
{
2015-03-22 18:49:20 +00:00
auto arg = pp;
2013-11-10 18:31:52 +00:00
if (++pp == end)
2015-03-22 18:49:21 +00:00
throw missing_parameter(std::move(*arg));
2015-03-22 18:49:20 +00:00
return std::move(*pp);
}
2013-11-10 18:31:52 +00:00
2015-03-22 18:49:20 +00:00
static long arg_integer(Arglist::iterator &pp, Arglist::const_iterator end)
2013-11-10 18:31:52 +00:00
{
2015-03-22 18:49:20 +00:00
auto arg = pp;
auto &&value = arg_string(pp, end);
2013-11-10 18:31:52 +00:00
char *p;
2015-03-22 18:49:20 +00:00
auto i = strtol(value.c_str(), &p, 10);
2013-11-10 18:31:52 +00:00
if (*p)
2015-03-22 18:49:21 +00:00
throw conversion_failure(std::move(*arg), std::move(value));
2013-11-10 18:31:52 +00:00
return i;
}
template<typename E> E arg_enum(Arglist::iterator &pp, Arglist::const_iterator end)
{
return static_cast<E>(arg_integer(pp, end));
}
#if DXX_USE_UDP
2015-03-22 18:49:20 +00:00
static void arg_port_number(Arglist::iterator &pp, Arglist::const_iterator end, uint16_t &out, bool allow_privileged)
{
auto port = arg_integer(pp, end);
if (static_cast<uint16_t>(port) == port && (allow_privileged || port >= 1024))
out = port;
}
#endif
2015-03-22 18:49:21 +00:00
static void InitGameArg()
{
CGameArg.SysMaxFPS = MAXIMUM_FPS;
#if DXX_USE_UDP
2015-12-24 04:01:27 +00:00
CGameArg.MplUdpHostAddr = UDP_MANUAL_ADDR_DEFAULT;
#if DXX_USE_TRACKER
2015-12-24 04:01:29 +00:00
CGameArg.MplTrackerAddr = TRACKER_ADDR_DEFAULT;
2015-12-24 04:01:29 +00:00
CGameArg.MplTrackerPort = TRACKER_PORT_DEFAULT;
2013-11-10 18:31:52 +00:00
#endif
#endif
2015-10-18 21:01:21 +00:00
CGameArg.DbgVerbose = CON_NORMAL;
2015-12-18 04:08:23 +00:00
CGameArg.DbgBpp = 32;
#if DXX_USE_OGL
2015-12-24 04:01:27 +00:00
CGameArg.OglSyncMethod = OGL_SYNC_METHOD_DEFAULT;
2015-12-24 04:01:27 +00:00
CGameArg.OglSyncWait = OGL_SYNC_WAIT_DEFAULT;
#if DXX_USE_STEREOSCOPIC_RENDER
CGameArg.OglStereo = false;
#endif
2015-12-18 04:08:23 +00:00
CGameArg.DbgGlIntensity4Ok = true;
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlLuminance4Alpha4Ok = true;
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlRGBA2Ok = true;
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlReadPixelsOk = true;
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlGetTexLevelParamOk = true;
2013-11-10 18:31:52 +00:00
#endif
2015-03-22 18:49:21 +00:00
}
2016-03-02 02:52:44 +00:00
}
2020-12-26 21:17:29 +00:00
}
2016-03-02 02:52:44 +00:00
namespace dsx {
Arg GameArg;
2020-12-26 21:17:29 +00:00
namespace {
static void InitGameArg()
{
#if defined(DXX_BUILD_DESCENT_II)
2023-01-07 22:17:31 +00:00
GameArg.SndDigiSampleRate = sound_sample_rate::_22k;
2020-12-26 21:17:29 +00:00
#endif
::dcx::InitGameArg();
}
2016-03-02 02:52:44 +00:00
static void ReadCmdArgs(Inilist &ini, Arglist &Args);
2015-03-22 18:49:21 +00:00
static void ReadIniArgs(Inilist &ini)
{
Arglist Args;
2020-04-26 17:26:23 +00:00
AppendIniArgs(ini.back().filename.c_str(), Args);
2015-03-22 18:49:21 +00:00
ReadCmdArgs(ini, Args);
ini.pop_back();
2015-03-22 18:49:21 +00:00
}
static void ReadCmdArgs(Inilist &ini, Arglist &Args)
{
2015-03-22 18:49:20 +00:00
for (Arglist::iterator pp = Args.begin(), end = Args.end(); pp != end; ++pp)
2013-11-10 18:31:52 +00:00
{
const char *p = pp->c_str();
// System Options
2013-11-10 18:31:52 +00:00
if (!d_stricmp(p, "-help") || !d_stricmp(p, "-h") || !d_stricmp(p, "-?") || !d_stricmp(p, "?"))
CGameArg.SysShowCmdHelp = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nonicefps"))
2015-12-24 04:01:26 +00:00
CGameArg.SysNoNiceFPS = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-maxfps"))
CGameArg.SysMaxFPS = arg_integer(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-hogdir"))
2015-12-24 04:01:26 +00:00
CGameArg.SysHogDir = arg_string(pp, end);
2015-10-11 22:21:00 +00:00
#if PHYSFS_VER_MAJOR >= 2
else if (!d_stricmp(p, "-add-missions-dir"))
CGameArg.SysMissionDir = arg_string(pp, end);
2015-10-11 22:21:00 +00:00
#endif
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nohogdir"))
2015-09-22 02:28:38 +00:00
{
/* No effect if no DXX_SHAREPATH. Ignore it so that players can
2015-09-22 02:28:38 +00:00
* pass it via a cross-platform ini.
*/
#if DXX_USE_SHAREPATH
CGameArg.SysNoHogDir = true;
2015-09-22 02:28:38 +00:00
#endif
}
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-use_players_dir"))
CGameArg.SysUsePlayersDir = static_cast<int8_t>(- (sizeof(PLAYER_DIRECTORY_TEXT) - 1));
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-lowmem"))
2015-12-24 04:01:26 +00:00
CGameArg.SysLowMem = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-pilot"))
2015-12-24 04:01:26 +00:00
CGameArg.SysPilot = arg_string(pp, end);
else if (!d_stricmp(p, "-record-demo-format"))
2015-12-24 04:01:26 +00:00
CGameArg.SysRecordDemoNameTemplate = arg_string(pp, end);
else if (!d_stricmp(p, "-auto-record-demo"))
2015-12-24 04:01:27 +00:00
CGameArg.SysAutoRecordDemo = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-window"))
2015-12-24 04:01:27 +00:00
CGameArg.SysWindow = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-noborders"))
2015-12-24 04:01:27 +00:00
CGameArg.SysNoBorders = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-notitles"))
2015-12-24 04:01:27 +00:00
CGameArg.SysNoTitles = true;
2015-10-09 02:46:09 +00:00
#if defined(DXX_BUILD_DESCENT_II)
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nomovies"))
GameArg.SysNoMovies = 1;
#endif
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-autodemo"))
2015-12-24 04:01:27 +00:00
CGameArg.SysAutoDemo = true;
2007-10-01 20:42:35 +00:00
// Control Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nocursor"))
2015-07-18 21:01:56 +00:00
CGameArg.CtlNoCursor = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nomouse"))
2015-07-18 21:01:56 +00:00
CGameArg.CtlNoMouse = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nojoystick"))
2015-11-26 02:56:55 +00:00
{
#if DXX_MAX_JOYSTICKS
2015-11-26 02:56:55 +00:00
CGameArg.CtlNoJoystick = 1;
#endif
}
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nostickykeys"))
2015-07-18 21:01:56 +00:00
CGameArg.CtlNoStickyKeys = true;
// Sound Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nosound"))
2015-11-24 04:05:36 +00:00
CGameArg.SndNoSound = 1;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nomusic"))
2015-12-24 04:01:26 +00:00
CGameArg.SndNoMusic = true;
#if defined(DXX_BUILD_DESCENT_II)
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-sound11k"))
2023-01-07 22:17:31 +00:00
GameArg.SndDigiSampleRate = sound_sample_rate::_11k;
#endif
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nosdlmixer"))
{
#if DXX_USE_SDLMIXER
2015-11-24 04:05:36 +00:00
CGameArg.SndDisableSdlMixer = true;
Add alternative mixer resamplers SDL2_mixer changed how it upsamples sounds, and some users complained about the difference. Add an internal resampler that emulates how SDL_mixer upsamples sounds. Since all Rebirth upsampling is an integer upsample (11Khz -> 44KHz, 22KHz -> 44Khz), this internal emulation is considerably simpler than a general purpose resampler. With this commit, the builder can choose which resamplers to enable. The available resamplers are chosen by preprocessor directive, and presently do not have an SConstruct flag. For each resampler, if no choice is made, then the resampler will be enabled if it is reasonable. At least one of the resamplers must be enabled, or the build will fail with a `#error` message. The user may choose at program start time which of the available resamplers to use for that execution of the program, through passing one of the command line arguments: - `-sdlmixer-resampler=sdl-native` - `-sdlmixer-resampler=emulate-sdl1` - `-sdlmixer-resampler=emulate-soundblaster16` Runtime switching is not supported. If the user does not choose, then the first enabled resampler from the list below will be used. The available resamplers are: - sdl_native (DXX_FEATURE_EXTERNAL_RESAMPLER_SDL_NATIVE) - delegates to SDL_mixer / SDL2_mixer, the way Rebirth has historically done. - emulate_sdl1 (DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SDL1) - an internal resampler that emulates how SDL_mixer worked. This should be equivalent to sdl_native when using SDL_mixer, so by default it is enabled when Rebirth is built to use SDL2_mixer and disabled when Rebirth is built to use SDL_mixer. It can still be enabled manually even when building for SDL_mixer, but this does not seem likely to be useful. - emulate_soundblaster16 (DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SOUNDBLASTER16) - an internal resampler submitted by @raptor in 5165efbc46b9f31a4f36b935322387e86955894a. Some users reported audio quality issues with this resampler, so it is not presently the default.
2023-02-11 10:50:21 +00:00
#endif
}
else if (!strncmp(p, "-sdlmixer-resampler=", 20))
{
#if DXX_USE_SDLMIXER
#if DXX_FEATURE_EXTERNAL_RESAMPLER_SDL_NATIVE
if (!strcmp(&p[20], "sdl-native"))
CGameArg.SndMixerMethod = digi_mixer_method::sdl_native;
else
#endif
#if DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SDL1
if (!strcmp(&p[20], "emulate-sdl1"))
CGameArg.SndMixerMethod = digi_mixer_method::emulate_sdl1;
else
#endif
#if DXX_FEATURE_INTERNAL_RESAMPLER_EMULATE_SOUNDBLASTER16
if (!strcmp(&p[20], "emulate-soundblaster16"))
CGameArg.SndMixerMethod = digi_mixer_method::emulate_soundblaster16;
else
#endif
throw unhandled_argument(std::move(*pp));
#endif
}
// Graphics Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-lowresfont"))
2015-12-24 04:01:26 +00:00
CGameArg.GfxSkipHiresFNT = true;
#if defined(DXX_BUILD_DESCENT_II)
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-lowresgraphics"))
GameArg.GfxSkipHiresGFX = 1;
else if (!d_stricmp(p, "-lowresmovies"))
GameArg.GfxSkipHiresMovie = 1;
#endif
#if DXX_USE_OGL
// OpenGL Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_fixedfont"))
2015-12-24 04:01:27 +00:00
CGameArg.OglFixedFont = true;
else if (!d_stricmp(p, "-gl_syncmethod"))
2015-12-24 04:01:27 +00:00
CGameArg.OglSyncMethod = arg_enum<SyncGLMethod>(pp, end);
else if (!d_stricmp(p, "-gl_syncwait"))
2015-12-24 04:01:27 +00:00
CGameArg.OglSyncWait = arg_integer(pp, end);
else if (!d_stricmp(p, "-gl_darkedges"))
CGameArg.OglDarkEdges = true;
#if DXX_USE_STEREOSCOPIC_RENDER
else if (!d_stricmp(p, "-gl_stereo"))
CGameArg.OglStereo = true;
else if (!d_stricmp(p, "-gl_stereoview"))
CGameArg.OglStereoView = arg_integer(pp, end);
#endif
#endif
// Multiplayer Options
#if DXX_USE_UDP
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-udp_hostaddr"))
2015-12-24 04:01:27 +00:00
CGameArg.MplUdpHostAddr = arg_string(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-udp_hostport"))
2015-01-25 05:32:44 +00:00
/* Peers use -udp_myport to change, so peer cannot set a
* privileged port.
*/
2015-12-24 04:01:28 +00:00
arg_port_number(pp, end, CGameArg.MplUdpHostPort, false);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-udp_myport"))
{
2015-12-24 04:01:29 +00:00
arg_port_number(pp, end, CGameArg.MplUdpMyPort, false);
}
else if (!d_stricmp(p, "-no-tracker"))
{
/* Always recognized. No-op if tracker support compiled
* out. */
#if DXX_USE_TRACKER
2015-12-24 04:01:29 +00:00
CGameArg.MplTrackerAddr.clear();
#endif
}
#if DXX_USE_TRACKER
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-tracker_hostaddr"))
{
2015-12-24 04:01:29 +00:00
CGameArg.MplTrackerAddr = arg_string(pp, end);
}
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-tracker_hostport"))
2015-12-24 04:01:29 +00:00
arg_port_number(pp, end, CGameArg.MplTrackerPort, true);
#endif
#endif
#if defined(DXX_BUILD_DESCENT_I)
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nobm"))
GameArg.EdiNoBm = 1;
#elif defined(DXX_BUILD_DESCENT_II)
#if DXX_USE_EDITOR
// Editor Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-autoload"))
GameArg.EdiAutoLoad = arg_string(pp, end);
else if (!d_stricmp(p, "-macdata"))
GameArg.EdiMacData = 1;
else if (!d_stricmp(p, "-hoarddata"))
GameArg.EdiSaveHoardData = 1;
#endif
#endif
// Debug Options
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-debug"))
{
if (CGameArg.DbgVerbose < CON_DEBUG)
CGameArg.DbgVerbose = CON_DEBUG;
}
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-verbose"))
{
if (CGameArg.DbgVerbose < CON_VERBOSE)
CGameArg.DbgVerbose = CON_VERBOSE;
}
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-no-grab"))
2015-07-18 21:01:56 +00:00
CGameArg.DbgForbidConsoleGrab = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-safelog"))
2015-10-18 21:01:21 +00:00
CGameArg.DbgSafelog = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-norun"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgNoRun = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-renderstats"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgRenderStats = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-text"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgAltTex = arg_string(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-showmeminfo"))
CGameArg.DbgShowMemInfo = 1;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-nodoublebuffer"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgNoDoubleBuffer = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-bigpig"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgNoCompressPigBitmap = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-16bpp"))
2015-12-18 04:08:23 +00:00
CGameArg.DbgBpp = 16;
2007-07-22 20:40:39 +00:00
#if DXX_USE_OGL
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_oldtexmerge"))
2015-12-18 04:08:24 +00:00
CGameArg.DbgUseOldTextureMerge = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_intensity4_ok"))
2015-12-18 04:08:23 +00:00
CGameArg.DbgGlIntensity4Ok = arg_integer(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_luminance4_alpha4_ok"))
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlLuminance4Alpha4Ok = arg_integer(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_rgba2_ok"))
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlRGBA2Ok = arg_integer(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_readpixels_ok"))
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlReadPixelsOk = arg_integer(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-gl_gettexlevelparam_ok"))
2015-12-18 04:08:24 +00:00
CGameArg.DbgGlGetTexLevelParamOk = arg_integer(pp, end);
#else
else if (!d_stricmp(p, "-tmap"))
CGameArg.DbgTexMap = arg_string(pp, end);
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-hwsurface"))
2015-12-24 04:01:27 +00:00
CGameArg.DbgSdlHWSurface = true;
2013-11-10 18:31:52 +00:00
else if (!d_stricmp(p, "-asyncblit"))
2015-12-24 04:01:28 +00:00
CGameArg.DbgSdlASyncBlit = true;
2007-07-22 01:34:00 +00:00
#endif
2015-03-22 18:49:21 +00:00
else if (!d_stricmp(p, "-ini"))
{
ini.emplace_back(arg_string(pp, end));
if (ini.size() > 10)
throw nesting_depth_exceeded();
ReadIniArgs(ini);
}
#if defined(__APPLE__) && defined(__MACH__)
else if (!strncmp(p, "-psn", 4))
{
//do nothing/gobble it up
}
#endif
2013-11-10 18:31:52 +00:00
else
2015-03-22 18:49:21 +00:00
throw unhandled_argument(std::move(*pp));
2013-11-10 18:31:52 +00:00
}
2015-03-22 18:49:21 +00:00
}
2013-11-10 18:31:52 +00:00
2016-03-02 02:52:44 +00:00
}
2020-12-26 21:17:29 +00:00
}
2016-03-02 02:52:44 +00:00
namespace dcx {
2020-12-26 21:17:29 +00:00
namespace {
2015-03-22 18:49:21 +00:00
static void PostProcessGameArg()
{
if (CGameArg.SysMaxFPS < MINIMUM_FPS)
CGameArg.SysMaxFPS = MINIMUM_FPS;
else if (CGameArg.SysMaxFPS > MAXIMUM_FPS)
CGameArg.SysMaxFPS = MAXIMUM_FPS;
2015-10-11 22:21:00 +00:00
#if PHYSFS_VER_MAJOR >= 2
if (!CGameArg.SysMissionDir.empty())
PHYSFS_mount(CGameArg.SysMissionDir.c_str(), MISSION_DIR, 1);
2015-10-11 22:21:00 +00:00
#endif
2013-11-10 18:31:52 +00:00
Enable building with SDL2 This commit enables Rebirth to build with SDL2, but the result is not perfect. - SDL2 removed some sticky key support. Rebirth may behave differently now in this area. - SDL2 removed some key-repeat related support. Rebirth may behave differently now in this area. - SDL2 gained the ability to make a window fullscreen by sizing it to the desktop instead of by changing the desktop resolution. Rebirth uses this, and it mostly works. - Resizing while in the automap does not notify the automap code, so the view is wrong until the player switches out of automap mode and back in. - SDL2 changed how to enumerate available resolutions. Since fitting the window to the desktop is generally more useful than fitting the desktop to the window, I chose to drop support for enumerating resolutions instead of porting to the new API. Users can now enter an arbitrary window dimension and Rebirth will make an attempt to use it. - It might be useful to cap the window dimension at the desktop dimension, but that is not done yet. - Entering fullscreen mode through the Controls->Graphics submenu failed to notify the relevant subsystems, causing the rendered content not to rescale. For now, compile out the option to toggle full screen through that menu. Toggling through Alt+Enter works properly. Despite these quirks, this is a substantial improvement over the prior commit, where SDL2 cannot be used at all. The remaining issues can be resolved in future work. References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/82>
2018-07-28 23:22:58 +00:00
#if SDL_MAJOR_VERSION == 1
2013-11-10 18:31:52 +00:00
static char sdl_disable_lock_keys[] = "SDL_DISABLE_LOCK_KEYS=0";
2015-07-18 21:01:56 +00:00
if (CGameArg.CtlNoStickyKeys) // Must happen before SDL_Init!
sdl_disable_lock_keys[sizeof(sdl_disable_lock_keys) - 2] = '1';
2013-11-10 18:31:52 +00:00
SDL_putenv(sdl_disable_lock_keys);
Enable building with SDL2 This commit enables Rebirth to build with SDL2, but the result is not perfect. - SDL2 removed some sticky key support. Rebirth may behave differently now in this area. - SDL2 removed some key-repeat related support. Rebirth may behave differently now in this area. - SDL2 gained the ability to make a window fullscreen by sizing it to the desktop instead of by changing the desktop resolution. Rebirth uses this, and it mostly works. - Resizing while in the automap does not notify the automap code, so the view is wrong until the player switches out of automap mode and back in. - SDL2 changed how to enumerate available resolutions. Since fitting the window to the desktop is generally more useful than fitting the desktop to the window, I chose to drop support for enumerating resolutions instead of porting to the new API. Users can now enter an arbitrary window dimension and Rebirth will make an attempt to use it. - It might be useful to cap the window dimension at the desktop dimension, but that is not done yet. - Entering fullscreen mode through the Controls->Graphics submenu failed to notify the relevant subsystems, causing the rendered content not to rescale. For now, compile out the option to toggle full screen through that menu. Toggling through Alt+Enter works properly. Despite these quirks, this is a substantial improvement over the prior commit, where SDL2 cannot be used at all. The remaining issues can be resolved in future work. References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/82>
2018-07-28 23:22:58 +00:00
#endif
}
2015-03-22 18:49:21 +00:00
static std::string ConstructIniStackExplanation(const Inilist &ini)
2006-03-20 17:12:09 +00:00
{
2015-03-22 18:49:21 +00:00
Inilist::const_reverse_iterator i = ini.rbegin(), e = ini.rend();
if (i == e)
return " while processing <command line>";
std::string result;
result.reserve(ini.size() * 128);
result += " while processing \"";
for (;;)
{
2020-04-26 17:26:23 +00:00
result += i->filename;
2015-03-22 18:49:21 +00:00
if (++ i == e)
return result += "\"";
result += "\"\n included from \"";
}
2006-03-20 17:12:09 +00:00
}
2016-03-02 02:52:44 +00:00
}
2020-12-26 21:17:29 +00:00
}
2016-03-02 02:52:44 +00:00
namespace dsx {
bool InitArgs( int argc,char **argv )
2006-03-20 17:12:09 +00:00
{
2015-03-22 18:49:21 +00:00
InitGameArg();
2006-03-20 17:12:09 +00:00
2015-03-22 18:49:21 +00:00
Inilist ini;
2013-11-10 18:31:52 +00:00
try {
2015-03-22 18:49:21 +00:00
{
assert(ini.empty());
2016-03-02 02:52:44 +00:00
#if defined(DXX_BUILD_DESCENT_I)
const auto INI_FILENAME = "d1x.ini";
#elif defined(DXX_BUILD_DESCENT_II)
const auto INI_FILENAME = "d2x.ini";
#endif
2015-03-22 18:49:21 +00:00
ini.emplace_back(INI_FILENAME);
ReadIniArgs(ini);
}
{
Arglist Args;
Args.reserve(argc);
range_for (auto &i, unchecked_partial_range(argv, 1u, static_cast<unsigned>(argc)))
Args.push_back(i);
ReadCmdArgs(ini, Args);
}
2015-03-22 18:49:21 +00:00
PostProcessGameArg();
return true;
2013-11-10 18:31:52 +00:00
} catch(const missing_parameter& e) {
UserError("Missing parameter for argument \"%s\"%s", e.arg.c_str(), ConstructIniStackExplanation(ini).c_str());
2013-11-10 18:31:52 +00:00
} catch(const unhandled_argument& e) {
UserError("Unhandled argument \"%s\"%s", e.arg.c_str(), ConstructIniStackExplanation(ini).c_str());
2013-11-10 18:31:52 +00:00
} catch(const conversion_failure& e) {
UserError("Failed to convert argument \"%s\" parameter \"%s\"%s", e.arg.c_str(), e.value.c_str(), ConstructIniStackExplanation(ini).c_str());
2015-03-22 18:49:21 +00:00
} catch(const nesting_depth_exceeded &) {
UserError("Nesting depth exceeded%s", ConstructIniStackExplanation(ini).c_str());
2013-11-10 18:31:52 +00:00
}
return false;
2006-03-20 17:12:09 +00:00
}
}