1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2020 EDuke32 developers and contributors
4 Copyright (C) 2020 sirlemonhead, Nuke.YKT
5 This file is part of ETekWar.
6 ETekWar is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License version 2
8 as published by the Free Software Foundation.
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.
12 See the GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 */
17 //-------------------------------------------------------------------------
18 
19 #include "compat.h"
20 #include "renderlayer.h"
21 #include "_control.h"
22 #include "build.h"
23 #include "cache1d.h"
24 #include "keyboard.h"
25 #include "control.h"
26 #include "tekwar.h"
27 #include "scriplib.h"
28 
29 #include "config.h"
30 
31 #include <string>
32 //#include <io.h>
33 #include <stdio.h>
34 #include <time.h>
35 
36 const char gamefunctions[kMaxGameFunctions][kMaxGameFuncLen] =
37 {
38   "Move_Forward",
39   "Move_Backward",
40   "Turn_Left",
41   "Turn_Right",
42   "Strafe",
43   "Strafe_Left",
44   "Strafe_Right",
45   "Run",
46   "Jump",
47   "Crouch",
48   "Fire",
49   "Open",
50   "Look_Up",
51   "Look_Down",
52   "Look_Straight",
53   "Aim_Up",
54   "Aim_Down",
55   "SendMessage",
56   "ConcealWeapon",
57   "SwitchPlayer",
58   "RearView",
59   "MatrixMeter",
60   "HealthMeter",
61   "ElapsedTime",
62   "Score",
63   "Inventory",
64   "Weapon_1",
65   "Weapon_2",
66   "Weapon_3",
67   "Weapon_4",
68   "Weapon_5",
69   "Weapon_6",
70   "Weapon_7",
71   "Weapon_8",
72   "Weapon_9",
73   "Pause",
74   "Map",
75   "Zoom_In",
76   "Zoom_Out",
77   "Gamma_Correction",
78   "Escape",
79   "Shrink_Screen",
80   "Enlarge_Screen",
81   "Mouse_Sensitivity_Up",
82   "Mouse_Sensitivity_Down",
83   "Show_Console",
84   "Mouse_Aiming",
85   "Toggle_Crosshair"
86 };
87 
88 const char keydefaults[kMaxGameFunctions * 2][kMaxGameFuncLen] =
89 {
90    "W", "Kpad8",
91    "S", "Kpad2",
92    "Left", "Kpad4",
93    "Right", "KPad6",
94    "LAlt", "RAlt",
95    "A", "",
96    "D", "",
97    "LShift", "RShift",
98    "Space", "",
99    "LCtrl", "",
100    "RCtrl", "",
101    "E", "",
102    "PgUp", "",
103    "PgDn", "",
104    "Home", "",
105    "", "", // aim up
106    "", "", // aim down
107    "M", "",
108    "/", "", // conceal weapon
109    "KpdEnt", "",
110    "R", "",
111    "E", "",
112    "H", "",
113    "T", "",
114    "",  "", // score
115    "I", "", // inventory
116    "1", "",
117    "2", "",
118    "3", "",
119    "4", "",
120    "5", "",
121    "6", "",
122    "7", "",
123    "8", "",
124    "9", "",
125    "Pause", "",
126    "Tab", "",
127    "=", "",
128    "-", "",
129    "F11", "",
130    "Escape", "",
131    "Kpad-", "",
132    "Kpad+", "",
133    "", "", // sensitivity up
134    "", "", // sensitivity down
135    "`", "",
136    "U", "",
137    "G", "",
138 };
139 
140 const char oldkeydefaults[kMaxGameFunctions * 2][kMaxGameFuncLen] =
141 {
142    "Up", "Kpad8",
143    "Down", "Kpad2",
144    "Left", "Kpad4",
145    "Right", "KPad6",
146    "LAlt", "RAlt",
147    ",", "",
148    ".", "",
149    "LShift", "RShift",
150    "A", "",
151    "Z", "",
152    "LCtrl", "RCtrl",
153    "Space", "",
154    "PgUp", "",
155    "PgDn", "",
156    "Home", "",
157    "Insert", "",
158    "Delete", "",
159    "T", "",
160    "1", "",
161    "2", "",
162    "3", "",
163    "4", "",
164    "5", "",
165    "6", "",
166    "7", "",
167    "Pause", "",
168    "Tab", "",
169    "=", "",
170    "-", "",
171    "F11", "",
172    "Escape", "",
173    "Kpad-", "",
174    "Kpad+", "",
175    "Enter", "",
176    "[", "",
177    "]", "",
178    "F7", "",
179    "F8", "",
180    "`", "",
181    "U", "",
182    "I", "",
183 };
184 
185 static const char* mousedefaults[MAXMOUSEBUTTONS] =
186 {
187    "Fire",
188    "Strafe",
189    "Move_Forward"
190    "",
191    "",
192    "",
193 };
194 
195 static const char* mouseclickeddefaults[MAXMOUSEBUTTONS] =
196 {
197 };
198 
199 static const char* mouseanalogdefaults[MAXMOUSEAXES] =
200 {
201 "analog_strafing",
202 "analog_moving",
203 };
204 
205 
206 static const char* mousedigitaldefaults[MAXMOUSEDIGITAL] =
207 {
208 };
209 
210 ud_setup_t gSetup;
211 
212 char setupfilename[BMAX_PATH] = {kSetupFilename};
213 
214 int lMouseSens = 32;
215 
216 int32_t FXVolume;
217 int32_t MusicVolume;
218 int32_t MixRate;
219 int32_t MidiPort;
220 int32_t NumVoices;
221 int32_t NumChannels;
222 int32_t NumBits;
223 int32_t ReverseStereo;
224 int32_t MusicDevice;
225 int32_t FXDevice;
226 int32_t ControllerType;
227 
228 int32_t scripthandle;
229 int32_t setupread;
230 // TODO: implement precaching toggle
231 int32_t useprecache;
232 int32_t MouseDeadZone, MouseBias;
233 
234 // JBF 20031211: Store the input settings because
235 // (currently) mact can't regurgitate them
236 int32_t MouseFunctions[MAXMOUSEBUTTONS][2];
237 int32_t MouseDigitalFunctions[MAXMOUSEAXES][2];
238 int32_t MouseAnalogueAxes[MAXMOUSEAXES];
239 int32_t MouseAnalogueScale[MAXMOUSEAXES];
240 int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2];
241 int32_t JoystickDigitalFunctions[MAXJOYAXES][2];
242 int32_t JoystickAnalogueAxes[MAXJOYAXES];
243 int32_t JoystickAnalogueScale[MAXJOYAXES];
244 int32_t JoystickAnalogueInvert[MAXJOYAXES];
245 int32_t JoystickAnalogueDead[MAXJOYAXES];
246 int32_t JoystickAnalogueSaturate[MAXJOYAXES];
247 uint8_t KeyboardKeys[kMaxGameFunctions][2];
248 
249 int32_t MAXCACHE1DSIZE = (96 * 1024 * 1024);
250 
251 
SetupGameButtons()252 void SetupGameButtons()
253 {
254     CONTROL_DefineFlag(gamefunc_Move_Forward, FALSE);
255     CONTROL_DefineFlag(gamefunc_Move_Backward, FALSE);
256     CONTROL_DefineFlag(gamefunc_Turn_Left, FALSE);
257     CONTROL_DefineFlag(gamefunc_Turn_Right, FALSE);
258     CONTROL_DefineFlag(gamefunc_Strafe, FALSE);
259     CONTROL_DefineFlag(gamefunc_Strafe_Left, FALSE);
260     CONTROL_DefineFlag(gamefunc_Strafe_Right, FALSE);
261     CONTROL_DefineFlag(gamefunc_Run, FALSE);
262     CONTROL_DefineFlag(gamefunc_Jump, FALSE);
263     CONTROL_DefineFlag(gamefunc_Crouch, FALSE);
264     CONTROL_DefineFlag(gamefunc_Fire, FALSE);
265     CONTROL_DefineFlag(gamefunc_Open, FALSE);
266     CONTROL_DefineFlag(gamefunc_Look_Up, FALSE);
267     CONTROL_DefineFlag(gamefunc_Look_Down, FALSE);
268     CONTROL_DefineFlag(gamefunc_Look_Straight, FALSE);
269     CONTROL_DefineFlag(gamefunc_Aim_Up, FALSE);
270     CONTROL_DefineFlag(gamefunc_Aim_Down, FALSE);
271     CONTROL_DefineFlag(gamefunc_SendMessage, FALSE);
272     CONTROL_DefineFlag(gamefunc_ConcealWeapon, FALSE);
273     CONTROL_DefineFlag(gamefunc_SwitchPlayer, FALSE);
274     CONTROL_DefineFlag(gamefunc_RearView, FALSE);
275     CONTROL_DefineFlag(gamefunc_MatrixMeter, FALSE);
276     CONTROL_DefineFlag(gamefunc_HealthMeter, FALSE);
277     CONTROL_DefineFlag(gamefunc_ElapsedTime, FALSE);
278     CONTROL_DefineFlag(gamefunc_Score, FALSE);
279     CONTROL_DefineFlag(gamefunc_Inventory, FALSE);
280     CONTROL_DefineFlag(gamefunc_Weapon_1, FALSE);
281     CONTROL_DefineFlag(gamefunc_Weapon_2, FALSE);
282     CONTROL_DefineFlag(gamefunc_Weapon_3, FALSE);
283     CONTROL_DefineFlag(gamefunc_Weapon_4, FALSE);
284     CONTROL_DefineFlag(gamefunc_Weapon_5, FALSE);
285     CONTROL_DefineFlag(gamefunc_Weapon_6, FALSE);
286     CONTROL_DefineFlag(gamefunc_Weapon_7, FALSE);
287     CONTROL_DefineFlag(gamefunc_Weapon_8, FALSE);
288     CONTROL_DefineFlag(gamefunc_Weapon_9, FALSE);
289     CONTROL_DefineFlag(gamefunc_Pause, FALSE);
290     CONTROL_DefineFlag(gamefunc_Map, FALSE);
291     CONTROL_DefineFlag(gamefunc_Zoom_In, FALSE);
292     CONTROL_DefineFlag(gamefunc_Zoom_Out, FALSE);
293     CONTROL_DefineFlag(gamefunc_Gamma_Correction, FALSE);
294     CONTROL_DefineFlag(gamefunc_Escape, FALSE);
295     CONTROL_DefineFlag(gamefunc_Shrink_Screen, FALSE);
296     CONTROL_DefineFlag(gamefunc_Enlarge_Screen, FALSE);
297     CONTROL_DefineFlag(gamefunc_Mouse_Sensitivity_Up, FALSE);
298     CONTROL_DefineFlag(gamefunc_Mouse_Sensitivity_Down, FALSE);
299     CONTROL_DefineFlag(gamefunc_Mouse_Aiming, FALSE);
300     CONTROL_DefineFlag(gamefunc_Toggle_Crosshair, FALSE);
301 }
302 
303 hashtable_t h_gamefuncs = {kMaxGameFunctions << 1, NULL};
304 
CONFIG_FunctionNameToNum(const char * func)305 int32_t CONFIG_FunctionNameToNum(const char* func)
306 {
307     if (!func)
308         return -1;
309 
310     return hash_findcase(&h_gamefuncs, func);
311 }
312 
313 
CONFIG_FunctionNumToName(int32_t func)314 static char const* CONFIG_FunctionNumToName(int32_t func)
315 {
316     if ((unsigned)func >= (unsigned)kMaxGameFunctions)
317         return "";
318     return gamefunctions[func];
319 }
320 
321 
CONFIG_AnalogNameToNum(const char * func)322 int32_t CONFIG_AnalogNameToNum(const char* func)
323 {
324     if (!func)
325         return -1;
326     else if (!Bstrcasecmp(func, "analog_turning"))
327         return analog_turning;
328     else if (!Bstrcasecmp(func, "analog_strafing"))
329         return analog_strafing;
330     else if (!Bstrcasecmp(func, "analog_moving"))
331         return analog_moving;
332     else if (!Bstrcasecmp(func, "analog_lookingupanddown"))
333         return analog_lookingupanddown;
334     else
335         return -1;
336 }
337 
338 
CONFIG_AnalogNumToName(int32_t func)339 static char const* CONFIG_AnalogNumToName(int32_t func)
340 {
341     switch (func)
342     {
343         case analog_turning:
344         return "analog_turning";
345         case analog_strafing:
346         return "analog_strafing";
347         case analog_moving:
348         return "analog_moving";
349         case analog_lookingupanddown:
350         return "analog_lookingupanddown";
351     }
352 
353     return "";
354 }
355 
356 
CONFIG_SetJoystickButtonFunction(int i,int j,int function)357 static void CONFIG_SetJoystickButtonFunction(int i, int j, int function)
358 {
359     JoystickFunctions[i][j] = function;
360     CONTROL_MapButton(function, i, j, controldevice_joystick);
361 }
CONFIG_SetJoystickAnalogAxisScale(int i,int scale)362 static void CONFIG_SetJoystickAnalogAxisScale(int i, int scale)
363 {
364     JoystickAnalogueScale[i] = scale;
365     CONTROL_SetAnalogAxisScale(i, scale, controldevice_joystick);
366 }
CONFIG_SetJoystickAnalogAxisInvert(int i,int invert)367 static void CONFIG_SetJoystickAnalogAxisInvert(int i, int invert)
368 {
369     JoystickAnalogueInvert[i] = invert;
370     CONTROL_SetAnalogAxisInvert(i, invert, controldevice_joystick);
371 }
CONFIG_SetJoystickAnalogAxisDeadSaturate(int i,int dead,int saturate)372 static void CONFIG_SetJoystickAnalogAxisDeadSaturate(int i, int dead, int saturate)
373 {
374     JoystickAnalogueDead[i] = dead;
375     JoystickAnalogueSaturate[i] = saturate;
376     joySetDeadZone(i, dead, saturate);
377 }
CONFIG_SetJoystickDigitalAxisFunction(int i,int j,int function)378 static void CONFIG_SetJoystickDigitalAxisFunction(int i, int j, int function)
379 {
380     JoystickDigitalFunctions[i][j] = function;
381     CONTROL_MapDigitalAxis(i, function, j, controldevice_joystick);
382 }
CONFIG_SetJoystickAnalogAxisFunction(int i,int function)383 static void CONFIG_SetJoystickAnalogAxisFunction(int i, int function)
384 {
385     JoystickAnalogueAxes[i] = function;
386     CONTROL_MapAnalogAxis(i, function, controldevice_joystick);
387 }
388 
389 
CONFIG_SetDefaultKeys(const char (* keyptr)[kMaxGameFuncLen],bool lazy)390 void CONFIG_SetDefaultKeys(const char(*keyptr)[kMaxGameFuncLen], bool lazy/*=false*/)
391 {
392     static char const s_gamefunc_[] = "gamefunc_";
393     int constexpr strlen_gamefunc_ = ARRAY_SIZE(s_gamefunc_) - 1;
394 
395     if (!lazy)
396     {
397         Bmemset(KeyboardKeys, 0xff, sizeof(KeyboardKeys));
398         CONTROL_ClearAllBinds();
399     }
400 
401     for (int i = 0; i < ARRAY_SSIZE(gamefunctions); ++i)
402     {
403         if (gamefunctions[i][0] == '\0')
404             continue;
405 
406         auto& key = KeyboardKeys[i];
407 
408         int const default0 = KB_StringToScanCode(keyptr[i << 1]);
409         int const default1 = KB_StringToScanCode(keyptr[(i << 1) + 1]);
410 
411         // skip the function if the default key is already used
412         // or the function is assigned to another key
413         if (lazy && (key[0] != 0xff || (CONTROL_KeyIsBound(default0) && Bstrlen(CONTROL_KeyBinds[default0].cmdstr) > strlen_gamefunc_
414             && CONFIG_FunctionNameToNum(CONTROL_KeyBinds[default0].cmdstr + strlen_gamefunc_) >= 0)))
415         {
416             #if 0 // defined(DEBUGGINGAIDS)
417             if (key[0] != 0xff)
418                 initprintf("Skipping %s bound to %s\n", keyptr[i << 1], CONTROL_KeyBinds[default0].cmdstr);
419             #endif
420             continue;
421         }
422 
423         key[0] = default0;
424         key[1] = default1;
425 
426         if (key[0])
427             CONTROL_FreeKeyBind(key[0]);
428 
429         if (key[1])
430             CONTROL_FreeKeyBind(key[1]);
431 
432         if (i == gamefunc_Show_Console)
433             OSD_CaptureKey(key[0]);
434         else
435             CONFIG_MapKey(i, key[0], 0, key[1], 0);
436     }
437 }
438 
CONFIG_SetDefaults()439 void CONFIG_SetDefaults()
440 {
441     scripthandle = -1;
442     # if defined RENDERTYPESDL && SDL_MAJOR_VERSION > 1
443     uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO);
444     if (inited == 0)
445         SDL_Init(SDL_INIT_VIDEO);
446     else if (!(inited & SDL_INIT_VIDEO))
447         SDL_InitSubSystem(SDL_INIT_VIDEO);
448 
449     SDL_DisplayMode dm;
450     if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
451     {
452         gSetup.xdim = dm.w;
453         gSetup.ydim = dm.h;
454     }
455     else
456         # endif
457     {
458         gSetup.xdim = 1024;
459         gSetup.ydim = 768;
460     }
461 
462     #ifdef USE_OPENGL
463     gSetup.bpp = 32;
464     #else
465     gSetup.bpp = 8;
466     #endif
467 
468     // currently settings.cfg is only read after the startup window launches the game,
469     // and rereading binds might be fickle so just enable this
470     gSetup.usejoystick = 1;
471 
472     gSetup.forcesetup = 1;
473     gSetup.noautoload = 1;
474     gSetup.fullscreen = 1;
475     gSetup.usemouse = 1;
476 
477     MixRate = 44100;
478     FXVolume = 255;
479     MusicVolume = 255;
480     NumChannels = 2;
481     NumBits = 16;
482     NumVoices = 32;
483     /* // TODO
484         mouseaiming = 0;
485         aimmode = 1;
486         mouseflip = 1;
487         runkey_mode = 0;
488         auto_run = 1;
489 
490         gFov = 90;
491     */
492     CONFIG_SetDefaultKeys(keydefaults);
493 
494     memset(MouseFunctions, -1, sizeof(MouseFunctions));
495     memset(MouseDigitalFunctions, -1, sizeof(MouseDigitalFunctions));
496     memset(JoystickFunctions, -1, sizeof(JoystickFunctions));
497     memset(JoystickDigitalFunctions, -1, sizeof(JoystickDigitalFunctions));
498 
499     CONTROL_MouseSensitivity = DEFAULTMOUSESENSITIVITY;
500 
501     for (int i = 0; i < MAXMOUSEBUTTONS; i++)
502     {
503         MouseFunctions[i][0] = CONFIG_FunctionNameToNum(mousedefaults[i]);
504         CONTROL_MapButton(MouseFunctions[i][0], i, 0, controldevice_mouse);
505         if (i >= 4) continue;
506         MouseFunctions[i][1] = CONFIG_FunctionNameToNum(mouseclickeddefaults[i]);
507         CONTROL_MapButton(MouseFunctions[i][1], i, 1, controldevice_mouse);
508     }
509 
510     for (int i = 0; i < MAXMOUSEAXES; i++)
511     {
512         MouseAnalogueScale[i] = DEFAULTMOUSEANALOGUESCALE;
513         CONTROL_SetAnalogAxisScale(i, MouseAnalogueScale[i], controldevice_mouse);
514 
515         MouseDigitalFunctions[i][0] = CONFIG_FunctionNameToNum(mousedigitaldefaults[i * 2]);
516         MouseDigitalFunctions[i][1] = CONFIG_FunctionNameToNum(mousedigitaldefaults[i * 2 + 1]);
517         CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][0], 0, controldevice_mouse);
518         CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][1], 1, controldevice_mouse);
519 
520         MouseAnalogueAxes[i] = CONFIG_AnalogNameToNum(mouseanalogdefaults[i]);
521         CONTROL_MapAnalogAxis(i, MouseAnalogueAxes[i], controldevice_mouse);
522     }
523 
524     // TODO:
525     //CONFIG_SetGameControllerDefaultsStandard();
526 
527     #if 0
528     FXVolume = 128;
529     MusicVolume = 128;
530     ReverseStereo = 0;
531     ControllerType = controltype_keyboardandmouse;
532     lMouseSens = 8;
533     #endif
534 }
535 
CONFIG_ReadSetup()536 int CONFIG_ReadSetup()
537 {
538     //char tempbuf[1024];
539 
540     CONTROL_ClearAssignments();
541     CONFIG_SetDefaults();
542 
543     setupread = 1;
544     pathsearchmode = 1;
545 
546     if (scripthandle < 0)
547     {
548         if (buildvfs_exists(setupfilename))  // JBF 20031211
549             scripthandle = SCRIPT_Load(setupfilename);
550         else if (buildvfs_exists(kSetupFilename))
551         {
552             int const i = wm_ynbox("Import Configuration Settings",
553                 "The configuration file \"%s\" was not found. "
554                 "Import configuration data from \"%s\"?",
555                 setupfilename, kSetupFilename);
556             if (i)
557                 scripthandle = SCRIPT_Load(kSetupFilename);
558         }
559     }
560 
561     pathsearchmode = 0;
562 
563     if (scripthandle < 0)
564         return -1;
565 
566     SCRIPT_GetNumber(scripthandle, "Options", "Difficulty", &difficulty);
567 // TODO    SCRIPT_GetNumber(scripthandle, "Options", "Brightness", &gbrightness);
568 
569     SCRIPT_GetNumber(scripthandle, "Setup", "ForceSetup", &gSetup.forcesetup);
570     SCRIPT_GetNumber(scripthandle, "Setup", "NoAutoLoad", &gSetup.noautoload);
571 
572     int32_t cachesize;
573     SCRIPT_GetNumber(scripthandle, "Setup", "CacheSize", &cachesize);
574 
575     if (cachesize > MAXCACHE1DSIZE)
576         MAXCACHE1DSIZE = cachesize;
577 
578 
579     if (g_noSetup == 0 && g_modDir[0] == '/')
580     {
581         SCRIPT_GetString(scripthandle, "Setup", "ModDir", &g_modDir[0]);
582 
583         if (!buildvfs_isdir(g_modDir))
584         {
585             initprintf("Invalid mod dir in cfg!\n");
586             Bsprintf(g_modDir, "/");
587         }
588     }
589 
590     windowx = -1;
591     windowy = -1;
592 
593     SCRIPT_GetNumber(scripthandle, "Screen Setup", "MaxRefreshFreq", (int32_t*)&maxrefreshfreq);
594     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenBPP", &gSetup.bpp);
595     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenHeight", &gSetup.ydim);
596     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenMode", &gSetup.fullscreen);
597     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenWidth", &gSetup.xdim);
598     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPosX", (int32_t*)&windowx);
599     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPosY", (int32_t*)&windowy);
600     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPositioning", (int32_t*)&windowpos);
601 
602     if (gSetup.bpp < 8) gSetup.bpp = 32;
603 
604     setupread = 1;
605     return 0;
606 }
607 
608 // wrapper for CONTROL_MapKey(), generates key bindings to reflect changes to keyboard setup
CONFIG_MapKey(int which,kb_scancode key1,kb_scancode oldkey1,kb_scancode key2,kb_scancode oldkey2)609 void CONFIG_MapKey(int which, kb_scancode key1, kb_scancode oldkey1, kb_scancode key2, kb_scancode oldkey2)
610 {
611     char tempbuf[256];
612     int const keys[] = {key1, key2, oldkey1, oldkey2};
613     char buf[2 * kMaxGameFuncLen];
614 
615     if (which == gamefunc_Show_Console)
616         OSD_CaptureKey(key1);
617 
618     for (int k = 0; (unsigned)k < ARRAY_SIZE(keys); k++)
619     {
620         if (keys[k] == 0xff || !keys[k])
621             continue;
622 
623         int match = 0;
624 
625         for (; match < ARRAY_SSIZE(sctokeylut); ++match)
626         {
627             if (keys[k] == sctokeylut[match].sc)
628                 break;
629         }
630 
631         tempbuf[0] = 0;
632 
633         for (int i = kMaxGameFunctions - 1; i >= 0; i--)
634         {
635             if (KeyboardKeys[i][0] == keys[k] || KeyboardKeys[i][1] == keys[k])
636             {
637                 Bsprintf(buf, "gamefunc_%s; ", CONFIG_FunctionNumToName(i));
638                 Bstrcat(tempbuf, buf);
639             }
640         }
641 
642         int const len = Bstrlen(tempbuf);
643 
644         if (len >= 2)
645         {
646             tempbuf[len - 2] = 0;  // cut off the trailing "; "
647             CONTROL_BindKey(keys[k], tempbuf, 1, sctokeylut[match].key?sctokeylut[match].key:"<?>");
648         }
649         else
650         {
651             CONTROL_FreeKeyBind(keys[k]);
652         }
653     }
654 }
655 
656 
CONFIG_SetupMouse(void)657 void CONFIG_SetupMouse(void)
658 {
659     if (scripthandle < 0)
660         return;
661 
662     char str[80];
663     char temp[80];
664 
665     for (int i = 0; i < MAXMOUSEBUTTONS; i++)
666     {
667         Bsprintf(str, "MouseButton%d", i);
668         temp[0] = 0;
669         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
670             MouseFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
671 
672         Bsprintf(str, "MouseButtonClicked%d", i);
673         temp[0] = 0;
674         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
675             MouseFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
676     }
677 
678     // map over the axes
679     for (int i = 0; i < MAXMOUSEAXES; i++)
680     {
681         Bsprintf(str, "MouseAnalogAxes%d", i);
682         temp[0] = 0;
683         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
684             MouseAnalogueAxes[i] = CONFIG_AnalogNameToNum(temp);
685 
686         Bsprintf(str, "MouseDigitalAxes%d_0", i);
687         temp[0] = 0;
688         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
689             MouseDigitalFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
690 
691         Bsprintf(str, "MouseDigitalAxes%d_1", i);
692         temp[0] = 0;
693         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
694             MouseDigitalFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
695 
696         Bsprintf(str, "MouseAnalogScale%d", i);
697         int32_t scale = MouseAnalogueScale[i];
698         SCRIPT_GetNumber(scripthandle, "Controls", str, &scale);
699         MouseAnalogueScale[i] = scale;
700     }
701 
702     for (int i = 0; i < MAXMOUSEBUTTONS; i++)
703     {
704         CONTROL_MapButton(MouseFunctions[i][0], i, 0, controldevice_mouse);
705         CONTROL_MapButton(MouseFunctions[i][1], i, 1, controldevice_mouse);
706     }
707     for (int i = 0; i < MAXMOUSEAXES; i++)
708     {
709         CONTROL_MapAnalogAxis(i, MouseAnalogueAxes[i], controldevice_mouse);
710         CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][0], 0, controldevice_mouse);
711         CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][1], 1, controldevice_mouse);
712         CONTROL_SetAnalogAxisScale(i, MouseAnalogueScale[i], controldevice_mouse);
713     }
714 }
715 
716 
CONFIG_SetupJoystick(void)717 void CONFIG_SetupJoystick(void)
718 {
719     int32_t i;
720     char str[80];
721     char temp[80];
722     int32_t scale;
723 
724     if (scripthandle < 0) return;
725 
726     for (i = 0; i < MAXJOYBUTTONSANDHATS; i++)
727     {
728         Bsprintf(str, "ControllerButton%d", i);
729         temp[0] = 0;
730         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
731             JoystickFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
732 
733         Bsprintf(str, "ControllerButtonClicked%d", i);
734         temp[0] = 0;
735         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
736             JoystickFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
737     }
738 
739     // map over the axes
740     for (i = 0; i < MAXJOYAXES; i++)
741     {
742         Bsprintf(str, "ControllerAnalogAxes%d", i);
743         temp[0] = 0;
744         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
745             JoystickAnalogueAxes[i] = CONFIG_AnalogNameToNum(temp);
746 
747         Bsprintf(str, "ControllerDigitalAxes%d_0", i);
748         temp[0] = 0;
749         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
750             JoystickDigitalFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
751 
752         Bsprintf(str, "ControllerDigitalAxes%d_1", i);
753         temp[0] = 0;
754         if (!SCRIPT_GetString(scripthandle, "Controls", str, temp))
755             JoystickDigitalFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
756 
757         Bsprintf(str, "ControllerAnalogScale%d", i);
758         scale = JoystickAnalogueScale[i];
759         SCRIPT_GetNumber(scripthandle, "Controls", str, &scale);
760         JoystickAnalogueScale[i] = scale;
761 
762         Bsprintf(str, "ControllerAnalogInvert%d", i);
763         scale = JoystickAnalogueInvert[i];
764         SCRIPT_GetNumber(scripthandle, "Controls", str, &scale);
765         JoystickAnalogueInvert[i] = scale;
766 
767         Bsprintf(str, "ControllerAnalogDead%d", i);
768         scale = JoystickAnalogueDead[i];
769         SCRIPT_GetNumber(scripthandle, "Controls", str, &scale);
770         JoystickAnalogueDead[i] = scale;
771 
772         Bsprintf(str, "ControllerAnalogSaturate%d", i);
773         scale = JoystickAnalogueSaturate[i];
774         SCRIPT_GetNumber(scripthandle, "Controls", str, &scale);
775         JoystickAnalogueSaturate[i] = scale;
776     }
777 
778     for (i = 0; i < MAXJOYBUTTONSANDHATS; i++)
779     {
780         CONTROL_MapButton(JoystickFunctions[i][0], i, 0, controldevice_joystick);
781         CONTROL_MapButton(JoystickFunctions[i][1], i, 1, controldevice_joystick);
782     }
783     for (i = 0; i < MAXJOYAXES; i++)
784     {
785         CONTROL_MapAnalogAxis(i, JoystickAnalogueAxes[i], controldevice_joystick);
786         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][0], 0, controldevice_joystick);
787         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][1], 1, controldevice_joystick);
788         CONTROL_SetAnalogAxisScale(i, JoystickAnalogueScale[i], controldevice_joystick);
789         CONTROL_SetAnalogAxisInvert(i, JoystickAnalogueInvert[i], controldevice_joystick);
790     }
791 }
792 
SetupInput()793 void SetupInput()
794 {
795     if (CONTROL_Startup(controltype_keyboardandmouse, &BGetTime, CLKIPS))
796     {
797         ERRprintf("There was an error initializing the CONTROL system.\n");
798         engineUnInit();
799         Bexit(5);
800     }
801     SetupGameButtons();
802     CONFIG_SetupMouse();
803     CONFIG_SetupJoystick();
804 
805     CONTROL_JoystickEnabled = (gSetup.usejoystick && CONTROL_JoyPresent);
806     CONTROL_MouseEnabled = (gSetup.usemouse && CONTROL_MousePresent);
807 
808     // JBF 20040215: evil and nasty place to do this, but joysticks are evil and nasty too
809     for (int i = 0; i < joystick.numAxes; i++)
810         joySetDeadZone(i, JoystickAnalogueDead[i], JoystickAnalogueSaturate[i]);
811 }
812 
CONFIG_WriteSettings(void)813 void CONFIG_WriteSettings(void) // save binds and aliases to <cfgname>_settings.cfg
814 {
815     char filename[BMAX_PATH];
816 
817 /*
818     if (!Bstrcmp(setupfilename, kSetupFilename))
819         Bsprintf(filename, "settings.cfg");
820     else
821         Bsprintf(filename, "%s_settings.cfg", strtok(setupfilename, "."));
822 */
823 
824     Bsprintf(filename, "etekwar_cvars.cfg");
825     buildvfs_FILE fp = buildvfs_fopen_write(filename);
826 
827     if (fp)
828     {
829         buildvfs_fputstr(fp, "// this file is automatically generated by ");
830         buildvfs_fputstrptr(fp, AppProperName);
831         buildvfs_fputstr(fp, "\nunbindall\n");
832 
833         for (int i = 0; i < MAXBOUNDKEYS + MAXMOUSEBUTTONS; i++)
834         {
835             if (CONTROL_KeyIsBound(i))
836             {
837                 buildvfs_fputstr(fp, "bind \"");
838                 buildvfs_fputstrptr(fp, CONTROL_KeyBinds[i].key);
839                 if (CONTROL_KeyBinds[i].repeat)
840                     buildvfs_fputstr(fp, "\" \"");
841                 else
842                     buildvfs_fputstr(fp, "\" norepeat \"");
843                 buildvfs_fputstrptr(fp, CONTROL_KeyBinds[i].cmdstr);
844                 buildvfs_fputstr(fp, "\"\n");
845             }
846         }
847 
848         for (int i = 0; i < kMaxGameFunctions; ++i)
849         {
850             char const* name = CONFIG_FunctionNumToName(i);
851             if (name && name[0] != '\0' && (KeyboardKeys[i][0] == 0xff || !KeyboardKeys[i][0]))
852             {
853                 buildvfs_fputstr(fp, "unbound ");
854                 buildvfs_fputstrptr(fp, name);
855                 buildvfs_fputstr(fp, "\n");
856             }
857         }
858 
859         OSD_WriteAliases(fp);
860 
861         //if (g_crosshairSum != -1 && g_crosshairSum != DefaultCrosshairColors.r+(DefaultCrosshairColors.g<<8)+(DefaultCrosshairColors.b<<16))
862         //{
863         //    buildvfs_fputstr(fp, "crosshaircolor ");
864         //    char buf[64];
865         //    snprintf(buf, sizeof(buf), "%d %d %d\n", CrosshairColors.r, CrosshairColors.g, CrosshairColors.b);
866         //    buildvfs_fputstrptr(fp, buf);
867         //}
868 
869         OSD_WriteCvars(fp);
870 
871         buildvfs_fclose(fp);
872 
873         OSD_Printf("Wrote %s\n", filename);
874 
875         return;
876     }
877 
878     OSD_Printf("Error writing %s: %s\n", filename, strerror(errno));
879 }
880 
CONFIG_WriteSetup(uint32_t flags)881 void CONFIG_WriteSetup(uint32_t flags)
882 {
883     char buf[256];
884     if (!setupread) return;
885 
886     if (scripthandle < 0)
887         scripthandle = SCRIPT_Init(setupfilename);
888 
889     SCRIPT_PutNumber(scripthandle, "Options", "Difficulty", difficulty, FALSE, 2);
890 // TODO    SCRIPT_PutNumber(scripthandle, "Options", "Brightness", gbrightness, FALSE, 0);
891 
892     SCRIPT_PutNumber(scripthandle, "Setup", "CacheSize", MAXCACHE1DSIZE, FALSE, FALSE);
893     //SCRIPT_PutNumber(scripthandle, "Setup", "ConfigVersion", BYTEVERSION_EDUKE32, FALSE, FALSE);
894     SCRIPT_PutNumber(scripthandle, "Setup", "ForceSetup", gSetup.forcesetup, FALSE, FALSE);
895     SCRIPT_PutNumber(scripthandle, "Setup", "NoAutoLoad", gSetup.noautoload, FALSE, FALSE);
896 
897     //#ifdef POLYMER
898     //    SCRIPT_PutNumber(ud.config.scripthandle, "Screen Setup", "Polymer", glrendmode == REND_POLYMER, FALSE, FALSE);
899     //#endif
900 
901     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenBPP", gSetup.bpp, FALSE, FALSE);
902     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenHeight", gSetup.ydim, FALSE, FALSE);
903     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenMode", gSetup.fullscreen, FALSE, FALSE);
904     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenWidth", gSetup.xdim, FALSE, FALSE);
905 
906     //if (g_grpNamePtr && !g_addonNum)
907     //    SCRIPT_PutString(ud.config.scripthandle, "Setup", "SelectedGRP", g_grpNamePtr);
908 
909     #ifdef STARTUP_SETUP_WINDOW
910     if (g_noSetup == 0)
911         SCRIPT_PutString(scripthandle, "Setup", "ModDir", &g_modDir[0]);
912     #endif
913     // exit early after only updating the values that can be changed from the startup window
914     if (flags & 1)
915     {
916         SCRIPT_Save(scripthandle, setupfilename);
917         SCRIPT_Free(scripthandle);
918         return;
919     }
920 
921     SCRIPT_PutNumber(scripthandle, "Screen Setup", "MaxRefreshFreq", maxrefreshfreq, FALSE, FALSE);
922     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPosX", windowx, FALSE, FALSE);
923     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPosY", windowy, FALSE, FALSE);
924     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPositioning", windowpos, FALSE, FALSE);
925 
926     //if (!NAM_WW2GI)
927     //{
928     //    SCRIPT_PutNumber(ud.config.scripthandle, "Screen Setup", "Out",ud.lockout,FALSE,FALSE);
929     //    SCRIPT_PutString(ud.config.scripthandle, "Screen Setup", "Password",ud.pwlockout);
930     //}
931 
932 //#ifdef _WIN32
933 //    SCRIPT_PutNumber(ud.config.scripthandle, "Updates", "CheckForUpdates", ud.config.CheckForUpdates, FALSE, FALSE);
934 //    SCRIPT_PutNumber(ud.config.scripthandle, "Updates", "LastUpdateCheck", ud.config.LastUpdateCheck, FALSE, FALSE);
935 //#endif
936 
937     if (gSetup.usemouse)
938     {
939         for (int i = 0; i < MAXMOUSEBUTTONS; i++)
940         {
941             if (CONFIG_FunctionNumToName(MouseFunctions[i][0]))
942             {
943                 Bsprintf(buf, "MouseButton%d", i);
944                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseFunctions[i][0]));
945             }
946 
947             if (i >= (MAXMOUSEBUTTONS - 2)) continue;
948 
949             if (CONFIG_FunctionNumToName(MouseFunctions[i][1]))
950             {
951                 Bsprintf(buf, "MouseButtonClicked%d", i);
952                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseFunctions[i][1]));
953             }
954         }
955 
956         for (int i = 0; i < MAXMOUSEAXES; i++)
957         {
958             if (CONFIG_AnalogNumToName(MouseAnalogueAxes[i]))
959             {
960                 Bsprintf(buf, "MouseAnalogAxes%d", i);
961                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_AnalogNumToName(MouseAnalogueAxes[i]));
962             }
963 
964             if (CONFIG_FunctionNumToName(MouseDigitalFunctions[i][0]))
965             {
966                 Bsprintf(buf, "MouseDigitalAxes%d_0", i);
967                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseDigitalFunctions[i][0]));
968             }
969 
970             if (CONFIG_FunctionNumToName(MouseDigitalFunctions[i][1]))
971             {
972                 Bsprintf(buf, "MouseDigitalAxes%d_1", i);
973                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseDigitalFunctions[i][1]));
974             }
975 
976             Bsprintf(buf, "MouseAnalogScale%d", i);
977             SCRIPT_PutNumber(scripthandle, "Controls", buf, MouseAnalogueScale[i], FALSE, FALSE);
978         }
979     }
980 
981     if (gSetup.usejoystick)
982     {
983         for (int dummy = 0; dummy < MAXJOYBUTTONSANDHATS; dummy++)
984         {
985             if (CONFIG_FunctionNumToName(JoystickFunctions[dummy][0]))
986             {
987                 Bsprintf(buf, "ControllerButton%d", dummy);
988                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickFunctions[dummy][0]));
989             }
990 
991             if (CONFIG_FunctionNumToName(JoystickFunctions[dummy][1]))
992             {
993                 Bsprintf(buf, "ControllerButtonClicked%d", dummy);
994                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickFunctions[dummy][1]));
995             }
996         }
997         for (int dummy = 0; dummy < MAXJOYAXES; dummy++)
998         {
999             if (CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy]))
1000             {
1001                 Bsprintf(buf, "ControllerAnalogAxes%d", dummy);
1002                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy]));
1003             }
1004 
1005             if (CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][0]))
1006             {
1007                 Bsprintf(buf, "ControllerDigitalAxes%d_0", dummy);
1008                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][0]));
1009             }
1010 
1011             if (CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][1]))
1012             {
1013                 Bsprintf(buf, "ControllerDigitalAxes%d_1", dummy);
1014                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][1]));
1015             }
1016 
1017             Bsprintf(buf, "ControllerAnalogScale%d", dummy);
1018             SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueScale[dummy], FALSE, FALSE);
1019 
1020             Bsprintf(buf, "ControllerAnalogInvert%d", dummy);
1021             SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueInvert[dummy], FALSE, FALSE);
1022 
1023             Bsprintf(buf, "ControllerAnalogDead%d", dummy);
1024             SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueDead[dummy], FALSE, FALSE);
1025 
1026             Bsprintf(buf, "ControllerAnalogSaturate%d", dummy);
1027             SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueSaturate[dummy], FALSE, FALSE);
1028         }
1029     }
1030 
1031     //SCRIPT_PutString(ud.config.scripthandle, "Comm Setup","PlayerName",&szPlayerName[0]);
1032 
1033     //SCRIPT_PutString(ud.config.scripthandle, "Comm Setup","RTSName",&ud.rtsname[0]);
1034 
1035  //   char commmacro[] = "CommbatMacro# ";
1036 
1037     //for (int dummy = 0; dummy < MAXRIDECULE; dummy++)
1038     //{
1039     //    commmacro[13] = dummy+'0';
1040     //    SCRIPT_PutString(ud.config.scripthandle, "Comm Setup",commmacro,&ud.ridecule[dummy][0]);
1041     //}
1042 
1043     SCRIPT_Save(scripthandle, setupfilename);
1044 
1045     if ((flags & 2) == 0)
1046         SCRIPT_Free(scripthandle);
1047 
1048     OSD_Printf("Wrote %s\n", setupfilename);
1049     CONFIG_WriteSettings();
1050     Bfflush(NULL);
1051 }
1052