1 //
2 // Copyright(C) 2005-2014 Simon Howard
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (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 
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #include "doomtype.h"
19 
20 #include "config.h"
21 #include "textscreen.h"
22 
23 #include "doomtype.h"
24 #include "d_mode.h"
25 #include "d_iwad.h"
26 #include "i_system.h"
27 #include "m_argv.h"
28 #include "m_config.h"
29 #include "m_controls.h"
30 #include "m_misc.h"
31 
32 #include "accessibility.h"
33 #include "compatibility.h"
34 #include "display.h"
35 #include "joystick.h"
36 #include "keyboard.h"
37 #include "mouse.h"
38 #include "multiplayer.h"
39 #include "sound.h"
40 
41 #include "mode.h"
42 
43 GameMission_t gamemission;
44 static const iwad_t **iwads;
45 
46 typedef struct
47 {
48     const char *label;
49     GameMission_t mission;
50     int mask;
51     const char *name;
52     const char *config_file;
53     const char *extra_config_file;
54     const char *executable;
55 } mission_config_t;
56 
57 // Default mission to fall back on, if no IWADs are found at all:
58 
59 #define DEFAULT_MISSION (&mission_configs[0])
60 
61 static mission_config_t mission_configs[] =
62 {
63     {
64         "Doom",
65         doom,
66         IWAD_MASK_DOOM,
67         "doom",
68         "default.cfg",
69         PROGRAM_PREFIX "doom.cfg",
70         PROGRAM_PREFIX "doom"
71     },
72     {
73         "Heretic",
74         heretic,
75         IWAD_MASK_HERETIC,
76         "heretic",
77         "heretic.cfg",
78         PROGRAM_PREFIX "heretic.cfg",
79         PROGRAM_PREFIX "heretic"
80     },
81     {
82         "Hexen",
83         hexen,
84         IWAD_MASK_HEXEN,
85         "hexen",
86         "hexen.cfg",
87         PROGRAM_PREFIX "hexen.cfg",
88         PROGRAM_PREFIX "hexen"
89     },
90     {
91         "Strife",
92         strife,
93         IWAD_MASK_STRIFE,
94         "strife",
95         "strife.cfg",
96         PROGRAM_PREFIX "strife.cfg",
97         PROGRAM_PREFIX "strife"
98     }
99 };
100 
101 static GameSelectCallback game_selected_callback;
102 
103 // Miscellaneous variables that aren't used in setup.
104 
105 static int showMessages = 1;
106 static int screenblocks = 10;
107 static int detailLevel = 0;
108 static char *savedir = NULL;
109 static char *executable = NULL;
110 static const char *game_title = "Doom";
111 static char *back_flat = "F_PAVE01";
112 static int comport = 0;
113 static char *nickname = NULL;
114 
BindMiscVariables(void)115 static void BindMiscVariables(void)
116 {
117     if (gamemission == doom)
118     {
119         M_BindIntVariable("detaillevel",   &detailLevel);
120         M_BindIntVariable("show_messages", &showMessages);
121     }
122 
123     if (gamemission == hexen)
124     {
125         M_BindStringVariable("savedir", &savedir);
126         M_BindIntVariable("messageson", &showMessages);
127 
128         // Hexen has a variable to control the savegame directory
129         // that is used.
130 
131         savedir = M_GetSaveGameDir("hexen.wad");
132 
133         // On Windows, hexndata\ is the default.
134 
135         if (!strcmp(savedir, ""))
136         {
137             free(savedir);
138             savedir = "hexndata" DIR_SEPARATOR_S;
139         }
140     }
141 
142     if (gamemission == strife)
143     {
144         // Strife has a different default value than the other games
145         screenblocks = 10;
146 
147         M_BindStringVariable("back_flat",   &back_flat);
148         M_BindStringVariable("nickname",    &nickname);
149 
150         M_BindIntVariable("screensize",     &screenblocks);
151         M_BindIntVariable("comport",        &comport);
152     }
153     else
154     {
155         M_BindIntVariable("screenblocks",   &screenblocks);
156     }
157 
158 }
159 
160 //
161 // Initialise all configuration file bindings.
162 //
163 
InitBindings(void)164 void InitBindings(void)
165 {
166     M_ApplyPlatformDefaults();
167 
168     // Keyboard, mouse, joystick controls
169 
170     M_BindBaseControls();
171     M_BindWeaponControls();
172     M_BindMapControls();
173     M_BindMenuControls();
174 
175     if (gamemission == heretic || gamemission == hexen)
176     {
177         M_BindHereticControls();
178     }
179 
180     if (gamemission == hexen)
181     {
182         M_BindHexenControls();
183     }
184 
185     if (gamemission == strife)
186     {
187         M_BindStrifeControls();
188     }
189 
190     // All other variables
191 
192     BindAccessibilityVariables();
193     BindCompatibilityVariables();
194     BindDisplayVariables();
195     BindJoystickVariables();
196     BindKeyboardVariables();
197     BindMouseVariables();
198     BindSoundVariables();
199     BindMiscVariables();
200     BindMultiplayerVariables();
201 }
202 
203 // Set the name of the executable program to run the game:
204 
SetExecutable(mission_config_t * config)205 static void SetExecutable(mission_config_t *config)
206 {
207     char *extension;
208 
209     free(executable);
210 
211 #ifdef _WIN32
212     extension = ".exe";
213 #else
214     extension = "";
215 #endif
216 
217     executable = M_StringJoin(config->executable, extension, NULL);
218 }
219 
SetMission(mission_config_t * config)220 static void SetMission(mission_config_t *config)
221 {
222     iwads = D_FindAllIWADs(config->mask);
223     gamemission = config->mission;
224     SetExecutable(config);
225     game_title = config->label;
226     M_SetConfigFilenames(config->config_file, config->extra_config_file);
227 }
228 
GetMissionForName(const char * name)229 static mission_config_t *GetMissionForName(const char *name)
230 {
231     int i;
232 
233     for (i=0; i<arrlen(mission_configs); ++i)
234     {
235         if (!strcmp(mission_configs[i].name, name))
236         {
237             return &mission_configs[i];
238         }
239     }
240 
241     return NULL;
242 }
243 
244 // Check the name of the executable.  If it contains one of the game
245 // names (eg. chocolate-hexen-setup.exe) then use that game.
246 
CheckExecutableName(GameSelectCallback callback)247 static boolean CheckExecutableName(GameSelectCallback callback)
248 {
249     mission_config_t *config;
250     const char *exe_name;
251     int i;
252 
253     exe_name = M_GetExecutableName();
254 
255     for (i=0; i<arrlen(mission_configs); ++i)
256     {
257         config = &mission_configs[i];
258 
259         if (strstr(exe_name, config->name) != NULL)
260         {
261             SetMission(config);
262             callback();
263             return true;
264         }
265     }
266 
267     return false;
268 }
269 
GameSelected(TXT_UNCAST_ARG (widget),TXT_UNCAST_ARG (config))270 static void GameSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(config))
271 {
272     TXT_CAST_ARG(mission_config_t, config);
273 
274     SetMission(config);
275     game_selected_callback();
276 }
277 
OpenGameSelectDialog(GameSelectCallback callback)278 static void OpenGameSelectDialog(GameSelectCallback callback)
279 {
280     mission_config_t *mission = NULL;
281     txt_window_t *window;
282     const iwad_t **iwads;
283     int num_games;
284     int i;
285 
286     window = TXT_NewWindow("Select game");
287 
288     TXT_AddWidget(window, TXT_NewLabel("Select a game to configure:\n"));
289     num_games = 0;
290 
291     // Add a button for each game.
292 
293     for (i=0; i<arrlen(mission_configs); ++i)
294     {
295         // Do we have any IWADs for this game installed?
296         // If so, add a button.
297 
298         iwads = D_FindAllIWADs(mission_configs[i].mask & (IWAD_MASK_DOOM|IWAD_MASK_HERETIC)); // [crispy] restrict game choice to Doom and Heretic
299 
300         if (iwads[0] != NULL)
301         {
302             mission = &mission_configs[i];
303             TXT_AddWidget(window, TXT_NewButton2(mission_configs[i].label,
304                                                  GameSelected,
305                                                  &mission_configs[i]));
306             ++num_games;
307         }
308 
309         free(iwads);
310     }
311 
312     TXT_AddWidget(window, TXT_NewStrut(0, 1));
313 
314     // No IWADs found at all?  Fall back to doom, then.
315 
316     if (num_games == 0)
317     {
318         TXT_CloseWindow(window);
319         SetMission(DEFAULT_MISSION);
320         callback();
321         return;
322     }
323 
324     // Only one game? Use that game, and don't bother with a dialog.
325 
326     if (num_games == 1)
327     {
328         TXT_CloseWindow(window);
329         SetMission(mission);
330         callback();
331         return;
332     }
333 
334     game_selected_callback = callback;
335 }
336 
SetupMission(GameSelectCallback callback)337 void SetupMission(GameSelectCallback callback)
338 {
339     mission_config_t *config;
340     const char *mission_name;
341     int p;
342 
343     //!
344     // @arg <game>
345     //
346     // Specify the game to configure the settings for.  Valid
347     // values are 'doom', 'heretic', 'hexen' and 'strife'.
348     //
349 
350     p = M_CheckParm("-game");
351 
352     if (p > 0)
353     {
354         mission_name = myargv[p + 1];
355 
356         config = GetMissionForName(mission_name);
357 
358         if (config == NULL)
359         {
360             I_Error("Invalid parameter - '%s'", mission_name);
361         }
362 
363         SetMission(config);
364         callback();
365     }
366     else if (!CheckExecutableName(callback))
367     {
368         OpenGameSelectDialog(callback);
369     }
370 }
371 
GetExecutableName(void)372 const char *GetExecutableName(void)
373 {
374     return executable;
375 }
376 
GetGameTitle(void)377 const char *GetGameTitle(void)
378 {
379     return game_title;
380 }
381 
GetIwads(void)382 const iwad_t **GetIwads(void)
383 {
384     return iwads;
385 }
386 
387