1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5 
6 This file is part of NBlood.
7 
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 
24 #include "baselayer.h"
25 #include "common_game.h"
26 #include "build.h"
27 #include "cache1d.h"
28 #include "sndcards.h"
29 #include "hash.h"
30 #include "scriplib.h"
31 #include "renderlayer.h"
32 #include "function.h"
33 #include "blood.h"
34 #include "config.h"
35 #include "gamedefs.h"
36 #include "globals.h"
37 #include "screen.h"
38 #include "sound.h"
39 #include "tile.h"
40 #include "view.h"
41 
42 #ifdef __ANDROID__
43 # include "android.h"
44 #endif
45 
46 #if defined RENDERTYPESDL && defined SDL_TARGET && SDL_TARGET > 1
47 # include "sdl_inc.h"
48 #endif
49 
50 // we load this in to get default button and key assignments
51 // as well as setting up function mappings
52 
53 #define __SETUP__   // JBF 20031211
54 #include "_functio.h"
55 
56 hashtable_t h_gamefuncs    = { NUMGAMEFUNCTIONS<<1, NULL };
57 
58 int32_t MouseDeadZone, MouseBias;
59 int32_t MouseFunctions[MAXMOUSEBUTTONS][2];
60 int32_t MouseAnalogueAxes[MAXMOUSEAXES];
61 int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2];
62 int32_t JoystickDigitalFunctions[MAXJOYAXES][2];
63 int32_t JoystickAnalogueAxes[MAXJOYAXES];
64 int32_t JoystickAnalogueScale[MAXJOYAXES];
65 int32_t JoystickAnalogueDead[MAXJOYAXES];
66 int32_t JoystickAnalogueSaturate[MAXJOYAXES];
67 uint8_t KeyboardKeys[NUMGAMEFUNCTIONS][2];
68 int32_t scripthandle;
69 int32_t setupread;
70 int32_t MusicRestartsOnLoadToggle;
71 int32_t configversion;
72 int32_t CheckForUpdates;
73 int32_t LastUpdateCheck;
74 int32_t useprecache;
75 char CommbatMacro[MAXRIDECULE][MAXRIDECULELENGTH];
76 char szPlayerName[MAXPLAYERNAME];
77 int32_t gTurnSpeed;
78 int32_t gDetail;
79 int32_t gMouseAim;
80 int32_t gAutoAim;
81 int32_t gWeaponSwitch;
82 int32_t gAutoRun;
83 int32_t gViewInterpolate;
84 int32_t gViewHBobbing;
85 int32_t gViewVBobbing;
86 int32_t gFollowMap;
87 int32_t gOverlayMap;
88 int32_t gRotateMap;
89 int32_t gAimReticle;
90 int32_t gSlopeTilting;
91 int32_t gMessageState;
92 int32_t gMessageCount;
93 int32_t gMessageTime;
94 int32_t gMessageFont;
95 int32_t gbAdultContent;
96 char gzAdultPassword[9];
97 int32_t gDoppler;
98 int32_t gShowPlayerNames;
99 int32_t gShowWeapon;
100 int32_t gMouseSensitivity;
101 int32_t gMouseAiming;
102 int32_t gMouseAimingFlipped;
103 int32_t gRunKeyMode;
104 bool gNoClip;
105 bool gInfiniteAmmo;
106 bool gFullMap;
107 int32_t gUpscaleFactor;
108 int32_t gLevelStats;
109 int32_t gPowerupDuration;
110 int32_t gShowMapTitle;
111 int32_t gFov;
112 int32_t gCenterHoriz;
113 int32_t gDeliriumBlur;
114 
115 //////////
116 int gWeaponsV10x;
117 /////////
118 
CONFIG_FunctionNameToNum(const char * func)119 int32_t CONFIG_FunctionNameToNum(const char *func)
120 {
121     int32_t i;
122 
123     if (!func)
124         return -1;
125 
126     i = hash_find(&h_gamefuncs,func);
127 
128     if (i < 0)
129     {
130         char *str = Bstrtolower(Xstrdup(func));
131         i = hash_find(&h_gamefuncs,str);
132         Bfree(str);
133 
134         return i;
135     }
136 
137     return i;
138 }
139 
140 
CONFIG_FunctionNumToName(int32_t func)141 char *CONFIG_FunctionNumToName(int32_t func)
142 {
143     if ((unsigned)func >= (unsigned)NUMGAMEFUNCTIONS)
144         return NULL;
145     return gamefunctions[func];
146 }
147 
148 
CONFIG_AnalogNameToNum(const char * func)149 int32_t CONFIG_AnalogNameToNum(const char *func)
150 {
151     if (!func)
152         return -1;
153 
154     if (!Bstrcasecmp(func,"analog_turning"))
155     {
156         return analog_turning;
157     }
158     if (!Bstrcasecmp(func,"analog_strafing"))
159     {
160         return analog_strafing;
161     }
162     if (!Bstrcasecmp(func,"analog_moving"))
163     {
164         return analog_moving;
165     }
166     if (!Bstrcasecmp(func,"analog_lookingupanddown"))
167     {
168         return analog_lookingupanddown;
169     }
170 
171     return -1;
172 }
173 
174 
CONFIG_AnalogNumToName(int32_t func)175 const char *CONFIG_AnalogNumToName(int32_t func)
176 {
177     switch (func)
178     {
179     case analog_turning:
180         return "analog_turning";
181     case analog_strafing:
182         return "analog_strafing";
183     case analog_moving:
184         return "analog_moving";
185     case analog_lookingupanddown:
186         return "analog_lookingupanddown";
187     }
188 
189     return NULL;
190 }
191 
192 
CONFIG_SetDefaultKeys(const char (* keyptr)[MAXGAMEFUNCLEN],bool lazy)193 void CONFIG_SetDefaultKeys(const char (*keyptr)[MAXGAMEFUNCLEN], bool lazy/*=false*/)
194 {
195     static char const s_gamefunc_[] = "gamefunc_";
196     int constexpr strlen_gamefunc_ = ARRAY_SIZE(s_gamefunc_) - 1;
197 
198     if (!lazy)
199     {
200         Bmemset(KeyboardKeys, 0xff, sizeof(KeyboardKeys));
201         CONTROL_ClearAllBinds();
202     }
203 
204     for (int i=0; i < ARRAY_SSIZE(gamefunctions); ++i)
205     {
206         if (gamefunctions[i][0] == '\0')
207             continue;
208 
209         auto &key = KeyboardKeys[i];
210 
211         int const default0 = KB_StringToScanCode(keyptr[i<<1]);
212         int const default1 = KB_StringToScanCode(keyptr[(i<<1)+1]);
213 
214         // skip the function if the default key is already used
215         // or the function is assigned to another key
216         if (lazy && (key[0] != 0xff || (CONTROL_KeyIsBound(default0) && Bstrlen(CONTROL_KeyBinds[default0].cmdstr) > strlen_gamefunc_
217                         && CONFIG_FunctionNameToNum(CONTROL_KeyBinds[default0].cmdstr + strlen_gamefunc_) >= 0)))
218         {
219 #if 0 // defined(DEBUGGINGAIDS)
220             if (key[0] != 0xff)
221                 initprintf("Skipping %s bound to %s\n", keyptr[i<<1], CONTROL_KeyBinds[default0].cmdstr);
222 #endif
223             continue;
224         }
225 
226         key[0] = default0;
227         key[1] = default1;
228 
229         if (key[0])
230             CONTROL_FreeKeyBind(key[0]);
231 
232         if (key[1])
233             CONTROL_FreeKeyBind(key[1]);
234 
235         if (i == gamefunc_Show_Console)
236             OSD_CaptureKey(key[0]);
237         else
238             CONFIG_MapKey(i, key[0], 0, key[1], 0);
239     }
240 }
241 
242 
CONFIG_SetDefaults(void)243 void CONFIG_SetDefaults(void)
244 {
245     scripthandle = -1;
246 
247 #ifdef __ANDROID__
248     droidinput.forward_sens = 5.f;
249     droidinput.gameControlsAlpha = 0.5;
250     droidinput.hideStick = 0;
251     droidinput.pitch_sens = 5.f;
252     droidinput.quickSelectWeapon = 1;
253     droidinput.strafe_sens = 5.f;
254     droidinput.toggleCrouch = 1;
255     droidinput.yaw_sens = 5.f;
256 
257     gSetup.xdim = droidinfo.screen_width;
258     gSetup.ydim = droidinfo.screen_height;
259 #else
260 # if defined RENDERTYPESDL && SDL_MAJOR_VERSION > 1
261     uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO);
262     if (inited == 0)
263         SDL_Init(SDL_INIT_VIDEO);
264     else if (!(inited & SDL_INIT_VIDEO))
265         SDL_InitSubSystem(SDL_INIT_VIDEO);
266 
267     SDL_DisplayMode dm;
268     if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
269     {
270         gSetup.xdim = dm.w;
271         gSetup.ydim = dm.h;
272     }
273     else
274 # endif
275     {
276         gSetup.xdim = 1024;
277         gSetup.ydim = 768;
278     }
279 #endif
280 
281 #ifdef USE_OPENGL
282     gSetup.bpp = 32;
283 #else
284     gSetup.bpp = 8;
285 #endif
286 
287 #if defined(_WIN32)
288     MixRate = 44100;
289 #elif defined __ANDROID__
290     MixRate = droidinfo.audio_sample_rate;
291 #else
292     MixRate = 48000;
293 #endif
294 
295 #if defined GEKKO || defined __OPENDINGUX__
296     NumVoices = 32;
297 #else
298     NumVoices = 64;
299 #endif
300 
301 #ifdef GEKKO
302     gSetup.usejoystick = 1;
303 #else
304     gSetup.usejoystick = 0;
305 #endif
306 
307     gSetup.forcesetup       = 1;
308     gSetup.noautoload       = 1;
309     gSetup.fullscreen       = 1;
310     gSetup.usemouse         = 1;
311 
312     //ud.config.AmbienceToggle  = 1;
313     //ud.config.AutoAim         = 1;
314     CheckForUpdates = 1;
315     FXVolume        = 255;
316     MouseBias       = 0;
317     MouseDeadZone   = 0;
318     MusicToggle     = 1;
319     MusicRestartsOnLoadToggle = 0;
320     MusicVolume     = 195;
321     NumBits         = 16;
322     NumChannels     = 2;
323 #ifdef ASS_REVERSESTEREO
324     ReverseStereo   = 0;
325 #endif
326     gBrightness = 8;
327     //ud.config.ShowWeapons     = 0;
328     SoundToggle     = 1;
329     CDAudioToggle = 0;
330     MusicDevice = ASS_AutoDetect;
331     //ud.config.VoiceToggle     = 5;  // bitfield, 1 = local, 2 = dummy, 4 = other players in DM
332     useprecache     = 1;
333     configversion          = 0;
334     //ud.crosshair              = 1;
335     //ud.crosshairscale         = 50;
336     //ud.default_skill          = 1;
337     //ud.democams               = 1;
338     gUpscaleFactor = 0;
339     //ud.display_bonus_screen   = 1;
340     //ud.drawweapon             = 1;
341     //ud.hudontop               = 0;
342     //ud.idplayers              = 1;
343     gLevelStats = 0;
344     gPowerupDuration = 1;
345     gShowMapTitle = 1;
346     //ud.lockout                = 0;
347     //ud.m_marker               = 1;
348     //ud.maxautosaves           = 5;
349     //ud.menu_scrollbartilenum  = -1;
350     //ud.menu_scrollbarz        = 65536;
351     //ud.menu_scrollcursorz     = 65536;
352     //ud.menu_slidebarmargin    = 65536;
353     //ud.menu_slidebarz         = 65536;
354     //ud.menu_slidecursorz      = 65536;
355     //ud.menubackground         = 1;
356     //ud.mouseaiming            = 0;
357     //ud.mouseflip              = 1;
358     //ud.msgdisptime            = 120;
359     //ud.obituaries             = 1;
360     //ud.pwlockout[0]           = '\0';
361     gRunKeyMode            = 0;
362     //ud.screen_size            = 4;
363     //ud.screen_tilting         = 1;
364     //ud.screenfade             = 1;
365     //ud.shadow_pal             = 4;
366     //ud.shadows                = 1;
367     //ud.show_level_text        = 1;
368     //ud.slidebar_paldisabled   = 1;
369     //ud.statusbarflags         = STATUSBAR_NOSHRINK;
370     //ud.statusbarmode          = 1;
371     //ud.statusbarscale         = 100;
372     //ud.team                   = 0;
373     //ud.textscale              = 200;
374     //ud.viewbob                = 1;
375     //ud.weaponscale            = 100;
376     //ud.weaponsway             = 1;
377     //ud.weaponswitch           = 3;  // new+empty
378     gFov = 90;
379     gCenterHoriz = 0;
380     gDeliriumBlur = 1;
381     gViewSize = 2;
382     gTurnSpeed = 92;
383     gDetail = 4;
384     gAutoRun = 0;
385     gViewInterpolate = 1;
386     gViewHBobbing = 1;
387     gViewVBobbing = 1;
388     gFollowMap = 1;
389     gOverlayMap = 0;
390     gRotateMap = 0;
391     gAimReticle = 0;
392     gSlopeTilting = 0;
393     gMessageState = 1;
394     gMessageCount = 4;
395     gMessageTime = 5;
396     gMessageFont = 0;
397     gbAdultContent = 0;
398     gDoppler = 1;
399     gShowPlayerNames = 0;
400     gShowWeapon = 0;
401     gzAdultPassword[0] = 0;
402 
403     gMouseAimingFlipped = 0;
404     gMouseAim = 1;
405     gAutoAim = 1;
406     gWeaponSwitch = 1;
407 
408     Bstrcpy(szPlayerName, "Player");
409 
410     Bstrcpy(CommbatMacro[0], "I love the smell of napalm...");
411     Bstrcpy(CommbatMacro[1], "Is that gasoline I smell?");
412     Bstrcpy(CommbatMacro[2], "Ta da!");
413     Bstrcpy(CommbatMacro[3], "Who wants some, huh? Who's next?");
414     Bstrcpy(CommbatMacro[4], "I have something for you.");
415     Bstrcpy(CommbatMacro[5], "You just gonna stand there...");
416     Bstrcpy(CommbatMacro[6], "That'll teach ya!");
417     Bstrcpy(CommbatMacro[7], "Ooh, that wasn't a bit nice.");
418     Bstrcpy(CommbatMacro[8], "Amateurs!");
419     Bstrcpy(CommbatMacro[9], "Fool! You are already dead.");
420 
421     CONFIG_SetDefaultKeys(keydefaults);
422 
423     memset(MouseFunctions, -1, sizeof(MouseFunctions));
424     memset(JoystickFunctions, -1, sizeof(JoystickFunctions));
425     memset(JoystickDigitalFunctions, -1, sizeof(JoystickDigitalFunctions));
426 
427     CONTROL_MouseSensitivity = DEFAULTMOUSESENSITIVITY;
428 
429     for (int i=0; i<MAXMOUSEBUTTONS; i++)
430     {
431         MouseFunctions[i][0] = CONFIG_FunctionNameToNum(mousedefaults[i]);
432         CONTROL_MapButton(MouseFunctions[i][0], i, 0, controldevice_mouse);
433         if (i>=4) continue;
434         MouseFunctions[i][1] = CONFIG_FunctionNameToNum(mouseclickeddefaults[i]);
435         CONTROL_MapButton(MouseFunctions[i][1], i, 1, controldevice_mouse);
436     }
437 
438     for (int i=0; i<MAXMOUSEAXES; i++)
439     {
440         CONTROL_SetAnalogAxisScale(i, DEFAULTMOUSEANALOGUESCALE, controldevice_mouse);
441 
442         MouseAnalogueAxes[i] = CONFIG_AnalogNameToNum(mouseanalogdefaults[i]);
443         CONTROL_MapAnalogAxis(i, MouseAnalogueAxes[i], controldevice_mouse);
444     }
445 
446     for (int i=0; i<MAXJOYBUTTONSANDHATS; i++)
447     {
448         JoystickFunctions[i][0] = CONFIG_FunctionNameToNum(joystickdefaults[i]);
449         JoystickFunctions[i][1] = CONFIG_FunctionNameToNum(joystickclickeddefaults[i]);
450         CONTROL_MapButton(JoystickFunctions[i][0], i, 0, controldevice_joystick);
451         CONTROL_MapButton(JoystickFunctions[i][1], i, 1, controldevice_joystick);
452     }
453 
454     for (int i=0; i<MAXJOYAXES; i++)
455     {
456         JoystickAnalogueScale[i] = DEFAULTJOYSTICKANALOGUESCALE;
457         JoystickAnalogueDead[i] = DEFAULTJOYSTICKANALOGUEDEAD;
458         JoystickAnalogueSaturate[i] = DEFAULTJOYSTICKANALOGUESATURATE;
459         CONTROL_SetAnalogAxisScale(i, JoystickAnalogueScale[i], controldevice_joystick);
460 
461         JoystickDigitalFunctions[i][0] = CONFIG_FunctionNameToNum(joystickdigitaldefaults[i*2]);
462         JoystickDigitalFunctions[i][1] = CONFIG_FunctionNameToNum(joystickdigitaldefaults[i*2+1]);
463         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][0], 0, controldevice_joystick);
464         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][1], 1, controldevice_joystick);
465 
466         JoystickAnalogueAxes[i] = CONFIG_AnalogNameToNum(joystickanalogdefaults[i]);
467         CONTROL_MapAnalogAxis(i, JoystickAnalogueAxes[i], controldevice_joystick);
468     }
469 }
470 
471 
472 // 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)473 void CONFIG_MapKey(int which, kb_scancode key1, kb_scancode oldkey1, kb_scancode key2, kb_scancode oldkey2)
474 {
475     int const keys[] = { key1, key2, oldkey1, oldkey2 };
476     char buf[2*MAXGAMEFUNCLEN];
477     char tempbuf[128];
478 
479     if (which == gamefunc_Show_Console)
480         OSD_CaptureKey(key1);
481 
482     for (int k = 0; (unsigned)k < ARRAY_SIZE(keys); k++)
483     {
484         if (keys[k] == 0xff || !keys[k])
485             continue;
486 
487         int match = 0;
488 
489         for (; sctokeylut[match].key; match++)
490         {
491             if (keys[k] == sctokeylut[match].sc)
492                 break;
493         }
494 
495         tempbuf[0] = 0;
496 
497         for (int i=NUMGAMEFUNCTIONS-1; i>=0; i--)
498         {
499             if (KeyboardKeys[i][0] == keys[k] || KeyboardKeys[i][1] == keys[k])
500             {
501                 Bsprintf(buf, "gamefunc_%s; ", CONFIG_FunctionNumToName(i));
502                 Bstrcat(tempbuf,buf);
503             }
504         }
505 
506         int const len = Bstrlen(tempbuf);
507 
508         if (len >= 2)
509         {
510             tempbuf[len-2] = 0;  // cut off the trailing "; "
511             CONTROL_BindKey(keys[k], tempbuf, 1, sctokeylut[match].key ? sctokeylut[match].key : "<?>");
512         }
513         else
514         {
515             CONTROL_FreeKeyBind(keys[k]);
516         }
517     }
518 }
519 
520 
CONFIG_SetupMouse(void)521 void CONFIG_SetupMouse(void)
522 {
523     if (scripthandle < 0)
524         return;
525 
526     char str[80];
527     char temp[80];
528 
529     for (int i=0; i<MAXMOUSEBUTTONS; i++)
530     {
531         Bsprintf(str,"MouseButton%d",i);
532         temp[0] = 0;
533         if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
534             MouseFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
535 
536         Bsprintf(str,"MouseButtonClicked%d",i);
537         temp[0] = 0;
538         if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
539             MouseFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
540     }
541 
542     // map over the axes
543     for (int i=0; i<MAXMOUSEAXES; i++)
544     {
545         Bsprintf(str,"MouseAnalogAxes%d",i);
546         temp[0] = 0;
547         if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
548             if (CONFIG_AnalogNameToNum(temp) != -1 || (!temp[0] && CONFIG_FunctionNameToNum(temp) != -1))
549                 MouseAnalogueAxes[i] = CONFIG_AnalogNameToNum(temp);
550     }
551 
552     for (int i=0; i<MAXMOUSEBUTTONS; i++)
553     {
554         CONTROL_MapButton(MouseFunctions[i][0], i, 0, controldevice_mouse);
555         CONTROL_MapButton(MouseFunctions[i][1], i, 1,  controldevice_mouse);
556     }
557     for (int i=0; i<MAXMOUSEAXES; i++)
558         CONTROL_MapAnalogAxis(i, MouseAnalogueAxes[i], controldevice_mouse);
559 }
560 
561 
CONFIG_SetupJoystick(void)562 void CONFIG_SetupJoystick(void)
563 {
564     int32_t i;
565     char str[80];
566     char temp[80];
567     int32_t scale;
568 
569     if (scripthandle < 0) return;
570 
571     for (i=0; i<MAXJOYBUTTONSANDHATS; i++)
572     {
573         Bsprintf(str,"JoystickButton%d",i);
574         temp[0] = 0;
575         if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
576             JoystickFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
577 
578         Bsprintf(str,"JoystickButtonClicked%d",i);
579         temp[0] = 0;
580         if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
581             JoystickFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
582     }
583 
584     // map over the axes
585     for (i=0; i<MAXJOYAXES; i++)
586     {
587         Bsprintf(str,"JoystickAnalogAxes%d",i);
588         temp[0] = 0;
589         if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
590             if (CONFIG_AnalogNameToNum(temp) != -1 || (!temp[0] && CONFIG_FunctionNameToNum(temp) != -1))
591                 JoystickAnalogueAxes[i] = CONFIG_AnalogNameToNum(temp);
592 
593         Bsprintf(str,"JoystickDigitalAxes%d_0",i);
594         temp[0] = 0;
595         if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
596             if (CONFIG_FunctionNameToNum(temp) != -1 || (!temp[0] && CONFIG_FunctionNameToNum(temp) != -1))
597                 JoystickDigitalFunctions[i][0] = CONFIG_FunctionNameToNum(temp);
598 
599         Bsprintf(str,"JoystickDigitalAxes%d_1",i);
600         temp[0] = 0;
601         if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
602             if (CONFIG_FunctionNameToNum(temp) != -1 || (!temp[0] && CONFIG_FunctionNameToNum(temp) != -1))
603                 JoystickDigitalFunctions[i][1] = CONFIG_FunctionNameToNum(temp);
604 
605         Bsprintf(str,"JoystickAnalogScale%d",i);
606         scale = JoystickAnalogueScale[i];
607         SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
608         JoystickAnalogueScale[i] = scale;
609 
610         Bsprintf(str,"JoystickAnalogDead%d",i);
611         scale = JoystickAnalogueDead[i];
612         SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
613         JoystickAnalogueDead[i] = scale;
614 
615         Bsprintf(str,"JoystickAnalogSaturate%d",i);
616         scale = JoystickAnalogueSaturate[i];
617         SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
618         JoystickAnalogueSaturate[i] = scale;
619     }
620 
621     for (i=0; i<MAXJOYBUTTONSANDHATS; i++)
622     {
623         CONTROL_MapButton(JoystickFunctions[i][0], i, 0, controldevice_joystick);
624         CONTROL_MapButton(JoystickFunctions[i][1], i, 1,  controldevice_joystick);
625     }
626     for (i=0; i<MAXJOYAXES; i++)
627     {
628         CONTROL_MapAnalogAxis(i, JoystickAnalogueAxes[i], controldevice_joystick);
629         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][0], 0, controldevice_joystick);
630         CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][1], 1, controldevice_joystick);
631         CONTROL_SetAnalogAxisScale(i, JoystickAnalogueScale[i], controldevice_joystick);
632     }
633 }
634 
635 
CONFIG_ReadSetup(void)636 int CONFIG_ReadSetup(void)
637 {
638     char tempbuf[1024];
639 
640     CONTROL_ClearAssignments();
641     CONFIG_SetDefaults();
642 
643     setupread = 1;
644     pathsearchmode = 1;
645 
646     if (scripthandle < 0)
647     {
648         if (buildvfs_exists(SetupFilename))  // JBF 20031211
649             scripthandle = SCRIPT_Load(SetupFilename);
650 #if !defined(EDUKE32_TOUCH_DEVICES) && !defined(EDUKE32_STANDALONE)
651         else if (buildvfs_exists(SETUPFILENAME))
652         {
653             int const i = wm_ynbox("Import Configuration Settings",
654                                    "The configuration file \"%s\" was not found. "
655                                    "Import configuration data from \"%s\"?",
656                                    SetupFilename, SETUPFILENAME);
657             if (i)
658                 scripthandle = SCRIPT_Load(SETUPFILENAME);
659         }
660 #endif
661     }
662 
663     pathsearchmode = 0;
664 
665     if (scripthandle < 0)
666         return -1;
667 
668     // Nuke: make cvar
669     ///////
670     SCRIPT_GetNumber(scripthandle, "Game Options", "WeaponsV10x", &gWeaponsV10x);
671     ///////
672 
673     char commmacro[] = "CommbatMacro# ";
674 
675     for (int i = 0; i < MAXRIDECULE; i++)
676     {
677         commmacro[13] = i+'0';
678         SCRIPT_GetString(scripthandle, "Comm Setup",commmacro,&CommbatMacro[i][0]);
679     }
680 
681     Bmemset(tempbuf, 0, sizeof(tempbuf));
682     SCRIPT_GetString(scripthandle, "Comm Setup","PlayerName",&tempbuf[0]);
683 
684     char nameBuf[64];
685 
686     while (Bstrlen(OSD_StripColors(nameBuf, tempbuf)) > 10)
687         tempbuf[Bstrlen(tempbuf) - 1] = '\0';
688 
689     Bstrncpyz(szPlayerName, tempbuf, sizeof(szPlayerName));
690 
691     //SCRIPT_GetString(scripthandle, "Comm Setup","RTSName",&ud.rtsname[0]);
692 
693     SCRIPT_GetNumber(scripthandle, "Setup", "ConfigVersion", &configversion);
694     SCRIPT_GetNumber(scripthandle, "Setup", "ForceSetup", &gSetup.forcesetup);
695     SCRIPT_GetNumber(scripthandle, "Setup", "NoAutoLoad", &gSetup.noautoload);
696 
697     int32_t cachesize;
698     SCRIPT_GetNumber(scripthandle, "Setup", "CacheSize", &cachesize);
699 
700     if (cachesize > MAXCACHE1DSIZE)
701         MAXCACHE1DSIZE = cachesize;
702 
703     if (gNoSetup == 0 && g_modDir[0] == '/')
704     {
705         struct Bstat st;
706         SCRIPT_GetString(scripthandle, "Setup","ModDir",&g_modDir[0]);
707 
708         if (Bstat(g_modDir, &st))
709         {
710             if ((st.st_mode & S_IFDIR) != S_IFDIR)
711             {
712                 initprintf("Invalid mod dir in cfg!\n");
713                 Bsprintf(g_modDir,"/");
714             }
715         }
716     }
717 
718     //if (g_grpNamePtr == NULL && g_addonNum == 0)
719     //{
720     //    SCRIPT_GetStringPtr(scripthandle, "Setup", "SelectedGRP", &g_grpNamePtr);
721     //    if (g_grpNamePtr && !Bstrlen(g_grpNamePtr))
722     //        g_grpNamePtr = dup_filename(G_DefaultGrpFile());
723     //}
724     //
725     //if (!NAM_WW2GI)
726     //{
727     //    SCRIPT_GetNumber(scripthandle, "Screen Setup", "Out", &ud.lockout);
728     //    SCRIPT_GetString(scripthandle, "Screen Setup", "Password", &ud.pwlockout[0]);
729     //}
730 
731     windowx = -1;
732     windowy = -1;
733 
734     SCRIPT_GetNumber(scripthandle, "Screen Setup", "MaxRefreshFreq", (int32_t *)&maxrefreshfreq);
735     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenBPP", &gSetup.bpp);
736     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenHeight", &gSetup.ydim);
737     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenMode", &gSetup.fullscreen);
738     SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenWidth", &gSetup.xdim);
739     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPosX", (int32_t *)&windowx);
740     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPosY", (int32_t *)&windowy);
741     SCRIPT_GetNumber(scripthandle, "Screen Setup", "WindowPositioning", (int32_t *)&windowpos);
742 
743     if (gSetup.bpp < 8) gSetup.bpp = 32;
744 
745 #ifdef POLYMER
746     int32_t rendmode = 0;
747     SCRIPT_GetNumber(scripthandle, "Screen Setup", "Polymer", &rendmode);
748     glrendmode = (rendmode > 0) ? REND_POLYMER : REND_POLYMOST;
749 #endif
750 
751     //SCRIPT_GetNumber(scripthandle, "Misc", "Executions", &ud.executions);
752 
753 #ifdef _WIN32
754     SCRIPT_GetNumber(scripthandle, "Updates", "CheckForUpdates", &CheckForUpdates);
755     SCRIPT_GetNumber(scripthandle, "Updates", "LastUpdateCheck", &LastUpdateCheck);
756 #endif
757 
758     setupread = 1;
759     return 0;
760 }
761 
762 
CONFIG_WriteSettings(void)763 void CONFIG_WriteSettings(void) // save binds and aliases to <cfgname>_settings.cfg
764 {
765     char *ptr = Xstrdup(SetupFilename);
766     char filename[BMAX_PATH];
767 
768     if (!Bstrcmp(SetupFilename, SETUPFILENAME))
769         Bsprintf(filename, "settings.cfg");
770     else
771         Bsprintf(filename, "%s_settings.cfg", strtok(ptr, "."));
772 
773     BFILE *fp = Bfopen(filename, "wt");
774 
775     if (fp)
776     {
777         Bfprintf(fp,"// this file is automatically generated by %s\n", AppProperName);
778         Bfprintf(fp,"unbindall\n");
779 
780         for (int i=0; i<MAXBOUNDKEYS+MAXMOUSEBUTTONS; i++)
781         {
782             if (CONTROL_KeyIsBound(i))
783             {
784                 Bfprintf(fp, "bind \"%s\"%s \"%s\"\n", CONTROL_KeyBinds[i].key,
785                                                        CONTROL_KeyBinds[i].repeat ? "" : " norepeat",
786                                                        CONTROL_KeyBinds[i].cmdstr);
787             }
788         }
789 
790         OSD_WriteAliases(fp);
791 
792         if (g_isAlterDefaultCrosshair)
793             Bfprintf(fp, "crosshaircolor %d %d %d\n", CrosshairColors.r, CrosshairColors.g, CrosshairColors.b);
794 
795         OSD_WriteCvars(fp);
796 
797         Bfclose(fp);
798         Bfree(ptr);
799 
800         OSD_Printf("Wrote %s\n", filename);
801 
802         return;
803     }
804 
805     OSD_Printf("Error writing %s: %s\n", filename, strerror(errno));
806 
807     Bfree(ptr);
808 }
809 
CONFIG_WriteSetup(uint32_t flags)810 void CONFIG_WriteSetup(uint32_t flags)
811 {
812     char buf[128];
813     if (!setupread) return;
814 
815     if (scripthandle < 0)
816         scripthandle = SCRIPT_Init(SetupFilename);
817 
818     //SCRIPT_PutNumber(scripthandle, "Misc", "Executions", ud.executions, FALSE, FALSE);
819 
820     SCRIPT_PutNumber(scripthandle, "Setup", "CacheSize", MAXCACHE1DSIZE, FALSE, FALSE);
821     SCRIPT_PutNumber(scripthandle, "Setup", "ConfigVersion", BYTEVERSION, FALSE, FALSE);
822     SCRIPT_PutNumber(scripthandle, "Setup", "ForceSetup", gSetup.forcesetup, FALSE, FALSE);
823     SCRIPT_PutNumber(scripthandle, "Setup", "NoAutoLoad", gSetup.noautoload, FALSE, FALSE);
824 
825 #ifdef POLYMER
826     SCRIPT_PutNumber(scripthandle, "Screen Setup", "Polymer", glrendmode == REND_POLYMER, FALSE, FALSE);
827 #endif
828 
829     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenBPP", gSetup.bpp, FALSE, FALSE);
830     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenHeight", gSetup.ydim, FALSE, FALSE);
831     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenMode", gSetup.fullscreen, FALSE, FALSE);
832     SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenWidth", gSetup.xdim, FALSE, FALSE);
833 
834     //if (g_grpNamePtr && !g_addonNum)
835     //    SCRIPT_PutString(scripthandle, "Setup", "SelectedGRP", g_grpNamePtr);
836 
837 #ifdef STARTUP_SETUP_WINDOW
838     if (gNoSetup == 0)
839         SCRIPT_PutString(scripthandle, "Setup", "ModDir", &g_modDir[0]);
840 #endif
841     // exit early after only updating the values that can be changed from the startup window
842     if (flags & 1)
843     {
844         SCRIPT_Save(scripthandle, SetupFilename);
845         SCRIPT_Free(scripthandle);
846         return;
847     }
848 
849     SCRIPT_PutNumber(scripthandle, "Screen Setup", "MaxRefreshFreq", maxrefreshfreq, FALSE, FALSE);
850     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPosX", windowx, FALSE, FALSE);
851     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPosY", windowy, FALSE, FALSE);
852     SCRIPT_PutNumber(scripthandle, "Screen Setup", "WindowPositioning", windowpos, FALSE, FALSE);
853 
854     //if (!NAM_WW2GI)
855     //{
856     //    SCRIPT_PutNumber(scripthandle, "Screen Setup", "Out",ud.lockout,FALSE,FALSE);
857     //    SCRIPT_PutString(scripthandle, "Screen Setup", "Password",ud.pwlockout);
858     //}
859 
860 #ifdef _WIN32
861     SCRIPT_PutNumber(scripthandle, "Updates", "CheckForUpdates", CheckForUpdates, FALSE, FALSE);
862     SCRIPT_PutNumber(scripthandle, "Updates", "LastUpdateCheck", LastUpdateCheck, FALSE, FALSE);
863 #endif
864 
865     if (gSetup.usemouse)
866     {
867         for (int i=0; i<MAXMOUSEBUTTONS; i++)
868         {
869             if (CONFIG_FunctionNumToName(MouseFunctions[i][0]))
870             {
871                 Bsprintf(buf, "MouseButton%d", i);
872                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseFunctions[i][0]));
873             }
874 
875             if (i >= (MAXMOUSEBUTTONS-2)) continue;
876 
877             if (CONFIG_FunctionNumToName(MouseFunctions[i][1]))
878             {
879                 Bsprintf(buf, "MouseButtonClicked%d", i);
880                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(MouseFunctions[i][1]));
881             }
882         }
883 
884         for (int i=0; i<MAXMOUSEAXES; i++)
885         {
886             if (CONFIG_AnalogNumToName(MouseAnalogueAxes[i]))
887             {
888                 Bsprintf(buf, "MouseAnalogAxes%d", i);
889                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_AnalogNumToName(MouseAnalogueAxes[i]));
890             }
891         }
892     }
893 
894     if (gSetup.usejoystick)
895     {
896         for (int dummy=0; dummy<MAXJOYBUTTONSANDHATS; dummy++)
897         {
898             if (CONFIG_FunctionNumToName(JoystickFunctions[dummy][0]))
899             {
900                 Bsprintf(buf, "JoystickButton%d", dummy);
901                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickFunctions[dummy][0]));
902             }
903 
904             if (CONFIG_FunctionNumToName(JoystickFunctions[dummy][1]))
905             {
906                 Bsprintf(buf, "JoystickButtonClicked%d", dummy);
907                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickFunctions[dummy][1]));
908             }
909         }
910         for (int dummy=0; dummy<MAXJOYAXES; dummy++)
911         {
912             if (CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy]))
913             {
914                 Bsprintf(buf, "JoystickAnalogAxes%d", dummy);
915                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy]));
916             }
917 
918             if (CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][0]))
919             {
920                 Bsprintf(buf, "JoystickDigitalAxes%d_0", dummy);
921                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][0]));
922             }
923 
924             if (CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][1]))
925             {
926                 Bsprintf(buf, "JoystickDigitalAxes%d_1", dummy);
927                 SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalFunctions[dummy][1]));
928             }
929 
930             if (JoystickAnalogueScale[dummy] != DEFAULTJOYSTICKANALOGUESCALE)
931             {
932                 Bsprintf(buf, "JoystickAnalogScale%d", dummy);
933                 SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueScale[dummy], FALSE, FALSE);
934             }
935 
936             if (JoystickAnalogueDead[dummy] != DEFAULTJOYSTICKANALOGUEDEAD)
937             {
938                 Bsprintf(buf, "JoystickAnalogDead%d", dummy);
939                 SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueDead[dummy], FALSE, FALSE);
940             }
941 
942             if (JoystickAnalogueSaturate[dummy] != DEFAULTJOYSTICKANALOGUESATURATE)
943             {
944                 Bsprintf(buf, "JoystickAnalogSaturate%d", dummy);
945                 SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogueSaturate[dummy], FALSE, FALSE);
946             }
947         }
948     }
949 
950     SCRIPT_PutString(scripthandle, "Comm Setup","PlayerName",&szPlayerName[0]);
951 
952     //SCRIPT_PutString(scripthandle, "Comm Setup","RTSName",&ud.rtsname[0]);
953 
954     char commmacro[] = "CommbatMacro# ";
955 
956     for (int dummy = 0; dummy < MAXRIDECULE; dummy++)
957     {
958         commmacro[13] = dummy+'0';
959         SCRIPT_PutString(scripthandle, "Comm Setup",commmacro,&CommbatMacro[dummy][0]);
960     }
961 
962     ///////
963     SCRIPT_PutNumber(scripthandle, "Game Options", "WeaponsV10x", gWeaponsV10x, FALSE, FALSE);
964     ///////
965 
966     SCRIPT_Save(scripthandle, SetupFilename);
967 
968     if ((flags & 2) == 0)
969         SCRIPT_Free(scripthandle);
970 
971     OSD_Printf("Wrote %s\n",SetupFilename);
972     CONFIG_WriteSettings();
973     Bfflush(NULL);
974 }
975 
976 #if 0
977 static const char *CONFIG_GetMapEntryName(char m[], char const * const mapname)
978 {
979     strcpy(m, mapname);
980 
981     char *p = strrchr(m, '/');
982     if (!p) p = strrchr(m, '\\');
983     if (p) Bmemmove(m, p, Bstrlen(p)+1);
984     for (p=m; *p; p++) *p = tolower(*p);
985 
986     // cheap hack because SCRIPT_GetNumber doesn't like the slashes
987     p = m;
988     while (*p == '/') p++;
989 
990     return p;
991 }
992 
993 static void CONFIG_GetMD4EntryName(char m[], uint8_t const * const md4)
994 {
995     sprintf(m, "MD4_%08x%08x%08x%08x",
996             B_BIG32(B_UNBUF32(&md4[0])), B_BIG32(B_UNBUF32(&md4[4])),
997             B_BIG32(B_UNBUF32(&md4[8])), B_BIG32(B_UNBUF32(&md4[12])));
998 }
999 
1000 int32_t CONFIG_GetMapBestTime(char const * const mapname, uint8_t const * const mapmd4)
1001 {
1002     if (!setupread || scripthandle < 0)
1003         return -1;
1004 
1005     char m[37];
1006 
1007     CONFIG_GetMD4EntryName(m, mapmd4);
1008 
1009     int32_t t = -1;
1010     if (SCRIPT_GetNumber(scripthandle, "MapTimes", m, &t))
1011     {
1012         // fall back to map filenames
1013         char m2[BMAX_PATH];
1014         auto p = CONFIG_GetMapEntryName(m2, mapname);
1015 
1016         SCRIPT_GetNumber(scripthandle, "MapTimes", p, &t);
1017     }
1018 
1019     return t;
1020 }
1021 
1022 int CONFIG_SetMapBestTime(uint8_t const * const mapmd4, int32_t tm)
1023 {
1024     if (scripthandle < 0 && (scripthandle = SCRIPT_Init(SetupFilename)) < 0)
1025         return -1;
1026 
1027     char m[37];
1028 
1029     CONFIG_GetMD4EntryName(m, mapmd4);
1030     SCRIPT_PutNumber(scripthandle, "MapTimes", m, tm, FALSE, FALSE);
1031 
1032     return 0;
1033 }
1034 
1035 #endif
1036