DEADSOFTWARE

alot of debugging code
[d2df-sdl.git] / src / game / g_window.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_window;
19 interface
21 uses
22 wadreader;
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();
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;
39 var
40 gwin_dump_extensions: Boolean = false;
41 gwin_has_stencil: Boolean = false;
42 gwin_k8_enable_light_experiments: Boolean = false;
45 // both for but and for bstate
46 const
47 MouseLeft = $0001;
48 MouseRight = $0002;
49 MouseMiddle = $0004;
50 MouseWheelUp = $0008;
51 MouseWheelDown = $0010;
53 type
54 // but=0: motion; but <0: release, do (-but) to get MouseXXX
55 // on press, bstate will contain pressed button; on release it won't
56 TMouseHandler = procedure (x, y, but: Integer; bstate: Integer);
58 var
59 evMouseCB: TMouseHandler = nil;
62 implementation
64 uses
65 {$IFDEF WINDOWS}Windows,{$ENDIF}
66 SDL2, GL, GLExt, e_graphics, e_log, g_main,
67 g_console, SysUtils, e_input, g_options, g_game,
68 g_basic, g_textures, e_sound, g_sound, g_menu, ENet, g_net,
69 g_map, g_gfx, g_monsters;
71 var
72 h_Wnd: PSDL_Window;
73 h_GL: TSDL_GLContext;
74 wFlags: LongWord = 0;
75 Time, Time_Delta, Time_Old: Int64;
76 flag: Boolean;
77 wTitle: PChar = nil;
78 wNeedTimeReset: Boolean = False;
79 //wWindowCreated: Boolean = False;
80 //wCursorShown: Boolean = False;
81 wMinimized: Boolean = False;
82 //wNeedFree: Boolean = True;
83 wLoadingProgress: Boolean = False;
84 wLoadingQuit: Boolean = False;
85 {wWinPause: Byte = 0;}
86 {$IFNDEF WINDOWS}
87 ticksOverflow: Int64 = -1;
88 lastTicks: Uint32 = 0; // to detect overflow
89 {$ENDIF}
90 curMsButState: Integer = 0;
91 curMsX: Integer = 0;
92 curMsY: Integer = 0;
94 const
95 // TODO: move this to a separate file
96 CP1251: array [0..127] of Word = (
97 $0402,$0403,$201A,$0453,$201E,$2026,$2020,$2021,$20AC,$2030,$0409,$2039,$040A,$040C,$040B,$040F,
98 $0452,$2018,$2019,$201C,$201D,$2022,$2013,$2014,$003F,$2122,$0459,$203A,$045A,$045C,$045B,$045F,
99 $00A0,$040E,$045E,$0408,$00A4,$0490,$00A6,$00A7,$0401,$00A9,$0404,$00AB,$00AC,$00AD,$00AE,$0407,
100 $00B0,$00B1,$0406,$0456,$0491,$00B5,$00B6,$00B7,$0451,$2116,$0454,$00BB,$0458,$0405,$0455,$0457,
101 $0410,$0411,$0412,$0413,$0414,$0415,$0416,$0417,$0418,$0419,$041A,$041B,$041C,$041D,$041E,$041F,
102 $0420,$0421,$0422,$0423,$0424,$0425,$0426,$0427,$0428,$0429,$042A,$042B,$042C,$042D,$042E,$042F,
103 $0430,$0431,$0432,$0433,$0434,$0435,$0436,$0437,$0438,$0439,$043A,$043B,$043C,$043D,$043E,$043F,
104 $0440,$0441,$0442,$0443,$0444,$0445,$0446,$0447,$0448,$0449,$044A,$044B,$044C,$044D,$044E,$044F
105 );
107 // TODO: make a transition table or something
108 function WCharToCP1251(wc: Word): Word;
109 var
110 n: Word;
111 begin
112 Result := 0;
113 for n := 0 to 127 do
114 if CP1251[n] = wc then begin Result := n; break end;
115 Result := Result + 128;
116 end;
118 function g_Window_SetDisplay(PreserveGL: Boolean = False): Boolean;
119 var
120 mode, cmode: TSDL_DisplayMode;
121 begin
122 {$IFDEF HEADLESS}
123 Result := True;
124 Exit;
125 {$ENDIF}
127 Result := False;
129 e_WriteLog('Setting display mode...', MSG_NOTIFY);
131 wFlags := SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE;
132 if gFullscreen then wFlags := wFlags or SDL_WINDOW_FULLSCREEN;
133 if gWinMaximized then wFlags := wFlags or SDL_WINDOW_MAXIMIZED;
135 if h_Wnd <> nil then
136 begin
137 SDL_DestroyWindow(h_Wnd);
138 h_Wnd := nil;
139 end;
141 if gFullscreen then
142 begin
143 mode.w := gScreenWidth;
144 mode.h := gScreenHeight;
145 mode.format := 0;
146 mode.refresh_rate := 0;
147 mode.driverdata := nil;
148 if SDL_GetClosestDisplayMode(0, @mode, @cmode) = nil then
149 begin
150 gScreenWidth := 800;
151 gScreenHeight := 600;
152 end
153 else
154 begin
155 gScreenWidth := cmode.w;
156 gScreenHeight := cmode.h;
157 end;
158 end;
160 h_Wnd := SDL_CreateWindow(PChar(wTitle), gWinRealPosX, gWinRealPosY, gScreenWidth, gScreenHeight, wFlags);
161 if h_Wnd = nil then Exit;
163 SDL_GL_MakeCurrent(h_Wnd, h_GL);
164 SDL_ShowCursor(SDL_DISABLE);
166 Result := True;
167 end;
169 procedure ReShowCursor();
170 begin
171 // TODO: what was this for?
172 end;
174 function GetDisplayModes(dBPP: DWORD; var SelRes: DWORD): SArray;
175 var
176 mode: TSDL_DisplayMode;
177 res, i, k, n, pw, ph: Integer;
178 begin
179 SetLength(Result, 0);
180 {$IFDEF HEADLESS}Exit;{$ENDIF}
181 k := 0; SelRes := 0;
182 n := SDL_GetNumDisplayModes(0);
183 pw := 0; ph := 0;
184 for i := 0 to n do
185 begin
186 res := SDL_GetDisplayMode(0, i, @mode);
187 if res < 0 then continue;
188 if SDL_BITSPERPIXEL(mode.format) = gBPP then continue;
189 if (mode.w = pw) and (mode.h = ph) then continue;
190 if (mode.w = gScreenWidth) and (mode.h = gScreenHeight) then
191 SelRes := k;
192 Inc(k);
193 SetLength(Result, k);
194 Result[k-1] := IntToStr(mode.w) + 'x' + IntToStr(mode.h);
195 pw := mode.w; ph := mode.h
196 end;
198 e_WriteLog('SDL: Got ' + IntToStr(k) + ' resolutions.', MSG_NOTIFY);
199 end;
201 procedure Sleep(ms: LongWord);
202 begin
203 SDL_Delay(ms);
204 end;
206 procedure ChangeWindowSize();
207 begin
208 gWinSizeX := gScreenWidth;
209 gWinSizeY := gScreenHeight;
210 {$IFDEF HEADLESS}Exit;{$ENDIF}
211 e_ResizeWindow(gScreenWidth, gScreenHeight);
212 g_Game_SetupScreenSize();
213 g_Menu_Reset();
214 g_Game_ClearLoading();
215 end;
217 function g_Window_SetSize(W, H: Word; FScreen: Boolean): Boolean;
218 var
219 Preserve: Boolean;
220 begin
221 Result := False;
222 {$IFDEF HEADLESS}Exit;{$ENDIF}
223 Preserve := False;
225 if (gScreenWidth <> W) or (gScreenHeight <> H) then
226 begin
227 Result := True;
228 gScreenWidth := W;
229 gScreenHeight := H;
230 end;
232 if gFullscreen <> FScreen then
233 begin
234 Result := True;
235 gFullscreen := FScreen;
236 Preserve := True;
237 end;
239 if Result then
240 begin
241 g_Window_SetDisplay(Preserve);
242 ChangeWindowSize();
243 end;
244 end;
246 function WindowEventHandler(ev: TSDL_WindowEvent): Boolean;
247 var
248 wActivate, wDeactivate: Boolean;
249 begin
250 Result := False;
251 wActivate := False;
252 wDeactivate := False;
254 case ev.event of
255 SDL_WINDOWEVENT_MOVED:
256 begin
257 if not (gFullscreen or gWinMaximized) then
258 begin
259 gWinRealPosX := ev.data1;
260 gWinRealPosY := ev.data2;
261 end;
262 end;
264 SDL_WINDOWEVENT_MINIMIZED:
265 begin
266 curMsButState := 0;
267 if not wMinimized then
268 begin
269 e_ResizeWindow(0, 0);
270 wMinimized := True;
272 if g_debug_WinMsgs then
273 begin
274 g_Console_Add('Now minimized');
275 e_WriteLog('[DEBUG] WinMsgs: Now minimized', MSG_NOTIFY);
276 end;
277 wDeactivate := True;
278 end;
279 end;
281 SDL_WINDOWEVENT_RESIZED:
282 begin
283 gScreenWidth := ev.data1;
284 gScreenHeight := ev.data2;
285 ChangeWindowSize();
286 SwapBuffers();
287 if g_debug_WinMsgs then
288 begin
289 g_Console_Add('Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2));
290 e_WriteLog('[DEBUG] WinMsgs: Resized to ' + IntToStr(ev.data1) + 'x' + IntToStr(ev.data2), MSG_NOTIFY);
291 end;
292 end;
294 SDL_WINDOWEVENT_EXPOSED:
295 SwapBuffers();
297 SDL_WINDOWEVENT_MAXIMIZED:
298 begin
299 if wMinimized then
300 begin
301 e_ResizeWindow(gScreenWidth, gScreenHeight);
302 wMinimized := False;
303 wActivate := True;
304 end;
305 if not gWinMaximized then
306 begin
307 gWinMaximized := True;
308 if g_debug_WinMsgs then
309 begin
310 g_Console_Add('Now maximized');
311 e_WriteLog('[DEBUG] WinMsgs: Now maximized', MSG_NOTIFY);
312 end;
313 end;
314 end;
316 SDL_WINDOWEVENT_RESTORED:
317 begin
318 curMsButState := 0;
319 if wMinimized then
320 begin
321 e_ResizeWindow(gScreenWidth, gScreenHeight);
322 wMinimized := False;
323 wActivate := True;
324 end;
325 if gWinMaximized then
326 gWinMaximized := False;
327 if g_debug_WinMsgs then
328 begin
329 g_Console_Add('Now restored');
330 e_WriteLog('[DEBUG] WinMsgs: Now restored', MSG_NOTIFY);
331 end;
332 end;
334 SDL_WINDOWEVENT_FOCUS_GAINED:
335 begin
336 wActivate := True;
337 //e_WriteLog('window gained focus!', MSG_NOTIFY);
338 curMsButState := 0;
339 end;
341 SDL_WINDOWEVENT_FOCUS_LOST:
342 begin
343 wDeactivate := True;
344 //e_WriteLog('window lost focus!', MSG_NOTIFY);
345 curMsButState := 0;
346 end;
347 end;
349 if wDeactivate then
350 begin
351 if gWinActive then
352 begin
353 e_WriteLog('deactivating window', MSG_NOTIFY);
354 e_EnableInput := False;
355 e_ClearInputBuffer();
357 if gMuteWhenInactive then
358 begin
359 //e_WriteLog('deactivating sounds', MSG_NOTIFY);
360 e_MuteChannels(True);
361 end;
363 if g_debug_WinMsgs then
364 begin
365 g_Console_Add('Now inactive');
366 e_WriteLog('[DEBUG] WinMsgs: Now inactive', MSG_NOTIFY);
367 end;
369 gWinActive := False;
370 end;
371 end
372 else if wActivate then
373 begin
374 if not gWinActive then
375 begin
376 //e_WriteLog('activating window', MSG_NOTIFY);
377 e_EnableInput := True;
379 if gMuteWhenInactive then
380 begin
381 //e_WriteLog('activating sounds', MSG_NOTIFY);
382 e_MuteChannels(False);
383 end;
385 if g_debug_WinMsgs then
386 begin
387 g_Console_Add('Now active');
388 e_WriteLog('[DEBUG] WinMsgs: Now active', MSG_NOTIFY);
389 end;
391 gWinActive := True;
392 end;
393 end;
394 end;
396 function EventHandler(ev: TSDL_Event): Boolean;
397 var
398 key, keychr: Word;
399 uc: UnicodeChar;
400 //joy: Integer;
401 but: Integer;
403 function buildBut (b: Byte): Integer;
404 begin
405 result := 0;
406 case b of
407 SDL_BUTTON_LEFT: result := result or MouseLeft;
408 SDL_BUTTON_MIDDLE: result := result or MouseMiddle;
409 SDL_BUTTON_RIGHT: result := result or MouseRight;
410 end;
411 end;
413 function buildButState (b: Byte): Integer;
414 begin
415 result := 0;
416 case b of
417 SDL_BUTTON_LEFT: result := result or MouseLeft;
418 SDL_BUTTON_MIDDLE: result := result or MouseMiddle;
419 SDL_BUTTON_RIGHT: result := result or MouseRight;
420 end;
421 end;
422 begin
423 Result := False;
424 case ev.type_ of
425 SDL_WINDOWEVENT:
426 Result := WindowEventHandler(ev.window);
428 SDL_QUITEV:
429 begin
430 if gExit <> EXIT_QUIT then
431 begin
432 if not wLoadingProgress then
433 begin
434 g_Game_Free();
435 g_Game_Quit();
436 end
437 else
438 wLoadingQuit := True;
439 end;
440 Result := True;
441 end;
443 SDL_KEYDOWN:
444 begin
445 key := ev.key.keysym.scancode;
446 KeyPress(key);
447 end;
449 SDL_MOUSEBUTTONDOWN:
450 begin
451 curMsX := ev.button.x;
452 curMsY := ev.button.y;
453 but := buildBut(ev.button.button);
454 if (but <> 0) then
455 begin
456 // ev.button.clicks: Byte
457 curMsButState := curMsButState or but;
458 if assigned(evMouseCB) then evMouseCB(ev.button.x, ev.button.y, but, curMsButState);
459 end;
460 end;
461 SDL_MOUSEBUTTONUP:
462 begin
463 curMsX := ev.button.x;
464 curMsY := ev.button.y;
465 but := buildBut(ev.button.button);
466 if (but <> 0) then
467 begin
468 curMsButState := curMsButState and (not but);
469 if assigned(evMouseCB) then evMouseCB(ev.button.x, ev.button.y, -but, curMsButState);
470 end;
471 end;
472 SDL_MOUSEWHEEL:
473 begin
474 if assigned(evMouseCB) then
475 begin
476 (*
477 if (ev.wheel.direction = SDL_MOUSEWHEEL_FLIPPED) then
478 begin
479 ev.wheel.x := -ev.wheel.x;
480 ev.wheel.y := -ev.wheel.y;
481 end;
482 *)
483 if (ev.wheel.y > 0) then evMouseCB(curMsX, curMsY, MouseWheelUp, curMsButState);
484 if (ev.wheel.y < 0) then evMouseCB(curMsX, curMsY, MouseWheelDown, curMsButState);
485 end;
486 end;
487 SDL_MOUSEMOTION:
488 begin
489 curMsX := ev.motion.x;
490 curMsY := ev.motion.y;
491 if assigned(evMouseCB) then evMouseCB(curMsX, curMsY, 0, curMsButState);
492 end;
494 SDL_TEXTINPUT:
495 begin
496 Utf8ToUnicode(@uc, PChar(ev.text.text), 1);
497 keychr := Word(uc);
498 if (keychr > 127) then
499 keychr := WCharToCP1251(keychr);
500 CharPress(Chr(keychr));
501 end;
503 // other key presses and joysticks are handled in e_input
504 end;
505 end;
507 procedure SwapBuffers();
508 begin
509 {$IFDEF HEADLESS}Exit;{$ENDIF}
510 SDL_GL_SwapWindow(h_Wnd);
511 end;
513 procedure KillGLWindow();
514 begin
515 if h_Wnd <> nil then SDL_DestroyWindow(h_Wnd);
516 if h_GL <> nil then SDL_GL_DeleteContext(h_GL);
517 h_Wnd := nil;
518 h_GL := nil;
519 //wWindowCreated := False;
520 end;
522 function CreateGLWindow(Title: PChar): Boolean;
523 //var
524 // flags: LongWord;
525 begin
526 Result := False;
528 gWinSizeX := gScreenWidth;
529 gWinSizeY := gScreenHeight;
531 wTitle := Title;
532 e_WriteLog('Creating window', MSG_NOTIFY);
534 if not g_Window_SetDisplay() then
535 begin
536 KillGLWindow();
537 e_WriteLog('Window creation error (resolution not supported?)', MSG_FATALERROR);
538 exit;
539 end;
541 {$IFNDEF HEADLESS}
542 h_Gl := SDL_GL_CreateContext(h_Wnd);
543 if h_Gl = nil then Exit;
544 {$ENDIF}
545 //wWindowCreated := True;
547 e_ResizeWindow(gScreenWidth, gScreenHeight);
548 e_InitGL();
550 Result := True;
551 end;
553 {$IFDEF WINDOWS}
554 // windoze sux; in headless mode `GetTickCount()` (and SDL) returns shit
555 function GetTimer(): Int64;
556 var
557 F, C: Int64;
558 begin
559 QueryPerformanceFrequency(F);
560 QueryPerformanceCounter(C);
561 Result := Round(C/F*1000{000});
562 end;
563 {$ELSE}
564 function GetTimer(): Int64;
565 var
566 t: Uint32;
567 tt: Int64;
568 begin
569 t := SDL_GetTicks() {* 1000}; // TODO: do we really need microseconds here? k8: NOPE!
570 if ticksOverflow = -1 then
571 begin
572 ticksOverflow := 0;
573 lastTicks := t;
574 end
575 else
576 begin
577 if lastTicks > t then
578 begin
579 // overflow, increment overflow ;-)
580 ticksOverflow := ticksOverflow+(Int64($ffffffff)+Int64(1));
581 tt := (Int64($ffffffff)+Int64(1))+Int64(t);
582 t := Uint32(tt-lastTicks);
583 end;
584 end;
585 lastTicks := t;
586 result := ticksOverflow+Int64(t);
587 end;
588 {$ENDIF}
590 procedure ResetTimer();
591 begin
592 wNeedTimeReset := True;
593 end;
595 procedure PushExitEvent();
596 var
597 ev: TSDL_Event;
598 begin
599 ev.type_ := SDL_QUITEV;
600 SDL_PushEvent(@ev);
601 end;
603 procedure ProcessLoading();
604 var
605 ev: TSDL_Event;
606 ID: DWORD;
607 begin
608 FillChar(ev, SizeOf(ev), 0);
609 //wNeedFree := False;
610 wLoadingProgress := True;
611 while SDL_PollEvent(@ev) > 0 do
612 begin
613 if (ev.type_ = SDL_QUITEV) then
614 break;
615 end;
616 //wNeedFree := True;
618 if (ev.type_ = SDL_QUITEV) or (gExit = EXIT_QUIT) then
619 begin
620 wLoadingProgress := False;
621 exit;
622 end;
624 if not wMinimized then
625 begin
626 if g_Texture_Get('INTER', ID) then
627 e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
628 else
629 e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
631 DrawLoadingStat();
632 SwapBuffers();
634 ReShowCursor();
635 end;
637 e_SoundUpdate();
639 if NetMode = NET_SERVER then
640 g_Net_Host_Update
641 else
642 if (NetMode = NET_CLIENT) and (NetState <> NET_STATE_AUTH) then
643 g_Net_Client_UpdateWhileLoading;
644 wLoadingProgress := False;
645 end;
647 function ProcessMessage(): Boolean;
648 var
649 i, t: Integer;
650 ev: TSDL_Event;
651 begin
652 Result := False;
653 FillChar(ev, SizeOf(ev), 0);
655 while SDL_PollEvent(@ev) > 0 do
656 begin
657 Result := EventHandler(ev);
658 if ev.type_ = SDL_QUITEV then exit;
659 end;
661 Time := GetTimer();
662 Time_Delta := Time - Time_Old;
664 flag := False;
666 if wNeedTimeReset then
667 begin
668 Time_Delta := 28{(27777 div 1000)};
669 wNeedTimeReset := False;
670 end;
672 g_Map_ProfilersBegin();
673 g_Mons_ProfilersBegin();
675 t := Time_Delta div 28{(27777 div 1000)};
676 if t > 0 then
677 begin
678 flag := True;
679 for i := 1 to t do
680 begin
681 if NetMode = NET_SERVER then g_Net_Host_Update()
682 else if NetMode = NET_CLIENT then g_Net_Client_Update();
683 Update();
684 end;
685 end
686 else
687 begin
688 if NetMode = NET_SERVER then g_Net_Host_Update()
689 else if NetMode = NET_CLIENT then g_Net_Client_Update();
690 end;
692 g_Map_ProfilersEnd();
693 g_Mons_ProfilersEnd();
695 if wLoadingQuit then
696 begin
697 g_Game_Free();
698 g_Game_Quit();
699 end;
701 if gExit = EXIT_QUIT then
702 begin
703 Result := True;
704 Exit;
705 end;
707 // Âðåìÿ ïðåäûäóùåãî îáíîâëåíèÿ:
708 if flag then
709 begin
710 Time_Old := Time - (Time_Delta mod 28{(27777 div 1000)});
711 if (not wMinimized) then
712 begin
713 Draw();
714 SwapBuffers();
715 ReShowCursor();
716 end;
717 end
718 else
719 Sleep(1);
721 e_SoundUpdate();
722 end;
724 procedure ReDrawWindow;
725 begin
726 SwapBuffers();
727 ReShowCursor();
728 end;
730 procedure InitOpenGL(VSync: Boolean);
731 var
732 v: Byte;
733 begin
734 {$IFDEF HEADLESS}Exit;{$ENDIF}
735 if VSync then v := 1 else v := 0;
736 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
737 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
738 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
739 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
740 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
741 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
742 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
743 if gwin_k8_enable_light_experiments then
744 begin
745 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); // lights; it is enough to have 1-bit stencil buffer for lighting
746 end;
747 SDL_GL_SetSwapInterval(v);
748 end;
750 function glHasExtension (name: AnsiString): Boolean;
751 var
752 exts: PChar;
753 i: Integer;
754 found: Boolean;
755 extName: ShortString;
756 begin
757 result := false;
758 if length(name) = 0 then exit;
759 exts := glGetString(GL_EXTENSIONS);
760 if exts = nil then exit;
761 while (exts[0] <> #0) and (exts[0] = ' ') do Inc(exts);
762 while exts[0] <> #0 do
763 begin
764 if gwin_dump_extensions then
765 begin
766 i := 0;
767 while (exts[i] <> #0) and (exts[i] <> ' ') do Inc(i);
768 if i > 255 then
769 begin
770 e_WriteLog('FUUUUUUUUUUUUU', MSG_WARNING);
771 end
772 else
773 begin
774 Move(exts^, extName[1], i);
775 extName[0] := Char(i);
776 e_WriteLog(Format('EXT: %s', [extName]), MSG_NOTIFY);
777 end;
778 end;
779 found := true;
780 for i := 0 to length(name)-1 do
781 begin
782 if exts[i] = #0 then begin found := false; break; end;
783 if exts[i] <> name[i+1] then begin found := false; break; end;
784 end;
785 if found and ((exts[length(name)] = #0) or (exts[length(name)] = ' ')) then begin result := true; exit; end;
786 while (exts[0] <> #0) and (exts[0] <> ' ') do Inc(exts);
787 while (exts[0] <> #0) and (exts[0] = ' ') do Inc(exts);
788 end;
789 end;
791 function SDLMain(): Integer;
792 var
793 idx: Integer;
794 ltmp: Integer;
795 begin
796 {$IFDEF HEADLESS}
797 e_NoGraphics := True;
798 {$ENDIF}
800 for idx := 1 to ParamCount do
801 begin
802 if ParamStr(idx) = '--opengl-dump-exts' then gwin_dump_extensions := true;
803 if ParamStr(idx) = '--twinkletwinkle' then gwin_k8_enable_light_experiments := true;
804 if ParamStr(idx) = '--jah' then g_profile_history_size := 100;
805 //if ParamStr(idx) = '--tree-draw' then gdbg_map_use_tree_draw := true;
806 //if ParamStr(idx) = '--grid-draw' then gdbg_map_use_tree_draw := false;
807 //if ParamStr(idx) = '--tree-coldet' then gdbg_map_use_tree_coldet := true;
808 //if ParamStr(idx) = '--grid-coldet' then gdbg_map_use_tree_coldet := false;
809 if ParamStr(idx) = '--no-particles' then gpart_dbg_enabled := false;
810 if ParamStr(idx) = '--no-los' then gmon_dbg_los_enabled := false;
812 if ParamStr(idx) = '--profile-render' then g_profile_frame_draw := true;
813 if ParamStr(idx) = '--profile-coldet' then g_profile_collision := true;
814 if ParamStr(idx) = '--profile-los' then g_profile_los := true;
816 if ParamStr(idx) = '--no-part-phys' then gpart_dbg_phys_enabled := false;
817 if ParamStr(idx) = '--no-part-physics' then gpart_dbg_phys_enabled := false;
818 if ParamStr(idx) = '--no-particles-phys' then gpart_dbg_phys_enabled := false;
819 if ParamStr(idx) = '--no-particles-physics' then gpart_dbg_phys_enabled := false;
820 if ParamStr(idx) = '--no-particle-phys' then gpart_dbg_phys_enabled := false;
821 if ParamStr(idx) = '--no-particle-physics' then gpart_dbg_phys_enabled := false;
822 end;
824 //if gdbg_map_use_tree_draw then e_WriteLog('using TREE renderer', MSG_NOTIFY);
825 //if not gdbg_map_use_tree_draw then e_WriteLog('using GRID renderer', MSG_NOTIFY);
827 //if gdbg_map_use_tree_coldet then e_WriteLog('using TREE coldet', MSG_NOTIFY);
828 //if not gdbg_map_use_tree_coldet then e_WriteLog('using GRID coldet', MSG_NOTIFY);
830 e_WriteLog('Initializing OpenGL', MSG_NOTIFY);
831 InitOpenGL(gVSync);
833 e_WriteLog('Creating GL window', MSG_NOTIFY);
834 if not CreateGLWindow(PChar(Format('Doom 2D: Forever %s', [GAME_VERSION]))) then
835 begin
836 Result := 0;
837 exit;
838 end;
840 {EnumDisplayModes();}
842 if gwin_k8_enable_light_experiments then
843 begin
844 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, @ltmp);
845 e_WriteLog(Format('stencil buffer size: %d', [ltmp]), MSG_WARNING);
846 gwin_has_stencil := (ltmp > 0);
847 end
848 else
849 begin
850 gwin_has_stencil := false;
851 end;
853 if not glHasExtension('GL_ARB_texture_non_power_of_two') then
854 begin
855 e_WriteLog('Driver DID''T advertised NPOT textures support', MSG_WARNING);
856 glLegacyNPOT := true;
857 end
858 else
859 begin
860 e_WriteLog('Driver advertised NPOT textures support', MSG_NOTIFY);
861 glLegacyNPOT := false;
862 end;
863 gwin_dump_extensions := false;
865 Init();
866 Time_Old := GetTimer();
868 // Êîìàíäíàÿ ñòðîêà:
869 if ParamCount > 0 then
870 g_Game_Process_Params();
872 // Çàïðîñ ÿçûêà:
873 if (not gGameOn) and gAskLanguage then
874 g_Menu_AskLanguage();
876 e_WriteLog('Entering the main loop', MSG_NOTIFY);
878 while not ProcessMessage() do
879 { Main Loop } ;
881 Release();
882 KillGLWindow();
884 Result := 0;
885 end;
887 end.