1 | // SuperTux |
2 | // Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "supertux/command_line_arguments.hpp" |
18 | |
19 | #include <boost/format.hpp> |
20 | #include <config.h> |
21 | #include <physfs.h> |
22 | |
23 | #include "supertux/gameconfig.hpp" |
24 | #include "util/gettext.hpp" |
25 | #include "version.h" |
26 | |
27 | CommandLineArguments::CommandLineArguments() : |
28 | m_action(NO_ACTION), |
29 | m_log_level(LOG_WARNING), |
30 | datadir(), |
31 | userdir(), |
32 | fullscreen_size(), |
33 | fullscreen_refresh_rate(), |
34 | window_size(), |
35 | aspect_size(), |
36 | use_fullscreen(), |
37 | video(), |
38 | show_fps(), |
39 | show_player_pos(), |
40 | sound_enabled(), |
41 | music_enabled(), |
42 | filenames(), |
43 | enable_script_debugger(), |
44 | start_demo(), |
45 | record_demo(), |
46 | tux_spawn_pos(), |
47 | sector(), |
48 | spawnpoint(), |
49 | developer_mode(), |
50 | christmas_mode(), |
51 | repository_url(), |
52 | editor(), |
53 | resave() |
54 | { |
55 | } |
56 | |
57 | void |
58 | CommandLineArguments::print_datadir() const |
59 | { |
60 | // Print the datadir searchpath to stdout, one path per |
61 | // line. Then exit. Intended for use by the supertux-editor. |
62 | char **sp; |
63 | sp = PHYSFS_getSearchPath(); |
64 | if (sp) |
65 | for (size_t sp_index = 0; sp[sp_index]; sp_index++) |
66 | std::cout << sp[sp_index] << std::endl; |
67 | PHYSFS_freeList(sp); |
68 | } |
69 | |
70 | void |
71 | CommandLineArguments::print_help(const char* arg0) const |
72 | { |
73 | std::cerr |
74 | << boost::format(_("Usage: %s [OPTIONS] [LEVELFILE]" )) % arg0 << "\n" << "\n" |
75 | << _("General Options:" ) << "\n" |
76 | << _(" -h, --help Show this help message and quit" ) << "\n" |
77 | << _(" -v, --version Show SuperTux version and quit" ) << "\n" |
78 | << _(" --verbose Print verbose messages" ) << "\n" |
79 | << _(" --debug Print extra verbose messages" ) << "\n" |
80 | << _( " --print-datadir Print SuperTux's primary data directory." ) << "\n" |
81 | << "\n" |
82 | << _("Video Options:" ) << "\n" |
83 | << _(" -f, --fullscreen Run in fullscreen mode" ) << "\n" |
84 | << _(" -w, --window Run in window mode" ) << "\n" |
85 | << _(" -g, --geometry WIDTHxHEIGHT Run SuperTux in given resolution" ) << "\n" |
86 | << _(" -a, --aspect WIDTH:HEIGHT Run SuperTux with given aspect ratio" ) << "\n" |
87 | << _(" -d, --default Reset video settings to default values" ) << "\n" |
88 | << _(" --renderer RENDERER Use sdl, opengl, or auto to render" ) << "\n" |
89 | << "\n" |
90 | << _("Audio Options:" ) << "\n" |
91 | << _(" --disable-sound Disable sound effects" ) << "\n" |
92 | << _(" --disable-music Disable music" ) << "\n" |
93 | << "\n" |
94 | << _("Game Options:" ) << "\n" |
95 | << _(" --edit-level Open given level in editor" ) << "\n" |
96 | << _(" --resave Loads given level and saves it" ) << "\n" |
97 | << _(" --show-fps Display framerate in levels" ) << "\n" |
98 | << _(" --no-show-fps Do not display framerate in levels" ) << "\n" |
99 | << _(" --show-pos Display player's current position" ) << "\n" |
100 | << _(" --no-show-pos Do not display player's position" ) << "\n" |
101 | << _(" --developer Switch on developer feature" ) << "\n" |
102 | << _(" -s, --debug-scripts Enable script debugger." ) << "\n" |
103 | << _(" --spawn-pos X,Y Where in the level to spawn Tux. Only used if level is specified." ) << "\n" |
104 | << _(" --sector SECTOR Spawn Tux in SECTOR\n" ) << "\n" |
105 | << _(" --spawnpoint SPAWNPOINT Spawn Tux at SPAWNPOINT\n" ) << "\n" |
106 | << "\n" |
107 | << _("Demo Recording Options:" ) << "\n" |
108 | << _(" --record-demo FILE LEVEL Record a demo to FILE" ) << "\n" |
109 | << _(" --play-demo FILE LEVEL Play a recorded demo" ) << "\n" |
110 | << "\n" |
111 | << _("Directory Options:" ) << "\n" |
112 | << _(" --datadir DIR Set the directory for the games datafiles" ) << "\n" |
113 | << _(" --userdir DIR Set the directory for user data (savegames, etc.)" ) << "\n" |
114 | << "\n" |
115 | << _("Add-On Options:" ) << "\n" |
116 | << _(" --repository-url URL Set the URL to the Add-On repository" ) << "\n" |
117 | << "\n" |
118 | << _("Environment variables:" ) << "\n" |
119 | << _(" SUPERTUX2_USER_DIR Directory for user data (savegames, etc.)" ) << "\n" |
120 | << _(" SUPERTUX2_DATA_DIR Directory for the games datafiles" ) << "\n" |
121 | << "\n" |
122 | << std::flush; |
123 | } |
124 | |
125 | void |
126 | CommandLineArguments::print_version() const |
127 | { |
128 | std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl; |
129 | } |
130 | |
131 | void |
132 | CommandLineArguments::parse_args(int argc, char** argv) |
133 | { |
134 | for (int i = 1; i < argc; ++i) |
135 | { |
136 | std::string arg = argv[i]; |
137 | |
138 | if (arg == "--version" || arg == "-v" ) |
139 | { |
140 | m_action = PRINT_VERSION; |
141 | |
142 | } |
143 | else if (arg == "--help" || arg == "-h" ) |
144 | { |
145 | m_action = PRINT_HELP; |
146 | } |
147 | else if (arg == "--print-datadir" ) |
148 | { |
149 | m_action = PRINT_DATADIR; |
150 | } |
151 | else if (arg == "--debug" ) |
152 | { |
153 | m_log_level = LOG_DEBUG; |
154 | } |
155 | else if (arg == "--verbose" ) |
156 | { |
157 | if (m_log_level < LOG_INFO) |
158 | { |
159 | m_log_level = LOG_INFO; |
160 | } |
161 | } |
162 | else if (arg == "--datadir" ) |
163 | { |
164 | if (i + 1 >= argc) |
165 | { |
166 | throw std::runtime_error("Need to specify a directory for --datadir" ); |
167 | } |
168 | else |
169 | { |
170 | datadir = argv[++i]; |
171 | } |
172 | } |
173 | else if (arg == "--userdir" ) |
174 | { |
175 | if (i + 1 >= argc) |
176 | { |
177 | throw std::runtime_error("Need to specify a directory for --userdir" ); |
178 | } |
179 | else |
180 | { |
181 | userdir = argv[++i]; |
182 | } |
183 | } |
184 | else if (arg == "--fullscreen" || arg == "-f" ) |
185 | { |
186 | use_fullscreen = true; |
187 | } |
188 | else if (arg == "--default" || arg == "-d" ) |
189 | { |
190 | use_fullscreen = false; |
191 | |
192 | window_size = Size(1280, 800); |
193 | fullscreen_size = Size(1280, 800); |
194 | fullscreen_refresh_rate = 0; |
195 | aspect_size = Size(0, 0); // auto detect |
196 | } |
197 | else if (arg == "--window" || arg == "-w" ) |
198 | { |
199 | use_fullscreen = false; |
200 | } |
201 | else if (arg == "--geometry" || arg == "-g" ) |
202 | { |
203 | i += 1; |
204 | if (i >= argc) |
205 | { |
206 | throw std::runtime_error("Need to specify a size (WIDTHxHEIGHT) for geometry argument" ); |
207 | } |
208 | else |
209 | { |
210 | int width, height; |
211 | if (sscanf(argv[i], "%9dx%9d" , &width, &height) != 2) |
212 | { |
213 | throw std::runtime_error("Invalid geometry spec, should be WIDTHxHEIGHT" ); |
214 | } |
215 | else |
216 | { |
217 | window_size = Size(width, height); |
218 | fullscreen_size = Size(width, height); |
219 | fullscreen_refresh_rate = 0; |
220 | } |
221 | } |
222 | } |
223 | else if (arg == "--aspect" || arg == "-a" ) |
224 | { |
225 | i += 1; |
226 | if (i >= argc) |
227 | { |
228 | throw std::runtime_error("Need to specify a ratio (WIDTH:HEIGHT) for aspect ratio" ); |
229 | } |
230 | else |
231 | { |
232 | int aspect_width = 0; |
233 | int aspect_height = 0; |
234 | if (strcmp(argv[i], "auto" ) == 0) |
235 | { |
236 | aspect_width = 0; |
237 | aspect_height = 0; |
238 | } |
239 | else if (sscanf(argv[i], "%9d:%9d" , &aspect_width, &aspect_height) != 2) |
240 | { |
241 | throw std::runtime_error("Invalid aspect spec, should be WIDTH:HEIGHT or auto" ); |
242 | } |
243 | else |
244 | { |
245 | // use aspect ratio to calculate logical resolution |
246 | if (aspect_width / aspect_height > 1) { |
247 | aspect_size = Size(600 * aspect_width / aspect_height, 600); |
248 | } else { |
249 | aspect_size = Size(600, 600 * aspect_height / aspect_width); |
250 | } |
251 | } |
252 | } |
253 | } |
254 | else if (arg == "--renderer" ) |
255 | { |
256 | i += 1; |
257 | if (i >= argc) |
258 | { |
259 | throw std::runtime_error("Need to specify a renderer for renderer argument" ); |
260 | } |
261 | else |
262 | { |
263 | video = VideoSystem::get_video_system(argv[i]); |
264 | } |
265 | } |
266 | else if (arg == "--show-fps" ) |
267 | { |
268 | show_fps = true; |
269 | } |
270 | else if (arg == "--no-show-fps" ) |
271 | { |
272 | show_fps = false; |
273 | } |
274 | else if (arg == "--show-pos" ) |
275 | { |
276 | show_player_pos = true; |
277 | } |
278 | else if (arg == "--no-show-pos" ) |
279 | { |
280 | show_player_pos = false; |
281 | } |
282 | else if (arg == "--developer" ) |
283 | { |
284 | developer_mode = true; |
285 | } |
286 | else if (arg == "--christmas" ) |
287 | { |
288 | christmas_mode = true; |
289 | } |
290 | else if (arg == "--no-christmas" ) |
291 | { |
292 | christmas_mode = false; |
293 | } |
294 | else if (arg == "--disable-sound" || arg == "--disable-sfx" ) |
295 | { |
296 | sound_enabled = false; |
297 | } |
298 | else if (arg == "--disable-music" ) |
299 | { |
300 | music_enabled = false; |
301 | } |
302 | else if (arg == "--play-demo" ) |
303 | { |
304 | if (i + 1 >= argc) |
305 | { |
306 | throw std::runtime_error("Need to specify a demo filename" ); |
307 | } |
308 | else |
309 | { |
310 | start_demo = argv[++i]; |
311 | } |
312 | } |
313 | else if (arg == "--record-demo" ) |
314 | { |
315 | if (i + 1 >= argc) |
316 | { |
317 | throw std::runtime_error("Need to specify a demo filename" ); |
318 | } |
319 | else |
320 | { |
321 | record_demo = argv[++i]; |
322 | } |
323 | } |
324 | else if (arg == "--spawn-pos" ) |
325 | { |
326 | Vector spawn_pos; |
327 | |
328 | if (++i >= argc) |
329 | throw std::runtime_error("Need to specify a spawn-pos X,Y" ); |
330 | else |
331 | { |
332 | int x, y; |
333 | if (sscanf(argv[i], "%9d,%9d" , &x, &y) != 2) |
334 | throw std::runtime_error("Invalid spawn-pos, should be X,Y" ); |
335 | spawn_pos.x = static_cast<float>(x); |
336 | spawn_pos.y = static_cast<float>(y); |
337 | } |
338 | |
339 | tux_spawn_pos = spawn_pos; |
340 | } |
341 | else if (arg == "--sector" ) { |
342 | if (++i >= argc) { |
343 | throw std::runtime_error("--sector SECTOR needs an argument" ); |
344 | } else { |
345 | sector = argv[i]; |
346 | } |
347 | } |
348 | else if (arg == "--spawnpoint" ) { |
349 | if (++i >= argc) { |
350 | throw std::runtime_error("--spawnpoint SPAWNPOINT needs an argument" ); |
351 | } else { |
352 | spawnpoint = argv[i]; |
353 | } |
354 | } |
355 | else if (arg == "--debug-scripts" || arg == "-s" ) |
356 | { |
357 | enable_script_debugger = true; |
358 | } |
359 | else if (arg == "--repository-url" ) |
360 | { |
361 | if (i + 1 >= argc) |
362 | { |
363 | throw std::runtime_error("Need to specify a repository URL" ); |
364 | } |
365 | else |
366 | { |
367 | repository_url = argv[++i]; |
368 | } |
369 | } |
370 | else if (arg == "--editor" || arg == "--edit-level" ) |
371 | { |
372 | editor = true; |
373 | } |
374 | else if (arg == "--resave" ) |
375 | { |
376 | resave = true; |
377 | } |
378 | else if (arg[0] != '-') |
379 | { |
380 | filenames.push_back(arg); |
381 | } |
382 | else |
383 | { |
384 | throw std::runtime_error((boost::format("Unknown option '%1%''. Use --help to see a list of options" ) % arg).str()); |
385 | } |
386 | } |
387 | |
388 | // some final checks |
389 | if (filenames.size() > 1 && !(resave && *resave)) { |
390 | throw std::runtime_error("Only one filename allowed for the given options" ); |
391 | } |
392 | } |
393 | |
394 | void |
395 | CommandLineArguments::merge_into(Config& config) |
396 | { |
397 | #define merge_option(x) if (x) { config.x = *(x); } |
398 | |
399 | merge_option(fullscreen_size); |
400 | merge_option(fullscreen_refresh_rate); |
401 | merge_option(window_size); |
402 | merge_option(aspect_size); |
403 | merge_option(use_fullscreen); |
404 | merge_option(video); |
405 | merge_option(show_fps); |
406 | merge_option(show_player_pos); |
407 | merge_option(sound_enabled); |
408 | merge_option(music_enabled); |
409 | merge_option(enable_script_debugger); |
410 | merge_option(start_demo); |
411 | merge_option(record_demo); |
412 | merge_option(tux_spawn_pos); |
413 | merge_option(developer_mode); |
414 | merge_option(christmas_mode); |
415 | merge_option(repository_url); |
416 | |
417 | #undef merge_option |
418 | } |
419 | |
420 | /* EOF */ |
421 | |