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
): SArray
;
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
, utils
;
60 Time
, Time_Delta
, Time_Old
: Int64;
63 wNeedTimeReset
: Boolean = False;
64 //wWindowCreated: Boolean = False;
65 //wCursorShown: Boolean = False;
66 wMinimized
: Boolean = False;
67 //wNeedFree: Boolean = True;
68 wLoadingProgress
: Boolean = False;
69 wLoadingQuit
: Boolean = False;
70 {wWinPause: Byte = 0;}
72 ticksOverflow
: Int64 = -1;
73 lastTicks
: Uint32
= 0; // to detect overflow
75 {$IF not DEFINED(HEADLESS)}
76 curMsButState
: Word = 0;
82 function g_Window_SetDisplay(PreserveGL
: Boolean = False): Boolean;
84 mode
, cmode
: TSDL_DisplayMode
;
93 e_WriteLog('Setting display mode...', TMsgType
.Notify
);
95 wFlags
:= SDL_WINDOW_OPENGL
or SDL_WINDOW_RESIZABLE
;
96 if gFullscreen
then wFlags
:= wFlags
or SDL_WINDOW_FULLSCREEN
;
97 if gWinMaximized
then wFlags
:= wFlags
or SDL_WINDOW_MAXIMIZED
;
101 SDL_DestroyWindow(h_Wnd
);
107 mode
.w
:= gScreenWidth
;
108 mode
.h
:= gScreenHeight
;
110 mode
.refresh_rate
:= 0;
111 mode
.driverdata
:= nil;
112 if SDL_GetClosestDisplayMode(0, @mode
, @cmode
) = nil then
115 gScreenHeight
:= 600;
119 gScreenWidth
:= cmode
.w
;
120 gScreenHeight
:= cmode
.h
;
124 h_Wnd
:= SDL_CreateWindow(PChar(wTitle
), gWinRealPosX
, gWinRealPosY
, gScreenWidth
, gScreenHeight
, wFlags
);
125 if h_Wnd
= nil then Exit
;
127 SDL_GL_MakeCurrent(h_Wnd
, h_GL
);
128 SDL_ShowCursor(SDL_DISABLE
);
133 procedure ReShowCursor();
135 // TODO: what was this for?
138 function GetDisplayModes(dBPP
: DWORD
; var SelRes
: DWORD
): SArray
;
140 mode
: TSDL_DisplayMode
;
141 res
, i
, k
, n
, pw
, ph
: Integer;
143 SetLength(Result
, 0);
144 {$IFDEF HEADLESS}Exit
;{$ENDIF}
146 n
:= SDL_GetNumDisplayModes(0);
150 res
:= SDL_GetDisplayMode(0, i
, @mode
);
151 if res
< 0 then continue
;
152 if SDL_BITSPERPIXEL(mode
.format
) = gBPP
then continue
;
153 if (mode
.w
= pw
) and (mode
.h
= ph
) then continue
;
154 if (mode
.w
= gScreenWidth
) and (mode
.h
= gScreenHeight
) then
157 SetLength(Result
, k
);
158 Result
[k
-1] := IntToStr(mode
.w
) + 'x' + IntToStr(mode
.h
);
159 pw
:= mode
.w
; ph
:= mode
.h
162 e_WriteLog('SDL: Got ' + IntToStr(k
) + ' resolutions.', TMsgType
.Notify
);
165 procedure Sleep(ms
: LongWord);
170 procedure ChangeWindowSize();
172 gWinSizeX
:= gScreenWidth
;
173 gWinSizeY
:= gScreenHeight
;
174 {$IFDEF HEADLESS}Exit
;{$ENDIF}
175 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
176 g_Game_SetupScreenSize();
178 g_Game_ClearLoading();
179 g_Holmes_VidModeChanged();
182 function g_Window_SetSize(W
, H
: Word; FScreen
: Boolean): Boolean;
187 {$IFDEF HEADLESS}Exit
;{$ENDIF}
190 if (gScreenWidth
<> W
) or (gScreenHeight
<> H
) then
197 if gFullscreen
<> FScreen
then
200 gFullscreen
:= FScreen
;
206 g_Window_SetDisplay(Preserve
);
211 procedure resetKMState ();
213 {$IF not DEFINED(HEADLESS)}
219 function WindowEventHandler(ev
: TSDL_WindowEvent
): Boolean;
221 wActivate
, wDeactivate
: Boolean;
225 wDeactivate
:= False;
228 SDL_WINDOWEVENT_MOVED
:
230 if not (gFullscreen
or gWinMaximized
) then
232 gWinRealPosX
:= ev
.data1
;
233 gWinRealPosY
:= ev
.data2
;
237 SDL_WINDOWEVENT_MINIMIZED
:
241 if not wMinimized
then
243 e_ResizeWindow(0, 0);
246 if g_debug_WinMsgs
then
248 g_Console_Add('Now minimized');
249 e_WriteLog('[DEBUG] WinMsgs: Now minimized', TMsgType
.Notify
);
255 SDL_WINDOWEVENT_RESIZED
:
258 gScreenWidth
:= ev
.data1
;
259 gScreenHeight
:= ev
.data2
;
262 if g_debug_WinMsgs
then
264 g_Console_Add('Resized to ' + IntToStr(ev
.data1
) + 'x' + IntToStr(ev
.data2
));
265 e_WriteLog('[DEBUG] WinMsgs: Resized to ' + IntToStr(ev
.data1
) + 'x' + IntToStr(ev
.data2
), TMsgType
.Notify
);
269 SDL_WINDOWEVENT_EXPOSED
:
272 SDL_WINDOWEVENT_MAXIMIZED
:
277 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
281 if not gWinMaximized
then
283 gWinMaximized
:= True;
284 if g_debug_WinMsgs
then
286 g_Console_Add('Now maximized');
287 e_WriteLog('[DEBUG] WinMsgs: Now maximized', TMsgType
.Notify
);
292 SDL_WINDOWEVENT_RESTORED
:
297 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
301 if gWinMaximized
then
302 gWinMaximized
:= False;
303 if g_debug_WinMsgs
then
305 g_Console_Add('Now restored');
306 e_WriteLog('[DEBUG] WinMsgs: Now restored', TMsgType
.Notify
);
310 SDL_WINDOWEVENT_FOCUS_GAINED
:
314 //e_WriteLog('window gained focus!', MSG_NOTIFY);
315 g_Holmes_WindowFocused();
318 SDL_WINDOWEVENT_FOCUS_LOST
:
323 //e_WriteLog('window lost focus!', MSG_NOTIFY);
324 g_Holmes_WindowBlured();
332 e_WriteLog('deactivating window', TMsgType
.Notify
);
333 e_EnableInput
:= False;
334 e_ClearInputBuffer();
336 if gMuteWhenInactive
then
338 //e_WriteLog('deactivating sounds', MSG_NOTIFY);
339 e_MuteChannels(True);
342 if g_debug_WinMsgs
then
344 g_Console_Add('Now inactive');
345 e_WriteLog('[DEBUG] WinMsgs: Now inactive', TMsgType
.Notify
);
351 else if wActivate
then
353 if not gWinActive
then
355 //e_WriteLog('activating window', MSG_NOTIFY);
356 e_EnableInput
:= True;
358 if gMuteWhenInactive
then
360 //e_WriteLog('activating sounds', MSG_NOTIFY);
361 e_MuteChannels(False);
364 if g_debug_WinMsgs
then
366 g_Console_Add('Now active');
367 e_WriteLog('[DEBUG] WinMsgs: Now active', TMsgType
.Notify
);
375 function EventHandler(ev
: TSDL_Event
): Boolean;
380 {$IF not DEFINED(HEADLESS)}
385 function buildBut (b
: Byte): Word;
389 SDL_BUTTON_LEFT
: result
:= result
or THMouseEvent
.Left
;
390 SDL_BUTTON_MIDDLE
: result
:= result
or THMouseEvent
.Middle
;
391 SDL_BUTTON_RIGHT
: result
:= result
or THMouseEvent
.Right
;
395 {$IF not DEFINED(HEADLESS)}
396 procedure updateKBState ();
401 kbstate
:= SDL_GetKeyboardState(nil);
402 if (kbstate
[SDL_SCANCODE_LCTRL
] <> 0) or (kbstate
[SDL_SCANCODE_RCTRL
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModCtrl
;
403 if (kbstate
[SDL_SCANCODE_LALT
] <> 0) or (kbstate
[SDL_SCANCODE_RALT
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModAlt
;
404 if (kbstate
[SDL_SCANCODE_LSHIFT
] <> 0) or (kbstate
[SDL_SCANCODE_RSHIFT
] <> 0) then curKbState
:= curKbState
or THKeyEvent
.ModShift
;
410 {$IF not DEFINED(HEADLESS)}
416 Result
:= WindowEventHandler(ev
.window
);
420 if gExit
<> EXIT_QUIT
then
422 if not wLoadingProgress
then
428 wLoadingQuit
:= True;
433 SDL_KEYDOWN
, SDL_KEYUP
:
435 key
:= ev
.key
.keysym
.scancode
;
436 {$IF not DEFINED(HEADLESS)}
437 if (g_holmes_enabled
) then
439 if (ev
.type_
= SDL_KEYDOWN
) then kbev
.kind
:= THKeyEvent
.Press
else kbev
.kind
:= THKeyEvent
.Release
;
440 kbev
.scan
:= ev
.key
.keysym
.scancode
;
441 kbev
.sym
:= ev
.key
.keysym
.sym
;
442 kbev
.bstate
:= curMsButState
;
443 kbev
.kstate
:= curKbState
;
444 if g_Holmes_keyEvent(kbev
) then
446 if (ev
.type_
<> SDL_KEYDOWN
) then e_KeyUpDown(ev
.key
.keysym
.scancode
, false);
451 if (ev
.type_
= SDL_KEYDOWN
) then KeyPress(key
);
452 e_KeyUpDown(ev
.key
.keysym
.scancode
, (ev
.type_
= SDL_KEYDOWN
));
455 {$IF not DEFINED(HEADLESS)}
456 SDL_MOUSEBUTTONDOWN
, SDL_MOUSEBUTTONUP
:
458 msev
.dx
:= ev
.button
.x
-curMsX
;
459 msev
.dy
:= ev
.button
.y
-curMsY
;
460 curMsX
:= ev
.button
.x
;
461 curMsY
:= ev
.button
.y
;
462 if (ev
.type_
= SDL_MOUSEBUTTONDOWN
) then msev
.kind
:= THMouseEvent
.Press
else msev
.kind
:= THMouseEvent
.Release
;
463 msev
.but
:= buildBut(ev
.button
.button
);
466 if (msev
.but
<> 0) then
468 // ev.button.clicks: Byte
469 if (ev
.type_
= SDL_MOUSEBUTTONDOWN
) then curMsButState
:= curMsButState
or msev
.but
else curMsButState
:= curMsButState
and (not msev
.but
);
470 msev
.bstate
:= curMsButState
;
471 msev
.kstate
:= curKbState
;
472 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
477 if (ev
.wheel
.y
<> 0) then
480 msev
.dy
:= ev
.wheel
.y
;
481 msev
.kind
:= THMouseEvent
.Press
;
482 if (ev
.wheel
.y
< 0) then msev
.but
:= THMouseEvent
.WheelUp
else msev
.but
:= THMouseEvent
.WheelDown
;
485 msev
.bstate
:= curMsButState
;
486 msev
.kstate
:= curKbState
;
487 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
492 msev
.dx
:= ev
.button
.x
-curMsX
;
493 msev
.dy
:= ev
.button
.y
-curMsY
;
494 curMsX
:= ev
.button
.x
;
495 curMsY
:= ev
.button
.y
;
496 msev
.kind
:= THMouseEvent
.Motion
;
500 msev
.bstate
:= curMsButState
;
501 msev
.kstate
:= curKbState
;
502 if (g_holmes_enabled
) then g_Holmes_mouseEvent(msev
);
508 Utf8ToUnicode(@uc
, PChar(ev
.text.text), 1);
510 if (keychr
> 127) then keychr
:= Word(wchar2win(WideChar(keychr
)));
511 CharPress(AnsiChar(keychr
));
514 // other key presses and joysticks are handled in e_input
518 procedure SwapBuffers();
520 {$IF not DEFINED(HEADLESS)}
521 SDL_GL_SwapWindow(h_Wnd
);
525 procedure KillGLWindow();
527 if h_Wnd
<> nil then SDL_DestroyWindow(h_Wnd
);
528 if h_GL
<> nil then SDL_GL_DeleteContext(h_GL
);
531 //wWindowCreated := False;
534 function CreateGLWindow(Title
: PChar): Boolean;
540 gWinSizeX
:= gScreenWidth
;
541 gWinSizeY
:= gScreenHeight
;
544 e_WriteLog('Creating window', TMsgType
.Notify
);
546 if not g_Window_SetDisplay() then
549 e_WriteLog('Window creation error (resolution not supported?)', TMsgType
.Fatal
);
554 h_Gl
:= SDL_GL_CreateContext(h_Wnd
);
555 if h_Gl
= nil then Exit
;
557 //wWindowCreated := True;
559 e_ResizeWindow(gScreenWidth
, gScreenHeight
);
566 // windoze sux; in headless mode `GetTickCount()` (and SDL) returns shit
567 function GetTimer(): Int64;
571 QueryPerformanceFrequency(F
);
572 QueryPerformanceCounter(C
);
573 Result
:= Round(C
/F
*1000{000});
576 function GetTimer(): Int64;
581 t
:= SDL_GetTicks() {* 1000}; // TODO: do we really need microseconds here? k8: NOPE!
582 if ticksOverflow
= -1 then
589 if lastTicks
> t
then
591 // overflow, increment overflow ;-)
592 ticksOverflow
:= ticksOverflow
+(Int64($ffffffff)+Int64(1));
593 tt
:= (Int64($ffffffff)+Int64(1))+Int64(t
);
594 t
:= Uint32(tt
-lastTicks
);
598 result
:= ticksOverflow
+Int64(t
);
602 procedure ResetTimer();
604 wNeedTimeReset
:= True;
607 procedure PushExitEvent();
611 ev
.type_
:= SDL_QUITEV
;
617 prevLoadingUpdateTime
: UInt64 = 0;
619 procedure ProcessLoading (forceUpdate
: Boolean=false);
625 FillChar(ev
, SizeOf(ev
), 0);
626 //wNeedFree := False;
627 wLoadingProgress
:= True;
628 while SDL_PollEvent(@ev
) > 0 do
630 if (ev
.type_
= SDL_QUITEV
) then
635 if (ev
.type_
= SDL_QUITEV
) or (gExit
= EXIT_QUIT
) then
637 wLoadingProgress
:= False;
641 if not wMinimized
then
645 prevLoadingUpdateTime
:= getTimeMilli();
649 stt
:= getTimeMilli();
650 if (stt
< prevLoadingUpdateTime
) or (stt
-prevLoadingUpdateTime
>= 400) then
652 prevLoadingUpdateTime
:= stt
;
659 if g_Texture_Get('INTER', ID
) then
661 e_DrawSize(ID
, 0, 0, 0, False, False, gScreenWidth
, gScreenHeight
)
665 e_Clear(GL_COLOR_BUFFER_BIT
, 0, 0, 0);
677 if NetMode
= NET_SERVER
then
683 if (NetMode
= NET_CLIENT
) and (NetState
<> NET_STATE_AUTH
) then g_Net_Client_UpdateWhileLoading();
685 wLoadingProgress
:= False;
688 function ProcessMessage(): Boolean;
694 FillChar(ev
, SizeOf(ev
), 0);
696 while SDL_PollEvent(@ev
) > 0 do
698 Result
:= EventHandler(ev
);
699 if ev
.type_
= SDL_QUITEV
then exit
;
703 Time_Delta
:= Time
- Time_Old
;
707 if wNeedTimeReset
then
709 Time_Delta
:= 28{(27777 div 1000)};
710 wNeedTimeReset
:= False;
713 g_Map_ProfilersBegin();
714 g_Mons_ProfilersBegin();
716 t
:= Time_Delta
div 28{(27777 div 1000)};
722 if NetMode
= NET_SERVER
then g_Net_Host_Update()
723 else if NetMode
= NET_CLIENT
then g_Net_Client_Update();
729 if NetMode
= NET_SERVER
then g_Net_Host_Update()
730 else if NetMode
= NET_CLIENT
then g_Net_Client_Update();
733 g_Map_ProfilersEnd();
734 g_Mons_ProfilersEnd();
742 if gExit
= EXIT_QUIT
then
748 // Âðåìÿ ïðåäûäóùåãî îáíîâëåíèÿ:
751 Time_Old
:= Time
- (Time_Delta
mod 28{(27777 div 1000)});
752 if (not wMinimized
) then
765 procedure ReDrawWindow
;
771 procedure InitOpenGL(VSync
: Boolean);
775 {$IFDEF HEADLESS}Exit
;{$ENDIF}
776 if VSync
then v
:= 1 else v
:= 0;
777 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION
, 2);
778 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION
, 1);
779 SDL_GL_SetAttribute(SDL_GL_RED_SIZE
, 8);
780 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE
, 8);
781 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE
, 8);
782 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE
, 16);
783 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
784 if gwin_k8_enable_light_experiments
then
786 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE
, 1); // lights; it is enough to have 1-bit stencil buffer for lighting
788 SDL_GL_SetSwapInterval(v
);
791 function glHasExtension (name
: AnsiString): Boolean;
796 extName
: ShortString;
799 if length(name
) = 0 then exit
;
800 exts
:= glGetString(GL_EXTENSIONS
);
801 if exts
= nil then exit
;
802 while (exts
[0] <> #0) and (exts
[0] = ' ') do Inc(exts
);
803 while exts
[0] <> #0 do
805 if gwin_dump_extensions
then
808 while (exts
[i
] <> #0) and (exts
[i
] <> ' ') do Inc(i
);
811 e_WriteLog('FUUUUUUUUUUUUU', TMsgType
.Warning
);
815 Move(exts
^, extName
[1], i
);
816 extName
[0] := Char(i
);
817 e_WriteLog(Format('EXT: %s', [extName
]), TMsgType
.Notify
);
821 for i
:= 0 to length(name
)-1 do
823 if exts
[i
] = #0 then begin found
:= false; break
; end;
824 if exts
[i
] <> name
[i
+1] then begin found
:= false; break
; end;
826 if found
and ((exts
[length(name
)] = #0) or (exts
[length(name
)] = ' ')) then begin result
:= true; exit
; end;
827 while (exts
[0] <> #0) and (exts
[0] <> ' ') do Inc(exts
);
828 while (exts
[0] <> #0) and (exts
[0] = ' ') do Inc(exts
);
832 function SDLMain(): Integer;
835 {$IF not DEFINED(HEADLESS)}
842 e_NoGraphics
:= True;
846 while (idx
<= ParamCount
) do
848 arg
:= ParamStr(idx
);
850 if arg
= '--opengl-dump-exts' then gwin_dump_extensions
:= true;
851 if arg
= '--twinkletwinkle' then gwin_k8_enable_light_experiments
:= true;
852 if arg
= '--jah' then g_profile_history_size
:= 100;
853 if arg
= '--no-particles' then gpart_dbg_enabled
:= false;
854 if arg
= '--no-los' then gmon_dbg_los_enabled
:= false;
856 if arg
= '--profile-render' then g_profile_frame_draw
:= true;
857 if arg
= '--profile-coldet' then g_profile_collision
:= true;
858 if arg
= '--profile-los' then g_profile_los
:= true;
860 if arg
= '--no-part-phys' then gpart_dbg_phys_enabled
:= false;
861 if arg
= '--no-part-physics' then gpart_dbg_phys_enabled
:= false;
862 if arg
= '--no-particles-phys' then gpart_dbg_phys_enabled
:= false;
863 if arg
= '--no-particles-physics' then gpart_dbg_phys_enabled
:= false;
864 if arg
= '--no-particle-phys' then gpart_dbg_phys_enabled
:= false;
865 if arg
= '--no-particle-physics' then gpart_dbg_phys_enabled
:= false;
867 {.$IF DEFINED(D2F_DEBUG)}
868 if arg
= '--aimline' then g_dbg_aimline_on
:= true;
871 if arg
= '--holmes' then begin g_holmes_enabled
:= true; g_Game_SetDebugMode(); end;
872 if (arg
= '--holmes-ui-scale') or (arg
= '-holmes-ui-scale') then
874 if (idx
<= ParamCount
) then
876 if not conParseFloat(g_holmes_ui_scale
, ParamStr(idx
)) then g_holmes_ui_scale
:= 1.0;
881 if (arg
= '--game-scale') or (arg
= '-game-scale') then
883 if (idx
<= ParamCount
) then
885 if not conParseFloat(g_dbg_scale
, ParamStr(idx
)) then g_dbg_scale
:= 1.0;
890 if (arg
= '--write-mapdef') or (arg
= '-write-mapdef') then
892 mdfo
:= createDiskFile('mapdef.txt');
893 mdfo
.WriteBuffer(defaultMapDef
[1], Length(defaultMapDef
));
899 e_WriteLog('Initializing OpenGL', TMsgType
.Notify
);
902 e_WriteLog('Creating GL window', TMsgType
.Notify
);
903 if not CreateGLWindow(PChar(Format('Doom 2D: Forever %s', [GAME_VERSION
]))) then
909 {EnumDisplayModes();}
912 gwin_k8_enable_light_experiments
:= false;
913 gwin_has_stencil
:= false;
914 glLegacyNPOT
:= false;
915 gwin_dump_extensions
:= false;
917 if gwin_k8_enable_light_experiments
then
919 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE
, @ltmp
);
920 e_WriteLog(Format('stencil buffer size: %d', [ltmp
]), TMsgType
.Warning
);
921 gwin_has_stencil
:= (ltmp
> 0);
925 gwin_has_stencil
:= false;
928 if not glHasExtension('GL_ARB_texture_non_power_of_two') then
930 e_WriteLog('Driver DID''T advertised NPOT textures support', TMsgType
.Warning
);
931 glLegacyNPOT
:= true;
935 e_WriteLog('Driver advertised NPOT textures support', TMsgType
.Notify
);
936 glLegacyNPOT
:= false;
938 gwin_dump_extensions
:= false;
942 Time_Old
:= GetTimer();
945 if ParamCount
> 0 then
946 g_Game_Process_Params();
949 if (not gGameOn
) and gAskLanguage
then
950 g_Menu_AskLanguage();
952 e_WriteLog('Entering the main loop', TMsgType
.Notify
);
954 while not ProcessMessage() do