1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10 #include "cmdline/cmdline.h"
11 #include "camera/camera.h" //VIEWER_ZOOM_DEFAULT
12 #include "cfile/cfilesystem.h"
13 #include "fireball/fireballs.h"
14 #include "globalincs/linklist.h"
15 #include "globalincs/pstypes.h"
16 #include "globalincs/systemvars.h"
17 #include "globalincs/version.h"
18 #include "graphics/shadows.h"
19 #include "hud/hudconfig.h"
20 #include "io/joy.h"
21 #include "network/multi.h"
22 #include "options/OptionsManager.h"
23 #include "osapi/osapi.h"
24 #include "parse/sexp.h"
25 #include "scripting/scripting.h"
26 #include "sound/openal.h"
27 #include "sound/speech.h"
28 #include "starfield/starfield.h"
29
30 #ifdef _WIN32
31 #include <io.h>
32 #include <direct.h>
33 #elif defined(APPLE_APP)
34 #include <CoreFoundation/CoreFoundation.h>
35 #endif
36
37 #ifdef SCP_UNIX
38 #include "osapi/osapi.h"
39 #include <dirent.h>
40 #endif
41
42 #include <cstring>
43 #include <cstdlib>
44 #include <cstdio>
45
46 #include <jansson.h>
47
48 // Stupid windows workaround...
49 #ifdef MessageBox
50 #undef MessageBox
51 #endif
52
53 enum cmdline_arg_type
54 {
55 AT_NONE =0,
56 AT_INT,
57 AT_FLOAT,
58 AT_STRING
59 };
60 // values and order MUST match cmdline_arg_type
61 const char *cmdline_arg_types[] =
62 {
63 "NONE",
64 "INT",
65 "FLOAT",
66 "STRING",
67 };
68
69 enum class flag_output_type {
70 Binary,
71 Json_V1,
72 };
73
74 // variables
75 class cmdline_parm {
76 public:
77 cmdline_parm *next, *prev;
78 const char *name; // name of parameter, must start with '-' char
79 const char *help; // help text for this parameter
80 const bool stacks; // whether this arg stacks with each use or is replaced by newest use (should only be used for strings!!)
81 char *args; // string value for parameter arguments (NULL if no arguments)
82 int name_found; // true if parameter on command line, otherwise false
83 const int arg_type; // from enum cmdline_arg_type; used for help
84
85 cmdline_parm(const char *name, const char *help, const int arg_type, const bool stacks = false) noexcept;
86 ~cmdline_parm() noexcept;
87 int found();
88 int get_int();
89 float get_float();
90 char *str();
91 bool check_if_args_is_valid();
92 bool has_param();
93 };
94
95 static cmdline_parm Parm_list(NULL, NULL, AT_NONE);
96 static int Parm_list_inited = 0;
97
98 extern int Show_framerate; // from freespace.cpp
99
100 enum
101 {
102 // DO NOT CHANGE ANYTHING ABOUT THESE FIRST TWO OR WILL MESS UP THE LAUNCHER
103 EASY_DEFAULT = 1 << 1, // Default FS2 (All features off)
104 EASY_ALL_ON = 1 << 2, // All features on
105
106 EASY_HI_MEM_ON = 1 << 3, // High memory usage features on
107 EASY_HI_MEM_OFF = 1 << 4, // High memory usage features off
108
109 // Add new flags here
110 };
111
112 enum BuildCaps
113 {
114 BUILD_CAPS_OPENAL = (1<<0),
115 BUILD_CAPS_NO_D3D = (1<<1),
116 BUILD_CAPS_NEW_SND = (1<<2),
117 BUILD_CAPS_SDL = (1<<3)
118 };
119
120 #define PARSE_COMMAND_LINE_STRING "-parse_cmdline_only"
121 #define GET_FLAGS_STRING "-get_flags"
122
123 typedef struct
124 {
125 // DO NOT CHANGE THE SIZE OF THIS AT_STRING!
126 char name[32];
127
128 } EasyFlag;
129
130 EasyFlag easy_flags[] =
131 {
132 { "Custom" },
133 { "Default FS2 (All features off)" },
134 { "All features on" },
135 { "High memory usage features on" },
136 { "High memory usage features off" }
137 };
138
139 // DO NOT CHANGE **ANYTHING** ABOUT THIS STRUCTURE AND ITS CONTENT
140 typedef struct
141 {
142 char name[20]; // The actual flag
143 char desc[40]; // The text that will appear in the launcher (unless its blank, other name is shown)
144 bool fso_only; // true if this is a fs2_open only feature
145 int on_flags; // "Easy setting" which will turn this option on
146 int off_flags; // "Easy setting" which will turn this option off
147 char type[16]; // Launcher uses this to put flags under different headings
148 char web_url[256]; // Link to documentation of feature (please use wiki or somewhere constant)
149
150 } Flag;
151
152 // clang-format off
153 // Please group them by type, ie graphics, gameplay etc, maximum 20 different types
154 Flag exe_params[] =
155 {
156 { "-nospec", "Disable specular", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nospec", },
157 { "-noglow", "Disable glow maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noglow", },
158 { "-noenv", "Disable environment maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noenv", },
159 { "-nonormal", "Disable normal maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nonormal" },
160 { "-emissive_light", "Enable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-emissive_light" },
161 { "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noheight" },
162 { "-3dshockwave", "Enable 3D shockwaves", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
163 { "-no_post_process", "Disable post-processing", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_post_process" },
164 { "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
165 { "-aa", "Enable Post-process anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-aa" },
166 { "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nolightshafts"},
167 { "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
168 { "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
169 { "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
170 { "-enable_shadows", "Enable Shadows", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-enable_shadows"},
171
172 { "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
173
174 { "-fps", "Show frames per second on HUD", false, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fps", },
175 { "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
176 { "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
177 { "-orbradar", "Enable 3D radar", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-orbradar", },
178 { "-rearm_timer", "Enable rearm/repair completion timer", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-rearm_timer", },
179 { "-ballistic_gauge", "Enable analog ballistic ammo gauge", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ballistic_gauge", },
180
181 { "-window", "Run in window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
182 { "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
183 { "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
184 { "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
185 { "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
186 { "-ship_choice_3d", "Use 3D models for ship selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ship_choice_3d", },
187 { "-weapon_choice_3d", "Use 3D models for weapon selection", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weapon_choice_3d", },
188 { "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
189 { "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
190 { "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
191 { "-no_screenshake", "Disable screen shaking", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_screenshake", },
192
193 { "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
194 { "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
195 { "-no_enhanced_sound", "Disable enhanced sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_enhanced_sound", },
196
197 { "-portable_mode", "Store config in portable location", false, 0, EASY_DEFAULT, "Launcher", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-portable_mode", },
198
199 { "-standalone", "Run as standalone server", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-standalone", },
200 { "-startgame", "Skip mainhall and start hosting", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-startgame", },
201 { "-closed", "Start hosted server as closed", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-closed", },
202 { "-restricted", "Host confirms join requests", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-restricted", },
203 { "-multilog", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-multilog", },
204 { "-clientdamage", "", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-clientdamage", },
205 { "-mpnoreturn", "Disable flight deck option", true, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mpnoreturn", },
206 { "-gateway_ip", "Set gateway IP address", false, 0, EASY_DEFAULT, "Multiplayer", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gateway_ip", },
207
208 { "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
209 { "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
210 { "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
211 { "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
212 { "-disable_fbo", "Disable OpenGL RenderTargets", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_fbo", },
213 { "-disable_pbo", "Disable OpenGL Pixel Buffer Objects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_pbo", },
214 { "-ati_swap", "Fix colour issues on some ATI cards", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ati_swap", },
215 { "-no_3d_sound", "Use only 2D/stereo for sound effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_3d_sound", },
216 { "-mipmap", "Enable mipmapping", true, 0, EASY_DEFAULT | EASY_HI_MEM_OFF, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mipmap", },
217 { "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
218 { "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
219 { "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_geo_effects", },
220 { "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-set_cpu_affinity", },
221 { "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
222 { "-noshadercache", "Disables the shader cache", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noshadercache", },
223 #ifdef WIN32
224 { "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fix_registry", },
225 #endif
226
227 { "-ingame_join", "Allow in-game joining", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ingame_join", },
228 { "-voicer", "Enable voice recognition", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-voicer", },
229
230 { "-bmpmanusage", "Show how many BMPMAN slots are in use", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-bmpmanusage", },
231 { "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
232 { "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
233 { "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
234 { "-pofspew", "Dump model information to pofspew.txt", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
235 { "-weaponspew", "Dump weapon stats and spreadsheets", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weaponspew", },
236 { "-tablecrcs", "Dump table CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tablecrcs", },
237 { "-missioncrcs", "Dump mission CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missioncrcs", },
238 { "-dis_collisions", "Disable collisions", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_collisions", },
239 { "-dis_weapons", "Disable weapon rendering", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_weapons", },
240 { "-output_sexps", "Output SEXPs to sexps.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_sexps", },
241 { "-output_scripting", "Output scripting to scripting.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_scripting", },
242 { "-output_script_json", "Output scripting doc to scripting.json", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_script_json", },
243 { "-save_render_target", "Save render targets to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-save_render_target", },
244 { "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", },
245 { "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", },
246 { "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
247 { "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
248 { "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
249 { "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
250 { "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
251 { "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
252 { "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
253 { "-gr_debug", "Output graphics debug information", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gr_debug", },
254 };
255 // clang-format on
256
257 // forward declaration
258 const char * get_param_desc(const char *flag_name);
259
260 // here are the command line parameters that we will be using for FreeSpace
261
262 // RETAIL options ----------------------------------------------
263 cmdline_parm connect_arg("-connect", "Automatically connect to multiplayer IP:PORT", AT_STRING); // Cmdline_connect_addr
264 cmdline_parm gamename_arg("-gamename", "Set multiplayer game name", AT_STRING); // Cmdline_game_name
265 cmdline_parm gamepassword_arg("-password", "Set multiplayer game password", AT_STRING); // Cmdline_game_password
266 cmdline_parm allowabove_arg("-allowabove", "Ranks above this can join multi", AT_STRING); // Cmdline_rank_above
267 cmdline_parm allowbelow_arg("-allowbelow", "Ranks below this can join multi", AT_STRING); // Cmdline_rank_below
268 cmdline_parm standalone_arg("-standalone", NULL, AT_NONE);
269 cmdline_parm nosound_arg("-nosound", NULL, AT_NONE); // Cmdline_freespace_no_sound
270 cmdline_parm nomusic_arg("-nomusic", NULL, AT_NONE); // Cmdline_freespace_no_music
271 cmdline_parm noenhancedsound_arg("-no_enhanced_sound", NULL, AT_NONE); // Cmdline_no_enhanced_sound
272 cmdline_parm startgame_arg("-startgame", NULL, AT_NONE); // Cmdline_start_netgame
273 cmdline_parm gameclosed_arg("-closed", NULL, AT_NONE); // Cmdline_closed_game
274 cmdline_parm gamerestricted_arg("-restricted", NULL, AT_NONE); // Cmdline_restricted_game
275 cmdline_parm port_arg("-port", "Multiplayer network port", AT_INT);
276 cmdline_parm multilog_arg("-multilog", NULL, AT_NONE); // Cmdline_multi_log
277 cmdline_parm pof_spew("-pofspew", NULL, AT_NONE); // Cmdline_spew_pof_info
278 cmdline_parm weapon_spew("-weaponspew", nullptr, AT_STRING); // Cmdline_spew_weapon_stats
279 cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
280 cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
281 cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
282
283 char *Cmdline_connect_addr = NULL;
284 char *Cmdline_game_name = NULL;
285 char *Cmdline_game_password = NULL;
286 char *Cmdline_rank_above = NULL;
287 char *Cmdline_rank_below = NULL;
288 int Cmdline_cd_check = 1;
289 int Cmdline_closed_game = 0;
290 int Cmdline_freespace_no_music = 0;
291 int Cmdline_freespace_no_sound = 0;
292 int Cmdline_gimme_all_medals = 0;
293 int Cmdline_mouse_coords = 0;
294 int Cmdline_multi_log = 0;
295 int Cmdline_multi_stream_chat_to_file = 0;
296 int Cmdline_network_port = -1;
297 int Cmdline_restricted_game = 0;
298 int Cmdline_spew_pof_info = 0;
299 WeaponSpewType Cmdline_spew_weapon_stats = WeaponSpewType::NONE;
300 int Cmdline_start_netgame = 0;
301 int Cmdline_timeout = -1;
302 int Cmdline_use_last_pilot = 0;
303
304
305 // FSO options -------------------------------------------------
306
307 // Graphics related
308 cmdline_parm fov_arg("-fov", "Vertical field-of-view factor", AT_FLOAT); // Cmdline_fov -- comand line FOV -Bobboau
309 cmdline_parm clip_dist_arg("-clipdist", "Changes the distance from the viewpoint for the near-clipping plane", AT_FLOAT); // Cmdline_clip_dist
310 cmdline_parm spec_static_arg("-spec_static", "Adjusts suns contribution to specular highlights", AT_FLOAT);
311 cmdline_parm spec_point_arg("-spec_point", "Adjusts laser weapons contribution to specular highlights", AT_FLOAT);
312 cmdline_parm spec_tube_arg("-spec_tube", "Adjusts beam weapons contribution to specular highlights", AT_FLOAT);
313 cmdline_parm ambient_factor_arg("-ambient_factor", "Adjusts ambient light applied to all parts of a ship", AT_INT); // Cmdline_ambient_factor
314 cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
315 cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
316 cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
317 cmdline_parm noscalevid_arg("-noscalevid", NULL, AT_NONE); // Cmdline_noscalevid -- disable video scaling that fits to window
318 cmdline_parm spec_arg("-nospec", NULL, AT_NONE); // Cmdline_spec --
319 cmdline_parm emissive_arg("-emissive_light", "Enable emissive light from ships", AT_NONE); // Cmdline_no_emissive -- don't use emissive light in OGL
320 cmdline_parm normal_arg("-nonormal", NULL, AT_NONE); // Cmdline_normal -- disable normal mapping
321 cmdline_parm height_arg("-noheight", NULL, AT_NONE); // Cmdline_height -- enable support for parallax mapping
322 cmdline_parm enable_3d_shockwave_arg("-3dshockwave", NULL, AT_NONE);
323 cmdline_parm softparticles_arg("-soft_particles", NULL, AT_NONE);
324 cmdline_parm no_postprocess_arg("-no_post_process", "Disables post-processing", AT_NONE);
325 cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires post-processing", AT_INT);
326 cmdline_parm post_process_aa_arg("-aa", "Enables post-process antialiasing", AT_NONE);
327 cmdline_parm post_process_aa_preset_arg("-aa_preset", "Sets the AA effect to use. See the wiki for details", AT_INT);
328 cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
329 cmdline_parm deprecated_fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-2), requires post-processing and -fxaa", AT_INT);
330 cmdline_parm deprecated_smaa_arg("-smaa", nullptr, AT_NONE);
331 cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), requires post-processing and -smaa", AT_INT);
332 cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
333 cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
334 cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
335 cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
336 cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
337 cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
338 cmdline_parm anisotropy_level_arg("-anisotropic_filter", NULL, AT_INT);
339
340 float Cmdline_clip_dist = Default_min_draw_distance;
341 int Cmdline_ambient_factor = 128;
342 int Cmdline_env = 1;
343 int Cmdline_mipmap = 0;
344 int Cmdline_glow = 1;
345 int Cmdline_noscalevid = 0;
346 int Cmdline_spec = 1;
347 int Cmdline_emissive = 0;
348 int Cmdline_normal = 1;
349 int Cmdline_height = 1;
350 int Cmdline_enable_3d_shockwave = 0;
351 int Cmdline_softparticles = 0;
352 int Cmdline_bloom_intensity = 25;
353 bool Cmdline_force_lightshaft_off = false;
354 int Cmdline_no_deferred_lighting = 0;
355 int Cmdline_aniso_level = 0;
356
357 // Game Speed related
358 cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
359 cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
360
361 int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
362 int Cmdline_no_vsync = 0;
363
364 // HUD related
365 cmdline_parm ballistic_gauge("-ballistic_gauge", NULL, AT_NONE); // Cmdline_ballistic_gauge
366 cmdline_parm dualscanlines_arg("-dualscanlines", NULL, AT_NONE); // Cmdline_dualscanlines -- Change to phreaks options including new targeting code
367 cmdline_parm orb_radar("-orbradar", NULL, AT_NONE); // Cmdline_orb_radar
368 cmdline_parm rearm_timer_arg("-rearm_timer", NULL, AT_NONE); // Cmdline_rearm_timer
369 cmdline_parm targetinfo_arg("-targetinfo", NULL, AT_NONE); // Cmdline_targetinfo -- Adds ship name/class to right of target box -C
370
371 int Cmdline_ballistic_gauge = 0; // WMCoolmon's gauge thingy
372 int Cmdline_dualscanlines = 0;
373 int Cmdline_orb_radar = 0;
374 int Cmdline_rearm_timer = 0;
375 int Cmdline_targetinfo = 0;
376
377 // Gameplay related
378 cmdline_parm use_3dwarp("-3dwarp", NULL, AT_NONE); // Cmdline_3dwarp
379 cmdline_parm ship_choice_3d_arg("-ship_choice_3d", NULL, AT_NONE); // Cmdline_ship_choice_3d
380 cmdline_parm weapon_choice_3d_arg("-weapon_choice_3d", NULL, AT_NONE); // Cmdline_weapon_choice_3d
381 cmdline_parm use_warp_flash("-warp_flash", NULL, AT_NONE); // Cmdline_warp_flash
382 cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", NULL, AT_NONE);
383 cmdline_parm stretch_menu("-stretch_menu", NULL, AT_NONE); // Cmdline_stretch_menu
384 cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
385
386 int Cmdline_3dwarp = 0;
387 int Cmdline_ship_choice_3d = 0;
388 int Cmdline_weapon_choice_3d = 0;
389 int Cmdline_warp_flash = 0;
390 int Cmdline_autopilot_interruptable = 1;
391 int Cmdline_stretch_menu = 0;
392 int Cmdline_no_screenshake = 0;
393
394 // Audio related
395 cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
396
397 int Cmdline_voice_recognition = 0;
398 int Cmdline_no_enhanced_sound = 0;
399
400 // MOD related
401 cmdline_parm mod_arg("-mod", "List of folders to overwrite/add-to the default data", AT_STRING, true); // Cmdline_mod -- DTP modsupport
402
403 char *Cmdline_mod = NULL; //DTP for mod argument
404
405 // Multiplayer/Network related
406 cmdline_parm almission_arg("-almission", "Autoload multiplayer mission", AT_STRING); // Cmdline_almission -- DTP for autoload Multi mission
407 cmdline_parm ingamejoin_arg("-ingame_join", NULL, AT_NONE); // Cmdline_ingamejoin
408 cmdline_parm mpnoreturn_arg("-mpnoreturn", NULL, AT_NONE); // Cmdline_mpnoreturn -- Removes 'Return to Flight Deck' in respawn dialog -C
409 cmdline_parm objupd_arg("-cap_object_update", "Multiplayer object update cap (0-3)", AT_INT);
410 cmdline_parm gateway_ip_arg("-gateway_ip", "Set gateway IP address", AT_STRING);
411
412 char *Cmdline_almission = NULL; //DTP for autoload multi mission.
413 int Cmdline_ingamejoin = 0;
414 int Cmdline_mpnoreturn = 0;
415 int Cmdline_objupd = 3; // client object updates on LAN by default
416 char *Cmdline_gateway_ip = nullptr;
417
418 // Launcher related options
419 cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
420
421 bool Cmdline_portable_mode = false;
422
423 // Troubleshooting
424 cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
425 cmdline_parm nomovies_arg("-nomovies", NULL, AT_NONE); // Cmdline_nomovies -- Allows video streaming
426 cmdline_parm no_set_gamma_arg("-no_set_gamma", NULL, AT_NONE); // Cmdline_no_set_gamma
427 cmdline_parm no_fbo_arg("-disable_fbo", NULL, AT_NONE); // Cmdline_no_fbo
428 cmdline_parm no_pbo_arg("-disable_pbo", NULL, AT_NONE); // Cmdline_no_pbo
429 cmdline_parm mipmap_arg("-mipmap", NULL, AT_NONE); // Cmdline_mipmap
430 cmdline_parm atiswap_arg("-ati_swap", NULL, AT_NONE); // Cmdline_atiswap - Fix ATI color swap issue for screenshots.
431 cmdline_parm no3dsound_arg("-no_3d_sound", NULL, AT_NONE); // Cmdline_no_3d_sound - Disable use of full 3D sounds
432 cmdline_parm no_drawrangeelements("-use_gldrawelements", NULL, AT_NONE); // Cmdline_drawelements -- Uses glDrawElements instead of glDrawRangeElements
433 cmdline_parm keyboard_layout("-keyboard_layout", "Specify keyboard layout (qwertz or azerty)", AT_STRING);
434 cmdline_parm gl_finish ("-gl_finish", NULL, AT_NONE);
435 cmdline_parm no_geo_sdr_effects("-no_geo_effects", NULL, AT_NONE);
436 cmdline_parm set_cpu_affinity("-set_cpu_affinity", NULL, AT_NONE);
437 cmdline_parm nograb_arg("-nograb", NULL, AT_NONE);
438 cmdline_parm noshadercache_arg("-noshadercache", NULL, AT_NONE);
439 #ifdef WIN32
440 cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
441 #endif
442
443 int Cmdline_load_all_weapons = 0;
444 int Cmdline_nomovies = 0;
445 int Cmdline_no_set_gamma = 0;
446 int Cmdline_no_fbo = 0;
447 int Cmdline_no_pbo = 0;
448 int Cmdline_ati_color_swap = 0;
449 int Cmdline_no_3d_sound = 0;
450 int Cmdline_drawelements = 0;
451 char* Cmdline_keyboard_layout = NULL;
452 bool Cmdline_gl_finish = false;
453 bool Cmdline_no_geo_sdr_effects = false;
454 bool Cmdline_set_cpu_affinity = false;
455 bool Cmdline_nograb = false;
456 bool Cmdline_noshadercache = false;
457 #ifdef WIN32
458 bool Cmdline_alternate_registry_path = false;
459 #endif
460
461 // Developer/Testing related
462 cmdline_parm start_mission_arg("-start_mission", "Skip mainhall and run this mission", AT_STRING); // Cmdline_start_mission
463 cmdline_parm dis_collisions("-dis_collisions", NULL, AT_NONE); // Cmdline_dis_collisions
464 cmdline_parm dis_weapons("-dis_weapons", NULL, AT_NONE); // Cmdline_dis_weapons
465 cmdline_parm noparseerrors_arg("-noparseerrors", NULL, AT_NONE); // Cmdline_noparseerrors -- turns off parsing errors -C
466 cmdline_parm extra_warn_arg("-extra_warn", "Enable 'extra' warnings", AT_NONE); // Cmdline_extra_warn
467 cmdline_parm fps_arg("-fps", NULL, AT_NONE); // Cmdline_show_fps
468 cmdline_parm bmpmanusage_arg("-bmpmanusage", NULL, AT_NONE); // Cmdline_bmpman_usage
469 cmdline_parm pos_arg("-pos", NULL, AT_NONE); // Cmdline_show_pos
470 cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
471 cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
472 cmdline_parm window_arg("-window", NULL, AT_NONE); // Cmdline_window
473 cmdline_parm fullscreen_window_arg("-fullscreen_window", "Fullscreen/borderless window (Windows only)", AT_NONE);
474 cmdline_parm res_arg("-res", "Resolution, formatted like 1600x900", AT_STRING);
475 cmdline_parm center_res_arg("-center_res", "Resolution of center monitor, formatted like 1600x900", AT_STRING);
476 cmdline_parm verify_vps_arg("-verify_vps", NULL, AT_NONE); // Cmdline_verify_vps -- spew VP crcs to vp_crcs.txt
477 cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_fso.cfg files", AT_NONE);
478 cmdline_parm reparse_mainhall_arg("-reparse_mainhall", NULL, AT_NONE); //Cmdline_reparse_mainhall
479 cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // Cmdline_profile_write_file
480 cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
481 cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
482 cmdline_parm pilot_arg("-pilot", nullptr, AT_STRING); //Cmdline_pilot
483 cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
484 cmdline_parm json_profiling("-json_profiling", NULL, AT_NONE); //Cmdline_json_profiling
485 cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_video_info
486 cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
487 cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_window
488 cmdline_parm graphics_debug_output_arg("-gr_debug", nullptr, AT_NONE); // Cmdline_graphics_debug_output
489 cmdline_parm log_to_stdout_arg("-stdout_log", nullptr, AT_NONE); // Cmdline_log_to_stdout
490
491
492 char *Cmdline_start_mission = NULL;
493 int Cmdline_dis_collisions = 0;
494 int Cmdline_dis_weapons = 0;
495 bool Cmdline_output_sexp_info = false;
496 int Cmdline_noparseerrors = 0;
497 #ifdef Allow_NoWarn
498 int Cmdline_nowarn = 0; // turn warnings off in FRED
499 #endif
500 int Cmdline_extra_warn = 0;
501 int Cmdline_bmpman_usage = 0;
502 int Cmdline_show_pos = 0;
503 int Cmdline_show_stats = 0;
504 int Cmdline_save_render_targets = 0;
505 int Cmdline_window = 0;
506 int Cmdline_fullscreen_window = 0;
507 char *Cmdline_res = 0;
508 char *Cmdline_center_res = 0;
509 int Cmdline_verify_vps = 0;
510 int Cmdline_reparse_mainhall = 0;
511 bool Cmdline_profile_write_file = false;
512 bool Cmdline_no_unfocus_pause = false;
513 bool Cmdline_benchmark_mode = false;
514 const char *Cmdline_pilot = nullptr;
515 bool Cmdline_noninteractive = false;
516 bool Cmdline_json_profiling = false;
517 bool Cmdline_frame_profile = false;
518 bool Cmdline_show_video_info = false;
519 bool Cmdline_debug_window = false;
520 bool Cmdline_graphics_debug_output = false;
521 bool Cmdline_log_to_stdout = false;
522
523 // Other
524 cmdline_parm get_flags_arg(GET_FLAGS_STRING, "Output the launcher flags file", AT_STRING);
525 cmdline_parm output_sexp_arg("-output_sexps", NULL, AT_NONE); //WMC - outputs all SEXPs to sexps.html
526 cmdline_parm output_scripting_arg("-output_scripting", NULL, AT_NONE); //WMC
527 cmdline_parm output_script_json_arg("-output_script_json", nullptr, AT_NONE); // m!m
528
529 // Deprecated flags - CommanderDJ
530 cmdline_parm deprecated_spec_arg("-spec", "Deprecated", AT_NONE);
531 cmdline_parm deprecated_glow_arg("-glow", "Deprecated", AT_NONE);
532 cmdline_parm deprecated_normal_arg("-normal", "Deprecated", AT_NONE);
533 cmdline_parm deprecated_env_arg("-env", "Deprecated", AT_NONE);
534 cmdline_parm deprecated_tbp_arg("-tbp", "Deprecated", AT_NONE);
535 cmdline_parm deprecated_jpgtga_arg("-jpgtga", "Deprecated", AT_NONE);
536 cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
537 cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
538 cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
539 cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
540 cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NONE);
541 cmdline_parm deprecated_no_emissive_arg("-no_emissive_light", "Deprecated", AT_NONE);
542 cmdline_parm deprecated_postprocess_arg("-post_process", "Deprecated", AT_NONE);
543
544 int Cmdline_deprecated_spec = 0;
545 int Cmdline_deprecated_glow = 0;
546 int Cmdline_deprecated_normal = 0;
547 int Cmdline_deprecated_env = 0;
548 int Cmdline_deprecated_tbp = 0;
549 int Cmdline_deprecated_jpgtga = 0;
550 int Cmdline_deprecated_nohtl = 0;
551 bool Cmdline_deprecated_brief_lighting = 0;
552 bool Cmdline_deprecated_missile_lighting = false;
553 bool Cmdline_deprecated_cache_bitmaps = false;
554 bool Cmdline_deprecated_postprocess = false;
555
556 #ifndef NDEBUG
557 // NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
cmdline_debug_print_cmdline()558 void cmdline_debug_print_cmdline()
559 {
560 cmdline_parm *parmp;
561 int found = 0;
562 mprintf(("Passed cmdline options:"));
563
564 for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
565 if ( parmp->name_found ) {
566 if ( parmp->args != NULL ) {
567 mprintf(("\n %s %s", parmp->name, parmp->args));
568 } else {
569 mprintf(("\n %s", parmp->name));
570 }
571 found++;
572 }
573 }
574
575 if ( !found )
576 mprintf(("\n <none>"));
577
578 mprintf(("\n"));
579
580 //Print log messages about any deprecated flags we found - CommanderDJ
581 if(Cmdline_deprecated_spec == 1)
582 {
583 mprintf(("Deprecated flag '-spec' found. Please remove from your cmdline.\n"));
584 }
585
586 if(Cmdline_deprecated_glow == 1)
587 {
588 mprintf(("Deprecated flag '-glow' found. Please remove from your cmdline.\n"));
589 }
590
591 if(Cmdline_deprecated_normal == 1)
592 {
593 mprintf(("Deprecated flag '-normal' found. Please remove from your cmdline.\n"));
594 }
595
596 if(Cmdline_deprecated_env == 1)
597 {
598 mprintf(("Deprecated flag '-env' found. Please remove from your cmdline.\n"));
599 }
600
601 if(Cmdline_deprecated_tbp == 1)
602 {
603 mprintf(("Deprecated flag '-tbp' found. Please remove from your cmdline.\n"));
604 }
605
606 if(Cmdline_deprecated_jpgtga == 1)
607 {
608 mprintf(("Deprecated flag '-jpgtga' found. Please remove from your cmdline.\n"));
609 }
610
611 if(Cmdline_deprecated_nohtl == 1)
612 {
613 mprintf(("Deprecated flag '-nohtl' found. Please remove from your cmdline.\n"));
614 }
615
616 if(Cmdline_deprecated_brief_lighting == 1)
617 {
618 mprintf(("Deprecated flag '-brief_lighting' found. Please remove from your cmdline.\n"));
619 }
620
621 if (Cmdline_deprecated_missile_lighting)
622 {
623 mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
624 }
625
626 if (Cmdline_deprecated_cache_bitmaps) {
627 mprintf(("Deprecated flag '-cache_bitmaps' found. Please remove from your cmdline.\n"));
628 }
629
630 if (Cmdline_deprecated_postprocess) {
631 mprintf(("Deprecated flag '-post_process' found. Please remove from your cmdline.\n"));
632 }
633 }
634 #endif
635
636 // Return true if this character is an extra char (white space and quotes)
is_extra_space(char ch)637 int is_extra_space(char ch)
638 {
639 return ((ch == ' ') || (ch == '\t') || (ch == 0x0a) || (ch == '\'') || (ch == '\"'));
640 }
641
642
643 // eliminates all leading and trailing extra chars from a string. Returns pointer passed in.
drop_extra_chars(char * str)644 char *drop_extra_chars(char *str)
645 {
646 size_t s;
647 size_t e;
648
649 s = 0;
650 while (str[s] && is_extra_space(str[s]))
651 s++;
652
653 e = strlen(str);
654
655 if (e > 0) {
656 // we already account for NULL later on, so the -1 is here to make
657 // sure we do our math without taking it into consideration
658 e -= 1;
659 }
660
661 while (e > s) {
662 if (!is_extra_space(str[e])){
663 break;
664 }
665
666 e--;
667 }
668
669 if (e >= s && e !=0 ){
670 memmove(str, str + s, e - s + 1);
671 }
672
673 str[e - s + 1] = 0;
674 return str;
675 }
676
677
678 /*
679 * @brief Processes one argument for the given parameter
680 *
681 * @param param The parameter to check
682 * @param argc The argument count
683 * @param argc The argument values
684 * @param argc The current index
685 * @return @c true when an extra parameter was found, @c false otherwise
686 */
parm_stuff_args(cmdline_parm * parm,int argc,char * argv[],int index)687 bool parm_stuff_args(cmdline_parm *parm, int argc, char *argv[], int index)
688 {
689 Assert(index < argc);
690
691 if (index + 1 < argc)
692 {
693 char* value = argv[index + 1];
694 if (value[0] == '-')
695 {
696 // Found another argument, just return
697 return false;
698 }
699 else
700 {
701 char* saved_args = NULL;
702
703 if (parm->args != NULL) {
704 if (parm->stacks) {
705 saved_args = parm->args;
706 }
707 else {
708 delete[] parm->args;
709 }
710
711 parm->args = NULL;
712 }
713
714 size_t argsize = strlen(argv[index + 1]);
715 size_t buffersize = argsize;
716
717 if (saved_args != NULL)
718 {
719 // Add one for the , separating args
720 buffersize += strlen(saved_args) + 1;
721 }
722
723 buffersize += 1; // Null-terminator
724
725 parm->args = new char[buffersize];
726 memset(parm->args, 0, buffersize);
727
728 if (saved_args != NULL)
729 {
730 // saved args go first, then new arg
731 strcpy_s(parm->args, buffersize, saved_args);
732 // add a separator too, so that we can tell the args apart
733 strcat_s(parm->args, buffersize, ",");
734 // now the new arg
735 strcat_s(parm->args, buffersize, argv[index + 1]);
736
737 delete[] saved_args;
738 }
739 else
740 {
741 strcpy_s(parm->args, buffersize, argv[index + 1]);
742 }
743
744 return true;
745 }
746 }
747 else
748 {
749 // Last argument, can't have any values
750 return false;
751 }
752 }
753
754
755 // internal function - parse the command line, extracting parameter arguments if they exist
756 // cmdline - command line string passed to the application
os_parse_parms(int argc,char * argv[])757 void os_parse_parms(int argc, char *argv[])
758 {
759 // locate command line parameters
760 cmdline_parm *parmp;
761
762 for (int i = 0; i < argc; i++)
763 {
764 // On OS X this gets passed if the application was launched by double-clicking in the Finder
765 if (i == 1 && strncmp(argv[i], "-psn", 4) == 0)
766 {
767 continue;
768 }
769
770 for (parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
771 if (!stricmp(parmp->name, argv[i]))
772 {
773 parmp->name_found = 1;
774 if (parm_stuff_args(parmp, argc, argv, i))
775 {
776 i++;
777 }
778 }
779 }
780 }
781 }
782
783
784 // validate the command line parameters. Display an error if an unrecognized parameter is located.
os_validate_parms(int argc,char * argv[])785 void os_validate_parms(int argc, char *argv[])
786 {
787 cmdline_parm *parmp;
788 char *token;
789 int parm_found;
790
791 for (int i = 0; i < argc; i++)
792 {
793 token = argv[i];
794
795 // On OS X this gets passed if the application was launched by double-clicking in the Finder
796 if (i == 1 && strncmp(token, "-psn", 4) == 0) {
797 continue;
798 }
799
800 if (token[0] == '-') {
801 parm_found = 0;
802
803 for (parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
804 if (!stricmp(parmp->name, token)) {
805 parm_found = 1;
806 break;
807 }
808 }
809
810 if (parm_found == 0) {
811 // if we got a -help, --help, -h, or -? then show the help text, otherwise show unknown option
812 if (!stricmp(token, "-help") || !stricmp(token, "--help") || !stricmp(token, "-h") || !stricmp(token, "-?")) {
813 printf("FreeSpace 2 Open, version %s\n", FS_VERSION_FULL);
814 printf("Website: http://scp.indiegames.us\n");
815 printf("Github (bug reporting): https://github.com/scp-fs2open/fs2open.github.com/issues\n\n");
816 printf("Usage: fs2_open [options]\n");
817
818 // not the prettiest thing but the job gets done
819 static const int STR_SIZE = 25; // max len of exe_params.name + 5 spaces
820 const int AT_SIZE = 8; // max len of cmdline_arg_types[] + 2 spaces
821 size_t atp = 0;
822 size_t sp = 0;
823 for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
824 // don't output deprecated flags
825 if (stricmp("deprecated", parmp->help) != 0) {
826 sp = strlen(parmp->name);
827 if (parmp->arg_type != AT_NONE) {
828 atp = strlen(cmdline_arg_types[parmp->arg_type]);
829 printf(" [ %s ]%*s[ %s ]%*s- %s\n", parmp->name, (int)(STR_SIZE - sp -1), NOX(" "), cmdline_arg_types[parmp->arg_type], (int)(AT_SIZE-atp), NOX(" "), parmp->help);
830 } else {
831 printf(" [ %s ]%*s- %s\n", parmp->name, (int)(STR_SIZE - sp -1 +AT_SIZE+4), NOX(" "), parmp->help);
832 }
833 }
834 }
835
836 printf("\n");
837 exit(0);
838 }
839 else {
840 char buffer[128];
841 sprintf(buffer, "Unrecognized command line parameter %s.", token);
842
843 os::dialogs::Message(os::dialogs::MESSAGEBOX_INFORMATION, buffer);
844 }
845 }
846 }
847 }
848 }
849
parse_cmdline_string(char * cmdline,char ** argv)850 int parse_cmdline_string(char* cmdline, char** argv)
851 {
852 size_t length = strlen(cmdline);
853
854 bool start_found = false;
855 bool quoted = false;
856
857 size_t argc = 0;
858 char* current_argv = NULL;
859 for (size_t i = 0; i < length; i++)
860 {
861 if (!start_found && !isspace(cmdline[i]))
862 {
863 start_found = true;
864 current_argv = (cmdline + i);
865 }
866 else if (start_found)
867 {
868 if (cmdline[i] == '"')
869 {
870 quoted = !quoted;
871
872 if (!quoted && current_argv != NULL)
873 {
874 if (argv != NULL)
875 {
876 // Terminate string at quote
877 cmdline[i] = '\0';
878 argv[argc] = current_argv;
879 current_argv = NULL;
880 }
881
882 argc++;
883 }
884 }
885 else if (isspace(cmdline[i]) && !quoted)
886 {
887 // Parameter terminated by space
888 if (current_argv != NULL) // == NULL means that we currently don't have a parameter
889 {
890 if (argv != NULL)
891 {
892 // Terminate string at quote
893 cmdline[i] = '\0';
894 argv[argc] = current_argv;
895 current_argv = NULL;
896 }
897
898 argc++;
899 }
900 }
901 else if (current_argv == NULL)
902 {
903 current_argv = cmdline + i;
904 }
905 }
906 }
907
908 if (current_argv != NULL)
909 {
910 if (argv != NULL)
911 {
912 // Terminate string at quote
913 argv[argc] = current_argv;
914 current_argv = NULL;
915 }
916
917 argc++;
918 }
919
920 return (int)argc;
921 }
922
os_process_cmdline(char * cmdline)923 void os_process_cmdline(char* cmdline)
924 {
925 int argc = parse_cmdline_string(cmdline, NULL);
926
927 char** argv = new char*[argc];
928
929 argc = parse_cmdline_string(cmdline, argv);
930
931 os_parse_parms(argc, argv);
932 os_validate_parms(argc, argv);
933
934 delete[] argv;
935 }
936
has_cmdline_only_or_get_flags(int argc,char * argv[])937 bool has_cmdline_only_or_get_flags(int argc, char *argv[])
938 {
939 for (int i = 0; i < argc; ++i)
940 {
941 if (!strcmp(argv[i], PARSE_COMMAND_LINE_STRING) || !strcmp(argv[i], GET_FLAGS_STRING))
942 {
943 return true;
944 }
945 }
946
947 return false;
948 }
949
950 // remove old parms - needed for tests
reset_cmdline_parms()951 static void reset_cmdline_parms()
952 {
953 for (cmdline_parm *parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
954 if (parmp->args != NULL) {
955 delete[] parmp->args;
956 parmp->args = NULL;
957 }
958 parmp->name_found = 0;
959 }
960 }
961
962 // Call once to initialize the command line system
963 //
964 // cmdline - command line string passed to the application
os_init_cmdline(int argc,char * argv[])965 void os_init_cmdline(int argc, char *argv[])
966 {
967 // Tests call this multiple times, so reset the params here.
968 // Otherwise e.g. the modlist just grows and grows...
969 reset_cmdline_parms();
970
971 FILE *fp;
972
973 // Don't parse any command-line config files if we specified PARSE_COMMAND_LINE_STRING (to explicitly prevent it),
974 // or GET_FLAGS_STRING (because the engine is going to do a quick exit and for GitHub issue #1221)
975 if (!has_cmdline_only_or_get_flags(argc, argv)) {
976 // Only parse the config file in the current directory if we are in legacy config mode
977 if (os_is_legacy_mode()) {
978 // read the cmdline_fso.cfg file from the data folder, and pass the command line arguments to
979 // the the parse_parms and validate_parms line. Read these first so anything actually on
980 // the command line will take precedence
981 #ifdef APPLE_APP
982 char resolved_path[MAX_PATH], data_path[MAX_PATH_LEN];
983
984 getcwd(data_path, sizeof(data_path));
985 snprintf(resolved_path, MAX_PATH, "%s/data/cmdline_fso.cfg", data_path);
986
987 fp = fopen(resolved_path, "rt");
988 #else
989 fp = fopen("data" DIR_SEPARATOR_STR "cmdline_fso.cfg", "rt");
990 #endif
991 // if the file exists, get a single line, and deal with it
992 if (fp) {
993 char *buf, *p;
994
995 auto len = static_cast<int>(filelength(fileno(fp))) + 2;
996 buf = new char[len];
997
998 if (fgets(buf, len - 1, fp) != nullptr)
999 {
1000 // replace the newline character with a NULL
1001 if ((p = strrchr(buf, '\n')) != NULL) {
1002 *p = '\0';
1003 }
1004 #ifdef SCP_UNIX
1005 // append a space for the os_parse_parms() check
1006 strcat_s(buf, len, " ");
1007 #endif
1008 os_process_cmdline(buf);
1009 }
1010 delete[] buf;
1011 fclose(fp);
1012 }
1013 } else {
1014 // parse user specific cmdline_fso config file (will supersede options in global file)
1015 fp = fopen(os_get_config_path("data/cmdline_fso.cfg").c_str(), "rt");
1016
1017 // if the file exists, get a single line, and deal with it
1018 if ( fp ) {
1019 char *buf, *p;
1020
1021 auto len = static_cast<int>(filelength( fileno(fp) )) + 2;
1022 buf = new char [len];
1023
1024 if (fgets(buf, len-1, fp) != nullptr)
1025 {
1026 // replace the newline character with a NULL
1027 if ( (p = strrchr(buf, '\n')) != NULL ) {
1028 *p = '\0';
1029 }
1030
1031 // append a space for the os_parse_parms() check
1032 strcat_s(buf, len, " ");
1033
1034 os_process_cmdline(buf);
1035 }
1036 delete [] buf;
1037 fclose(fp);
1038 }
1039 }
1040 } // If cmdline included PARSE_COMMAND_LINE_STRING or GET_FLAGS_STRING
1041
1042 // By parsing cmdline last, anything actually on the command line will take precedence.
1043 os_parse_parms(argc, argv);
1044 os_validate_parms(argc, argv);
1045 }
1046
1047
1048 /*
1049 * arg constructor
1050 *
1051 * @param name_ name of the parameter, must start with '-' character
1052 * @param help_ help text for this parameter
1053 * @param arg_type_ parameters arguement type (if any)
1054 * @param stacks_ can the parameter be stacked
1055 */
cmdline_parm(const char * name_,const char * help_,const int arg_type_,const bool stacks_)1056 cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_type_, const bool stacks_) noexcept:
1057 name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
1058 {
1059 args = NULL;
1060 name_found = 0;
1061
1062 if (Parm_list_inited == 0) {
1063 Assertion(&Parm_list == this, "Coding error! 1st initialised cmdline_parm must be static Parm_list\n");
1064 list_init(this);
1065 Parm_list_inited = 1;
1066 } else {
1067 Assertion(name, "Coding error! cmdline_parm's must have a non-NULL name\n");
1068 Assertion(name[0] == '-', "Coding error! cmdline_parm's must start with a '-'\n");
1069 // not in the static Parm_list init, so lookup the NULL help args
1070 if (help == NULL) {
1071 help = get_param_desc(name);
1072 }
1073 list_append(&Parm_list, this);
1074 }
1075 }
1076
1077
1078 // destructor - frees any allocated memory
~cmdline_parm()1079 cmdline_parm::~cmdline_parm() noexcept
1080 {
1081 #ifndef FRED
1082 if (args) {
1083 delete [] args;
1084 args = NULL;
1085 }
1086 #endif
1087 }
1088
1089 // checks if the objects args variable is valid
1090 // returns true if it is, shows an error box and returns false if not valid.
check_if_args_is_valid()1091 bool cmdline_parm::check_if_args_is_valid() {
1092 if ( args == NULL ) {
1093 Error(__FILE__, __LINE__,
1094 "Command line flag passed that requires an argument, but the argument is missing!\r\n"
1095 "The flag is '%s', make sure that you have an argument that follows it.\r\n"
1096 "You may need to close your launcher and remove the flag manually from %s/data/cmdline_fso.cfg\r\n",
1097 name, "<Freespace directory>");
1098 return false;
1099 } else {
1100 return true;
1101 }
1102 }
1103
1104
1105 // returns - true if the parameter exists on the command line, otherwise false
found()1106 int cmdline_parm::found()
1107 {
1108 return name_found;
1109 }
1110
1111 // returns - the interger representation for the parameter argument
get_int()1112 int cmdline_parm::get_int()
1113 {
1114 Assertion(arg_type == AT_INT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_int() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
1115 check_if_args_is_valid();
1116
1117 size_t offset = 0;
1118
1119 if (stacks) {
1120 // first off, DON'T STACK NON-STRINGS!!
1121 Int3();
1122
1123 // secondly, we still need to get it right for the user's sake...
1124 char *moron = strstr(args, ",");
1125
1126 if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
1127 // we get the last arg, since it's the newest one
1128 offset = strlen(args) - strlen(moron) + 1;
1129 }
1130 }
1131
1132 return atoi(args+offset);
1133 }
1134
1135
1136 // returns - the float representation for the parameter argument
get_float()1137 float cmdline_parm::get_float()
1138 {
1139 Assertion(arg_type == AT_FLOAT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_float() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
1140 check_if_args_is_valid();
1141
1142 size_t offset = 0;
1143
1144 if (stacks) {
1145 // first off, DON'T STACK NON-STRINGS!!
1146 Int3();
1147
1148 // secondly, we still need to get it right for the user's sake
1149 char *moron = strstr(args, ",");
1150
1151 if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
1152 // we get the last arg, since it's the newest one
1153 offset = strlen(args) - strlen(moron) + 1;
1154 }
1155 }
1156
1157 return (float)atof(args+offset);
1158 }
1159
1160
1161 // returns - the string value for the parameter argument
str()1162 char *cmdline_parm::str()
1163 {
1164 Assertion(arg_type == AT_STRING, "Coding error! Cmdline arg (%s) called cmdline_parm::str() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
1165 check_if_args_is_valid();
1166
1167 return args;
1168 }
has_param()1169 bool cmdline_parm::has_param() {
1170 return args != nullptr;
1171 }
1172
1173 #ifdef SCP_UNIX
1174 // Return a vector with all filesystem names of "parent/dir" relative to parent.
1175 // dir must not contain a slash.
unix_get_single_dir_names(const SCP_string & parent,const SCP_string & dir)1176 static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
1177 {
1178 SCP_vector<SCP_string> ret;
1179
1180 DIR *dp;
1181 if ((dp = opendir(parent.c_str())) == NULL) {
1182 Warning(LOCATION, "Can't open directory '%s' when searching mod paths. Ignoring. errno=%d", parent.c_str(), errno);
1183 return ret;
1184 }
1185
1186 dirent *dirp;
1187 while ((dirp = readdir(dp)) != NULL) {
1188 if (!stricmp(dirp->d_name, dir.c_str())) {
1189 ret.push_back(dirp->d_name);
1190 }
1191 }
1192 (void)closedir(dp);
1193
1194 return ret;
1195 }
1196
1197 // Return a vector with all filesystem names of "parent/dir" relative to parent.
1198 // Recurses to deal with slashes in dir.
unix_get_dir_names(const SCP_string & parent,const SCP_string & dir)1199 static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
1200 {
1201 size_t slash = dir.find_first_of("/\\");
1202
1203 // no subdirectories, no need to recurse
1204 if (slash == std::string::npos) {
1205 return unix_get_single_dir_names(parent, dir);
1206 }
1207
1208 // get the names of the first component of dir
1209 SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names(parent, dir.substr(0, slash));
1210
1211 SCP_string rest = dir.substr(slash + 1);
1212
1213 SCP_vector<SCP_string> ret;
1214
1215 // search for the rest of dir in each of these
1216 SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end();
1217 for (ii = this_dir_names.begin(); ii != end; ++ii) {
1218 SCP_string this_dir_path = parent + "/" + *ii;
1219 SCP_vector<SCP_string> mod_path = unix_get_dir_names(this_dir_path, rest);
1220
1221 // add all found paths relative to parent
1222 SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end();
1223 for (ii2 = mod_path.begin(); ii2 != end2; ++ii2) {
1224 ret.push_back(*ii + "/" + *ii2);
1225 }
1226 }
1227
1228 return ret;
1229 }
1230
1231 // For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
handle_unix_modlist(char ** modlist,size_t * len)1232 static void handle_unix_modlist(char **modlist, size_t *len)
1233 {
1234 // search filesystem for given paths
1235 SCP_vector<SCP_string> mod_paths;
1236 for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
1237 {
1238 SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
1239 // Ignore non-existing mods for unit tests
1240 if (!running_unittests && this_mod_paths.empty()) {
1241 ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
1242 }
1243 mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
1244 }
1245
1246 // create new char[] to replace modlist
1247 size_t total_len = 0;
1248 SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
1249 for (ii = mod_paths.begin(); ii != end; ++ii) {
1250 total_len += ii->length() + 1;
1251 }
1252
1253 char *new_modlist = new char[total_len + 1];
1254 memset(new_modlist, 0, total_len + 1);
1255 end = mod_paths.end();
1256 for (ii = mod_paths.begin(); ii != end; ++ii) {
1257 strcat_s(new_modlist, total_len + 1, ii->c_str());
1258 strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
1259 }
1260
1261 // make the rest of the modlist manipulation unaware that anything happened here
1262 delete [] *modlist;
1263 *modlist = new_modlist;
1264 *len = total_len;
1265 }
1266 #endif /* SCP_UNIX */
1267
1268 // external entry point into this modules
1269
json_get_v1()1270 static json_t* json_get_v1() {
1271 auto root = json_object();
1272
1273 {
1274 auto version_obj = json_object();
1275
1276 json_object_set_new(version_obj, "full", json_string(FS_VERSION_FULL));
1277 json_object_set_new(version_obj, "major", json_integer(FS_VERSION_MAJOR));
1278 json_object_set_new(version_obj, "minor", json_integer(FS_VERSION_MINOR));
1279 json_object_set_new(version_obj, "build", json_integer(FS_VERSION_BUILD));
1280
1281 json_object_set_new(version_obj, "has_revision", json_boolean(FS_VERSION_HAS_REVIS));
1282 json_object_set_new(version_obj, "revision", json_integer(FS_VERSION_REVIS));
1283 json_object_set_new(version_obj, "revision_str", json_string(FS_VERSION_REVIS_STR));
1284
1285 json_object_set_new(root, "version", version_obj);
1286 }
1287 {
1288 auto easy_array = json_array();
1289
1290 for (auto& easy_flag : easy_flags) {
1291 json_array_append_new(easy_array, json_string(easy_flag.name));
1292 }
1293
1294 json_object_set_new(root, "easy_flags", easy_array);
1295 }
1296 {
1297 auto flags_array = json_array();
1298
1299 for (auto& flag : exe_params) {
1300 auto flag_obj = json_object();
1301
1302 json_object_set_new(flag_obj, "name", json_string(flag.name));
1303 json_object_set_new(flag_obj, "description", json_string(flag.desc));
1304 json_object_set_new(flag_obj, "fso_only", json_boolean(flag.fso_only));
1305 json_object_set_new(flag_obj, "on_flags", json_integer(flag.on_flags));
1306 json_object_set_new(flag_obj, "off_flags", json_integer(flag.off_flags));
1307 json_object_set_new(flag_obj, "type", json_string(flag.type));
1308 json_object_set_new(flag_obj, "web_url", json_string(flag.web_url));
1309
1310 json_array_append_new(flags_array, flag_obj);
1311 }
1312
1313 json_object_set_new(root, "flags", flags_array);
1314 }
1315 {
1316 auto caps_array = json_array();
1317
1318 json_array_append_new(caps_array, json_string("OpenAL"));
1319 json_array_append_new(caps_array, json_string("No D3D"));
1320 json_array_append_new(caps_array, json_string("New Sound"));
1321 json_array_append_new(caps_array, json_string("SDL"));
1322
1323 json_object_set_new(root, "caps", caps_array);
1324 }
1325 {
1326 auto voices_array = json_array();
1327
1328 auto voices = speech_enumerate_voices();
1329
1330 for (auto& voice : voices) {
1331 json_array_append_new(voices_array, json_string(voice.c_str()));
1332 }
1333
1334 json_object_set_new(root, "voices", voices_array);
1335 }
1336 {
1337 auto resolution_array = json_array();
1338
1339 auto displays = gr_enumerate_displays();
1340
1341 for (auto& display : displays) {
1342 auto display_obj = json_object();
1343
1344 json_object_set_new(display_obj, "index", json_integer(display.index));
1345 json_object_set_new(display_obj, "name", json_string(display.name.c_str()));
1346
1347 json_object_set_new(display_obj, "x", json_integer(display.x));
1348 json_object_set_new(display_obj, "y", json_integer(display.y));
1349 json_object_set_new(display_obj, "width", json_integer(display.width));
1350 json_object_set_new(display_obj, "height", json_integer(display.height));
1351
1352 auto modes_array = json_array();
1353
1354 for (auto& mode : display.video_modes) {
1355 auto mode_obj = json_object();
1356
1357 json_object_set_new(mode_obj, "x", json_integer(mode.width));
1358 json_object_set_new(mode_obj, "y", json_integer(mode.height));
1359 json_object_set_new(mode_obj, "bits", json_integer(mode.bit_depth));
1360
1361 json_array_append_new(modes_array, mode_obj);
1362 }
1363
1364 json_object_set_new(display_obj, "modes", modes_array);
1365
1366 json_array_append_new(resolution_array, display_obj);
1367 }
1368
1369 json_object_set_new(root, "displays", resolution_array);
1370 }
1371 {
1372 auto openal_obj = json_object();
1373
1374 auto openal_info = openal_get_platform_information();
1375
1376 json_object_set_new(openal_obj, "version_major", json_integer(openal_info.version_major));
1377 json_object_set_new(openal_obj, "version_minor", json_integer(openal_info.version_minor));
1378
1379 json_object_set(openal_obj, "default_playback", json_string(openal_info.default_playback_device.c_str()));
1380 json_object_set(openal_obj, "default_capture", json_string(openal_info.default_capture_device.c_str()));
1381
1382 {
1383 auto playback_array = json_array();
1384
1385 for (auto& device : openal_info.playback_devices) {
1386 json_array_append_new(playback_array, json_string(device.c_str()));
1387 }
1388
1389 json_object_set_new(openal_obj, "playback_devices", playback_array);
1390 }
1391 {
1392 auto capture_array = json_array();
1393
1394 for (auto& device : openal_info.capture_devices) {
1395 json_array_append_new(capture_array, json_string(device.c_str()));
1396 }
1397
1398 json_object_set_new(openal_obj, "capture_devices", capture_array);
1399 }
1400 {
1401 auto efx_support_obj = json_object();
1402
1403 for (auto& pair : openal_info.efx_support) {
1404 json_object_set_new(efx_support_obj, pair.first.c_str(), json_boolean(pair.second));
1405 }
1406
1407 json_object_set_new(openal_obj, "efx_support", efx_support_obj);
1408 }
1409
1410 json_object_set_new(root, "openal", openal_obj);
1411 }
1412 {
1413 auto joystick_array = json_array();
1414
1415 auto joysticks = io::joystick::getJoystickInformations();
1416 for (auto& info : joysticks) {
1417 auto joystick_obj = json_object();
1418
1419 json_object_set_new(joystick_obj, "name", json_string(info.name.c_str()));
1420 json_object_set_new(joystick_obj, "guid", json_string(info.guid.c_str()));
1421
1422 json_object_set_new(joystick_obj, "num_axes", json_integer(info.num_axes));
1423 json_object_set_new(joystick_obj, "num_balls", json_integer(info.num_balls));
1424 json_object_set_new(joystick_obj, "num_buttons", json_integer(info.num_buttons));
1425 json_object_set_new(joystick_obj, "num_hats", json_integer(info.num_hats));
1426
1427 json_object_set_new(joystick_obj, "is_haptic", json_boolean(info.is_haptic));
1428
1429 json_array_append_new(joystick_array, joystick_obj);
1430 }
1431
1432 json_object_set_new(root, "joysticks", joystick_array);
1433 }
1434 {
1435 json_object_set_new(root, "pref_path", json_string(os_get_config_path().c_str()));
1436 }
1437
1438 return root;
1439 }
1440
write_flags_file()1441 static void write_flags_file() {
1442 FILE *fp = fopen("flags.lch","w");
1443
1444 if (fp == NULL) {
1445 os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "Error creating flag list for launcher");
1446 return;
1447 }
1448
1449 int easy_flag_size = sizeof(EasyFlag);
1450 int flag_size = sizeof(Flag);
1451
1452 int num_easy_flags = sizeof(easy_flags) / easy_flag_size;
1453 int num_flags = sizeof(exe_params) / flag_size;
1454
1455 // Launcher will check its using structures of the same size
1456 fwrite(&easy_flag_size, sizeof(int), 1, fp);
1457 fwrite(&flag_size, sizeof(int), 1, fp);
1458
1459 fwrite(&num_easy_flags, sizeof(int), 1, fp);
1460 fwrite(&easy_flags, sizeof(easy_flags), 1, fp);
1461
1462 fwrite(&num_flags, sizeof(int), 1, fp);
1463 fwrite(&exe_params, sizeof(exe_params), 1, fp);
1464
1465 {
1466 // cheap and bastardly cap check for builds
1467 // (needs to be compatible with older Launchers, which means having
1468 // this implies an OpenAL build for old Launchers)
1469 ubyte build_caps = 0;
1470
1471 /* portej05 defined this always */
1472 build_caps |= BUILD_CAPS_OPENAL;
1473 build_caps |= BUILD_CAPS_NO_D3D;
1474 build_caps |= BUILD_CAPS_NEW_SND;
1475 build_caps |= BUILD_CAPS_SDL;
1476
1477 fwrite(&build_caps, 1, 1, fp);
1478 }
1479
1480 fflush(fp);
1481 fclose(fp);
1482 }
1483
get_flags_output_type()1484 static flag_output_type get_flags_output_type() {
1485 Assertion(get_flags_arg.found(), "This function is only valid if " GET_FLAGS_STRING " is present!");
1486
1487 if (!get_flags_arg.has_param()) {
1488 // Default to binary mode
1489 return flag_output_type::Binary;
1490 }
1491
1492 SCP_string type(get_flags_arg.str());
1493
1494 if (type == "binary") {
1495 return flag_output_type::Binary;
1496 } else if (type == "json_v1") {
1497 return flag_output_type::Json_V1;
1498 } else {
1499 // This is supposed to make it easy for the launcher to recognize an unsupported type
1500 printf("OUTPUT TYPE NOT SUPPORTED!\n");
1501 // Default to json in this case so that no flags.lch file is created
1502 return flag_output_type::Json_V1;
1503 }
1504 }
1505
write_flags()1506 static void write_flags() {
1507 auto type = get_flags_output_type();
1508 switch(type) {
1509 case flag_output_type::Binary:
1510 write_flags_file();
1511 break;
1512 case flag_output_type::Json_V1:
1513 json_t* root = json_get_v1();
1514
1515 json_dumpf(root, stdout, JSON_INDENT(4));
1516 json_decref(root);
1517 break;
1518 }
1519 }
1520
SetCmdlineParams()1521 bool SetCmdlineParams()
1522 // Sets externed variables used for communication cmdline information
1523 {
1524 //getcwd(FreeSpace_Directory, 256); // set the directory to our fs2 root
1525
1526 // DO THIS FIRST to avoid unrecognized flag warnings when just getting flag file
1527 if ( get_flags_arg.found() ) {
1528 write_flags();
1529
1530 return false;
1531 }
1532
1533 if (no_fpscap.found())
1534 {
1535 Cmdline_NoFPSCap = 1;
1536 }
1537
1538 if(loadallweapons_arg.found())
1539 {
1540 Cmdline_load_all_weapons = 1;
1541 }
1542
1543 if(voice_recognition_arg.found())
1544 {
1545 Cmdline_voice_recognition = 1;
1546 }
1547
1548 #ifdef Allow_NoWarn
1549 if (nowarn_arg.found())
1550 {
1551 Cmdline_nowarn = 1;
1552 }
1553 #endif
1554
1555 if (extra_warn_arg.found())
1556 {
1557 Cmdline_extra_warn = 1;
1558 }
1559
1560 if (!Fred_running) { //There is no standalone FRED
1561 // is this a standalone server??
1562 if (standalone_arg.found()) {
1563 Is_standalone = 1;
1564 }
1565 }
1566
1567 // object update control
1568 if(objupd_arg.found()){
1569 Cmdline_objupd = objupd_arg.get_int();
1570 if (Cmdline_objupd < 0)
1571 {
1572 Cmdline_objupd = 0;
1573 }
1574 if (Cmdline_objupd > 3)
1575 {
1576 Cmdline_objupd = 3;
1577 }
1578 }
1579
1580 if(mpnoreturn_arg.found()) {
1581 Cmdline_mpnoreturn = 1;
1582 }
1583
1584 // run with no sound
1585 if ( nosound_arg.found() ) {
1586 Cmdline_freespace_no_sound = 1;
1587 // and since music is automatically unusable...
1588 Cmdline_freespace_no_music = 1;
1589 }
1590
1591 // run with no music
1592 if ( nomusic_arg.found() ) {
1593 Cmdline_freespace_no_music = 1;
1594 }
1595
1596 // Disable enhanced sound
1597 if (noenhancedsound_arg.found()) {
1598 Cmdline_no_enhanced_sound = 1;
1599 }
1600
1601 // should we start a network game
1602 if ( startgame_arg.found() ) {
1603 Cmdline_use_last_pilot = 1;
1604 Cmdline_start_netgame = 1;
1605 }
1606
1607 // closed network game
1608 if ( gameclosed_arg.found() ) {
1609 Cmdline_closed_game = 1;
1610 }
1611
1612 // restircted network game
1613 if ( gamerestricted_arg.found() ) {
1614 Cmdline_restricted_game = 1;
1615 }
1616
1617 // get the name of the network game
1618 if ( gamename_arg.found() ) {
1619 Cmdline_game_name = gamename_arg.str();
1620
1621 // be sure that this string fits in our limits
1622 if ( strlen(Cmdline_game_name) >= MAX_GAMENAME_LEN ) {
1623 Cmdline_game_name[MAX_GAMENAME_LEN-1] = '\0';
1624 }
1625 }
1626
1627 // get the password for a pssword game
1628 if ( gamepassword_arg.found() ) {
1629 Cmdline_game_password = gamepassword_arg.str();
1630
1631 // be sure that this string fits in our limits
1632 if ( strlen(Cmdline_game_password) >= MAX_PASSWD_LEN ) {
1633 ReleaseWarning(LOCATION, "Multi game password is longer than max of %d charaters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
1634 Cmdline_game_password[MAX_PASSWD_LEN-1] = '\0';
1635 }
1636 }
1637
1638 // set the rank above/below arguments
1639 if ( allowabove_arg.found() ) {
1640 Cmdline_rank_above = allowabove_arg.str();
1641 }
1642 if ( allowbelow_arg.found() ) {
1643 Cmdline_rank_below = allowbelow_arg.str();
1644 }
1645
1646 // get the port number for games
1647 if ( port_arg.found() ) {
1648 Cmdline_network_port = port_arg.get_int();
1649 }
1650
1651 // get IP address of gateway, for auto port forwarding
1652 if ( gateway_ip_arg.found() ) {
1653 Cmdline_gateway_ip = gateway_ip_arg.str();
1654 }
1655
1656 // the connect argument specifies to join a game at this particular address
1657 if ( connect_arg.found() ) {
1658 Cmdline_use_last_pilot = 1;
1659 Cmdline_connect_addr = connect_arg.str();
1660 }
1661
1662 // see if the multilog flag was set
1663 if ( multilog_arg.found() ){
1664 Cmdline_multi_log = 1;
1665 }
1666
1667 // spew pof info
1668 if(pof_spew.found()){
1669 Cmdline_spew_pof_info = 1;
1670 }
1671
1672 // spew weapon stats
1673 if (weapon_spew.found()) {
1674 Cmdline_spew_weapon_stats = WeaponSpewType::STANDARD;
1675
1676 // currently just one argument
1677 if (weapon_spew.has_param()) {
1678 if (!stricmp(weapon_spew.str(), "all")) {
1679 Cmdline_spew_weapon_stats = WeaponSpewType::ALL;
1680 }
1681 }
1682 }
1683
1684 // mouse coords
1685 if(mouse_coords.found()){
1686 Cmdline_mouse_coords = 1;
1687 }
1688
1689 // net timeout
1690 if(timeout.found()){
1691 Cmdline_timeout = timeout.get_int();
1692 }
1693
1694 // d3d windowed
1695 if(window_arg.found()) {
1696 // We need to set both values since we don't know if we are going to use the new config system
1697 options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
1698 Cmdline_window = 1;
1699 }
1700
1701 if ( fullscreen_window_arg.found( ) )
1702 {
1703 options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
1704 Cmdline_fullscreen_window = 1;
1705 Cmdline_window = 0; /* Make sure no-one sets both */
1706 }
1707
1708 if(res_arg.found()){
1709 Cmdline_res = res_arg.str();
1710
1711 int width = 0;
1712 int height = 0;
1713
1714 if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
1715 SCP_string override;
1716 sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
1717 options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
1718 } else {
1719 mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res));
1720 }
1721 }
1722 if(center_res_arg.found()){
1723 Cmdline_center_res = center_res_arg.str();
1724 }
1725 if(almission_arg.found()){//DTP for autoload mission // developer oritentated
1726 Cmdline_almission = almission_arg.str();
1727 Cmdline_use_last_pilot = 1;
1728 Cmdline_start_netgame = 1;
1729 }
1730
1731 if(dualscanlines_arg.found() ) {
1732 Cmdline_dualscanlines = 1;
1733 }
1734
1735 if(targetinfo_arg.found())
1736 {
1737 Cmdline_targetinfo = 1;
1738 }
1739
1740 if(nomovies_arg.found() ) {
1741 Cmdline_nomovies = 1;
1742 }
1743
1744 if ( noscalevid_arg.found() ) {
1745 Cmdline_noscalevid = 1;
1746 }
1747
1748 if(noparseerrors_arg.found()) {
1749 Cmdline_noparseerrors = 1;
1750 }
1751
1752
1753 if(mod_arg.found() ) {
1754 Cmdline_mod = mod_arg.str();
1755
1756 // strip off blank space it it's there
1757 if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
1758 Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
1759 }
1760
1761 // Ok - mod stacking support
1762 size_t len = strlen(Cmdline_mod);
1763 char *modlist = new char[len+2];
1764 memset( modlist, 0, len + 2 );
1765 strcpy_s(modlist, len+2, Cmdline_mod);
1766
1767 #ifdef SCP_UNIX
1768 // handle case-insensitive searching
1769 handle_unix_modlist(&modlist, &len);
1770 #endif
1771
1772 // null terminate each individual
1773 for (size_t i = 0; i < len; i++)
1774 {
1775 if (modlist[i] == ',')
1776 modlist[i] = '\0';
1777 }
1778
1779 //copy over - we don't have to delete[] Cmdline_mod because it's a pointer to an automatic global char*
1780 Cmdline_mod = modlist;
1781 }
1782
1783
1784 if (fps_arg.found())
1785 {
1786 Show_framerate = 1;
1787 }
1788
1789 if (bmpmanusage_arg.found())
1790 {
1791 Cmdline_bmpman_usage = 1;
1792 }
1793
1794 if(pos_arg.found())
1795 {
1796 Cmdline_show_pos = 1;
1797 }
1798
1799 if ( nomotiondebris_arg.found() ) {
1800 Motion_debris_enabled = false;
1801 }
1802
1803 if( mipmap_arg.found() ) {
1804 Cmdline_mipmap = 1;
1805 }
1806
1807 if( stats_arg.found() ) {
1808 Cmdline_show_stats = 1;
1809 }
1810
1811 if ( fov_arg.found() ) {
1812 auto val = fov_arg.get_float();
1813 if (val > 0.1) {
1814 VIEWER_ZOOM_DEFAULT = val;
1815 } else {
1816 VIEWER_ZOOM_DEFAULT = 0.75f;
1817 }
1818 }
1819
1820 if( clip_dist_arg.found() ) {
1821 Min_draw_distance = Cmdline_clip_dist = clip_dist_arg.get_float();
1822 }
1823
1824 if (orb_radar.found())
1825 {
1826 Cmdline_orb_radar = 1;
1827 }
1828
1829 if ( use_3dwarp.found() ) {
1830 Fireball_use_3d_warp = true;
1831 }
1832
1833 if ( use_warp_flash.found() ) {
1834 Cmdline_warp_flash = 1;
1835 }
1836
1837 if ( allow_autpilot_interrupt.found() ) {
1838 Cmdline_autopilot_interruptable = 0;
1839 }
1840
1841 if ( no_screenshake.found() ) {
1842 Cmdline_no_screenshake = 1;
1843 }
1844
1845 if ( stretch_menu.found() ) {
1846 Cmdline_stretch_menu = 1;
1847 }
1848
1849 // specular comand lines
1850 if ( spec_point_arg.found() ) {
1851 static_point_factor = spec_point_arg.get_float();
1852 }
1853
1854 if ( spec_static_arg.found() ) {
1855 static_light_factor = spec_static_arg.get_float();
1856 }
1857
1858 if ( spec_tube_arg.found() ) {
1859 static_tube_factor = spec_tube_arg.get_float();
1860 }
1861
1862 if ( spec_arg.found() )
1863 {
1864 Cmdline_spec = 0;
1865 }
1866
1867 if( no_set_gamma_arg.found() )
1868 {
1869 Cmdline_no_set_gamma = 1;
1870 }
1871
1872 if(no_vsync_arg.found() )
1873 {
1874 Gr_enable_vsync = false;
1875 }
1876
1877 if ( normal_arg.found() ) {
1878 Cmdline_normal = 0;
1879 }
1880
1881 if ( height_arg.found() ) {
1882 Cmdline_height = 0;
1883 }
1884
1885 if (post_process_aa_arg.found() || post_process_aa_preset_arg.found()) {
1886 Gr_aa_mode = AntiAliasMode::SMAA_Low;
1887
1888 if (post_process_aa_preset_arg.found()) {
1889 switch (post_process_aa_preset_arg.get_int()) {
1890 case 0:
1891 Gr_aa_mode = AntiAliasMode::FXAA_Low;
1892 break;
1893 case 1:
1894 Gr_aa_mode = AntiAliasMode::FXAA_Medium;
1895 break;
1896 case 2:
1897 Gr_aa_mode = AntiAliasMode::FXAA_High;
1898 break;
1899 case 3:
1900 Gr_aa_mode = AntiAliasMode::SMAA_Low;
1901 break;
1902 case 4:
1903 Gr_aa_mode = AntiAliasMode::SMAA_Medium;
1904 break;
1905 case 5:
1906 Gr_aa_mode = AntiAliasMode::SMAA_High;
1907 break;
1908 case 6:
1909 Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
1910 break;
1911 }
1912 }
1913 }
1914
1915 if ( glow_arg.found() )
1916 Cmdline_glow = 0;
1917
1918 if ( ship_choice_3d_arg.found() )
1919 Cmdline_ship_choice_3d = 1;
1920
1921 if ( weapon_choice_3d_arg.found() )
1922 Cmdline_weapon_choice_3d = 1;
1923
1924 if (ingamejoin_arg.found() )
1925 Cmdline_ingamejoin = 1;
1926
1927 if ( start_mission_arg.found() ) {
1928 Cmdline_start_mission = start_mission_arg.str();
1929 }
1930
1931 if ( ambient_factor_arg.found() )
1932 Cmdline_ambient_factor = ambient_factor_arg.get_int();
1933
1934 if ( output_scripting_arg.found() )
1935 Output_scripting_meta = true;
1936
1937 if (output_script_json_arg.found() )
1938 Output_scripting_json = true;
1939
1940 if (output_sexp_arg.found() ) {
1941 Cmdline_output_sexp_info = true;
1942 }
1943
1944 if ( no_pbo_arg.found() )
1945 {
1946 Cmdline_no_pbo = 1;
1947 }
1948
1949 if ( no_drawrangeelements.found() )
1950 {
1951 Cmdline_drawelements = 1;
1952 }
1953
1954 if( keyboard_layout.found())
1955 {
1956 Cmdline_keyboard_layout = keyboard_layout.str();
1957 }
1958
1959 if (gl_finish.found())
1960 {
1961 Cmdline_gl_finish = true;
1962 }
1963
1964 if ( no_geo_sdr_effects.found() )
1965 {
1966 Cmdline_no_geo_sdr_effects = true;
1967 }
1968
1969 if (set_cpu_affinity.found())
1970 {
1971 Cmdline_set_cpu_affinity = true;
1972 }
1973
1974 if (nograb_arg.found())
1975 {
1976 Cmdline_nograb = true;
1977 }
1978
1979 if (noshadercache_arg.found())
1980 {
1981 Cmdline_noshadercache = true;
1982 }
1983
1984 if (portable_mode.found())
1985 {
1986 Cmdline_portable_mode = true;
1987 }
1988
1989 #ifdef WIN32
1990 if (fix_registry.found()) {
1991 Cmdline_alternate_registry_path = true;
1992 }
1993 #endif
1994
1995 if ( env.found() ) {
1996 Cmdline_env = 0;
1997 }
1998
1999 if ( ballistic_gauge.found() ) {
2000 Cmdline_ballistic_gauge = 1;
2001 }
2002
2003 if(dis_collisions.found())
2004 Cmdline_dis_collisions = 1;
2005
2006 if(dis_weapons.found())
2007 Cmdline_dis_weapons = 1;
2008
2009 if ( no_fbo_arg.found() ) {
2010 Cmdline_no_fbo = 1;
2011 }
2012
2013 if ( emissive_arg.found() ) {
2014 Cmdline_emissive = 1;
2015 }
2016
2017 if ( rearm_timer_arg.found() )
2018 Cmdline_rearm_timer = 1;
2019
2020 if ( save_render_targets_arg.found() )
2021 Cmdline_save_render_targets = 1;
2022
2023 if ( verify_vps_arg.found() )
2024 Cmdline_verify_vps = 1;
2025
2026 if ( no3dsound_arg.found() )
2027 Cmdline_no_3d_sound = 1;
2028
2029 if ( atiswap_arg.found() )
2030 {
2031 Cmdline_ati_color_swap = 1;
2032 }
2033
2034 if ( enable_3d_shockwave_arg.found() )
2035 {
2036 Cmdline_enable_3d_shockwave = 1;
2037 }
2038
2039 if ( softparticles_arg.found() )
2040 {
2041 Cmdline_softparticles = 1;
2042 }
2043
2044 if ( fb_explosions_arg.found() )
2045 {
2046 Gr_framebuffer_effects.set(FramebufferEffects::Shockwaves, true);
2047 }
2048
2049 if (fb_thrusters_arg.found())
2050 {
2051 Gr_framebuffer_effects.set(FramebufferEffects::Thrusters, true);
2052 }
2053
2054 if ( no_postprocess_arg.found() )
2055 {
2056 Gr_post_processing_enabled = false;
2057 }
2058
2059 if ( bloom_intensity_arg.found() )
2060 {
2061 Cmdline_bloom_intensity = bloom_intensity_arg.get_int();
2062 }
2063
2064 if ( flightshaftsoff_arg.found() )
2065 {
2066 Cmdline_force_lightshaft_off = true;
2067 }
2068
2069 if( reparse_mainhall_arg.found() )
2070 {
2071 Cmdline_reparse_mainhall = 1;
2072 }
2073
2074 if( enable_shadows_arg.found() )
2075 {
2076 Shadow_quality = ShadowQuality::Medium;
2077 }
2078
2079 if( shadow_quality_arg.found() )
2080 {
2081 switch (shadow_quality_arg.get_int()) {
2082 case 0:
2083 Shadow_quality = ShadowQuality::Disabled;
2084 break;
2085 case 1:
2086 Shadow_quality = ShadowQuality::Low;
2087 break;
2088 case 2:
2089 Shadow_quality = ShadowQuality::Medium;
2090 break;
2091 case 3:
2092 Shadow_quality = ShadowQuality::High;
2093 break;
2094 case 4:
2095 Shadow_quality = ShadowQuality::Ultra;
2096 break;
2097 default:
2098 mprintf(("Invalid shadow quality %d. Disabling shadows...\n", shadow_quality_arg.get_int()));
2099 Shadow_quality = ShadowQuality::Disabled;
2100 break;
2101 }
2102 }
2103
2104 if( no_deferred_lighting_arg.found() )
2105 {
2106 Cmdline_no_deferred_lighting = 1;
2107 }
2108
2109 if (anisotropy_level_arg.found())
2110 {
2111 Cmdline_aniso_level = anisotropy_level_arg.get_int();
2112 }
2113
2114 if (frame_profile_write_file.found())
2115 {
2116 Cmdline_profile_write_file = true;
2117 }
2118
2119 if (no_unfocused_pause_arg.found())
2120 {
2121 Cmdline_no_unfocus_pause = true;
2122 }
2123
2124 if (benchmark_mode_arg.found())
2125 {
2126 Cmdline_benchmark_mode = true;
2127 }
2128
2129 if (pilot_arg.found())
2130 {
2131 Cmdline_pilot = pilot_arg.str();
2132 }
2133
2134 if (noninteractive_arg.found())
2135 {
2136 Cmdline_noninteractive = true;
2137 }
2138
2139 if (json_profiling.found())
2140 {
2141 Cmdline_json_profiling = true;
2142 }
2143
2144 if (frame_profile_arg.found() )
2145 {
2146 Cmdline_frame_profile = true;
2147 }
2148
2149 if (debug_window_arg.found()) {
2150 Cmdline_debug_window = true;
2151 }
2152
2153 if (graphics_debug_output_arg.found()) {
2154 Cmdline_graphics_debug_output = true;
2155 }
2156
2157 if (log_to_stdout_arg.found()) {
2158 Cmdline_log_to_stdout = true;
2159 }
2160
2161 if (show_video_info.found())
2162 {
2163 Cmdline_show_video_info = true;
2164 }
2165
2166 //Deprecated flags - CommanderDJ
2167 if( deprecated_spec_arg.found() )
2168 {
2169 Cmdline_deprecated_spec = 1;
2170 }
2171
2172 if( deprecated_glow_arg.found() )
2173 {
2174 Cmdline_deprecated_glow = 1;
2175 }
2176
2177 if( deprecated_normal_arg.found() )
2178 {
2179 Cmdline_deprecated_normal = 1;
2180 }
2181
2182 if( deprecated_env_arg.found() )
2183 {
2184 Cmdline_deprecated_env = 1;
2185 }
2186
2187 if( deprecated_tbp_arg.found() )
2188 {
2189 Cmdline_deprecated_tbp = 1;
2190 }
2191
2192 if( deprecated_jpgtga_arg.found() )
2193 {
2194 Cmdline_deprecated_jpgtga = 1;
2195 }
2196
2197 if ( deprecated_htl_arg.found() )
2198 {
2199 Cmdline_deprecated_nohtl = 1;
2200 }
2201
2202 if ( deprecated_brieflighting_arg.found() )
2203 {
2204 Cmdline_deprecated_brief_lighting = 1;
2205 }
2206
2207 if (deprecated_missile_lighting_arg.found())
2208 {
2209 Cmdline_deprecated_missile_lighting = true;
2210 }
2211
2212 if (deprecated_cache_bitmaps_arg.found()) {
2213 Cmdline_deprecated_cache_bitmaps = true;
2214 }
2215
2216 if (deprecated_no_emissive_arg.found()) {
2217 Cmdline_emissive = 0;
2218 }
2219
2220 if (deprecated_postprocess_arg.found()) {
2221 Cmdline_deprecated_postprocess = true;
2222 }
2223
2224 if (deprecated_fxaa_arg.found() ) {
2225 Gr_aa_mode = AntiAliasMode::FXAA_Medium;
2226
2227 if (deprecated_fxaa_preset_arg.found()) {
2228 auto val = deprecated_fxaa_preset_arg.get_int();
2229 if (val > 6) {
2230 Gr_aa_mode = AntiAliasMode::FXAA_High;
2231 } else if (val > 3) {
2232 Gr_aa_mode = AntiAliasMode::FXAA_Medium;
2233 } else {
2234 Gr_aa_mode = AntiAliasMode::FXAA_Low;
2235 }
2236 }
2237 }
2238
2239 if (deprecated_smaa_arg.found()) {
2240 Gr_aa_mode = AntiAliasMode::SMAA_Medium;
2241
2242 if (deprecated_smaa_preset_arg.found()) {
2243 switch (deprecated_smaa_preset_arg.get_int()) {
2244 case 0:
2245 Gr_aa_mode = AntiAliasMode::SMAA_Low;
2246 break;
2247 case 1:
2248 Gr_aa_mode = AntiAliasMode::SMAA_Medium;
2249 break;
2250 case 2:
2251 Gr_aa_mode = AntiAliasMode::SMAA_High;
2252 break;
2253 case 3:
2254 Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
2255 break;
2256 default:
2257 Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
2258 break;
2259 }
2260 }
2261 }
2262
2263 return true;
2264 }
2265
parse_cmdline(int argc,char * argv[])2266 int parse_cmdline(int argc, char *argv[])
2267 {
2268 // mprintf(("I got to parse_cmdline()!!\n"));
2269
2270 os_init_cmdline(argc, argv);
2271
2272 // --------------- Kazan -------------
2273 // If you're looking for the list of if (someparam.found()) { cmdline_someparam = something; } look above at this function
2274 // I did this because of fred2_parse_cmdline()
2275 return SetCmdlineParams();
2276 }
2277
get_param_desc(const char * flag_name)2278 const char * get_param_desc(const char *flag_name)
2279 {
2280 int i;
2281 int flag_size = sizeof(Flag);
2282 int num_flags = sizeof(exe_params) / flag_size;
2283 for (i = 0; i < num_flags; ++i) {
2284 if (!strcmp(flag_name, exe_params[i].name)) {
2285 return exe_params[i].desc;
2286 }
2287 }
2288 return "UNKNOWN - FIXME!";
2289 }
2290