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 <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "config.h"
20 #include "textscreen.h"
21 
22 #include "execute.h"
23 
24 #include "m_argv.h"
25 #include "m_config.h"
26 #include "m_controls.h"
27 #include "m_misc.h"
28 #include "z_zone.h"
29 
30 #include "setup_icon.c"
31 #include "mode.h"
32 
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 #define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup"
42 
43 static const int cheat_sequence[] =
44 {
45     KEY_UPARROW, KEY_UPARROW, KEY_DOWNARROW, KEY_DOWNARROW,
46     KEY_LEFTARROW, KEY_RIGHTARROW, KEY_LEFTARROW, KEY_RIGHTARROW,
47     'b', 'a', KEY_ENTER, 0
48 };
49 
50 static unsigned int cheat_sequence_index = 0;
51 
52 // I think these are good "sensible" defaults:
53 
SensibleDefaults(void)54 static void SensibleDefaults(void)
55 {
56     key_up = 'w';
57     key_down = 's';
58     key_strafeleft = 'a';
59     key_straferight = 'd';
60     key_jump = '/';
61     key_lookup = KEY_PGUP;
62     key_lookdown = KEY_PGDN;
63     key_lookcenter = KEY_HOME;
64     key_flyup = KEY_INS;
65     key_flydown = KEY_DEL;
66     key_flycenter = KEY_END;
67     key_prevweapon = ',';
68     key_nextweapon = '.';
69     key_invleft = '[';
70     key_invright = ']';
71     key_message_refresh = '\'';
72     key_mission = 'i';              // Strife keys
73     key_invpop = 'o';
74     key_invkey = 'p';
75     key_multi_msgplayer[0] = 'g';
76     key_multi_msgplayer[1] = 'h';
77     key_multi_msgplayer[2] = 'j';
78     key_multi_msgplayer[3] = 'k';
79     key_multi_msgplayer[4] = 'v';
80     key_multi_msgplayer[5] = 'b';
81     key_multi_msgplayer[6] = 'n';
82     key_multi_msgplayer[7] = 'm';
83     mousebprevweapon = 4;           // Scroll wheel = weapon cycle
84     mousebnextweapon = 3;
85     snd_musicdevice = 3;
86     joybspeed = 29;                 // Always run
87     vanilla_savegame_limit = 0;
88     vanilla_keyboard_mapping = 0;
89     vanilla_demo_limit = 0;
90     graphical_startup = 0;
91     show_endoom = 0;
92     dclick_use = 0;
93     novert = 1;
94     snd_dmxoption = "-opl3 -reverse";
95     png_screenshots = 1;
96 }
97 
MainMenuKeyPress(txt_window_t * window,int key,void * user_data)98 static int MainMenuKeyPress(txt_window_t *window, int key, void *user_data)
99 {
100     if (key == cheat_sequence[cheat_sequence_index])
101     {
102         ++cheat_sequence_index;
103 
104         if (cheat_sequence[cheat_sequence_index] == 0)
105         {
106             SensibleDefaults();
107             cheat_sequence_index = 0;
108 
109             window = TXT_MessageBox(NULL, "    \x01    ");
110 
111             return 1;
112         }
113     }
114     else
115     {
116         cheat_sequence_index = 0;
117     }
118 
119     return 0;
120 }
121 
DoQuit(void * widget,void * dosave)122 static void DoQuit(void *widget, void *dosave)
123 {
124     if (dosave != NULL)
125     {
126         M_SaveDefaults();
127     }
128 
129     TXT_Shutdown();
130 
131     exit(0);
132 }
133 
QuitConfirm(void * unused1,void * unused2)134 static void QuitConfirm(void *unused1, void *unused2)
135 {
136     txt_window_t *window;
137     txt_label_t *label;
138     txt_button_t *yes_button;
139     txt_button_t *no_button;
140 
141     window = TXT_NewWindow(NULL);
142 
143     TXT_AddWidgets(window,
144                    label = TXT_NewLabel("Exiting setup.\nSave settings?"),
145                    TXT_NewStrut(24, 0),
146                    yes_button = TXT_NewButton2("  Yes  ", DoQuit, DoQuit),
147                    no_button = TXT_NewButton2("  No   ", DoQuit, NULL),
148                    NULL);
149 
150     TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER);
151     TXT_SetWidgetAlign(yes_button, TXT_HORIZ_CENTER);
152     TXT_SetWidgetAlign(no_button, TXT_HORIZ_CENTER);
153 
154     // Only an "abort" button in the middle.
155     TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL);
156     TXT_SetWindowAction(window, TXT_HORIZ_CENTER,
157                         TXT_NewWindowAbortAction(window));
158     TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL);
159 }
160 
LaunchDoom(void * unused1,void * unused2)161 static void LaunchDoom(void *unused1, void *unused2)
162 {
163     execute_context_t *exec;
164 
165     // Save configuration first
166 
167     M_SaveDefaults();
168 
169     // Shut down textscreen GUI
170 
171     TXT_Shutdown();
172 
173     // Launch Doom
174 
175     exec = NewExecuteContext();
176     PassThroughArguments(exec);
177     ExecuteDoom(exec);
178 
179     exit(0);
180 }
181 
GetLaunchButton(void)182 static txt_button_t *GetLaunchButton(void)
183 {
184     char *label;
185 
186     switch (gamemission)
187     {
188         case doom:
189             label = "Save parameters and launch DOOM";
190             break;
191         case heretic:
192             label = "Save parameters and launch Heretic";
193             break;
194         case hexen:
195             label = "Save parameters and launch Hexen";
196             break;
197         case strife:
198             label = "Save parameters and launch STRIFE!";
199             break;
200         default:
201             label = "Save parameters and launch game";
202             break;
203     }
204 
205     return TXT_NewButton2(label, LaunchDoom, NULL);
206 }
207 
MainMenu(void)208 void MainMenu(void)
209 {
210     txt_window_t *window;
211     txt_window_action_t *quit_action;
212     txt_window_action_t *warp_action;
213 
214     window = TXT_NewWindow("Main Menu");
215 
216     TXT_SetWindowHelpURL(window, WINDOW_HELP_URL);
217 
218     TXT_AddWidgets(window,
219         TXT_NewButton2("Configure Display",
220                        (TxtWidgetSignalFunc) ConfigDisplay, NULL),
221         TXT_NewButton2("Configure Sound",
222                        (TxtWidgetSignalFunc) ConfigSound, NULL),
223         TXT_NewButton2("Configure Keyboard",
224                        (TxtWidgetSignalFunc) ConfigKeyboard, NULL),
225         TXT_NewButton2("Configure Mouse",
226                        (TxtWidgetSignalFunc) ConfigMouse, NULL),
227         TXT_NewButton2("Configure Gamepad/Joystick",
228                        (TxtWidgetSignalFunc) ConfigJoystick, NULL),
229         TXT_NewButton2("Compatibility",
230                        (TxtWidgetSignalFunc) CompatibilitySettings, NULL),
231         GetLaunchButton(),
232         TXT_NewStrut(0, 1),
233         TXT_NewButton2("Start a Network Game",
234                        (TxtWidgetSignalFunc) StartMultiGame, NULL),
235         TXT_NewButton2("Join a Network Game",
236                        (TxtWidgetSignalFunc) JoinMultiGame, NULL),
237         TXT_NewButton2("Multiplayer Configuration",
238                        (TxtWidgetSignalFunc) MultiplayerConfig, NULL),
239         NULL);
240 
241     quit_action = TXT_NewWindowAction(KEY_ESCAPE, "Quit");
242     warp_action = TXT_NewWindowAction(KEY_F2, "Warp");
243     TXT_SignalConnect(quit_action, "pressed", QuitConfirm, NULL);
244     TXT_SignalConnect(warp_action, "pressed",
245                       (TxtWidgetSignalFunc) WarpMenu, NULL);
246     TXT_SetWindowAction(window, TXT_HORIZ_LEFT, quit_action);
247     TXT_SetWindowAction(window, TXT_HORIZ_CENTER, warp_action);
248 
249     TXT_SetKeyListener(window, MainMenuKeyPress, NULL);
250 }
251 
252 //
253 // Initialize all configuration variables, load config file, etc
254 //
255 
InitConfig(void)256 static void InitConfig(void)
257 {
258     M_SetConfigDir(NULL);
259     InitBindings();
260 
261     SetChatMacroDefaults();
262     SetPlayerNameDefault();
263 
264     M_LoadDefaults();
265 }
266 
267 //
268 // Application icon
269 //
270 
SetIcon(void)271 static void SetIcon(void)
272 {
273     extern SDL_Window *TXT_SDLWindow;
274     SDL_Surface *surface;
275 
276     surface = SDL_CreateRGBSurfaceFrom((void *) setup_icon_data, setup_icon_w,
277                                        setup_icon_h, 32, setup_icon_w * 4,
278                                        0xff << 24, 0xff << 16,
279                                        0xff << 8, 0xff << 0);
280 
281     SDL_SetWindowIcon(TXT_SDLWindow, surface);
282     SDL_FreeSurface(surface);
283 }
284 
SetWindowTitle(void)285 static void SetWindowTitle(void)
286 {
287     char *title;
288 
289     title = M_StringReplace(PACKAGE_NAME " Setup ver " PACKAGE_VERSION,
290                             "Doom",
291                             GetGameTitle());
292 
293 
294     TXT_SetDesktopTitle(title);
295 
296     free(title);
297 }
298 
299 // Initialize the textscreen library.
300 
InitTextscreen(void)301 static void InitTextscreen(void)
302 {
303     SetDisplayDriver();
304 
305     if (!TXT_Init())
306     {
307         fprintf(stderr, "Failed to initialize GUI\n");
308         exit(-1);
309     }
310 
311     SetIcon();
312     SetWindowTitle();
313 }
314 
315 // Restart the textscreen library.  Used when the video_driver variable
316 // is changed.
317 
RestartTextscreen(void)318 void RestartTextscreen(void)
319 {
320     TXT_Shutdown();
321     InitTextscreen();
322 }
323 
324 //
325 // Initialize and run the textscreen GUI.
326 //
327 
RunGUI(void)328 static void RunGUI(void)
329 {
330     InitTextscreen();
331 
332     TXT_GUIMainLoop();
333 }
334 
MissionSet(void)335 static void MissionSet(void)
336 {
337     SetWindowTitle();
338     InitConfig();
339     MainMenu();
340 }
341 
D_DoomMain(void)342 void D_DoomMain(void)
343 {
344     SetupMission(MissionSet);
345 
346     RunGUI();
347 }
348