a26f8eb77611e52efc1f78c10dc2588963320e29
[supertux.git] / src / supertux / command_line_arguments.cpp
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 <iostream>
21 #include <physfs.h>
22 #include <stdexcept>
23
24 #include "supertux/gameconfig.hpp"
25 #include "supertux/main.hpp"
26 #include "util/gettext.hpp"
27 #include "version.h"
28
29 CommandLineArguments::CommandLineArguments() :
30   m_action(NO_ACTION),
31   m_log_level(LOG_WARNING),
32   datadir(),
33   userdir(),
34   fullscreen_size(),
35   fullscreen_refresh_rate(),
36   window_size(),
37   aspect_size(),
38   use_fullscreen(),
39   video(),
40   show_fps(),
41   sound_enabled(),
42   music_enabled(),
43   console_enabled(),
44   start_level(),
45   enable_script_debugger(),
46   start_demo(),
47   record_demo(),
48   developer_mode()
49 {
50 }
51
52 CommandLineArguments::~CommandLineArguments()
53 {
54 }
55
56 void
57 CommandLineArguments::print_datadir()
58 {
59   // Print the datadir searchpath to stdout, one path per
60   // line. Then exit. Intended for use by the supertux-editor.
61   char **sp;
62   size_t sp_index;
63   sp = PHYSFS_getSearchPath();
64   if (sp)
65     for (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)
72 {
73   std::cerr << boost::format(_(
74                  "Usage: %s [OPTIONS] [LEVELFILE]\n"
75                  "\n"
76                  "General Options:\n"
77                  "  -h, --help                   Show this help message and quit\n"
78                  "  -v, --version                Show SuperTux version and quit\n"
79                  "  --verbose                    Print verbose messages\n"
80                  "  --debug                      Print extra verbose messages\n"
81                  "  --print-datadir              Print supertux's primary data directory.\n"
82                  "\n"
83                  "Video Options:\n"
84                  "  -f, --fullscreen             Run in fullscreen mode\n"
85                  "  -w, --window                 Run in window mode\n"
86                  "  -g, --geometry WIDTHxHEIGHT  Run SuperTux in given resolution\n"
87                  "  -a, --aspect WIDTH:HEIGHT    Run SuperTux with given aspect ratio\n"
88                  "  -d, --default                Reset video settings to default values\n"
89                  "  --renderer RENDERER          Use sdl, opengl, or auto to render\n"
90                  "\n"
91                  "Audio Options:\n"
92                  "  --disable-sound              Disable sound effects\n"
93                  "  --disable-music              Disable music\n"
94                  "\n"
95                  "Game Options:\n"
96                  "  --console                    Enable ingame scripting console\n"
97                  "  --noconsole                  Disable ingame scripting console\n"
98                  "  --show-fps                   Display framerate in levels\n"
99                  "  --no-show-fps                Do not display framerate in levels\n"
100                  "  --developer                  Switch on developer feature\n"
101                  "  -s, --debug-scripts          Enable script debugger.\n"
102                  "\n"
103                  "Demo Recording Options:\n"
104                  "  --record-demo FILE LEVEL     Record a demo to FILE\n"
105                  "  --play-demo FILE LEVEL       Play a recorded demo\n"
106                  "\n"
107                  "Directory Options:\n"
108                  "  --datadir DIR                Set the directory for the games datafiles\n"
109                  "  --userdir DIR                Set the directory for user data (savegames, etc.)\n"
110                  "\n"
111                  "Environment variables:\n"
112                  "  SUPERTUX2_USER_DIR           Directory for user data (savegames, etc.)\n"
113                  "  SUPERTUX2_DATA_DIR           Directory for the games datafiles\n"
114                  "\n"
115                  ))
116             % arg0
117             << std::flush;
118 }
119
120 void
121 CommandLineArguments::print_version()
122 {
123   std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl;
124 }
125
126 void
127 CommandLineArguments::parse_args(int argc, char** argv)
128 {
129   for(int i = 1; i < argc; ++i)
130   {
131     std::string arg = argv[i];
132
133     if (arg == "--version" || arg == "-v")
134     {
135       m_action = PRINT_VERSION;
136
137     }
138     else if (arg == "--help" || arg == "-h")
139     {
140       m_action = PRINT_HELP;
141     }
142     else if (arg == "--print-datadir")
143     {
144       m_action = PRINT_DATADIR;
145     }
146     else if (arg == "--debug")
147     {
148       m_log_level = LOG_DEBUG;
149     }
150     else if (arg == "--verbose")
151     {
152       if (m_log_level < LOG_INFO)
153       {
154         m_log_level = LOG_INFO;
155       }
156     }
157     else if (arg == "--datadir")
158     {
159       if (i+1 >= argc)
160       {
161         throw std::runtime_error("Need to specify a directory for --datadir");
162       }
163       else
164       {
165         datadir = argv[++i];
166       }
167     }
168     else if (arg == "--userdir")
169     {
170       if (i+1 >= argc)
171       {
172         throw std::runtime_error("Need to specify a directory for --userdir");
173       }
174       else
175       {
176         userdir = argv[++i];
177       }
178     }
179     else if (arg == "--fullscreen" || arg == "-f")
180     {
181       use_fullscreen = true;
182     }
183     else if (arg == "--default" || arg == "-d")
184     {
185       use_fullscreen = false;
186
187       window_size = Size(800, 600);
188       fullscreen_size = Size(800, 600);
189       fullscreen_refresh_rate = 0;
190       aspect_size = Size(0, 0);  // auto detect
191     }
192     else if (arg == "--window" || arg == "-w")
193     {
194       use_fullscreen = false;
195     }
196     else if (arg == "--geometry" || arg == "-g")
197     {
198       i += 1;
199       if (i >= argc)
200       {
201         throw std::runtime_error("Need to specify a size (WIDTHxHEIGHT) for geometry argument");
202       }
203       else
204       {
205         int width, height;
206         if (sscanf(argv[i], "%dx%d", &width, &height) != 2)
207         {
208           throw std::runtime_error("Invalid geometry spec, should be WIDTHxHEIGHT");
209         }
210         else
211         {
212           window_size     = Size(width, height);
213           fullscreen_size = Size(width, height);
214           fullscreen_refresh_rate = 0;
215         }
216       }
217     }
218     else if (arg == "--aspect" || arg == "-a")
219     {
220       i += 1;
221       if (i >= argc)
222       {
223         throw std::runtime_error("Need to specify a ratio (WIDTH:HEIGHT) for aspect ratio");
224       }
225       else
226       {
227         int aspect_width  = 0;
228         int aspect_height = 0;
229         if (strcmp(argv[i], "auto") == 0)
230         {
231           aspect_width  = 0;
232           aspect_height = 0;
233         }
234         else if (sscanf(argv[i], "%d:%d", &aspect_width, &aspect_height) != 2)
235         {
236           throw std::runtime_error("Invalid aspect spec, should be WIDTH:HEIGHT or auto");
237         }
238         else
239         {
240           float aspect_ratio = static_cast<float>(aspect_width) / static_cast<float>(aspect_height);
241
242           // use aspect ratio to calculate logical resolution
243           if (aspect_ratio > 1) {
244             aspect_size = Size(static_cast<int>(600 * aspect_ratio + 0.5),
245                                          600);
246           } else {
247             aspect_size = Size(600,
248                                          static_cast<int>(600 * 1/aspect_ratio + 0.5));
249           }
250         }
251       }
252     }
253     else if (arg == "--renderer")
254     {
255       i += 1;
256       if (i >= argc)
257       {
258         throw std::runtime_error("Need to specify a renderer for renderer argument");
259       }
260       else
261       {
262         video = VideoSystem::get_video_system(argv[i]);
263       }
264     }
265     else if (arg == "--show-fps")
266     {
267       show_fps = true;
268     }
269     else if (arg == "--no-show-fps")
270     {
271       show_fps = false;
272     }
273     else if (arg == "--developer")
274     {
275       developer_mode = true;
276     }
277     else if (arg == "--console")
278     {
279       console_enabled = true;
280     }
281     else if (arg == "--noconsole")
282     {
283       console_enabled = false;
284     }
285     else if (arg == "--disable-sound" || arg == "--disable-sfx")
286     {
287       sound_enabled = false;
288     }
289     else if (arg == "--disable-music")
290     {
291       music_enabled = false;
292     }
293     else if (arg == "--play-demo")
294     {
295       if (i+1 >= argc)
296       {
297         throw std::runtime_error("Need to specify a demo filename");
298       }
299       else
300       {
301         start_demo = argv[++i];
302       }
303     }
304     else if (arg == "--record-demo")
305     {
306       if (i+1 >= argc)
307       {
308         throw std::runtime_error("Need to specify a demo filename");
309       }
310       else
311       {
312         record_demo = argv[++i];
313       }
314     }
315     else if (arg == "--debug-scripts" || arg == "-s")
316     {
317       enable_script_debugger = true;
318     }
319     else if (arg[0] != '-')
320     {
321       start_level = arg;
322     }
323     else
324     {
325       throw std::runtime_error((boost::format("Unknown option '%1%''. Use --help to see a list of options") % arg).str());
326     }
327   }
328 }
329
330 void
331 CommandLineArguments::merge_into(Config& config)
332 {
333 #define merge_option(x) if (x) { config.x = *x; }
334
335   merge_option(fullscreen_size);
336   merge_option(fullscreen_refresh_rate);
337   merge_option(window_size);
338   merge_option(aspect_size);
339   merge_option(use_fullscreen);
340   merge_option(video);
341   merge_option(show_fps);
342   merge_option(sound_enabled);
343   merge_option(music_enabled);
344   merge_option(console_enabled);
345   merge_option(start_level);
346   merge_option(enable_script_debugger);
347   merge_option(start_demo);
348   merge_option(record_demo);
349   merge_option(developer_mode);
350
351 #undef merge_option
352 }
353
354 /* EOF */