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, either version 3 of the License, or
6 * (at your option) any later version.
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.
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/>.
16 {$INCLUDE ../shared/a_modes.inc}
24 function SDLMain(): Integer;
25 function GetTimer(): Int64;
26 procedure ResetTimer();
27 function CreateGLWindow(Title
: PChar): Boolean;
28 procedure KillGLWindow();
29 procedure PushExitEvent();
30 function ProcessMessage(): Boolean;
31 procedure ProcessLoading (forceUpdate
: Boolean=false);
32 procedure ReDrawWindow();
33 procedure SwapBuffers();
34 procedure Sleep(ms
: LongWord);
35 function GetDisplayModes(dBPP
: DWORD
; var SelRes
: DWORD
): SSArray
;
36 function g_Window_SetDisplay(PreserveGL
: Boolean = False): Boolean;
37 function g_Window_SetSize(W
, H
: Word; FScreen
: Boolean): Boolean;
40 gwin_dump_extensions
: Boolean = false;
41 gwin_has_stencil
: Boolean = false;
42 gwin_k8_enable_light_experiments
: Boolean = false;
43 g_dbg_aimline_on
: Boolean = false;
49 {$IFDEF WINDOWS}Windows
,{$ENDIF}
50 SysUtils
, Classes
, MAPDEF
,
51 SDL2
, GL
, GLExt
, e_graphics
, e_log
, e_texture
, g_main
,
52 g_console
, e_input
, g_options
, g_game
,
53 g_basic
, g_textures
, e_sound
, g_sound
, g_menu
, ENet
, g_net
,
54 g_map
, g_gfx
, g_monsters
, g_holmes
, xprofiler
;
60 Time
, Time_Delta
, Time_Old
: Int64;
63 wNeedTimeReset
: Boolean = False;
64 wMinimized
: Boolean = False;
65 wLoadingProgress
: Boolean = False;
66 wLoadingQuit
: Boolean = False;
68 ticksOverflow
: Int64 = -1;
69 lastTicks
: Uint32
= 0; // to detect overflow
71 {$IF not DEFINED(HEADLESS)}
72 curMsButState
: Word = 0;
78 function g_Window_SetDisplay(PreserveGL
: Boolean = False): Boolean;
80 mode
, cmode
: TSDL_DisplayMode
;
89 e_WriteLog('Setting display mode...', TMsgType
.Notify
);
91 wFlags
:= SDL_WINDOW_OPENGL
or SDL_WINDOW_RESIZABLE
;
92 if gFullscreen
then wFlags
:= wFlags
or SDL_WINDOW_FULLSCREEN
;
93 if gWinMaximized
then wFlags
:= wFlags
or SDL_WINDOW_MAXIMIZED
;
97 SDL_DestroyWindow(h_Wnd
);
103 mode
.w
:= gScreenWidth
;
104 mode
.h
:= gScreenHeight
;
106 mode
.refresh_rate
:= 0;
107 mode
.driverdata
:= nil;
108 if SDL_GetClosestDisplayMode(0, @mode
, @cmode
) = nil then
111 gScreenHeight
:= 600;
115 gScreenWidth
:= cmode
.w
;
116 gScreenHeight
:= cmode
.h
;
120 h_Wnd
:= SDL_CreateWindow(PChar(wTitle
), gWinRealPosX
, gWinRealPosY
, gScreenWidth
, gScreenHeight
, wFlags
);
121 if h_Wnd
= nil then Exit
;
123 SDL_GL_MakeCurrent(h_Wnd
, h_GL
);
124 SDL_ShowCursor(SDL_DISABLE
);
129 procedure ReShowCursor();
131 // TODO: what was this for?
134 function GetDisplayModes(dBPP
: DWORD
; var SelRes
: DWORD
): SSArray
;
136 mode
: TSDL_DisplayMode
;
137 res
, i
, k
, n
, pw
, ph
: Integer;
139 SetLength(Result
, 0);
140 {$IFDEF HEADLESS}Exit
;{$ENDIF}
142 n
:= SDL_GetNumDisplayModes(0);
146 res
:= SDL_GetDisplayMode(0, i
, @mode
);
147 if res
< 0 then continue
;
148 if SDL_BITSPERPIXEL(mode
.format
) = gBPP
then continue
;
149 if (mode
.w
= pw
) and (mode
.h
= ph
) then continue
;
150 if (mode
.w
= gScreenWidth
) and (mode
.h
= gScreenHeight
) then
153 SetLength(Result
, k
);
154 Result
[k
-1] := IntToStr(mode
.w
) + 'x' + IntToStr(mode
.h
);
155 pw
:= mode
.w
; ph
:= mode
.h
158 e_WriteLog('SDL: Got ' + IntToStr(k
) + ' resolutions.', TMsgType
.Notify
);
161 procedure Sleep(ms
: LongWord);
166 procedure ChangeWindowSize();
168 gWinSizeX
:= gScreenWidth
;
169 gWinSizeY
:= gScreenHeight
;
170 {$IFDEF HEADLESS}Exit
;{$ENDIF}
171 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
172 g_Game_SetupScreenSize();
174 g_Game_ClearLoading();
175 g_Holmes_VidModeChanged();
178 function g_Window_SetSize(W
, H
: Word; FScreen
: Boolean): Boolean;
183 {$IFDEF HEADLESS}Exit
;{$ENDIF}
186 if (gScreenWidth
<> W
) or (gScreenHeight
<> H
) then
193 if gFullscreen
<> FScreen
then
196 gFullscreen
:= FScreen
;
202 g_Window_SetDisplay(Preserve
);
207 procedure resetKMState ();
209 {$IF not DEFINED(HEADLESS)}
215 function WindowEventHandler(ev
: TSDL_WindowEvent
): Boolean;
217 wActivate
, wDeactivate
: Boolean;
221 wDeactivate
:= False;
224 SDL_WINDOWEVENT_MOVED
:
226 if not (gFullscreen
or gWinMaximized
) then
228 gWinRealPosX
:= ev
.data1
;
229 gWinRealPosY
:= ev
.data2
;
233 SDL_WINDOWEVENT_MINIMIZED
:
237 if not wMinimized
then
239 e_ResizeWindow(0, 0);
242 if g_debug_WinMsgs
then
244 g_Console_Add('Now minimized');
245 e_WriteLog('[DEBUG] WinMsgs: Now minimized', TMsgType
.Notify
);
251 SDL_WINDOWEVENT_RESIZED
:
254 gScreenWidth
:= ev
.data1
;
255 gScreenHeight
:= ev
.data2
;
258 if g_debug_WinMsgs
then
260 g_Console_Add('Resized to ' + IntToStr(ev
.data1
) + 'x' + IntToStr(ev
.data2
));
261 e_WriteLog('[DEBUG] WinMsgs: Resized to ' + IntToStr(ev
.data1
) + 'x' + IntToStr(ev
.data2
), TMsgType
.Notify
);
265 SDL_WINDOWEVENT_EXPOSED
:
268 SDL_WINDOWEVENT_MAXIMIZED
:
273 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
277 if not gWinMaximized
then
279 gWinMaximized
:= True;
280 if g_debug_WinMsgs
then
282 g_Console_Add('Now maximized');
283 e_WriteLog('[DEBUG] WinMsgs: Now maximized', TMsgType
.Notify
);
288 SDL_WINDOWEVENT_RESTORED
:
293 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
297 if gWinMaximized
then
298 gWinMaximized
:= False;
299 if g_debug_WinMsgs
then
301 g_Console_Add('Now restored');
302 e_WriteLog('[DEBUG] WinMsgs: Now restored', TMsgType
.Notify
);
306 SDL_WINDOWEVENT_FOCUS_GAINED
:
310 //e_WriteLog('window gained focus!', MSG_NOTIFY);
311 g_Holmes_WindowFocused();
314 SDL_WINDOWEVENT_FOCUS_LOST
:
319 //e_WriteLog('window lost focus!', MSG_NOTIFY);
320 g_Holmes_WindowBlured();
328 e_WriteLog('deactivating window', TMsgType
.Notify
);
329 e_EnableInput
:= False;
330 e_ClearInputBuffer();
332 if gMuteWhenInactive
then
334 //e_WriteLog('deactivating sounds', MSG_NOTIFY);
335 e_MuteChannels(True);
338 if g_debug_WinMsgs
then
340 g_Console_Add('Now inactive');
341 e_WriteLog('[DEBUG] WinMsgs: Now inactive', TMsgType
.Notify
);
347 else if wActivate
then
349 if not gWinActive
then
351 //e_WriteLog('activating window', MSG_NOTIFY);
352 e_EnableInput
:= True;
354 if gMuteWhenInactive
then
356 //e_WriteLog('activating sounds', MSG_NOTIFY);
357 e_MuteChannels(False);
360 if g_debug_WinMsgs
then
362 g_Console_Add('Now active');
363 e_WriteLog('[DEBUG] WinMsgs: Now active', TMsgType
.Notify
);
371 function EventHandler(ev
: TSDL_Event
): Boolean;
376 {$IF not DEFINED(HEADLESS)}
381 function buildBut (b
: Byte): Word;
385 SDL_BUTTON_LEFT
: result
:= result
or THMouseEvent
.Left
;
386 SDL_BUTTON_MIDDLE
: result
:= result
or THMouseEvent
.Middle
;
387 SDL_BUTTON_RIGHT
: result
:= result
or THMouseEvent
.Right
;
391 {$IF not DEFINED(HEADLESS)}
392 procedure updateKBState ();
397 kbstate
:= SDL_GetKeyboardState(nil);
398 if (kbstate
[SDL_SCANCODE_LCTRL
] <> 0) or (kbstate
[SDL_SCANCODE_RCTRL
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModCtrl
;
399 if (kbstate
[SDL_SCANCODE_LALT
] <> 0) or (kbstate
[SDL_SCANCODE_RALT
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModAlt
;
400 if (kbstate
[SDL_SCANCODE_LSHIFT
] <> 0) or (kbstate
[SDL_SCANCODE_RSHIFT
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModShift
;
406 {$IF not DEFINED(HEADLESS)}
412 Result
:= WindowEventHandler(ev
.window
);
416 if gExit
<> EXIT_QUIT
then
418 if not wLoadingProgress
then
424 wLoadingQuit
:= True;
429 SDL_KEYDOWN
, SDL_KEYUP
:
431 key
:= ev
.key
.keysym
.scancode
;
432 {$IF not DEFINED(HEADLESS)}
433 if (g_holmes_enabled
) then
435 if (ev
.type_
= SDL_KEYDOWN
) then kbev
.kind
:= THKeyEvent
.Press
else kbev
.kind
:= THKeyEvent
.Release
;
436 kbev
.scan
:= ev
.key
.keysym
.scancode
;
437 kbev
.sym
:= ev
.key
.keysym
.sym
;
438 kbev
.bstate
:= curMsButState
;
439 kbev
.kstate
:= curKbState
;
440 if g_Holmes_keyEvent(kbev
) then
442 if (ev
.type_
<> SDL_KEYDOWN
) then e_KeyUpDown(ev
.key
.keysym
.scancode
, false);
447 if (ev
.type_
= SDL_KEYDOWN
) then KeyPress(key
);
448 e_KeyUpDown(ev
.key
.keysym
.scancode
, (ev
.type_
= SDL_KEYDOWN
));
451 {$IF not DEFINED(HEADLESS)}
452 SDL_MOUSEBUTTONDOWN
, SDL_MOUSEBUTTONUP
:
454 msev
.dx
:= ev
.button
.x
-curMsX
;
455 msev
.dy
:= ev
.button
.y
-curMsY
;
456 curMsX
:= ev
.button
.x
;
457 curMsY
:= ev
.button
.y
;
458 if (ev
.type_
= SDL_MOUSEBUTTONDOWN
) then msev
.kind
:= THMouseEvent
.Press
else msev
.kind
:= THMouseEvent
.Release
;
459 msev
.but
:= buildBut(ev
.button
.button
);
462 if (msev
.but
<> 0) then
464 // ev.button.clicks: Byte
465 if (ev
.type_
= SDL_MOUSEBUTTONDOWN
) then curMsButState
:= curMsButState
or msev
.but
else curMsButState
:= curMsButState
and (not msev
.but
);
466 msev
.bstate
:= curMsButState
;
467 msev
.kstate
:= curKbState
;
468 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
473 if (ev
.wheel
.y
<> 0) then
476 msev
.dy
:= ev
.wheel
.y
;
477 msev
.kind
:= THMouseEvent
.Press
;
478 if (ev
.wheel
.y
< 0) then msev
.but
:= THMouseEvent
.WheelUp
else msev
.but
:= THMouseEvent
.WheelDown
;
481 msev
.bstate
:= curMsButState
;
482 msev
.kstate
:= curKbState
;
483 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
488 msev
.dx
:= ev
.button
.x
-curMsX
;
489 msev
.dy
:= ev
.button
.y
-curMsY
;
490 curMsX
:= ev
.button
.x
;
491 curMsY
:= ev
.button
.y
;
492 msev
.kind
:= THMouseEvent
.Motion
;
496 msev
.bstate
:= curMsButState
;
497 msev
.kstate
:= curKbState
;
498 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
504 Utf8ToUnicode(@uc
, PChar(ev
.text.text), 1);
506 if (keychr
> 127) then keychr
:= Word(wchar2win(WideChar(keychr
)));
507 CharPress(AnsiChar(keychr
));
510 // other key presses and joysticks are handled in e_input
514 procedure SwapBuffers();
516 {$IF not DEFINED(HEADLESS)}
517 SDL_GL_SwapWindow(h_Wnd
);
521 procedure KillGLWindow();
523 if h_Wnd
<> nil then SDL_DestroyWindow(h_Wnd
);
524 if h_GL
<> nil then SDL_GL_DeleteContext(h_GL
);
529 function CreateGLWindow(Title
: PChar): Boolean;
535 gWinSizeX
:= gScreenWidth
;
536 gWinSizeY
:= gScreenHeight
;
539 e_WriteLog('Creating window', TMsgType
.Notify
);
541 if not g_Window_SetDisplay() then
544 e_WriteLog('Window creation error (resolution not supported?)', TMsgType
.Fatal
);
549 h_Gl
:= SDL_GL_CreateContext(h_Wnd
);
550 if h_Gl
= nil then Exit
;
553 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
560 // windoze sux; in headless mode `GetTickCount()` (and SDL) returns shit
561 function GetTimer(): Int64;
565 QueryPerformanceFrequency(F
);
566 QueryPerformanceCounter(C
);
567 Result
:= Round(C
/F
*1000{000});
570 function GetTimer(): Int64;
575 t
:= SDL_GetTicks() {* 1000}; // TODO: do we really need microseconds here? k8: NOPE!
576 if ticksOverflow
= -1 then
583 if lastTicks
> t
then
585 // overflow, increment overflow ;-)
586 ticksOverflow
:= ticksOverflow
+(Int64($ffffffff)+Int64(1));
587 tt
:= (Int64($ffffffff)+Int64(1))+Int64(t
);
588 t
:= Uint32(tt
-lastTicks
);
592 result
:= ticksOverflow
+Int64(t
);
596 procedure ResetTimer();
598 wNeedTimeReset
:= True;
601 procedure PushExitEvent();
605 ev
.type_
:= SDL_QUITEV
;
611 prevLoadingUpdateTime
: UInt64 = 0;
613 procedure ProcessLoading (forceUpdate
: Boolean=false);
619 FillChar(ev
, SizeOf(ev
), 0);
620 wLoadingProgress
:= True;
621 while SDL_PollEvent(@ev
) > 0 do
623 if (ev
.type_
= SDL_QUITEV
) then
627 if (ev
.type_
= SDL_QUITEV
) or (gExit
= EXIT_QUIT
) then
629 wLoadingProgress
:= False;
633 if not wMinimized
then
637 prevLoadingUpdateTime
:= getTimeMilli();
641 stt
:= getTimeMilli();
642 if (stt
< prevLoadingUpdateTime
) or (stt
-prevLoadingUpdateTime
>= 400) then
644 prevLoadingUpdateTime
:= stt
;
651 if g_Texture_Get('INTER', ID
) then
653 e_DrawSize(ID
, 0, 0, 0, False, False, gScreenWidth
, gScreenHeight
)
657 e_Clear(GL_COLOR_BUFFER_BIT
, 0, 0, 0);
669 if NetMode
= NET_SERVER
then
675 if (NetMode
= NET_CLIENT
) and (NetState
<> NET_STATE_AUTH
) then g_Net_Client_UpdateWhileLoading();
677 wLoadingProgress
:= False;
680 function ProcessMessage(): Boolean;
686 FillChar(ev
, SizeOf(ev
), 0);
688 while SDL_PollEvent(@ev
) > 0 do
690 Result
:= EventHandler(ev
);
691 if ev
.type_
= SDL_QUITEV
then exit
;
695 Time_Delta
:= Time
- Time_Old
;
699 if wNeedTimeReset
then
702 wNeedTimeReset
:= False;
705 g_Map_ProfilersBegin();
706 g_Mons_ProfilersBegin();
708 t
:= Time_Delta
div 28;
714 if NetMode
= NET_SERVER
then g_Net_Host_Update()
715 else if NetMode
= NET_CLIENT
then g_Net_Client_Update();
721 if NetMode
= NET_SERVER
then g_Net_Host_Update()
722 else if NetMode
= NET_CLIENT
then g_Net_Client_Update();
725 g_Map_ProfilersEnd();
726 g_Mons_ProfilersEnd();
734 if gExit
= EXIT_QUIT
then
740 // Âðåìÿ ïðåäûäóùåãî îáíîâëåíèÿ:
743 Time_Old
:= Time
-(Time_Delta
mod 28);
744 if (not wMinimized
) then
757 procedure ReDrawWindow
;
763 procedure InitOpenGL(VSync
: Boolean);
767 {$IFDEF HEADLESS}Exit
;{$ENDIF}
768 if VSync
then v
:= 1 else v
:= 0;
769 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION
, 2);
770 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION
, 1);
771 SDL_GL_SetAttribute(SDL_GL_RED_SIZE
, 8);
772 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE
, 8);
773 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE
, 8);
774 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE
, 16);
775 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
776 if gwin_k8_enable_light_experiments
then
778 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE
, 1); // lights; it is enough to have 1-bit stencil buffer for lighting
780 SDL_GL_SetSwapInterval(v
);
783 function glHasExtension (name
: AnsiString): Boolean;
788 extName
: ShortString;
791 if length(name
) = 0 then exit
;
792 exts
:= glGetString(GL_EXTENSIONS
);
793 if exts
= nil then exit
;
794 while (exts
[0] <> #0) and (exts
[0] = ' ') do Inc(exts
);
795 while exts
[0] <> #0 do
797 if gwin_dump_extensions
then
800 while (exts
[i
] <> #0) and (exts
[i
] <> ' ') do Inc(i
);
803 e_WriteLog('FUUUUUUUUUUUUU', TMsgType
.Warning
);
807 Move(exts
^, extName
[1], i
);
808 extName
[0] := Char(i
);
809 e_WriteLog(Format('EXT: %s', [extName
]), TMsgType
.Notify
);
813 for i
:= 0 to length(name
)-1 do
815 if exts
[i
] = #0 then begin found
:= false; break
; end;
816 if exts
[i
] <> name
[i
+1] then begin found
:= false; break
; end;
818 if found
and ((exts
[length(name
)] = #0) or (exts
[length(name
)] = ' ')) then begin result
:= true; exit
; end;
819 while (exts
[0] <> #0) and (exts
[0] <> ' ') do Inc(exts
);
820 while (exts
[0] <> #0) and (exts
[0] = ' ') do Inc(exts
);
824 function SDLMain(): Integer;
827 {$IF not DEFINED(HEADLESS)}
834 e_NoGraphics
:= True;
838 while (idx
<= ParamCount
) do
840 arg
:= ParamStr(idx
);
842 if arg
= '--opengl-dump-exts' then gwin_dump_extensions
:= true;
843 if arg
= '--twinkletwinkle' then gwin_k8_enable_light_experiments
:= true;
844 if arg
= '--jah' then g_profile_history_size
:= 100;
845 if arg
= '--no-particles' then gpart_dbg_enabled
:= false;
846 if arg
= '--no-los' then gmon_dbg_los_enabled
:= false;
848 if arg
= '--profile-render' then g_profile_frame_draw
:= true;
849 if arg
= '--profile-coldet' then g_profile_collision
:= true;
850 if arg
= '--profile-los' then g_profile_los
:= true;
852 if arg
= '--no-part-phys' then gpart_dbg_phys_enabled
:= false;
853 if arg
= '--no-part-physics' then gpart_dbg_phys_enabled
:= false;
854 if arg
= '--no-particles-phys' then gpart_dbg_phys_enabled
:= false;
855 if arg
= '--no-particles-physics' then gpart_dbg_phys_enabled
:= false;
856 if arg
= '--no-particle-phys' then gpart_dbg_phys_enabled
:= false;
857 if arg
= '--no-particle-physics' then gpart_dbg_phys_enabled
:= false;
859 {.$IF DEFINED(D2F_DEBUG)}
860 if arg
= '--aimline' then g_dbg_aimline_on
:= true;
863 if arg
= '--holmes' then begin g_holmes_enabled
:= true; g_Game_SetDebugMode(); end;
864 if (arg
= '--holmes-ui-scale') or (arg
= '-holmes-ui-scale') then
866 if (idx
<= ParamCount
) then
868 if not conParseFloat(g_holmes_ui_scale
, ParamStr(idx
)) then g_holmes_ui_scale
:= 1.0;
873 if (arg
= '--game-scale') or (arg
= '-game-scale') then
875 if (idx
<= ParamCount
) then
877 if not conParseFloat(g_dbg_scale
, ParamStr(idx
)) then g_dbg_scale
:= 1.0;
882 if (arg
= '--write-mapdef') or (arg
= '-write-mapdef') then
884 mdfo
:= createDiskFile('mapdef.txt');
885 mdfo
.WriteBuffer(defaultMapDef
[1], Length(defaultMapDef
));
891 e_WriteLog('Initializing OpenGL', TMsgType
.Notify
);
894 e_WriteLog('Creating GL window', TMsgType
.Notify
);
895 if not CreateGLWindow(PChar(Format('Doom 2D: Forever %s', [GAME_VERSION
]))) then
901 {EnumDisplayModes();}
904 gwin_k8_enable_light_experiments
:= false;
905 gwin_has_stencil
:= false;
906 glLegacyNPOT
:= false;
907 gwin_dump_extensions
:= false;
909 if gwin_k8_enable_light_experiments
then
911 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE
, @ltmp
);
912 e_WriteLog(Format('stencil buffer size: %d', [ltmp
]), TMsgType
.Warning
);
913 gwin_has_stencil
:= (ltmp
> 0);
917 gwin_has_stencil
:= false;
920 if not glHasExtension('GL_ARB_texture_non_power_of_two') then
922 e_WriteLog('Driver DID''T advertised NPOT textures support', TMsgType
.Warning
);
923 glLegacyNPOT
:= true;
927 e_WriteLog('Driver advertised NPOT textures support', TMsgType
.Notify
);
928 glLegacyNPOT
:= false;
930 gwin_dump_extensions
:= false;
934 Time_Old
:= GetTimer();
937 if ParamCount
> 0 then
938 g_Game_Process_Params();
941 if (not gGameOn
) and gAskLanguage
then
942 g_Menu_AskLanguage();
944 e_WriteLog('Entering the main loop', TMsgType
.Notify
);
946 while not ProcessMessage() do