command_line_arguments.cpp 11 KB

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