1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2017 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 /** ***************************************************************************
12 *** \file    main_options.cpp
13 *** \author  Tyler Olsen, roots@allacrost.org
14 *** \author  Yohann Ferreira, yohann ferreira orange fr
15 *** \brief   Implementations for functions that handle command-line arguments.
16 *** **************************************************************************/
17 
18 #include "main_options.h"
19 
20 #include "engine/audio/audio.h"
21 #include "engine/video/video.h"
22 #include "script/script_write.h"
23 #include "engine/input.h"
24 #include "engine/system.h"
25 #include "engine/mode_manager.h"
26 
27 #include "utils/utils_files.h"
28 
29 #include "common/app_name.h"
30 #include "common/app_settings.h"
31 #include "common/global/global.h"
32 
33 #include <SDL2/SDL_ttf.h>
34 
35 namespace vt_battle {
36 extern bool BATTLE_DEBUG;
37 }
38 namespace vt_boot {
39 extern bool BOOT_DEBUG;
40 }
41 namespace vt_common {
42 extern bool COMMON_DEBUG;
43 }
44 namespace vt_menu {
45 extern bool MENU_DEBUG;
46 }
47 namespace vt_pause {
48 extern bool PAUSE_DEBUG;
49 }
50 namespace vt_shop {
51 extern bool SHOP_DEBUG;
52 }
53 
54 using namespace vt_utils;
55 using namespace vt_common;
56 
57 namespace vt_main
58 {
59 
ParseProgramOptions(int32_t & return_code,int32_t argc,char * argv[])60 bool ParseProgramOptions(int32_t &return_code, int32_t argc, char* argv[])
61 {
62     // Convert the argument list to a vector of strings for convenience
63     std::vector<std::string> options(argv, argv + argc);
64     return_code = 0;
65 
66     for(uint32_t i = 1; i < options.size(); i++) {
67         if(options[i] == "-d" || options[i] == "--debug") {
68             if((i + 1) >= options.size()) {
69                 std::cerr << "Option " << options[i] << " requires an argument." << std::endl;
70                 PrintUsage();
71                 return_code = 1;
72                 return false;
73             }
74             if(EnableDebugging(options[i + 1]) == false) {
75                 return_code = 1;
76                 return false;
77             }
78             i++;
79         } else if(options[i] == "--disable-audio") {
80             vt_audio::AUDIO_ENABLE = false;
81         } else if(options[i] == "-h" || options[i] == "--help") {
82             PrintUsage();
83             return_code = 0;
84             return false;
85         } else if(options[i] == "-i" || options[i] == "--info") {
86             if(PrintSystemInformation()) {
87                 return_code = 0;
88             } else {
89                 return_code = 1;
90             }
91             return false;
92         } else if(options[i] == "-r" || options[i] == "--reset") {
93             if(ResetSettings()) {
94                 return_code = 0;
95             } else {
96                 return_code = 1;
97             }
98             return_code = 0;
99             return false;
100         } else {
101             std::cerr << "Unrecognized option: " << options[i] << std::endl;
102             PrintUsage();
103             return_code = 1;
104             return false;
105         }
106     }
107 
108     return true;
109 } // bool ParseProgramOptions(int32_t &return_code, int32_t argc, char *argv[])
110 
ParseSecondaryOptions(const std::string & vars,std::vector<std::string> & options)111 bool ParseSecondaryOptions(const std::string &vars, std::vector<std::string>& options)
112 {
113     uint32_t sbegin = 0;
114 
115     if(vars.empty()) {
116         std::cerr << "ERROR: debug specifier string is empty" << std::endl;
117         return false;
118     }
119 
120     // Find the first non-whitespace character
121     // TODO: this loop needs to be made more robust to errors
122     while(vars[sbegin] == ' ' || vars[sbegin] == '\t') {
123         sbegin++;
124         if(sbegin >= vars.size()) {
125             std::cerr << "ERROR: no white-space characters in debug specifier string" << std::endl;
126             return false;
127         }
128     }
129 
130     // Parse the vars string on white-space characters and fill the args vector
131     // TODO: this loop needs to be made more robust to errors
132     for(uint32_t i = sbegin; i < vars.size(); i++) {
133         if(vars[i] == ' ' || vars[i] == '\t') {
134             options.push_back(vars.substr(sbegin, i - sbegin));
135             sbegin = i + 1;
136         }
137     }
138     options.push_back(vars.substr(sbegin, vars.size() - sbegin));
139     return true;
140 } // bool ParseSecondaryOptions(string vars, vector<string>& options);
141 
142 
143 // Prints out the usage options (arguments) for running the program (work in progress)
PrintUsage()144 void PrintUsage()
145 {
146     std::cout
147             << "usage: " APPSHORTNAME " [options]" << std::endl
148             << "  --debug/-d <args> :: enables debug statements in specified sections of the" << std::endl
149             << "                       program, where <args> can be:" << std::endl
150             << "                       all, audio, battle, boot, data, global, input," << std::endl
151             << "                       map, mode_manager, pause, quit, scene, system" << std::endl
152             << "                       utils, video" << std::endl
153             << "  --disable-audio   :: disables loading and playing audio" << std::endl
154             << "  --help/-h         :: prints this help menu" << std::endl
155             << "  --info/-i         :: prints information about the user's system" << std::endl
156             << "  --reset/-r        :: resets game configuration to use default settings" << std::endl;
157 }
158 
PrintSystemInformation()159 bool PrintSystemInformation()
160 {
161     printf("\n===== System Information\n");
162 
163     // Initialize SDL and its subsystems and make sure it shutdowns properly on exit
164     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0) {
165         std::cerr << "ERROR: Unable to initialize SDL: " << SDL_GetError() << std::endl;
166         return false;
167     }
168     atexit(SDL_Quit);
169 
170     SDL_version sdl_linked_ver;
171     SDL_GetVersion(&sdl_linked_ver);
172 
173     std::cout
174       << "SDL version (compiled):  "
175       << SDL_MAJOR_VERSION << '.' << SDL_MINOR_VERSION << '.' << SDL_PATCHLEVEL
176       << std::endl;
177     std::cout
178       << "SDL version (linked):    "
179       << sdl_linked_ver.major << '.'
180       << sdl_linked_ver.minor << '.'
181       << sdl_linked_ver.patch
182       << std::endl;
183 
184     int32_t js_num = SDL_NumJoysticks();
185     printf("Number of joysticks found:  %d\n", js_num);
186 
187     // Print out information about each joystick
188     for(int32_t i = 0; i < js_num; i++) {
189         printf("  Joystick #%d\n", i);
190         //printf("    Joystick Name: %s\n", SDL_GameControllerNameForIndex(i));
191         SDL_Joystick* js_test = SDL_JoystickOpen(i);
192         if(js_test == nullptr)
193             printf("    ERROR: SDL was unable to open joystick #%d!\n", i);
194         else {
195             printf("    Number Axes: %d\n", SDL_JoystickNumAxes(js_test));
196             printf("    Number Buttons: %d\n", SDL_JoystickNumButtons(js_test));
197             printf("    Number Trackballs: %d\n", SDL_JoystickNumBalls(js_test));
198             printf("    Number Hat Switches: %d\n", SDL_JoystickNumHats(js_test));
199             SDL_JoystickClose(js_test);
200         }
201     }
202 
203     printf("\n===== Video Information\n");
204 
205     // TODO: This code should be re-located to a function (DEBUG_PrintInfo()) in the video engine
206 // 	vt_video::VideoManager = vt_video::VideoEngine::SingletonCreate();
207 // 	if (vt_video::VideoManager->SingletonInitialize() == false) {
208 // 		cerr << "ERROR: unable to initialize the VideoManager" << std::endl;
209 // 		return false;
210 // 	}
211 // 	else {
212 // 		vt_video::VideoManager->DEBUG_PrintInfo();
213 // 	}
214 // 	vt_video::VideoEngine::SingletonDestroy();
215 
216     // TODO: print the OpenGL version number here
217 
218     printf("SDL_ttf version (compiled): %d.%d.%d\n",
219            SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
220 /*
221     char video_driver[80];
222     SDL_VideoDriverName(video_driver, 80);
223     printf("Name of video driver: %s\n", video_driver);
224 
225     const SDL_VideoInfo *user_video;
226     user_video = SDL_GetVideoInfo(); // Get information about the user's video system
227     std::cout << "  Best available video mode" << std::endl
228               << "    Creates hardware surfaces: ";
229     if(user_video->hw_available == 1)
230         std::cout << "yes\n";
231     else
232         std::cout << "no\n";
233     std::cout << "    Has window manager available: ";
234     if(user_video->wm_available == 1)
235         std::cout << "yes\n";
236     else
237         std::cout << "no\n";
238     std::cout << "    Hardware to hardware blits accelerated: ";
239     if(user_video->blit_hw == 1)
240         std::cout << "yes\n";
241     else
242         std::cout << "no\n";
243     std::cout << "    Hardware to hardware colorkey blits accelerated: ";
244     if(user_video->blit_hw_CC == 1)
245         std::cout << "yes\n";
246     else
247         std::cout << "no\n";
248     std::cout << "    Hardware to hardware alpha blits accelerated: ";
249     if(user_video->blit_hw_A == 1)
250         std::cout << "yes\n";
251     else
252         std::cout << "no\n";
253     std::cout << "    Software to hardware blits acceleerated: ";
254     if(user_video->blit_sw == 1)
255         std::cout << "yes\n";
256     else
257         std::cout << "no\n";
258     std::cout << "    Software to hardware colorkey blits accelerated: ";
259     if(user_video->blit_sw_CC == 1)
260         std::cout << "yes\n";
261     else
262         std::cout << "no\n";
263     std::cout << "    Software to hardware alpha blits accelerated: ";
264     if(user_video->blit_sw_A == 1)
265         std::cout << "yes\n";
266     else
267         std::cout << "no\n";
268     std::cout << "    Color fills accelerated: ";
269     if(user_video->blit_fill == 1)
270         std::cout << "yes\n";
271     else
272         std::cout << "no\n";
273     std::cout << "    Total video memory: " << user_video->video_mem << " kilobytes" << std::endl;
274     // std::cout << "    Best pixel format: " << user_video->vfmt << std::endl;
275 */
276     printf("\n===== Audio Information\n");
277 
278     vt_audio::AudioManager = vt_audio::AudioEngine::SingletonCreate();
279     if(vt_audio::AudioManager->SingletonInitialize() == false) {
280         std::cerr << "ERROR: unable to initialize the AudioManager" << std::endl;
281         return false;
282     }
283     vt_audio::AudioManager->DEBUG_PrintInfo();
284     vt_audio::AudioEngine::SingletonDestroy();
285 
286     std::cout << std::endl;
287 
288     return true;
289 } // bool PrintSystemInformation()
290 
ResetSettings()291 bool ResetSettings()
292 {
293     std::string file = GetUserConfigPath() + "settings.lua";
294 
295     // Copy the default file to the user location.
296     vt_utils::CopyAFile(std::string("data/config/settings.lua"), file);
297     std::cout << "Copied default settings.lua file to: " << file << std::endl;
298 
299     return false;
300 } // bool ResetSettings()
301 
EnableDebugging(const std::string & vars)302 bool EnableDebugging(const std::string &vars)
303 {
304     // A vector of all the debug arguments
305     std::vector<std::string> args;
306     ParseSecondaryOptions(vars, args);
307 
308     // Enable all specified debug variables
309     for(uint32_t i = 0; i < args.size(); i++) {
310         if(args[i] == "all") {
311             // This causes every call to SDL_SetError to also print an error message on stderr.
312             // NOTE: commented out because apparently SDL_putenv is not yet an available function on some systems
313             // SDL_putenv("SDL_DEBUG=1");
314 
315             vt_audio::AUDIO_DEBUG                  = true;
316             vt_battle::BATTLE_DEBUG                = true;
317             vt_boot::BOOT_DEBUG                    = true;
318             vt_common::COMMON_DEBUG                = true;
319             vt_script::SCRIPT_DEBUG                = true;
320             vt_mode_manager::MODE_MANAGER_DEBUG    = true;
321             vt_input::INPUT_DEBUG                  = true;
322             vt_system::SYSTEM_DEBUG                = true;
323             vt_global::GLOBAL_DEBUG                = true;
324             vt_map::MAP_DEBUG                      = true;
325             vt_menu::MENU_DEBUG                    = true;
326             vt_pause::PAUSE_DEBUG                  = true;
327             vt_shop::SHOP_DEBUG                    = true;
328             vt_video::VIDEO_DEBUG                  = true;
329         } else if(args[i] == "audio") {
330             vt_audio::AUDIO_DEBUG = true;
331         } else if(args[i] == "battle") {
332             vt_battle::BATTLE_DEBUG = true;
333         } else if(args[i] == "boot") {
334             vt_boot::BOOT_DEBUG = true;
335         } else if(args[i] == "common") {
336             vt_common::COMMON_DEBUG = true;
337         } else if(args[i] == "data") {
338             vt_script::SCRIPT_DEBUG = true;
339         } else if(args[i] == "mode_manager") {
340             vt_mode_manager::MODE_MANAGER_DEBUG = true;
341         } else if(args[i] == "input") {
342             vt_input::INPUT_DEBUG = true;
343         } else if(args[i] == "system") {
344             vt_system::SYSTEM_DEBUG = true;
345         } else if(args[i] == "global") {
346             vt_global::GLOBAL_DEBUG = true;
347         } else if(args[i] == "map") {
348             vt_map::MAP_DEBUG = true;
349         } else if(args[i] == "menu") {
350             vt_menu::MENU_DEBUG = true;
351         } else if(args[i] == "pause") {
352             vt_pause::PAUSE_DEBUG = true;
353         } else if(args[i] == "shop") {
354             vt_shop::SHOP_DEBUG = true;
355         } else if(args[i] == "video") {
356             vt_video::VIDEO_DEBUG = true;
357         } else {
358             std::cerr << "ERROR: invalid debug argument: " << args[i] << std::endl;
359             return false;
360         }
361     } // for (uint32_t i = 0; i < args.size(); i++)
362 
363     return true;
364 } // bool EnableDebugging(string vars)
365 
366 } // namespace vt_main
367