1 (* Copyright (C) Doom 2D: Forever Developers
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, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE ../shared/a_modes.inc}
27 procedure KeyPress (K
: Word);
28 procedure CharPress (C
: AnsiChar);
35 {--- Read-only dirs ---}
42 AllMapDirs
: SSArray
; // Maps + Megawads
44 {--- Read-Write dirs ---}
50 ScreenshotDirs
: SSArray
;
51 MapDownloadDirs
: SSArray
;
52 WadDownloadDirs
: SSArray
;
57 {$INCLUDE ../nogl/noGLuses.inc}
58 {$IFDEF ENABLE_HOLMES}
59 g_holmes
, sdlcarcass
, fui_ctls
, fui_wadread
, fui_style
, fui_gfx_gl
,
67 wadreader
, e_log
, g_window
,
68 e_graphics
, e_input
, g_game
, g_console
, g_gui
,
69 e_sound
, g_options
, g_sound
, g_player
, g_basic
,
70 g_weapons
, SysUtils
, g_triggers
, MAPDEF
, g_map
, e_res
,
71 g_menu
, g_language
, g_net
, g_touch
, g_system
, g_res_downloader
,
77 charbuff
: packed array [0..15] of AnsiChar;
78 binPath
: AnsiString = '';
79 forceCurrentDir
: Boolean = false;
82 function GetBinaryPath (): AnsiString;
89 result
:= ExtractFilePath(ParamStr(0));
91 // it may be a symlink; do some guesswork here
92 sl
:= fpReadLink(ExtractFileName(ParamStr(0)));
93 if (sl
= ParamStr(0)) then
95 // use current directory, as we don't have anything better
100 result
:= fixSlashes(result
);
101 if (length(result
) > 0) and (result
[length(result
)] <> '/') then result
:= result
+'/';
104 procedure PrintDirs (msg
: AnsiString; dirs
: SSArray
);
107 e_LogWriteln(msg
+ ':');
109 e_LogWriteln(' ' + dir
);
113 var i
: Integer; rwdir
, rodir
: AnsiString; rwdirs
, rodirs
: SSArray
;
114 //first: Boolean = true;
116 procedure xput (s
: AnsiString);
121 AssignFile(f, 'zzz.log');
138 procedure AddPath (var arr
: SSArray
; str
: AnsiString; usecwd
: Boolean=true);
142 if (length(str
) = 0) then exit
;
143 //writeln('NEW PATH(0): ['+str+']');
144 if (forceCurrentDir
or usecwd
) then
146 str
:= fixSlashes(ExpandFileName(str
));
150 str
:= fixSlashes(str
);
151 if (not isAbsolutePath(str
)) then str
:= binPath
+str
;
152 while (length(str
) > 0) do
154 if (isRootPath(str
)) then exit
;
155 if (str
[length(str
)] = '/') then begin Delete(str
, length(str
), 1); continue
; end;
156 if (length(str
) >= 2) and (Copy(str
, length(str
)-1, 2) = '/.') then begin Delete(str
, length(str
)-1, 2); continue
; end;
160 if (length(str
) = 0) then exit
;
161 if (length(str
) > 255) then
163 xput('path too long: ['+str
+']');
164 raise Exception
.Create(Format('path "%s" too long', [str
]));
168 //writeln('<<<', ss, '>>> : [', str, ']');
169 if (ss
= str
) then exit
;
171 SetLength(arr
, Length(arr
)+1);
172 //arr[High(arr)] := ExpandFileName(str);
173 arr
[High(arr
)] := str
;
174 //writeln('NEW PATH(1): ['+str+']');
177 procedure AddDef (var dirs
: SSArray
; base
: SSArray
; append
: AnsiString);
180 if Length(dirs
) = 0 then
182 AddPath(dirs
, e_CatPath(s
, append
), false)
185 procedure AddDir (var dirs
: SSArray
; append
: AnsiString);
187 SetLength(dirs
, Length(dirs
) + 1);
188 dirs
[High(dirs
)] := append
191 function GetDefaultRODirs (): SSArray
;
193 var home
: AnsiString;
196 if forceCurrentDir
= false then
199 AddDir(result
, SDL_GetBasePath());
200 AddDir(result
, SDL_GetPrefPath('', 'doom2df'));
203 AddDir(result
, '/usr/share/doom2df');
204 AddDir(result
, '/usr/local/share/doom2df');
205 home
:= GetEnvironmentVariable('HOME');
207 AddDir(result
, e_CatPath(home
, '.doom2df'));
209 {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)}
210 AddDir(result
, SDL_AndroidGetInternalStoragePath());
211 if SDL_AndroidGetExternalStorageState() <> 0 then
212 AddDir(result
, SDL_AndroidGetExternalStoragePath());
218 function GetDefaultRWDirs (): SSArray
;
220 var home
: AnsiString;
223 if forceCurrentDir
= false then
225 {$IF DEFINED(USE_SDL2)}
226 AddDir(result
, SDL_GetPrefPath('', 'doom2df'));
229 home
:= GetEnvironmentVariable('HOME');
231 AddDir(result
, e_CatPath(home
, '.doom2df'));
233 {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)}
234 if SDL_AndroidGetExternalStorageState() <> 0 then
235 AddDir(result
, SDL_AndroidGetExternalStoragePath());
242 //GetDir(0, GameDir);
243 binPath
:= GetBinaryPath();
244 xput('binPath=['+binPath
+']');
246 for i
:= 1 to ParamCount
do
248 // use it only if you ketmar
249 if (ParamStr(i
) = '--cwd') then
251 forceCurrentDir
:= true;
257 while i
< ParamCount
do
263 rwdir
:= ParamStr(i
);
265 AddPath(LogDirs
, e_CatPath(rwdir
, ''));
266 AddPath(SaveDirs
, e_CatPath(rwdir
, 'data'));
267 AddPath(CacheDirs
, e_CatPath(rwdir
, 'data/cache'));
268 AddPath(ConfigDirs
, e_CatPath(rwdir
, ''));
269 AddPath(MapDownloadDirs
, e_CatPath(rwdir
, 'maps/downloads'));
270 AddPath(WadDownloadDirs
, e_CatPath(rwdir
, 'wads/downloads'));
271 AddPath(ScreenshotDirs
, e_CatPath(rwdir
, 'screenshots'));
273 AddPath(DataDirs
, e_CatPath(rwdir
, 'data'));
274 AddPath(ModelDirs
, e_CatPath(rwdir
, 'data/models'));
275 AddPath(MegawadDirs
, e_CatPath(rwdir
, 'maps/megawads'));
276 AddPath(MapDirs
, e_CatPath(rwdir
, 'maps'));
277 AddPath(WadDirs
, e_CatPath(rwdir
, 'wads'));
282 rodir
:= ParamStr(i
);
284 AddPath(DataDirs
, e_CatPath(rodir
, 'data'));
285 AddPath(ModelDirs
, e_CatPath(rodir
, 'data/models'));
286 AddPath(MegawadDirs
, e_CatPath(rodir
, 'maps/megawads'));
287 AddPath(MapDirs
, e_CatPath(rodir
, 'maps'));
288 AddPath(WadDirs
, e_CatPath(rodir
, 'wads'));
295 rodirs
:= GetDefaultRODirs();
296 AddDef(DataDirs
, rodirs
, 'data');
297 AddDef(ModelDirs
, rodirs
, 'data/models');
298 AddDef(MegawadDirs
, rodirs
, 'maps/megawads');
299 AddDef(MapDirs
, rodirs
, 'maps');
300 AddDef(WadDirs
, rodirs
, 'wads');
303 rwdirs
:= GetDefaultRWDirs();
304 AddDef(LogDirs
, rwdirs
, '');
305 AddDef(SaveDirs
, rwdirs
, 'data');
306 AddDef(CacheDirs
, rwdirs
, 'data/cache');
307 AddDef(ConfigDirs
, rwdirs
, '');
308 AddDef(MapDownloadDirs
, rwdirs
, 'maps/downloads');
309 AddDef(WadDownloadDirs
, rwdirs
, 'wads/downloads');
310 AddDef(ScreenshotDirs
, rwdirs
, 'screenshots');
312 for i
:= 0 to High(MapDirs
) do
313 AddPath(AllMapDirs
, MapDirs
[i
]);
314 for i
:= 0 to High(MegawadDirs
) do
315 AddPath(AllMapDirs
, MegawadDirs
[i
]);
317 if LogFileName
= '' then
319 rwdir
:= e_GetWriteableDir(LogDirs
, false);
323 LogFileName
:= e_CatPath(rwdir
, 'Doom2DF_H.log');
325 LogFileName
:= e_CatPath(rwdir
, 'Doom2DF.log');
330 xput('binPath=['+binPath
+']');
334 {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)}
335 var timiditycfg
: AnsiString;
340 conbufDumpToStdOut
:= true;
342 for i
:= 1 to ParamCount
do
344 if (ParamStr(i
) = '--con-stdout') then
346 conbufDumpToStdOut
:= true;
351 if LogFileName
<> '' then
352 e_InitLog(LogFileName
, TWriteMode
.WM_NEWFILE
);
353 e_InitWritelnDriver();
354 e_WriteLog('Doom 2D: Forever version ' + GAME_VERSION
+ ' proto ' + IntToStr(NET_PROTOCOL_VER
), TMsgType
.Notify
);
355 e_WriteLog('Build date: ' + GAME_BUILDDATE
+ ' ' + GAME_BUILDTIME
, TMsgType
.Notify
);
357 e_LogWritefln('BINARY PATH: [%s]', [binPath
], TMsgType
.Notify
);
359 PrintDirs('DataDirs', DataDirs
);
360 PrintDirs('ModelDirs', ModelDirs
);
361 PrintDirs('MegawadDirs', MegawadDirs
);
362 PrintDirs('MapDirs', MapDirs
);
363 PrintDirs('WadDirs', WadDirs
);
365 PrintDirs('LogDirs', LogDirs
);
366 PrintDirs('SaveDirs', SaveDirs
);
367 PrintDirs('CacheDirs', CacheDirs
);
368 PrintDirs('ConfigDirs', ConfigDirs
);
369 PrintDirs('ScreenshotDirs', ScreenshotDirs
);
370 PrintDirs('MapDownloadDirs', MapDownloadDirs
);
371 PrintDirs('WadDownloadDirs', WadDownloadDirs
);
373 GameWAD
:= e_FindWad(DataDirs
, 'GAME');
376 e_WriteLog('GAME.WAD not installed?', TMsgType
.Fatal
);
377 {$IF DEFINED(USE_SDL2) AND NOT DEFINED(HEADLESS)}
378 if forceCurrentDir
= false then
379 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR
, 'Doom 2D Forever', 'GAME.WAD not installed?', nil);
385 {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)}
386 timiditycfg
:= 'timidity.cfg';
387 if e_FindResource(ConfigDirs
, timiditycfg
) = true then
389 timiditycfg
:= ExpandFileName(timiditycfg
);
390 SetEnvVar('TIMIDITY_CFG', timiditycfg
);
391 e_LogWritefln('Set TIMIDITY_CFG = "%s"', [timiditycfg
]);
397 {$IFDEF ENABLE_HOLMES}
398 var flexloaded
: Boolean;
407 s
:= CONFIG_FILENAME
;
408 if e_FindResource(ConfigDirs
, s
) = true then
414 g_Options_SetDefault
;
415 g_Options_SetDefaultVideo
417 if sys_SetDisplayMode(gScreenWidth
, gScreenHeight
, gBPP
, gFullScreen
) = False then
418 raise Exception
.Create('Failed to set videomode on startup.');
421 e_WriteLog(gLanguage
, TMsgType
.Notify
);
422 g_Language_Set(gLanguage
);
424 {$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)}
426 if not fuiAddWad('flexui.wad') then
428 if not fuiAddWad('./data/flexui.wad') then fuiAddWad('./flexui.wad');
431 fuiGfxLoadFont('win8', 'flexui/fonts/win8.fuifont');
432 fuiGfxLoadFont('win14', 'flexui/fonts/win14.fuifont');
433 fuiGfxLoadFont('win16', 'flexui/fonts/win16.fuifont');
434 fuiGfxLoadFont('dos8', 'flexui/fonts/dos8.fuifont');
435 fuiGfxLoadFont('msx6', 'flexui/fonts/msx6.fuifont');
436 except on e
: Exception
do
438 writeln('ERROR loading FlexUI fonts');
451 e_LogWriteln('FlexUI: loading stylesheet...');
452 uiLoadStyles('flexui/widgets.wgs');
453 except on e
: TParserException
do
455 writeln('ERROR at (', e
.tokLine
, ',', e
.tokCol
, '): ', e
.message);
466 g_holmes_imfunctional
:= not flexloaded
;
468 if (not g_holmes_imfunctional
) then
471 uiContext
.font
:= 'win14';
474 if assigned(oglInitCB
) then oglInitCB
;
477 //g_Res_CreateDatabases(true); // it will be done before connecting to the server for the first time
479 e_WriteLog('Entering SDLMain', TMsgType
.Notify
);
485 {$IFDEF ENABLE_HOLMES}
486 if assigned(oglDeinitCB
) then oglDeinitCB
;
499 {$IFDEF USE_SDLMIXER}
500 NoSound
:= False; // hope env has set SDL_AUDIODRIVER to dummy
502 NoSound
:= True; // FMOD backend will sort it out
511 if (e_JoysticksAvailable > 0) then
512 e_WriteLog('Input: Joysticks available.', TMsgType.Notify)
514 e_WriteLog('Input: No Joysticks.', TMsgType.Notify);
517 if (not gNoSound
) then
519 e_WriteLog('Initializing sound system', TMsgType
.Notify
);
520 e_InitSoundSystem(NoSound
);
523 e_WriteLog('Init game', TMsgType
.Notify
);
526 FillChar(charbuff
, sizeof(charbuff
), ' ');
532 e_WriteLog('Releasing engine', TMsgType
.Notify
);
535 e_WriteLog('Releasing input', TMsgType
.Notify
);
540 e_WriteLog('Releasing sound', TMsgType
.Notify
);
541 e_ReleaseSoundSystem();
558 function Translit (const S
: AnsiString): AnsiString;
563 for i
:= 1 to Length(Result
) do
566 'É': Result
[i
] := 'Q';
567 'Ö': Result
[i
] := 'W';
568 'Ó': Result
[i
] := 'E';
569 'Ê': Result
[i
] := 'R';
570 'Å': Result
[i
] := 'T';
571 'Í': Result
[i
] := 'Y';
572 'Ã': Result
[i
] := 'U';
573 'Ø': Result
[i
] := 'I';
574 'Ù': Result
[i
] := 'O';
575 'Ç': Result
[i
] := 'P';
576 'Õ': Result
[i
] := '['; //Chr(219);
577 'Ú': Result
[i
] := ']'; //Chr(221);
578 'Ô': Result
[i
] := 'A';
579 'Û': Result
[i
] := 'S';
580 'Â': Result
[i
] := 'D';
581 'À': Result
[i
] := 'F';
582 'Ï': Result
[i
] := 'G';
583 'Ð': Result
[i
] := 'H';
584 'Î': Result
[i
] := 'J';
585 'Ë': Result
[i
] := 'K';
586 'Ä': Result
[i
] := 'L';
587 'Æ': Result
[i
] := ';'; //Chr(186);
588 'Ý': Result
[i
] := #39; //Chr(222);
589 'ß': Result
[i
] := 'Z';
590 '×': Result
[i
] := 'X';
591 'Ñ': Result
[i
] := 'C';
592 'Ì': Result
[i
] := 'V';
593 'È': Result
[i
] := 'B';
594 'Ò': Result
[i
] := 'N';
595 'Ü': Result
[i
] := 'M';
596 'Á': Result
[i
] := ','; //Chr(188);
597 'Þ': Result
[i
] := '.'; //Chr(190);
603 function CheckCheat (ct
: TStrings_Locale
; eofs
: Integer=0): Boolean;
608 ls2
:= Translit(CheatRus
[ct
]);
609 if length(ls1
) = 0 then ls1
:= '~';
610 if length(ls2
) = 0 then ls2
:= '~';
612 (Copy(charbuff
, 17-Length(ls1
)-eofs
, Length(ls1
)) = ls1
) or
613 (Translit(Copy(charbuff
, 17-Length(ls1
)-eofs
, Length(ls1
))) = ls1
) or
614 (Copy(charbuff
, 17-Length(ls2
)-eofs
, Length(ls2
)) = ls2
) or
615 (Translit(Copy(charbuff
, 17-Length(ls2
)-eofs
, Length(ls2
))) = ls2
);
617 if ct = I_GAME_CHEAT_JETPACK then
619 e_WriteLog('ls1: ['+ls1+']', MSG_NOTIFY);
620 e_WriteLog('ls2: ['+ls2+']', MSG_NOTIFY);
621 e_WriteLog('bf0: ['+Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))+']', MSG_NOTIFY);
622 e_WriteLog('bf1: ['+Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)))+']', MSG_NOTIFY);
623 e_WriteLog('bf2: ['+Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))+']', MSG_NOTIFY);
624 e_WriteLog('bf3: ['+Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)))+']', MSG_NOTIFY);
641 if (not gGameOn) or (not gCheats) or ((gGameSettings.GameType <> GT_SINGLE) and
642 (gGameSettings.GameMode <> GM_COOP) and (not gDebugMode))
643 or g_Game_IsNet then Exit;
645 if not gGameOn
then exit
;
646 if not conIsCheatsEnabled
then exit
;
648 s
:= 'SOUND_GAME_RADIO';
651 if CheckCheat(I_GAME_CHEAT_GODMODE
) then
653 if gPlayer1
<> nil then gPlayer1
.GodMode
:= not gPlayer1
.GodMode
;
654 if gPlayer2
<> nil then gPlayer2
.GodMode
:= not gPlayer2
.GodMode
;
658 if CheckCheat(I_GAME_CHEAT_WEAPONS
) then
660 if gPlayer1
<> nil then gPlayer1
.AllRulez(False);
661 if gPlayer2
<> nil then gPlayer2
.AllRulez(False);
665 if CheckCheat(I_GAME_CHEAT_HEALTH
) then
667 if gPlayer1
<> nil then gPlayer1
.AllRulez(True);
668 if gPlayer2
<> nil then gPlayer2
.AllRulez(True);
672 if CheckCheat(I_GAME_CHEAT_DEATH
) then
674 if gPlayer1
<> nil then gPlayer1
.Damage(CHEAT_DAMAGE
, 0, 0, 0, HIT_TRAP
);
675 if gPlayer2
<> nil then gPlayer2
.Damage(CHEAT_DAMAGE
, 0, 0, 0, HIT_TRAP
);
676 s
:= 'SOUND_MONSTER_HAHA';
680 if CheckCheat(I_GAME_CHEAT_DOORS
) then
682 g_Triggers_OpenAll();
686 if CheckCheat(I_GAME_CHEAT_NEXTMAP
) then
688 if gTriggers
<> nil then
689 for a
:= 0 to High(gTriggers
) do
690 if gTriggers
[a
].TriggerType
= TRIGGER_EXIT
then
692 gExitByTrigger
:= True;
693 //g_Game_ExitLevel(gTriggers[a].Data.MapName);
694 g_Game_ExitLevel(gTriggers
[a
].tgcMap
);
700 s2
:= Copy(charbuff
, 15, 2);
701 if CheckCheat(I_GAME_CHEAT_CHANGEMAP
, 2) and (s2
[1] >= '0') and (s2
[1] <= '9') and (s2
[2] >= '0') and (s2
[2] <= '9') then
703 if g_Map_Exist(gGameSettings
.WAD
+ ':\MAP' + s2
) then
711 if CheckCheat(I_GAME_CHEAT_FLY
) then
717 if CheckCheat(I_GAME_CHEAT_JUMPS
) then
719 VEL_JUMP
:= 30-VEL_JUMP
;
723 if CheckCheat(I_GAME_CHEAT_SPEED
) then
725 MAX_RUNVEL
:= 32-MAX_RUNVEL
;
729 if CheckCheat(I_GAME_CHEAT_SUIT
) then
731 if gPlayer1
<> nil then gPlayer1
.GiveItem(ITEM_SUIT
);
732 if gPlayer2
<> nil then gPlayer2
.GiveItem(ITEM_SUIT
);
736 if CheckCheat(I_GAME_CHEAT_AIR
) then
738 if gPlayer1
<> nil then gPlayer1
.GiveItem(ITEM_OXYGEN
);
739 if gPlayer2
<> nil then gPlayer2
.GiveItem(ITEM_OXYGEN
);
743 if CheckCheat(I_GAME_CHEAT_BERSERK
) then
745 if gPlayer1
<> nil then gPlayer1
.GiveItem(ITEM_MEDKIT_BLACK
);
746 if gPlayer2
<> nil then gPlayer2
.GiveItem(ITEM_MEDKIT_BLACK
);
750 if CheckCheat(I_GAME_CHEAT_JETPACK
) then
752 if gPlayer1
<> nil then gPlayer1
.GiveItem(ITEM_JETPACK
);
753 if gPlayer2
<> nil then gPlayer2
.GiveItem(ITEM_JETPACK
);
757 if CheckCheat(I_GAME_CHEAT_NOCLIP
) then
759 if gPlayer1
<> nil then gPlayer1
.SwitchNoClip
;
760 if gPlayer2
<> nil then gPlayer2
.SwitchNoClip
;
764 if CheckCheat(I_GAME_CHEAT_NOTARGET
) then
766 if gPlayer1
<> nil then gPlayer1
.NoTarget
:= not gPlayer1
.NoTarget
;
767 if gPlayer2
<> nil then gPlayer2
.NoTarget
:= not gPlayer2
.NoTarget
;
771 if CheckCheat(I_GAME_CHEAT_NORELOAD
) then
773 if gPlayer1
<> nil then gPlayer1
.NoReload
:= not gPlayer1
.NoReload
;
774 if gPlayer2
<> nil then gPlayer2
.NoReload
:= not gPlayer2
.NoReload
;
777 if CheckCheat(I_GAME_CHEAT_AIMLINE
) then
779 gAimLine
:= not gAimLine
;
782 if CheckCheat(I_GAME_CHEAT_AUTOMAP
) then
784 gShowMap
:= not gShowMap
;
794 procedure KeyPress (K
: Word);
804 if (g_ActiveWindow
<> nil) then
806 Msg
.Msg
:= WM_KEYDOWN
;
807 Msg
.WParam
:= VK_ESCAPE
;
808 g_ActiveWindow
.OnMessage(Msg
);
809 if (not g_Game_IsNet
) and (g_ActiveWindow
= nil) then g_Game_Pause(false); //Fn loves to do this
811 else if (gState
<> STATE_FOLD
) then
813 if gGameOn
or (gState
= STATE_INTERSINGLE
) or (gState
= STATE_INTERCUSTOM
) then
815 g_Game_InGameMenu(True);
817 else if (gExit
= 0) and (gState
<> STATE_SLIST
) then
819 if (gState
<> STATE_MENU
) then
821 if (NetMode
<> NET_NONE
) then
823 g_Game_StopAllSounds(True);
825 gState
:= STATE_MENU
;
829 g_GUI_ShowWindow('MainMenu');
830 g_Sound_PlayEx('MENU_OPEN');
835 IK_F2
, IK_F3
, IK_F4
, IK_F5
, IK_F6
, IK_F7
, IK_F10
:
836 begin // <F2> .. <F6> � <F12>
837 if gGameOn
and (not gConsoleShow
) and (not gChatShow
) then
839 while (g_ActiveWindow
<> nil) do g_GUI_HideWindow(False);
840 if (not g_Game_IsNet
) then g_Game_Pause(True);
842 IK_F2
: g_Menu_Show_SaveMenu();
843 IK_F3
: g_Menu_Show_LoadMenu();
844 IK_F4
: g_Menu_Show_GameSetGame();
845 IK_F5
: g_Menu_Show_OptionsVideo();
846 IK_F6
: g_Menu_Show_OptionsSound();
847 IK_F7
: g_Menu_Show_EndGameMenu();
848 IK_F10
: g_Menu_Show_QuitGameMenu();
855 gJustChatted
:= False;
856 if gConsoleShow
or gChatShow
then
858 g_Console_Control(K
);
860 else if (g_ActiveWindow
<> nil) then
862 Msg
.Msg
:= WM_KEYDOWN
;
864 g_ActiveWindow
.OnMessage(Msg
);
866 else if (gState
= STATE_MENU
) then
868 g_GUI_ShowWindow('MainMenu');
869 g_Sound_PlayEx('MENU_OPEN');
877 procedure CharPress (C
: AnsiChar);
882 if gConsoleShow
or gChatShow
then
886 else if (g_ActiveWindow
<> nil) then
889 Msg
.WParam
:= Ord(C
);
890 g_ActiveWindow
.OnMessage(Msg
);
894 for a
:= 0 to 14 do charbuff
[a
] := charbuff
[a
+1];
895 charbuff
[15] := upcase1251(C
);