DEADSOFTWARE

Fix resolution detecting, add vsync
[d2df-sdl.git] / src / game / g_options.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_options;
19 interface
21 uses
22 g_language, g_weapons;
24 type
25 TPlayerControl = record
26 KeyRight: Word;
27 KeyLeft: Word;
28 KeyUp: Word;
29 KeyDown: Word;
30 KeyFire: Word;
31 KeyJump: Word;
32 KeyNextWeapon: Word;
33 KeyPrevWeapon: Word;
34 KeyOpen: Word;
35 KeyStrafe: Word;
36 KeyWeapon: array [WP_FIRST..WP_LAST] of Word;
38 KeyRight2: Word;
39 KeyLeft2: Word;
40 KeyUp2: Word;
41 KeyDown2: Word;
42 KeyFire2: Word;
43 KeyJump2: Word;
44 KeyNextWeapon2: Word;
45 KeyPrevWeapon2: Word;
46 KeyOpen2: Word;
47 KeyStrafe2: Word;
48 KeyWeapon2: array [WP_FIRST..WP_LAST] of Word;
49 end;
51 TGameControls = record
52 TakeScreenshot: Word;
53 Stat: Word;
54 Chat: Word;
55 TeamChat: Word;
56 end;
58 TControls = record
59 GameControls: TGameControls;
60 P1Control: TPlayerControl;
61 P2Control: TPlayerControl;
62 end;
64 function GenPlayerName (n: Integer): String;
66 procedure g_Options_SetDefault();
67 procedure g_Options_Read(FileName: String);
68 procedure g_Options_Write(FileName: String);
69 procedure g_Options_Write_Language(FileName: String);
70 procedure g_Options_Write_Video(FileName: String);
71 procedure g_Options_Write_Gameplay_Custom(FileName: String);
72 procedure g_Options_Write_Gameplay_Net(FileName: String);
73 procedure g_Options_Write_Net_Server(FileName: String);
74 procedure g_Options_Write_Net_Client(FileName: String);
76 const DF_Default_Megawad_Start = 'megawads/DOOM2D.WAD:\MAP01';
78 var
79 gGameControls: TControls;
80 gScreenWidth: Word;
81 gScreenHeight: Word;
82 gWinRealPosX: Integer;
83 gWinRealPosY: Integer;
84 gBPP: Byte;
85 gFreq: Byte;
86 gFullscreen: Boolean;
87 gWinMaximized: Boolean;
88 gVSync: Boolean;
89 glLegacyNPOT: Boolean;
90 gTextureFilter: Boolean;
91 gNoSound: Boolean;
92 gSoundLevel: Byte;
93 gMusicLevel: Byte;
94 gMaxSimSounds: Byte;
95 gMuteWhenInactive: Boolean;
96 gAdvCorpses: Boolean;
97 gAdvBlood: Boolean;
98 gAdvGibs: Boolean;
99 gGibsCount: Integer;
100 gBloodCount: Byte;
101 gFlash: Byte;
102 gDrawBackGround: Boolean;
103 gShowMessages: Boolean;
104 gRevertPlayers: Boolean;
105 gLanguage: String;
106 gAskLanguage: Boolean;
107 gcMap: String;
108 gcGameMode: String;
109 gcTimeLimit: Word;
110 gcGoalLimit: Word;
111 gcMaxLives: Byte;
112 gcPlayers: Byte;
113 gcTeamDamage: Boolean;
114 gcAllowExit: Boolean;
115 gcWeaponStay: Boolean;
116 gcMonsters: Boolean;
117 gcBotsVS: String;
118 gnMap: String;
119 gnGameMode: String;
120 gnTimeLimit: Word;
121 gnGoalLimit: Word;
122 gnMaxLives: Byte;
123 gnPlayers: Byte;
124 gnTeamDamage: Boolean;
125 gnAllowExit: Boolean;
126 gnWeaponStay: Boolean;
127 gnMonsters: Boolean;
128 gnBotsVS: String;
129 gsSDLSampleRate: Integer;
130 gsSDLBufferSize: Integer;
131 gSFSDebug: Boolean;
132 gSFSFastMode: Boolean;
133 gDefaultMegawadStart: AnsiString;
134 gBerserkAutoswitch: Boolean;
136 implementation
138 uses
139 {$INCLUDE ../nogl/noGLuses.inc}
140 e_log, e_input, g_window, g_sound, g_gfx, g_player, Math,
141 g_map, g_net, g_netmaster, SysUtils, CONFIG, g_game, g_main, e_texture,
142 g_items, wadreader, e_graphics, g_touch, SDL2, envvars;
144 var
145 machine: Integer;
147 function GenPlayerName (n: Integer): String;
148 begin
149 ASSERT(n >= 1);
150 Result := GetUserName;
151 if Result = '' then
152 Result := 'Player' + IntToStr(machine MOD 10000);
153 if n = 1 then
154 Result := Copy(Result, 1, 12) + ' '
155 else
156 Result := Copy(Result, 1, 10) + ' ' + IntToStr(n)
157 end;
159 procedure g_Options_SetDefaultVideo;
160 var
161 target, closest, display: TSDL_DisplayMode;
162 percentage: Integer;
163 begin
164 (* Display 0 = Primary display *)
165 if SDL_GetDesktopDisplayMode(0, @display) <> 0 then
166 begin
167 display.format := SDL_PIXELFORMAT_UNKNOWN;
168 display.w := 640;
169 display.h := 480;
170 display.refresh_rate := 0;
171 display.driverdata := nil
172 end;
173 {$IF DEFINED(ANDROID)}
174 gScreenWidth := display.w;
175 gScreenHeight := display.h;
176 gBPP := SDL_BITSPERPIXEL(dispaly.format);
177 if gBPP = 0 then gBPP := 32;
178 gFullScreen := True; (* rotation not allowed? *)
179 {$ELSEIF DEFINED(GO32V2)}
180 gScreenWidth := display.w;
181 gScreenHeight := display.h;
182 gBPP := SDL_BITSPERPIXEL(display.format);
183 if gBPP = 0 then gBPP := 8;
184 gFullScreen := False; (* Do not change videomode twice *)
185 {$ELSE}
186 (* Window must be smaller than display *)
187 closest.w := display.w;
188 closest.h := display.h;
189 percentage := 75;
190 while (display.w - closest.w < 48) or (display.h - closest.h < 48) do
191 begin
192 if percentage < 25 then
193 begin
194 closest.w := display.w * 75 div 100;
195 closest.h := display.h * 75 div 100;
196 break;
197 end;
198 target.w := display.w * percentage div 100;
199 target.h := display.h * percentage div 100;
200 target.format := 0; (* didn't care *)
201 target.refresh_rate := 0; (* didn't care *)
202 target.driverdata := nil; (* init *)
203 SDL_GetClosestDisplayMode(0, @target, @closest);
204 Dec(percentage);
205 end;
206 gScreenWidth := closest.w;
207 gScreenHeight := closest.h;
208 //gBPP := SDL_BITSPERPIXEL(closest.format); (* Resolution list didn't work for some reason *)
209 gBPP := 32;
210 gFullScreen := False;
211 {$ENDIF}
212 (* Must be positioned on primary display *)
213 gWinRealPosX := SDL_WINDOWPOS_CENTERED;
214 gWinRealPosY := SDL_WINDOWPOS_CENTERED;
215 gWinMaximized := False;
216 gVSync := True;
217 gTextureFilter := True;
218 glLegacyNPOT := False;
219 e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight));
220 end;
222 procedure g_Options_SetDefault();
223 var
224 i: Integer;
225 begin
226 (* section Sound *)
227 gNoSound := False;
228 gSoundLevel := 75;
229 gMusicLevel := 65;
230 gMaxSimSounds := 8;
231 gMuteWhenInactive := False;
232 gAnnouncer := ANNOUNCE_MEPLUS;
233 gSoundEffectsDF := True;
234 gUseChatSounds := True;
235 gsSDLSampleRate := 44100;
236 gsSDLBufferSize := 2048;
238 g_Sound_SetupAllVolumes(gSoundLevel, gMusicLevel);
240 (* section GameControls *)
241 with gGameControls.GameControls do
242 begin
243 TakeScreenshot := SDL_SCANCODE_F12;
244 Stat := SDL_SCANCODE_TAB;
245 Chat := SDL_SCANCODE_T;
246 TeamChat := SDL_SCANCODE_Y;
247 end;
249 (* section Player1 *)
250 with gGameControls.P1Control do
251 begin
252 KeyRight := SDL_SCANCODE_KP_6;
253 KeyLeft := SDL_SCANCODE_KP_4;
254 KeyUp := SDL_SCANCODE_KP_8;
255 KeyDown := SDL_SCANCODE_KP_5;
256 KeyFire := SDL_SCANCODE_SLASH;
257 KeyJump := SDL_SCANCODE_RCTRL;
258 KeyNextWeapon := SDL_SCANCODE_KP_9;
259 KeyPrevWeapon := SDL_SCANCODE_KP_7;
260 KeyOpen := SDL_SCANCODE_RSHIFT;
261 KeyStrafe := SDL_SCANCODE_PERIOD;
263 for i := 0 to 9 do
264 begin
265 KeyWeapon[i] := SDL_SCANCODE_1 + i (* 1, ..., 9, 0 *)
266 end;
267 KeyWeapon[10] := SDL_SCANCODE_MINUS;
268 for i := 11 to High(KeyWeapon) do
269 begin
270 KeyWeapon[i] := 0
271 end;
273 KeyRight2 := VK_RIGHT;
274 KeyLeft2 := VK_LEFT;
275 KeyUp2 := VK_UP;
276 KeyDown2 := VK_DOWN;
277 KeyFire2 := VK_FIRE;
278 KeyJump2 := VK_JUMP;
279 KeyNextWeapon2 := VK_NEXT;
280 KeyPrevWeapon2 := VK_PREV;
281 KeyOpen2 := VK_OPEN;
282 KeyStrafe2 := VK_STRAFE;
284 for i := 0 to High(KeyWeapon2) do
285 begin
286 KeyWeapon2[i] := VK_0 + i
287 end;
288 end;
290 with gPlayer1Settings do
291 begin
292 Name := GenPlayerName(1);
293 Model := STD_PLAYER_MODEL;
294 Color.R := PLAYER1_DEF_COLOR.R;
295 Color.G := PLAYER1_DEF_COLOR.G;
296 Color.B := PLAYER1_DEF_COLOR.B;
297 Team := TEAM_RED;
298 end;
300 (* section Player2 *)
301 with gGameControls.P2Control do
302 begin
303 KeyRight := SDL_SCANCODE_D;
304 KeyLeft := SDL_SCANCODE_A;
305 KeyUp := SDL_SCANCODE_W;
306 KeyDown := SDL_SCANCODE_S;
307 KeyFire := SDL_SCANCODE_G;
308 KeyJump := SDL_SCANCODE_SPACE;
309 KeyNextWeapon := SDL_SCANCODE_E;
310 KeyPrevWeapon := SDL_SCANCODE_Q;
311 KeyOpen := SDL_SCANCODE_F;
312 KeyStrafe := SDL_SCANCODE_LSHIFT;
313 for i := 0 to High(KeyWeapon) do
314 begin
315 KeyWeapon[i] := 0
316 end;
318 KeyRight2 := 0;
319 KeyLeft2 := 0;
320 KeyUp2 := 0;
321 KeyDown2 := 0;
322 KeyFire2 := 0;
323 KeyJump2 := 0;
324 KeyNextWeapon2 := 0;
325 KeyPrevWeapon2 := 0;
326 KeyOpen2 := 0;
327 KeyStrafe2 := 0;
329 for i := 0 to High(KeyWeapon2) do
330 begin
331 KeyWeapon2[i] := 0;
332 end
333 end;
335 with gPlayer2Settings do
336 begin
337 Name := GenPlayerName(2);
338 Model := STD_PLAYER_MODEL;
339 Color.R := PLAYER2_DEF_COLOR.R;
340 Color.G := PLAYER2_DEF_COLOR.G;
341 Color.B := PLAYER2_DEF_COLOR.B;
342 Team := TEAM_BLUE;
343 end;
345 (* section Joysticks *)
346 for i := 0 to e_MaxJoys - 1 do
347 begin
348 e_JoystickDeadzones[i] := 8192
349 end;
351 (* section Touch *)
352 g_touch_size := 1.0;
353 g_touch_fire := True;
354 g_touch_offset := 50;
355 g_touch_alt := False;
357 (* section Game *)
358 g_GFX_SetMax(2000);
359 g_Shells_SetMax(300);
360 g_Gibs_SetMax(150);
361 g_Corpses_SetMax(20);
362 gGibsCount := 32;
363 ITEM_RESPAWNTIME := 60 * 36;
364 gBloodCount := 4;
365 gAdvBlood := True;
366 gAdvCorpses := True;
367 gAdvGibs := True;
368 gFlash := 1;
369 gDrawBackGround := True;
370 gShowMessages := True;
371 gRevertPlayers := False;
372 gChatBubble := 4;
373 gPlayerIndicator := True;
374 gSFSDebug := False;
375 gSFSFastMode := False;
376 e_FastScreenshots := True;
377 gDefaultMegawadStart := DF_Default_Megawad_Start;
378 gBerserkAutoswitch := True;
379 g_dbg_scale := 1.0;
381 gAskLanguage := True;
382 gLanguage := LANGUAGE_ENGLISH;
384 (* section GameplayCustom *)
385 gcMap := '';
386 gcGameMode := _lc[I_MENU_GAME_TYPE_DM];
387 gcTimeLimit := 0;
388 gcGoalLimit := 0;
389 gcMaxLives := 0;
390 gcPlayers := 1;
391 gcTeamDamage := False;
392 gcAllowExit := True;
393 gcWeaponStay := False;
394 gcMonsters := False;
395 gcBotsVS := 'Everybody';
397 (* section GameplayNetwork *)
398 gnMap := '';
399 gnGameMode := _lc[I_MENU_GAME_TYPE_DM];
400 gnTimeLimit := 0;
401 gnGoalLimit := 0;
402 gnMaxLives := 0;
403 gnPlayers := 1;
404 gnTeamDamage := False;
405 gnAllowExit := True;
406 gnWeaponStay := False;
407 gnMonsters := False;
408 gnBotsVS := 'Everybody';
410 (* section MasterServer *)
411 NetSlistIP := 'mpms.doom2d.org';
412 NetSlistPort := 25665;
413 g_Net_Slist_Set(NetSlistIP, NetSlistPort);
415 (* section Server *)
416 NetServerName := 'Unnamed Server';
417 NetPassword := '';
418 NetPort := 25666;
419 NetMaxClients := 16;
420 NetAllowRCON := False;
421 NetRCONPassword := 'default';
422 NetUseMaster := True;
423 NetUpdateRate := 0;
424 NetRelupdRate := 18;
425 NetMasterRate := 60000;
426 NetForwardPorts := False;
428 (* section Client *)
429 NetInterpLevel := 2;
430 NetForcePlayerUpdate := False;
431 NetPredictSelf := True;
432 NetClientIP := '127.0.0.1';
433 NetClientPort := NetPort;
434 end;
436 procedure g_Options_Read(FileName: String);
437 var
438 i: Integer;
439 config: TConfig;
440 section: String;
442 procedure ReadInteger (VAR v: Integer; param: String; minv: Integer = Low(Integer); maxv: Integer = High(Integer));
443 begin
444 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
445 end;
447 procedure ReadInteger (VAR v: LongWord; param: String; minv: LongWord = Low(LongWord); maxv: LongWord = High(LongWord)); overload;
448 begin
449 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
450 end;
452 procedure ReadInteger (VAR v: Word; param: String; minv: Word = Low(Word); maxv: Word = High(Word)); overload;
453 begin
454 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
455 end;
457 procedure ReadInteger (VAR v: Byte; param: String; minv: Byte = Low(Byte); maxv: Byte = High(Byte)); overload;
458 begin
459 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
460 end;
462 procedure ReadBoolean (VAR v: Boolean; param: String);
463 begin
464 v := config.ReadBool(section, param, v)
465 end;
467 procedure ReadString (VAR v: String; param: String);
468 begin
469 v := config.ReadStr(section, param, v)
470 end;
472 begin
473 gAskLanguage := True;
474 e_WriteLog('Reading config', TMsgType.Notify);
475 g_Options_SetDefault;
477 if FileExists(FileName) = False then
478 begin
479 e_WriteLog('Config file '+FileName+' not found', TMsgType.Warning);
480 g_Options_SetDefaultVideo;
481 Exit
482 end;
484 config := TConfig.CreateFile(FileName);
486 section := 'Video';
487 ReadInteger(gScreenWidth, 'ScreenWidth', 0);
488 ReadInteger(gScreenHeight, 'ScreenHeight', 0);
489 ReadInteger(gWinRealPosX, 'WinPosX', 60);
490 ReadInteger(gWinRealPosY, 'WinPosY', 60);
491 ReadBoolean(gFullScreen, 'Fullscreen');
492 ReadBoolean(gWinMaximized, 'Maximized');
493 ReadInteger(gBPP, 'BPP', 0);
494 ReadInteger(gFreq, 'Freq', 0);
495 ReadBoolean(gVSync, 'VSync');
496 ReadBoolean(gTextureFilter, 'TextureFilter');
497 ReadBoolean(glLegacyNPOT, 'LegacyCompatible');
499 section := 'Sound';
500 ReadBoolean(gNoSound, 'NoSound');
501 ReadInteger(gSoundLevel, 'SoundLevel', 0, 255);
502 ReadInteger(gMusicLevel, 'MusicLevel', 0, 255);
503 ReadInteger(gMaxSimSounds, 'MaxSimSounds', 2, 66);
504 ReadBoolean(gMuteWhenInactive, 'MuteInactive');
505 ReadInteger(gAnnouncer, 'Announcer', ANNOUNCE_NONE, ANNOUNCE_ALL);
506 ReadBoolean(gSoundEffectsDF, 'SoundEffectsDF');
507 ReadBoolean(gUseChatSounds, 'ChatSounds');
508 ReadInteger(gsSDLSampleRate, 'SDLSampleRate', 11025, 96000);
509 ReadInteger(gsSDLBufferSize, 'SDLBufferSize', 64, 16384);
511 section := 'GameControls';
512 with gGameControls.GameControls do
513 begin
514 ReadInteger(TakeScreenshot, 'TakeScreenshot');
515 ReadInteger(Stat, 'Stat');
516 ReadInteger(Chat, 'Chat');
517 ReadInteger(TeamChat, 'TeamChat');
518 end;
520 section := 'Player1';
521 with gGameControls.P1Control do
522 begin
523 ReadInteger(KeyRight, 'KeyRight');
524 ReadInteger(KeyLeft, 'KeyLeft');
525 ReadInteger(KeyUp, 'KeyUp');
526 ReadInteger(KeyDown, 'KeyDown');
527 ReadInteger(KeyFire, 'KeyFire');
528 ReadInteger(KeyJump, 'KeyJump');
529 ReadInteger(KeyNextWeapon, 'KeyNextWeapon');
530 ReadInteger(KeyPrevWeapon, 'KeyPrevWeapon');
531 ReadInteger(KeyOpen, 'KeyOpen');
532 ReadInteger(KeyStrafe, 'KeyStrafe');
534 for i := 0 to High(KeyWeapon) do
535 begin
536 ReadInteger(KeyWeapon[i], 'KeyWeapon' + IntToStr(i))
537 end;
539 ReadInteger(KeyRight2, 'KeyRight2');
540 ReadInteger(KeyLeft2, 'KeyLeft2');
541 ReadInteger(KeyUp2, 'KeyUp2');
542 ReadInteger(KeyDown2, 'KeyDown2');
543 ReadInteger(KeyFire2, 'KeyFire2');
544 ReadInteger(KeyJump2, 'KeyJump2');
545 ReadInteger(KeyNextWeapon2, 'KeyNextWeapon2');
546 ReadInteger(KeyPrevWeapon2, 'KeyPrevWeapon2');
547 ReadInteger(KeyOpen2, 'KeyOpen2');
548 ReadInteger(KeyStrafe2, 'KeyStrafe2');
550 for i := 0 to High(KeyWeapon2) do
551 begin
552 ReadInteger(KeyWeapon2[i], 'KeyWeapon2' + IntToStr(i))
553 end;
554 end;
556 section := 'Player1';
557 with gPlayer1Settings do
558 begin
559 ReadString(Name, 'name');
560 ReadString(Model, 'model');
561 ReadInteger(Color.R, 'red', 0, 255);
562 ReadInteger(Color.G, 'green', 0, 255);
563 ReadInteger(Color.B, 'blue', 0, 255);
564 ReadInteger(Team, 'team');
565 if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
566 Team := TEAM_RED;
567 end;
569 section := 'Player2';
570 with gGameControls.P2Control do
571 begin
572 ReadInteger(KeyRight, 'KeyRight');
573 ReadInteger(KeyLeft, 'KeyLeft');
574 ReadInteger(KeyUp, 'KeyUp');
575 ReadInteger(KeyDown, 'KeyDown');
576 ReadInteger(KeyFire, 'KeyFire');
577 ReadInteger(KeyJump, 'KeyJump');
578 ReadInteger(KeyNextWeapon, 'KeyNextWeapon');
579 ReadInteger(KeyPrevWeapon, 'KeyPrevWeapon');
580 ReadInteger(KeyOpen, 'KeyOpen');
581 ReadInteger(KeyStrafe, 'KeyStrafe');
583 for i := 0 to High(KeyWeapon) do
584 begin
585 ReadInteger(KeyWeapon[i], 'KeyWeapon' + IntToStr(i))
586 end;
588 ReadInteger(KeyRight2, 'KeyRight2');
589 ReadInteger(KeyLeft2, 'KeyLeft2');
590 ReadInteger(KeyUp2, 'KeyUp2');
591 ReadInteger(KeyDown2, 'KeyDown2');
592 ReadInteger(KeyFire2, 'KeyFire2');
593 ReadInteger(KeyJump2, 'KeyJump2');
594 ReadInteger(KeyNextWeapon2, 'KeyNextWeapon2');
595 ReadInteger(KeyPrevWeapon2, 'KeyPrevWeapon2');
596 ReadInteger(KeyOpen2, 'KeyOpen2');
597 ReadInteger(KeyStrafe2, 'KeyStrafe2');
599 for i := 0 to High(KeyWeapon2) do
600 begin
601 ReadInteger(KeyWeapon2[i], 'KeyWeapon2' + IntToStr(i))
602 end;
603 end;
605 section := 'Player2';
606 with gPlayer2Settings do
607 begin
608 ReadString(Name, 'name');
609 ReadString(Model, 'model');
610 ReadInteger(Color.R, 'red', 0, 255);
611 ReadInteger(Color.G, 'green', 0, 255);
612 ReadInteger(Color.B, 'blue', 0, 255);
613 ReadInteger(Team, 'team');
614 if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
615 Team := TEAM_RED;
616 end;
618 section := 'Joysticks';
619 for i := 0 to e_MaxJoys - 1 do
620 begin
621 ReadInteger(e_JoystickDeadzones[i], 'Deadzone' + IntToStr(i))
622 end;
624 section := 'Touch';
625 i := Trunc(g_touch_size * 10); ReadInteger(i, 'Size', 0); g_touch_size := i / 10;
626 ReadBoolean(g_touch_fire, 'Fire');
627 i := Round(g_touch_offset); ReadInteger(i, 'Offset', 0, 100); g_touch_offset := i;
628 ReadBoolean(g_touch_alt, 'Alt');
630 section := 'Game';
631 ReadInteger(i, 'MaxParticles', 0, 50000); g_GFX_SetMax(i);
632 ReadInteger(i, 'MaxShells', 0, 600); g_Shells_SetMax(i);
633 ReadInteger(i, 'MaxGibs', 0, 500); g_Gibs_SetMax(i);
634 ReadInteger(i, 'MaxCorpses', 0, 100); g_Corpses_SetMax(i);
635 ReadInteger(i, 'GibsCount');
636 case i of
637 0: gGibsCount := 0;
638 1: gGibsCount := 8;
639 2: gGibsCount := 16;
640 3: gGibsCount := 32;
641 else gGibsCount := 48;
642 end;
643 i := ITEM_RESPAWNTIME div 36; ReadInteger(i, 'ItemRespawnTime', 0); ITEM_RESPAWNTIME := i * 36;
644 ReadInteger(gBloodCount, 'BloodCount', 0, 4);
645 ReadBoolean(gAdvBlood, 'AdvancesBlood');
646 ReadBoolean(gAdvCorpses, 'AdvancesCorpses');
647 ReadBoolean(gAdvGibs, 'AdvancesGibs');
648 ReadInteger(gFlash, 'Flash', 0, 2);
649 ReadBoolean(gDrawBackGround, 'BackGround');
650 ReadBoolean(gShowMessages, 'Messages');
651 ReadBoolean(gRevertPlayers, 'RevertPlayers');
652 ReadInteger(gChatBubble, 'ChatBubble', 0, 4);
653 ReadBoolean(gPlayerIndicator, 'PlayerIndicator');
654 ReadBoolean(gSFSDebug, 'SFSDebug'); wadoptDebug := gSFSDebug;
655 ReadBoolean(gSFSFastMode, 'SFSFastMode'); wadoptFast := gSFSFastMode;
656 ReadBoolean(e_FastScreenshots, 'FastScreenshots');
657 ReadString(gDefaultMegawadStart, 'DefaultMegawadStart');
658 ReadBoolean(gBerserkAutoswitch, 'BerserkAutoswitching');
659 i := Trunc(g_dbg_scale * 100); ReadInteger(i, 'Scale', 100); g_dbg_scale := i / 100;
660 ReadString(gLanguage, 'Language');
661 if (gLanguage = LANGUAGE_RUSSIAN) or (gLanguage = LANGUAGE_ENGLISH) then
662 gAskLanguage := False
663 else
664 gLanguage := LANGUAGE_ENGLISH;
666 section := 'GameplayCustom';
667 ReadString(gcMap, 'Map');
668 ReadString(gcGameMode, 'GameMode');
669 ReadInteger(gcTimeLimit, 'TimeLimit', 0, 65535);
670 ReadInteger(gcGoalLimit, 'GoalLimit', 0, 65535);
671 ReadInteger(gcMaxLives, 'MaxLives', 0, 255);
672 ReadInteger(gcPlayers, 'Players', 0, 2);
673 ReadBoolean(gcTeamDamage, 'TeamDamage');
674 ReadBoolean(gcAllowExit, 'AllowExit');
675 ReadBoolean(gcWeaponStay, 'WeaponStay');
676 ReadBoolean(gcMonsters, 'Monsters');
677 ReadString(gcBotsVS, 'BotsVS');
679 with gGameSettings do
680 begin
681 GameMode := g_Game_TextToMode(gcGameMode);
682 if GameMode = GM_NONE then
683 GameMode := GM_DM;
684 if GameMode = GM_SINGLE then
685 GameMode := GM_COOP;
686 TimeLimit := gcTimeLimit;
687 GoalLimit := gcGoalLimit;
688 MaxLives := gcMaxLives;
690 Options := 0;
691 if gcTeamDamage then
692 Options := Options or GAME_OPTION_TEAMDAMAGE;
693 if gcAllowExit then
694 Options := Options or GAME_OPTION_ALLOWEXIT;
695 if gcWeaponStay then
696 Options := Options or GAME_OPTION_WEAPONSTAY;
697 if gcMonsters then
698 Options := Options or GAME_OPTION_MONSTERS;
699 if gcBotsVS = 'Everybody' then
700 Options := Options or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
701 if gcBotsVS = 'Players' then
702 Options := Options or GAME_OPTION_BOTVSPLAYER;
703 if gcBotsVS = 'Monsters' then
704 Options := Options or GAME_OPTION_BOTVSMONSTER;
705 end;
707 section := 'GameplayNetwork';
708 ReadString(gnMap, 'Map');
709 ReadString(gnGameMode, 'GameMode');
710 ReadInteger(gnTimeLimit, 'TimeLimit', 0, 65535);
711 ReadInteger(gnGoalLimit, 'GoalLimit', 0, 65535);
712 ReadInteger(gnMaxLives, 'MaxLives', 0, 255);
713 ReadInteger(gnPlayers, 'Players', 0, 2);
714 ReadBoolean(gnTeamDamage, 'TeamDamage');
715 ReadBoolean(gnAllowExit, 'AllowExit');
716 ReadBoolean(gnWeaponStay, 'WeaponStay');
717 ReadBoolean(gnMonsters, 'Monsters');
718 ReadString(gnBotsVS, 'BotsVS');
720 section := 'MasterServer';
721 ReadString(NetSlistIP, 'IP');
722 ReadInteger(NetSlistPort, 'Port', 0, 65535);
723 g_Net_Slist_Set(NetSlistIP, NetSlistPort);
725 section := 'Server';
726 ReadString(NetServerName, 'Name');
727 ReadString(NetPassword, 'Password');
728 ReadInteger(NetPort, 'Port', 0, 65535);
729 ReadInteger(NetMaxClients, 'MaxClients', 0, NET_MAXCLIENTS);
730 ReadBoolean(NetAllowRCON, 'RCON');
731 ReadString(NetRCONPassword, 'RCONPassword');
732 ReadBoolean(NetUseMaster, 'SyncWithMaster');
733 ReadInteger(NetUpdateRate, 'UpdateInterval', 0);
734 ReadInteger(NetRelupdRate, 'ReliableUpdateInterval', 0);
735 ReadInteger(NetMasterRate, 'MasterSyncInterval', 1);
736 ReadBoolean(NetForwardPorts, 'ForwardPorts');
738 section := 'Client';
739 ReadInteger(NetInterpLevel, 'InterpolationSteps', 0);
740 ReadBoolean(NetForcePlayerUpdate, 'ForcePlayerUpdate');
741 ReadBoolean(NetPredictSelf, 'PredictSelf');
742 ReadString(NetClientIP, 'LastIP');
743 ReadInteger(NetClientPort, 'LastPort', 0, 65535);
745 config.Free();
747 //if gTextureFilter then TEXTUREFILTER := GL_LINEAR else TEXTUREFILTER := GL_NEAREST;
748 end;
750 procedure g_Options_Write(FileName: String);
751 var
752 config: TConfig;
753 i: Integer;
754 begin
755 e_WriteLog('Writing config', TMsgType.Notify);
757 config := TConfig.CreateFile(FileName);
759 config.WriteInt('Video', 'ScreenWidth', gScreenWidth);
760 config.WriteInt('Video', 'ScreenHeight', gScreenHeight);
761 config.WriteInt('Video', 'WinPosX', gWinRealPosX);
762 config.WriteInt('Video', 'WinPosY', gWinRealPosY);
763 config.WriteBool('Video', 'Fullscreen', gFullScreen);
764 config.WriteBool('Video', 'Maximized', gWinMaximized);
765 config.WriteInt('Video', 'BPP', gBPP);
766 config.WriteBool('Video', 'VSync', gVSync);
767 config.WriteBool('Video', 'TextureFilter', gTextureFilter);
768 config.WriteBool('Video', 'LegacyCompatible', glLegacyNPOT);
770 config.WriteBool('Sound', 'NoSound', gNoSound);
771 config.WriteInt('Sound', 'SoundLevel', gSoundLevel);
772 config.WriteInt('Sound', 'MusicLevel', gMusicLevel);
773 config.WriteInt('Sound', 'MaxSimSounds', gMaxSimSounds);
774 config.WriteBool('Sound', 'MuteInactive', gMuteWhenInactive);
775 config.WriteInt('Sound', 'Announcer', gAnnouncer);
776 config.WriteBool('Sound', 'SoundEffectsDF', gSoundEffectsDF);
777 config.WriteBool('Sound', 'ChatSounds', gUseChatSounds);
778 config.WriteInt('Sound', 'SDLSampleRate', gsSDLSampleRate);
779 config.WriteInt('Sound', 'SDLBufferSize', gsSDLBufferSize);
781 with config, gGameControls.GameControls do
782 begin
783 WriteInt('GameControls', 'TakeScreenshot', TakeScreenshot);
784 WriteInt('GameControls', 'Stat', Stat);
785 WriteInt('GameControls', 'Chat', Chat);
786 WriteInt('GameControls', 'TeamChat', TeamChat);
787 end;
789 with config, gGameControls.P1Control, gPlayer1Settings do
790 begin
791 WriteInt('Player1', 'KeyRight', KeyRight);
792 WriteInt('Player1', 'KeyLeft', KeyLeft);
793 WriteInt('Player1', 'KeyUp', KeyUp);
794 WriteInt('Player1', 'KeyDown', KeyDown);
795 WriteInt('Player1', 'KeyFire', KeyFire);
796 WriteInt('Player1', 'KeyJump', KeyJump);
797 WriteInt('Player1', 'KeyNextWeapon', KeyNextWeapon);
798 WriteInt('Player1', 'KeyPrevWeapon', KeyPrevWeapon);
799 WriteInt('Player1', 'KeyOpen', KeyOpen);
800 WriteInt('Player1', 'KeyStrafe', KeyStrafe);
801 for i := 0 to High(KeyWeapon) do
802 WriteInt('Player1', 'KeyWeapon' + IntToStr(i), KeyWeapon[i]);
804 WriteInt('Player1', 'KeyRight2', KeyRight2);
805 WriteInt('Player1', 'KeyLeft2', KeyLeft2);
806 WriteInt('Player1', 'KeyUp2', KeyUp2);
807 WriteInt('Player1', 'KeyDown2', KeyDown2);
808 WriteInt('Player1', 'KeyFire2', KeyFire2);
809 WriteInt('Player1', 'KeyJump2', KeyJump2);
810 WriteInt('Player1', 'KeyNextWeapon2', KeyNextWeapon2);
811 WriteInt('Player1', 'KeyPrevWeapon2', KeyPrevWeapon2);
812 WriteInt('Player1', 'KeyOpen2', KeyOpen2);
813 WriteInt('Player1', 'KeyStrafe2', KeyStrafe2);
814 for i := 0 to High(KeyWeapon2) do
815 WriteInt('Player1', 'KeyWeapon2' + IntToStr(i), KeyWeapon2[i]);
817 WriteStr('Player1', 'Name', Name);
818 WriteStr('Player1', 'model', Model);
819 WriteInt('Player1', 'red', Color.R);
820 WriteInt('Player1', 'green', Color.G);
821 WriteInt('Player1', 'blue', Color.B);
822 WriteInt('Player1', 'team', Team);
823 end;
825 with config, gGameControls.P2Control, gPlayer2Settings do
826 begin
827 WriteInt('Player2', 'KeyRight', KeyRight);
828 WriteInt('Player2', 'KeyLeft', KeyLeft);
829 WriteInt('Player2', 'KeyUp', KeyUp);
830 WriteInt('Player2', 'KeyDown', KeyDown);
831 WriteInt('Player2', 'KeyFire', KeyFire);
832 WriteInt('Player2', 'KeyJump', KeyJump);
833 WriteInt('Player2', 'KeyNextWeapon', KeyNextWeapon);
834 WriteInt('Player2', 'KeyPrevWeapon', KeyPrevWeapon);
835 WriteInt('Player2', 'KeyOpen', KeyOpen);
836 WriteInt('Player2', 'KeyStrafe', KeyStrafe);
837 for i := 0 to High(KeyWeapon) do
838 WriteInt('Player2', 'KeyWeapon' + IntToStr(i), KeyWeapon[i]);
840 WriteInt('Player2', 'KeyRight2', KeyRight2);
841 WriteInt('Player2', 'KeyLeft2', KeyLeft2);
842 WriteInt('Player2', 'KeyUp2', KeyUp2);
843 WriteInt('Player2', 'KeyDown2', KeyDown2);
844 WriteInt('Player2', 'KeyFire2', KeyFire2);
845 WriteInt('Player2', 'KeyJump2', KeyJump2);
846 WriteInt('Player2', 'KeyNextWeapon2', KeyNextWeapon2);
847 WriteInt('Player2', 'KeyPrevWeapon2', KeyPrevWeapon2);
848 WriteInt('Player2', 'KeyOpen2', KeyOpen2);
849 WriteInt('Player2', 'KeyStrafe2', KeyStrafe2);
850 for i := 0 to High(KeyWeapon2) do
851 WriteInt('Player2', 'KeyWeapon2' + IntToStr(i), KeyWeapon2[i]);
853 WriteStr('Player2', 'Name', Name);
854 WriteStr('Player2', 'model', Model);
855 WriteInt('Player2', 'red', Color.R);
856 WriteInt('Player2', 'green', Color.G);
857 WriteInt('Player2', 'blue', Color.B);
858 WriteInt('Player2', 'team', Team);
859 end;
861 for i := 0 to e_MaxJoys-1 do
862 config.WriteInt('Joysticks', 'Deadzone' + IntToStr(i), e_JoystickDeadzones[i]);
864 config.WriteInt('Touch', 'Size', Round(g_touch_size * 10));
865 config.WriteBool('Touch', 'Fire', g_touch_fire);
866 config.WriteInt('Touch', 'Offset', Round(g_touch_offset));
867 config.WriteBool('Touch', 'Alt', g_touch_alt);
869 with config do
870 case gGibsCount of
871 0: config.WriteInt('Game', 'GibsCount', 0);
872 8: config.WriteInt('Game', 'GibsCount', 1);
873 16: config.WriteInt('Game', 'GibsCount', 2);
874 32: config.WriteInt('Game', 'GibsCount', 3);
875 else config.WriteInt('Game', 'GibsCount', 4);
876 end;
878 config.WriteInt('Game', 'ItemRespawnTime', ITEM_RESPAWNTIME div 36);
879 config.WriteInt('Game', 'MaxParticles', g_GFX_GetMax());
880 config.WriteInt('Game', 'MaxShells', g_Shells_GetMax());
881 config.WriteInt('Game', 'MaxGibs', g_Gibs_GetMax());
882 config.WriteInt('Game', 'MaxCorpses', g_Corpses_GetMax());
883 config.WriteInt('Game', 'BloodCount', gBloodCount);
884 config.WriteBool('Game', 'AdvancesBlood', gAdvBlood);
885 config.WriteBool('Game', 'AdvancesCorpses', gAdvCorpses);
886 config.WriteBool('Game', 'AdvancesGibs', gAdvGibs);
887 config.WriteInt('Game', 'Flash', gFlash);
888 config.WriteBool('Game', 'BackGround', gDrawBackGround);
889 config.WriteBool('Game', 'Messages', gShowMessages);
890 config.WriteBool('Game', 'RevertPlayers', gRevertPlayers);
891 config.WriteInt('Game', 'ChatBubble', gChatBubble);
892 config.WriteBool('Game', 'PlayerIndicator', gPlayerIndicator);
893 config.WriteBool('Game', 'SFSDebug', gSFSDebug);
894 config.WriteBool('Game', 'SFSFastMode', gSFSFastMode);
895 config.WriteBool('Game', 'FastScreenshots', e_FastScreenshots);
896 config.WriteStr('Game', 'DefaultMegawadStart', gDefaultMegawadStart);
897 config.WriteBool('Game', 'BerserkAutoswitching', gBerserkAutoswitch);
898 config.WriteInt('Game', 'Scale', Round(g_dbg_scale * 100));
900 config.WriteStr ('GameplayCustom', 'Map', gcMap);
901 config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
902 config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
903 config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
904 config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
905 config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
906 config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
907 config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
908 config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
909 config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
910 config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
912 config.WriteStr ('GameplayNetwork', 'Map', gnMap);
913 config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
914 config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
915 config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
916 config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
917 config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
918 config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
919 config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
920 config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
921 config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
922 config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
924 config.WriteStr('MasterServer', 'IP', NetSlistIP);
925 config.WriteInt('MasterServer', 'Port', NetSlistPort);
927 config.WriteStr ('Server', 'Name', NetServerName);
928 config.WriteStr ('Server', 'Password', NetPassword);
929 config.WriteInt ('Server', 'Port', NetPort);
930 config.WriteInt ('Server', 'MaxClients', NetMaxClients);
931 config.WriteBool('Server', 'RCON', NetAllowRCON);
932 config.WriteStr ('Server', 'RCONPassword', NetRCONPassword);
933 config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
934 config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
935 config.WriteInt ('Server', 'UpdateInterval', NetUpdateRate);
936 config.WriteInt ('Server', 'ReliableUpdateInterval', NetRelupdRate);
937 config.WriteInt ('Server', 'MasterSyncInterval', NetMasterRate);
939 config.WriteInt ('Client', 'InterpolationSteps', NetInterpLevel);
940 config.WriteBool ('Client', 'ForcePlayerUpdate', NetForcePlayerUpdate);
941 config.WriteBool ('Client', 'PredictSelf', NetPredictSelf);
942 config.WriteStr ('Client', 'LastIP', NetClientIP);
943 config.WriteInt ('Client', 'LastPort', NetClientPort);
945 config.SaveFile(FileName);
946 config.Free();
947 end;
949 procedure g_Options_Write_Language(FileName: String);
950 var
951 config: TConfig;
952 begin
953 e_WriteLog('Writing language config', TMsgType.Notify);
955 config := TConfig.CreateFile(FileName);
956 config.WriteStr('Game', 'Language', gLanguage);
957 config.SaveFile(FileName);
958 config.Free();
959 end;
961 procedure g_Options_Write_Video(FileName: String);
962 var
963 config: TConfig;
964 sW, sH: Integer;
965 begin
966 e_WriteLog('Writing resolution to config', TMsgType.Notify);
968 config := TConfig.CreateFile(FileName);
970 if gWinMaximized and (not gFullscreen) then
971 begin
972 sW := gWinSizeX;
973 sH := gWinSizeY;
974 end
975 else
976 begin
977 sW := gScreenWidth;
978 sH := gScreenHeight;
979 end;
980 e_LogWritefln(' (ws=%dx%d) (ss=%dx%d)', [gWinSizeX, gWinSizeY, gScreenWidth, gScreenHeight]);
982 config.WriteInt('Video', 'ScreenWidth', sW);
983 config.WriteInt('Video', 'ScreenHeight', sH);
984 config.WriteInt('Video', 'WinPosX', gWinRealPosX);
985 config.WriteInt('Video', 'WinPosY', gWinRealPosY);
986 config.WriteBool('Video', 'Fullscreen', gFullscreen);
987 config.WriteBool('Video', 'Maximized', gWinMaximized);
989 config.WriteStr('Player1', 'Name', gPlayer1Settings.Name);
990 config.WriteStr('Player2', 'Name', gPlayer2Settings.Name);
992 config.SaveFile(FileName);
993 config.Free();
994 end;
996 procedure g_Options_Write_Gameplay_Custom(FileName: String);
997 var
998 config: TConfig;
999 begin
1000 e_WriteLog('Writing custom gameplay config', TMsgType.Notify);
1002 config := TConfig.CreateFile(FileName);
1004 config.WriteStr ('GameplayCustom', 'Map', gcMap);
1005 config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
1006 config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
1007 config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
1008 config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
1009 config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
1010 config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
1011 config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
1012 config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
1013 config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
1014 config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
1016 config.SaveFile(FileName);
1017 config.Free();
1018 end;
1020 procedure g_Options_Write_Gameplay_Net(FileName: String);
1021 var
1022 config: TConfig;
1023 begin
1024 e_WriteLog('Writing network gameplay config', TMsgType.Notify);
1026 config := TConfig.CreateFile(FileName);
1028 config.WriteStr ('GameplayNetwork', 'Map', gnMap);
1029 config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
1030 config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
1031 config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
1032 config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
1033 config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
1034 config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
1035 config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
1036 config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
1037 config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
1038 config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
1040 config.SaveFile(FileName);
1041 config.Free();
1042 end;
1044 procedure g_Options_Write_Net_Server(FileName: String);
1045 var
1046 config: TConfig;
1047 begin
1048 e_WriteLog('Writing server config', TMsgType.Notify);
1050 config := TConfig.CreateFile(FileName);
1052 config.WriteStr ('Server', 'Name', NetServerName);
1053 config.WriteStr ('Server', 'Password', NetPassword);
1054 config.WriteInt ('Server', 'Port', NetPort);
1055 config.WriteInt ('Server', 'MaxClients', NetMaxClients);
1056 config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
1057 config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
1059 config.SaveFile(FileName);
1060 config.Free();
1061 end;
1063 procedure g_Options_Write_Net_Client(FileName: String);
1064 var
1065 config: TConfig;
1066 begin
1067 e_WriteLog('Writing client config', TMsgType.Notify);
1069 config := TConfig.CreateFile(FileName);
1071 config.WriteStr('Client', 'LastIP', NetClientIP);
1072 config.WriteInt('Client', 'LastPort', NetClientPort);
1074 config.SaveFile(FileName);
1075 config.Free();
1076 end;
1078 initialization
1079 Randomize;
1080 machine := Random(10000)
1081 end.