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