1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "SDL.h"
7 #include "oglfunc.h"
8
9 #if !defined(_MSC_VER)
10 #ifndef _GNU_SOURCE
11 #define _GNU_SOURCE
12 #endif
13 #include <getopt.h>
14 #endif
15
16 #include "fixer.h"
17
18 #include "3dc.h"
19 #include "platform.h"
20 #include "inline.h"
21 #include "gamedef.h"
22 #include "gameplat.h"
23 #include "ffstdio.h"
24 #include "vision.h"
25 #include "comp_shp.h"
26 #include "avp_envinfo.h"
27 #include "stratdef.h"
28 #include "bh_types.h"
29 #include "avp_userprofile.h"
30 #include "pldnet.h"
31 #include "cdtrackselection.h"
32 #include "gammacontrol.h"
33 #include "opengl.h"
34 #include "avp_menus.h"
35 #include "avp_mp_config.h"
36 #include "npcsetup.h"
37 #include "cdplayer.h"
38 #include "hud.h"
39 #include "player.h"
40 #include "mempool.h"
41 #include "avpview.h"
42 #include "consbind.hpp"
43 #include "progress_bar.h"
44 #include "scrshot.hpp"
45 #include "version.h"
46 #include "fmv.h"
47
48 #if EMSCRIPTEN
49 #include <emscripten.h>
50 #endif
51
52 #if defined(__IPHONEOS__) || defined(__ANDROID__)
53 #define FIXED_WINDOW_SIZE 1
54 #endif
55
56 #if defined(__IPHONEOS__) || defined(__ANDROID__)
57 #define USE_OPENGL_ES 1
58 #endif
59
60 #warning WINDOW_SIZE_DEBUG is on in all builds
61 #if 1 //!defined(NDEBUG)
62 #define WINDOW_SIZE_DEBUG
63 #endif
64
65 static void main_loop(void);
66
67 void RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_CHAR(char Ch);
68 void RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(int wParam);
69
70 static int SDLCALL SDLEventFilter(void* userData, SDL_Event* event);
71
72 char LevelName[] = {"predbit6\0QuiteALongNameActually"}; /* the real way to load levels */
73
74 int DebouncedGotAnyKey;
75 unsigned char DebouncedKeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
76 int GotJoystick;
77 int GotMouse;
78 int JoystickEnabled;
79 int MouseVelX;
80 int MouseVelY;
81
82 extern int ScanDrawMode;
83 extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
84 extern unsigned char KeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
85 extern unsigned char GotAnyKey;
86 extern int NormalFrameTime;
87
88 SDL_Window *window;
89 SDL_GLContext context;
90 SDL_Surface *surface;
91
92 SDL_Joystick *joy;
93 JOYINFOEX JoystickData;
94 JOYCAPS JoystickCaps;
95
96 static int main_loop_state = 0;
97
98 // Window configuration and state
99 static int WindowWidth;
100 static int WindowHeight;
101 static int ViewportWidth;
102 static int ViewportHeight;
103 static int DrawableWidth;
104 static int DrawableHeight;
105
106 enum RENDERING_MODE {
107 RENDERING_MODE_SOFTWARE,
108 RENDERING_MODE_OPENGL
109 };
110
111 enum RENDERING_MODE RenderingMode;
112
113 #if defined(FIXED_WINDOW_SIZE)
114 static int WantFullscreen = 1;
115 static int WantFullscreenToggle = 0;
116 static int WantResolutionChange = 0;
117 static int WantMouseGrab = 1;
118 #else
119 static int WantFullscreen = 0;
120 static int WantFullscreenToggle = 1;
121 static int WantResolutionChange = 1;
122 static int WantMouseGrab = 0;
123 #endif
124
125 // Additional configuration
126 int WantSound = 1;
127 static int WantCDRom = 0;
128 static int WantJoystick = 1;
129
130 static GLuint FullscreenTexture;
131 static GLsizei FullscreenTextureWidth;
132 static GLsizei FullscreenTextureHeight;
133
134 static GLuint FullscreenArrayBuffer;
135 static GLuint FullscreenElementArrayBuffer;
136
137 static GLuint FramebufferTexture;
138 static GLsizei FramebufferTextureWidth;
139 static GLsizei FramebufferTextureHeight;
140 static GLuint FramebufferObject;
141 static GLuint FramebufferDepthObject;
142
143 /* originally was "/usr/lib/libGL.so.1:/usr/lib/tls/libGL.so.1:/usr/X11R6/lib/libGL.so" */
144 static const char * opengl_library = NULL;
145
146 /* ** */
147
IngameKeyboardInput_ClearBuffer(void)148 static void IngameKeyboardInput_ClearBuffer(void)
149 {
150 // clear the keyboard state
151 memset((void*) KeyboardInput, 0, MAX_NUMBER_OF_INPUT_KEYS);
152 GotAnyKey = 0;
153 }
154
DirectReadKeyboard()155 void DirectReadKeyboard()
156 {
157 }
158
DirectReadMouse()159 void DirectReadMouse()
160 {
161 }
162
ReadJoysticks()163 void ReadJoysticks()
164 {
165 int axes, balls, hats;
166 Uint8 hat;
167
168 JoystickData.dwXpos = 0;
169 JoystickData.dwYpos = 0;
170 JoystickData.dwRpos = 0;
171 JoystickData.dwUpos = 0;
172 JoystickData.dwVpos = 0;
173 JoystickData.dwPOV = (DWORD) -1;
174
175 if (joy == NULL || !GotJoystick) {
176 return;
177 }
178
179 SDL_JoystickUpdate();
180
181 axes = SDL_JoystickNumAxes(joy);
182 balls = SDL_JoystickNumBalls(joy);
183 hats = SDL_JoystickNumHats(joy);
184
185 if (axes > 0) {
186 JoystickData.dwXpos = SDL_JoystickGetAxis(joy, 0) + 32768;
187 }
188 if (axes > 1) {
189 JoystickData.dwYpos = SDL_JoystickGetAxis(joy, 1) + 32768;
190 }
191
192 if (hats > 0) {
193 hat = SDL_JoystickGetHat(joy, 0);
194
195 switch (hat) {
196 default:
197 case SDL_HAT_CENTERED:
198 JoystickData.dwPOV = (DWORD) -1;
199 break;
200 case SDL_HAT_UP:
201 JoystickData.dwPOV = 0;
202 break;
203 case SDL_HAT_RIGHT:
204 JoystickData.dwPOV = 9000;
205 break;
206 case SDL_HAT_DOWN:
207 JoystickData.dwPOV = 18000;
208 break;
209 case SDL_HAT_LEFT:
210 JoystickData.dwPOV = 27000;
211 break;
212 case SDL_HAT_RIGHTUP:
213 JoystickData.dwPOV = 4500;
214 break;
215 case SDL_HAT_RIGHTDOWN:
216 JoystickData.dwPOV = 13500;
217 break;
218 case SDL_HAT_LEFTUP:
219 JoystickData.dwPOV = 31500;
220 break;
221 case SDL_HAT_LEFTDOWN:
222 JoystickData.dwPOV = 22500;
223 break;
224 }
225 }
226 }
227
228 /* ** */
229
GetScreenShot24(int * width,int * height)230 unsigned char *GetScreenShot24(int *width, int *height)
231 {
232 unsigned char *buf;
233
234 if (surface == NULL) {
235 return NULL;
236 }
237
238 if (RenderingMode == RENDERING_MODE_OPENGL) {
239 buf = (unsigned char *)malloc(DrawableWidth * DrawableHeight * 3);
240
241 *width = DrawableWidth;
242 *height = DrawableHeight;
243
244 pglPixelStorei(GL_PACK_ALIGNMENT, 1);
245 pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
246 pglReadPixels(0, 0, DrawableWidth, DrawableHeight, GL_RGB, GL_UNSIGNED_BYTE, buf);
247 } else {
248 buf = (unsigned char *)malloc(surface->w * surface->h * 3);
249
250 unsigned char *ptrd;
251 unsigned short int *ptrs;
252 int x, y;
253
254 if (SDL_MUSTLOCK(surface)) {
255 if (SDL_LockSurface(surface) < 0) {
256 free(buf);
257 return NULL; /* ... */
258 }
259 }
260
261 ptrd = buf;
262 for (y = 0; y < surface->h; y++) {
263 ptrs = (unsigned short *)(((unsigned char *)surface->pixels) + (surface->h-y-1)*surface->pitch);
264 for (x = 0; x < surface->w; x++) {
265 unsigned int c;
266
267 c = *ptrs;
268 ptrd[0] = (c & 0xF800)>>8;
269 ptrd[1] = (c & 0x07E0)>>3;
270 ptrd[2] = (c & 0x001F)<<3;
271
272 ptrs++;
273 ptrd += 3;
274 }
275 }
276
277 *width = surface->w;
278 *height = surface->h;
279
280 if (SDL_MUSTLOCK(surface)) {
281 SDL_UnlockSurface(surface);
282 }
283 }
284
285 #if 0
286 Uint16 redtable[256], greentable[256], bluetable[256];
287
288 if (SDL_GetGammaRamp(redtable, greentable, bluetable) != -1) {
289 unsigned char *ptr;
290 int i;
291
292 ptr = buf;
293 for (i = 0; i < surface->w*surface->h; i++) {
294 ptr[i*3+0] = redtable[ptr[i*3+0]]>>8;
295 ptr[i*3+1] = greentable[ptr[i*3+1]]>>8;
296 ptr[i*3+2] = bluetable[ptr[i*3+2]]>>8;
297 ptr += 3;
298 }
299 }
300 #endif
301
302 return buf;
303 }
304
305 /* ** */
306
ReadProcessorType()307 PROCESSORTYPES ReadProcessorType()
308 {
309 return PType_PentiumMMX;
310 }
311
312 /* ** */
313
314 typedef struct VideoModeStruct
315 {
316 int w;
317 int h;
318 int available;
319 } VideoModeStruct;
320 VideoModeStruct VideoModeList[] = {
321 { 512, 384, 0 },
322 { 640, 480, 0 },
323 { 800, 600, 0 },
324 { 1024, 768, 0 },
325 { 1152, 864, 0 },
326 { 1280, 720, 0 },
327 { 1280, 960, 0 },
328 { 1280, 1024, 0 },
329 { 1600, 1200, 0 },
330 { 1920, 1080, 0 }
331 };
332
333 int CurrentVideoMode;
334 const int TotalVideoModes = sizeof(VideoModeList) / sizeof(VideoModeList[0]);
335
LoadDeviceAndVideoModePreferences()336 void LoadDeviceAndVideoModePreferences()
337 {
338 FILE *fp;
339 int mode;
340
341 fp = OpenGameFile("AvP_TempVideo.cfg", FILEMODE_READONLY, FILETYPE_CONFIG);
342
343 if (fp != NULL) {
344 // fullscreen mode (0=window,1=fullscreen,2=fullscreen desktop)
345 // window width
346 // window height
347 // fullscreen width
348 // fullscreen height
349 // fullscreen desktop aspect ratio n
350 // fullscreen desktop aspect ratio d
351 // fullscreen desktop scale n
352 // fullscreen desktop scale d
353 // multisample number of samples (0/2/4)
354 if (fscanf(fp, "%d", &mode) == 1) {
355 fclose(fp);
356
357 if (mode >= 0 && mode < TotalVideoModes && VideoModeList[mode].available) {
358 CurrentVideoMode = mode;
359 return;
360 }
361 } else {
362 fclose(fp);
363 }
364 }
365
366 /* No, or invalid, mode found */
367
368 /* Try 640x480 first */
369 if (VideoModeList[1].available) {
370 CurrentVideoMode = 1;
371 } else {
372 int i;
373
374 for (i = 0; i < TotalVideoModes; i++) {
375 if (VideoModeList[i].available) {
376 CurrentVideoMode = i;
377 break;
378 }
379 }
380 }
381 }
382
SaveDeviceAndVideoModePreferences()383 void SaveDeviceAndVideoModePreferences()
384 {
385 FILE *fp;
386
387 fp = OpenGameFile("AvP_TempVideo.cfg", FILEMODE_WRITEONLY, FILETYPE_CONFIG);
388 if (fp != NULL) {
389 fprintf(fp, "%d\n", CurrentVideoMode);
390 fclose(fp);
391 }
392 }
393
PreviousVideoMode2()394 void PreviousVideoMode2()
395 {
396 int cur = CurrentVideoMode;
397
398 do {
399 if (cur == 0)
400 cur = TotalVideoModes;
401 cur--;
402 if (cur == CurrentVideoMode)
403 return;
404 } while(!VideoModeList[cur].available);
405
406 CurrentVideoMode = cur;
407 }
408
NextVideoMode2()409 void NextVideoMode2()
410 {
411 int cur = CurrentVideoMode;
412
413 do {
414 cur++;
415 if (cur == TotalVideoModes)
416 cur = 0;
417
418 if (cur == CurrentVideoMode)
419 return;
420 } while(!VideoModeList[cur].available);
421
422 CurrentVideoMode = cur;
423 }
424
GetVideoModeDescription2()425 char *GetVideoModeDescription2()
426 {
427 return "SDL2";
428 }
429
GetVideoModeDescription3()430 char *GetVideoModeDescription3()
431 {
432 static char buf[64];
433
434 _snprintf(buf, 64, "%dx%d", VideoModeList[CurrentVideoMode].w, VideoModeList[CurrentVideoMode].h);
435
436 return buf;
437 }
438
InitSDL()439 int InitSDL()
440 {
441 #if EMSCRIPTEN
442 printf("Setting main loop...\n");
443 emscripten_set_main_loop(main_loop, 0, 0);
444 #endif
445
446 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
447 fprintf(stderr, "SDL Init failed: %s\n", SDL_GetError());
448 exit(EXIT_FAILURE);
449 }
450
451 atexit(SDL_Quit);
452
453 SDL_AddEventWatch(SDLEventFilter, NULL);
454
455 #if 0
456 SDL_Rect **SDL_AvailableVideoModes;
457 SDL_AvailableVideoModes = SDL_ListModes(NULL, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
458 if (SDL_AvailableVideoModes == NULL)
459 return -1;
460
461 if (SDL_AvailableVideoModes != (SDL_Rect **)-1) {
462 int i, j, foundit;
463
464 foundit = 0;
465 for (i = 0; i < TotalVideoModes; i++) {
466 SDL_Rect **modes = SDL_AvailableVideoModes;
467
468 for (j = 0; modes[j]; j++) {
469 if (modes[j]->w >= VideoModeList[i].w &&
470 modes[j]->h >= VideoModeList[i].h) {
471 if (SDL_VideoModeOK(VideoModeList[i].w, VideoModeList[i].h, 16, SDL_FULLSCREEN | SDL_OPENGL)) {
472 /* assume SDL isn't lying to us */
473 VideoModeList[i].available = 1;
474
475 foundit = 1;
476 }
477 break;
478 }
479 }
480 }
481 if (foundit == 0)
482 return -1;
483 } else {
484 int i, foundit;
485
486 foundit = 0;
487 for (i = 0; i < TotalVideoModes; i++) {
488 if (SDL_VideoModeOK(VideoModeList[i].w, VideoModeList[i].h, 16, SDL_FULLSCREEN | SDL_OPENGL)) {
489 /* assume SDL isn't lying to us */
490 VideoModeList[i].available = 1;
491
492 foundit = 1;
493 }
494 }
495
496 if (foundit == 0)
497 return -1;
498 }
499 #endif
500
501 {
502 int i;
503
504 for (i = 0; i < TotalVideoModes; i++) {
505 //if (SDL_VideoModeOK(VideoModeList[i].w, VideoModeList[i].h, 16, SDL_FULLSCREEN | SDL_OPENGL)) {
506 /* assume SDL isn't lying to us */
507 VideoModeList[i].available = 1;
508
509 //foundit = 1;
510 //}
511 }
512 }
513
514 LoadDeviceAndVideoModePreferences();
515
516 if (WantJoystick) {
517 SDL_InitSubSystem(SDL_INIT_JOYSTICK);
518
519 if (SDL_NumJoysticks() > 0) {
520 /* TODO: make joystick number a configuration parameter */
521
522 joy = SDL_JoystickOpen(0);
523 if (joy) {
524 GotJoystick = 1;
525 }
526
527 JoystickCaps.wCaps = 0; /* no rudder... ? */
528
529 JoystickData.dwXpos = 0;
530 JoystickData.dwYpos = 0;
531 JoystickData.dwRpos = 0;
532 JoystickData.dwUpos = 0;
533 JoystickData.dwVpos = 0;
534 JoystickData.dwPOV = (DWORD) -1;
535 }
536 }
537
538 Uint32 rmask, gmask, bmask, amask;
539
540 // pre-create the software surface in OpenGL RGBA order
541 // menus.c assumes RGB565; possible to support both?
542 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
543 rmask = 0xff000000;
544 gmask = 0x00ff0000;
545 bmask = 0x0000ff00;
546 amask = 0x000000ff;
547 #else
548 rmask = 0x0000f800;
549 gmask = 0x000007e0;
550 bmask = 0x0000001f;
551 amask = 0x00000000;
552 #endif
553
554 surface = SDL_CreateRGBSurface(0, 640, 480, 16, rmask, gmask, bmask, amask);
555 if (surface == NULL) {
556 return -1;
557 }
558
559 return 0;
560 }
561
562 #if defined(WINDOW_SIZE_DEBUG)
DumpVideoModeInfo(SDL_Window * w)563 static void DumpVideoModeInfo(SDL_Window* w) {
564 int numVideoDisplays;
565 int displayIndex;
566 int numDisplayModes;
567 int modeIndex;
568 const char* displayName;
569 numVideoDisplays = SDL_GetNumVideoDisplays();
570 if (numVideoDisplays > 0) {
571 for (displayIndex = 0; displayIndex < numVideoDisplays; displayIndex++) {
572 displayName = SDL_GetDisplayName(displayIndex);
573 printf("%d: %s\n", displayIndex, displayName);
574
575 SDL_Rect bounds;
576 SDL_DisplayMode mode;
577
578 if (SDL_GetDisplayBounds(displayIndex, &bounds) == 0) {
579 printf("\tbounds: %4d,%4d,%4d,%4d\n",
580 bounds.x,
581 bounds.y,
582 bounds.w,
583 bounds.h);
584 }
585
586 if (SDL_GetDesktopDisplayMode(displayIndex, &mode) == 0) {
587 printf("\tdesktop: %08x,%4d,%4d,%d\n",
588 mode.format,
589 mode.w,
590 mode.h,
591 mode.refresh_rate);
592 }
593
594 if (SDL_GetCurrentDisplayMode(displayIndex, &mode) == 0) {
595 printf("\tcurrent: %08x,%4d,%4d,%d\n",
596 mode.format,
597 mode.w,
598 mode.h,
599 mode.refresh_rate);
600 }
601
602 numDisplayModes = SDL_GetNumDisplayModes(displayIndex);
603 for (modeIndex = 0; modeIndex < numDisplayModes; modeIndex++) {
604 if (SDL_GetDisplayMode(displayIndex, modeIndex, &mode) == 0) {
605 printf("\t%2d: %08x,%4d,%4d,%d\n",
606 modeIndex,
607 mode.format,
608 mode.w,
609 mode.h,
610 mode.refresh_rate);
611 }
612 }
613 }
614 }
615
616 if (w != NULL) {
617 int displayIndex;
618 SDL_DisplayMode mode;
619
620 displayIndex = SDL_GetWindowDisplayIndex(w);
621
622 printf("Window display index: %d\n", displayIndex);
623 if (SDL_GetWindowDisplayMode(w, &mode) == 0) {
624 printf("Window display mode: %08x,%4d,%4d,%d\n",
625 mode.format,
626 mode.w,
627 mode.h,
628 mode.refresh_rate);
629 }
630
631 int width, height;
632 SDL_GetWindowSize(w, &width, &height);
633 printf("Window size: %4d,%4d\n", width, height);
634
635 SDL_GL_GetDrawableSize(w, &width, &height);
636 printf("Window drawable size: %4d,%4d\n", width, height);
637 }
638 }
639 #endif
640
SetWindowSize(int PhysicalWidth,int PhysicalHeight,int VirtualWidth,int VirtualHeight)641 static void SetWindowSize(int PhysicalWidth, int PhysicalHeight, int VirtualWidth, int VirtualHeight)
642 {
643 #if defined(WINDOW_SIZE_DEBUG)
644 printf("SetWindowSize(%d,%d,%d,%d); %d\n", PhysicalWidth, PhysicalHeight, VirtualWidth, VirtualHeight, CurrentVideoMode);
645 #endif
646
647 ViewportWidth = PhysicalWidth;
648 ViewportHeight = PhysicalHeight;
649 DrawableWidth = ViewportWidth;
650 DrawableHeight = ViewportHeight;
651
652 ScreenDescriptorBlock.SDB_Width = VirtualWidth;
653 ScreenDescriptorBlock.SDB_Height = VirtualHeight;
654 ScreenDescriptorBlock.SDB_CentreX = VirtualWidth/2;
655 ScreenDescriptorBlock.SDB_CentreY = VirtualHeight/2;
656 ScreenDescriptorBlock.SDB_ProjX = VirtualWidth/2;
657 ScreenDescriptorBlock.SDB_ProjY = VirtualHeight/2;
658 ScreenDescriptorBlock.SDB_ClipLeft = 0;
659 ScreenDescriptorBlock.SDB_ClipRight = VirtualWidth;
660 ScreenDescriptorBlock.SDB_ClipUp = 0;
661 ScreenDescriptorBlock.SDB_ClipDown = VirtualHeight;
662
663 if (window != NULL) {
664 SDL_SetWindowSize(window, PhysicalWidth, PhysicalHeight);
665
666 SDL_GL_GetDrawableSize(window, &DrawableWidth, &DrawableHeight);
667 pglViewport(0, 0, DrawableWidth, DrawableHeight);
668 }
669
670 #if defined(WINDOW_SIZE_DEBUG)
671 DumpVideoModeInfo(window);
672 #endif
673 }
674
SetSoftVideoMode(int Width,int Height,int Depth)675 static int SetSoftVideoMode(int Width, int Height, int Depth)
676 {
677 //TODO: clear surface
678
679 RenderingMode = RENDERING_MODE_SOFTWARE;
680 ScanDrawMode = ScanDrawD3DHardwareRGB;
681 GotMouse = 1;
682
683 // reset input
684 IngameKeyboardInput_ClearBuffer();
685
686 SetWindowSize(ViewportWidth, ViewportHeight, Width, Height);
687
688 return 0;
689 }
690
691 /* ** */
load_opengl_library(const char * lib)692 static void load_opengl_library(const char *lib)
693 {
694 char tmppath[PATH_MAX];
695 size_t len, copylen;
696
697 if (lib == NULL) {
698 if (SDL_GL_LoadLibrary(NULL) == 0) {
699 /* success */
700 return;
701 }
702
703 fprintf( stderr, "ERROR: no opengl libraries given\n" );
704 exit( EXIT_FAILURE );
705 }
706
707 while (lib != NULL && *lib) {
708 len = strcspn(lib, ":");
709
710 copylen = min(len, PATH_MAX-1);
711
712 strncpy(tmppath, lib, copylen);
713 tmppath[copylen] = 0;
714
715 if (SDL_GL_LoadLibrary(tmppath) == 0) {
716 /* success */
717 return;
718 }
719
720 lib += len;
721 lib += strspn(lib, ":");
722 }
723
724 fprintf(stderr, "ERROR: unable to initialize opengl library: %s\n", SDL_GetError());
725 exit(EXIT_FAILURE);
726 }
727
728 /* ** */
SDLEventFilter(void * userData,SDL_Event * event)729 static int SDLCALL SDLEventFilter(void* userData, SDL_Event* event) {
730 (void) userData;
731
732 //printf("SDLEventFilter: %d\n", event->type);
733
734 switch (event->type) {
735 case SDL_APP_TERMINATING:
736 AvP.MainLoopRunning = 0; /* TODO */
737 break;
738 }
739
740 return 1;
741 }
742
InitSDLVideo(void)743 static int InitSDLVideo(void) {
744 return 0;
745 }
746
SetOGLVideoMode(int Width,int Height)747 static int SetOGLVideoMode(int Width, int Height)
748 {
749 GLenum status;
750 int firsttime = 0;
751 int oldflags;
752 int flags;
753
754 RenderingMode = RENDERING_MODE_OPENGL;
755 ScanDrawMode = ScanDrawD3DHardwareRGB;
756 GotMouse = 1;
757
758 #if defined(FIXED_WINDOW_SIZE)
759 // force the game to use the full desktop
760 SDL_DisplayMode dm;
761 if (SDL_GetDesktopDisplayMode(0, &dm) == 0) {
762 Width = dm.w;
763 Height = dm.h;
764 }
765 #endif
766
767 if (window == NULL) {
768 firsttime = 1;
769
770 load_ogl_functions(0);
771
772 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_ALLOW_HIGHDPI;
773
774 #if defined(FIXED_WINDOW_SIZE)
775 flags |= SDL_WINDOW_BORDERLESS;
776 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
777 #else
778 if (WantFullscreen) {
779 flags |= (WantResolutionChange != 0 ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP);
780 }
781
782 // the game doesn't properly support window resizing
783 //flags |= SDL_WINDOW_RESIZABLE;
784 #endif
785
786 // reset input
787 IngameKeyboardInput_ClearBuffer();
788
789 // force restart the video system
790 SDL_QuitSubSystem(SDL_INIT_VIDEO);
791 SDL_InitSubSystem(SDL_INIT_VIDEO);
792
793 // set OpenGL attributes first
794 #if defined(USE_OPENGL_ES)
795 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
796 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
797 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
798 #else
799 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
800 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
801 #endif
802 // These should be configurable video options.
803 // If user requests 8bpp, try that, else fall back to 5.
804 // Same with depth. Try 32, 24, 16.
805 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
806 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
807 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
808 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
809 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
810
811 load_opengl_library(opengl_library);
812
813 // These should be configurable video options.
814 //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
815 //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
816
817 window = SDL_CreateWindow("Aliens vs Predator",
818 SDL_WINDOWPOS_UNDEFINED,
819 SDL_WINDOWPOS_UNDEFINED,
820 WindowWidth,
821 WindowHeight,
822 flags);
823 if (window == NULL) {
824 fprintf(stderr, "(OpenGL) SDL SDL_CreateWindow failed: %s\n", SDL_GetError());
825 exit(EXIT_FAILURE);
826 }
827
828 context = SDL_GL_CreateContext(window);
829 if (context == NULL) {
830 fprintf(stderr, "(OpenGL) SDL SDL_GL_CreateContext failed: %s\n", SDL_GetError());
831 exit(EXIT_FAILURE);
832 }
833 SDL_GL_MakeCurrent(window, context);
834
835 // These should be configurable video options.
836 SDL_GL_SetSwapInterval(1);
837
838 load_ogl_functions(1);
839
840 SDL_GL_GetDrawableSize(window, &Width, &Height);
841 #if defined(WINDOW_SIZE_DEBUG)
842 printf("glViewport(0, 0, %d, %d)\n", Width, Height);
843 #endif
844 pglViewport(0, 0, Width, Height);
845
846 // create fullscreen window texture
847 pglGenTextures(1, &FullscreenTexture);
848
849 pglBindTexture(GL_TEXTURE_2D, FullscreenTexture);
850
851 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
852 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
853 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
854 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
855
856 FullscreenTextureWidth = 640;
857 FullscreenTextureHeight = 480;
858 pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FullscreenTextureWidth, FullscreenTextureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
859
860 // this should be deleted and rebuilt when the screen size changes
861 GLint maxRenderbufferSize;
862 GLint maxTextureSize;
863 GLint maxViewportDims;
864 GLint maxRenderSize;
865
866 pglGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize);
867 pglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
868 pglGetIntegerv(GL_MAX_VIEWPORT_DIMS, &maxViewportDims);
869 printf("DEBUG:%d,%d,%d\n", maxRenderbufferSize, maxTextureSize, maxViewportDims);
870
871 FramebufferTextureWidth = Width * 2;
872 FramebufferTextureHeight = Height * 2;
873 printf("DEBUG2:%d,%d\n", FramebufferTextureWidth, FramebufferTextureHeight);
874
875 maxRenderSize = maxRenderbufferSize;
876 if (maxRenderSize > maxTextureSize) {
877 maxRenderSize = maxTextureSize;
878 }
879 if (maxRenderSize > maxViewportDims) {
880 maxRenderSize = maxViewportDims;
881 }
882
883 if (FramebufferTextureWidth > maxRenderSize) {
884 FramebufferTextureWidth = maxRenderSize;
885 }
886 if (FramebufferTextureHeight > maxRenderSize) {
887 FramebufferTextureHeight = maxRenderSize;
888 }
889 printf("DEBUG3:%d,%d\n", FramebufferTextureWidth, FramebufferTextureHeight);
890
891 pglGenTextures(1, &FramebufferTexture);
892 pglGenFramebuffers(1, &FramebufferObject);
893 pglGenRenderbuffers(1, &FramebufferDepthObject);
894
895 pglBindTexture(GL_TEXTURE_2D, FramebufferTexture);
896 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
897 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
898 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
899 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
900 pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FramebufferTextureWidth, FramebufferTextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
901
902 pglBindTexture(GL_TEXTURE_2D, 0);
903 pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
904 pglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FramebufferTexture, 0);
905 pglBindRenderbuffer(GL_RENDERBUFFER, FramebufferDepthObject);
906 pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, FramebufferTextureWidth, FramebufferTextureHeight);
907 pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, FramebufferDepthObject);
908
909 pglGenBuffers(1, &FullscreenArrayBuffer);
910 pglGenBuffers(1, &FullscreenElementArrayBuffer);
911
912 check_for_errors();
913
914 status = pglCheckFramebufferStatus(GL_FRAMEBUFFER);
915 if (status != GL_FRAMEBUFFER_COMPLETE) {
916 fprintf(stderr, "Incomplete framebuffer, status:%04x\n", status);
917 }
918
919 pglBindFramebuffer(GL_FRAMEBUFFER, 0);
920 pglBindRenderbuffer(GL_RENDERBUFFER, 0);
921 }
922
923 SDL_GetWindowSize(window, &Width, &Height);
924
925 SetWindowSize(Width, Height, Width, Height);
926
927 int NewWidth, NewHeight;
928 SDL_GetWindowSize(window, &NewWidth, &NewHeight);
929 if (Width != NewWidth || Height != NewHeight) {
930 //printf("Failed to change size: %d,%d vs. %d,%d\n", Width, Height, NewWidth, NewHeight);
931 //Width = NewWidth;
932 //Height = NewHeight;
933 //SetWindowSize(Width, Height, Width, Height);
934 }
935
936 pglEnable(GL_BLEND);
937 pglBlendFunc(GL_SRC_ALPHA, GL_ONE);
938
939 pglEnable(GL_DEPTH_TEST);
940 pglDepthFunc(GL_LEQUAL);
941 pglDepthMask(GL_TRUE);
942 pglDepthRange(0.0, 1.0);
943
944 pglDisable(GL_CULL_FACE);
945
946 pglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
947
948 InitOpenGL(firsttime);
949
950 check_for_errors();
951
952 return 0;
953 }
954
InitialiseWindowsSystem(HANDLE hInstance,int nCmdShow,int WinInitMode)955 int InitialiseWindowsSystem(HANDLE hInstance, int nCmdShow, int WinInitMode)
956 {
957 return 0;
958 }
959
ExitWindowsSystem()960 int ExitWindowsSystem()
961 {
962 if (joy != NULL) {
963 SDL_JoystickClose(joy);
964 }
965
966 if (FullscreenTexture != 0) {
967 pglDeleteTextures(1, &FullscreenTexture);
968 }
969 FullscreenTexture = 0;
970
971 if (FullscreenArrayBuffer != 0) {
972 pglDeleteBuffers(1, &FullscreenArrayBuffer);
973 }
974 FullscreenArrayBuffer = 0;
975
976 if (FullscreenElementArrayBuffer != 0) {
977 pglDeleteBuffers(1, &FullscreenElementArrayBuffer);
978 }
979 FullscreenElementArrayBuffer = 0;
980
981 load_ogl_functions(0);
982
983 if (surface != NULL) {
984 SDL_FreeSurface(surface);
985 }
986 surface = NULL;
987
988 if (context != NULL) {
989 SDL_GL_DeleteContext(context);
990 }
991 context = NULL;
992
993 if (window != NULL) {
994 SDL_DestroyWindow(window);
995 }
996 window = NULL;
997
998 return 0;
999 }
1000
1001 static int GotPrintScn, HavePrintScn;
1002
KeySymToKey(int keysym)1003 static int KeySymToKey(int keysym)
1004 {
1005 switch(keysym) {
1006 case SDLK_ESCAPE:
1007 return KEY_ESCAPE;
1008
1009 case SDLK_0:
1010 return KEY_0;
1011 case SDLK_1:
1012 return KEY_1;
1013 case SDLK_2:
1014 return KEY_2;
1015 case SDLK_3:
1016 return KEY_3;
1017 case SDLK_4:
1018 return KEY_4;
1019 case SDLK_5:
1020 return KEY_5;
1021 case SDLK_6:
1022 return KEY_6;
1023 case SDLK_7:
1024 return KEY_7;
1025 case SDLK_8:
1026 return KEY_8;
1027 case SDLK_9:
1028 return KEY_9;
1029
1030 case SDLK_a:
1031 return KEY_A;
1032 case SDLK_b:
1033 return KEY_B;
1034 case SDLK_c:
1035 return KEY_C;
1036 case SDLK_d:
1037 return KEY_D;
1038 case SDLK_e:
1039 return KEY_E;
1040 case SDLK_f:
1041 return KEY_F;
1042 case SDLK_g:
1043 return KEY_G;
1044 case SDLK_h:
1045 return KEY_H;
1046 case SDLK_i:
1047 return KEY_I;
1048 case SDLK_j:
1049 return KEY_J;
1050 case SDLK_k:
1051 return KEY_K;
1052 case SDLK_l:
1053 return KEY_L;
1054 case SDLK_m:
1055 return KEY_M;
1056 case SDLK_n:
1057 return KEY_N;
1058 case SDLK_o:
1059 return KEY_O;
1060 case SDLK_p:
1061 return KEY_P;
1062 case SDLK_q:
1063 return KEY_Q;
1064 case SDLK_r:
1065 return KEY_R;
1066 case SDLK_s:
1067 return KEY_S;
1068 case SDLK_t:
1069 return KEY_T;
1070 case SDLK_u:
1071 return KEY_U;
1072 case SDLK_v:
1073 return KEY_V;
1074 case SDLK_w:
1075 return KEY_W;
1076 case SDLK_x:
1077 return KEY_X;
1078 case SDLK_y:
1079 return KEY_Y;
1080 case SDLK_z:
1081 return KEY_Z;
1082
1083 case SDLK_LEFT:
1084 return KEY_LEFT;
1085 case SDLK_RIGHT:
1086 return KEY_RIGHT;
1087 case SDLK_UP:
1088 return KEY_UP;
1089 case SDLK_DOWN:
1090 return KEY_DOWN;
1091 case SDLK_RETURN:
1092 return KEY_CR;
1093 case SDLK_TAB:
1094 return KEY_TAB;
1095 case SDLK_INSERT:
1096 return KEY_INS;
1097 case SDLK_DELETE:
1098 return KEY_DEL;
1099 case SDLK_END:
1100 return KEY_END;
1101 case SDLK_HOME:
1102 return KEY_HOME;
1103 case SDLK_PAGEUP:
1104 return KEY_PAGEUP;
1105 case SDLK_PAGEDOWN:
1106 return KEY_PAGEDOWN;
1107 case SDLK_BACKSPACE:
1108 return KEY_BACKSPACE;
1109 case SDLK_COMMA:
1110 return KEY_COMMA;
1111 case SDLK_PERIOD:
1112 return KEY_FSTOP;
1113 case SDLK_SPACE:
1114 return KEY_SPACE;
1115
1116 case SDLK_LSHIFT:
1117 return KEY_LEFTSHIFT;
1118 case SDLK_RSHIFT:
1119 return KEY_RIGHTSHIFT;
1120 case SDLK_LALT:
1121 return KEY_LEFTALT;
1122 case SDLK_RALT:
1123 return KEY_RIGHTALT;
1124 case SDLK_LCTRL:
1125 return KEY_LEFTCTRL;
1126 case SDLK_RCTRL:
1127 return KEY_RIGHTCTRL;
1128
1129 case SDLK_CAPSLOCK:
1130 return KEY_CAPS;
1131 case SDLK_NUMLOCKCLEAR:
1132 return KEY_NUMLOCK;
1133 case SDLK_SCROLLLOCK:
1134 return KEY_SCROLLOK;
1135
1136 case SDLK_KP_0:
1137 return KEY_NUMPAD0;
1138 case SDLK_KP_1:
1139 return KEY_NUMPAD1;
1140 case SDLK_KP_2:
1141 return KEY_NUMPAD2;
1142 case SDLK_KP_3:
1143 return KEY_NUMPAD3;
1144 case SDLK_KP_4:
1145 return KEY_NUMPAD4;
1146 case SDLK_KP_5:
1147 return KEY_NUMPAD5;
1148 case SDLK_KP_6:
1149 return KEY_NUMPAD6;
1150 case SDLK_KP_7:
1151 return KEY_NUMPAD7;
1152 case SDLK_KP_8:
1153 return KEY_NUMPAD8;
1154 case SDLK_KP_9:
1155 return KEY_NUMPAD9;
1156 case SDLK_KP_MINUS:
1157 return KEY_NUMPADSUB;
1158 case SDLK_KP_PLUS:
1159 return KEY_NUMPADADD;
1160 case SDLK_KP_PERIOD:
1161 return KEY_NUMPADDEL;
1162 case SDLK_KP_ENTER:
1163 return KEY_NUMPADENTER;
1164 case SDLK_KP_DIVIDE:
1165 return KEY_NUMPADDIVIDE;
1166 case SDLK_KP_MULTIPLY:
1167 return KEY_NUMPADMULTIPLY;
1168
1169 case SDLK_LEFTBRACKET:
1170 return KEY_LBRACKET;
1171 case SDLK_RIGHTBRACKET:
1172 return KEY_RBRACKET;
1173 case SDLK_SEMICOLON:
1174 return KEY_SEMICOLON;
1175 case SDLK_QUOTE:
1176 return KEY_APOSTROPHE;
1177 case SDLK_BACKQUOTE:
1178 return KEY_GRAVE;
1179 case SDLK_BACKSLASH:
1180 return KEY_BACKSLASH;
1181 case SDLK_SLASH:
1182 return KEY_SLASH;
1183 /* case SDLK_
1184 return KEY_CAPITAL; */
1185 case SDLK_MINUS:
1186 return KEY_MINUS;
1187 case SDLK_EQUALS:
1188 return KEY_EQUALS;
1189 case SDLK_LGUI:
1190 return KEY_LWIN;
1191 case SDLK_RGUI:
1192 return KEY_RWIN;
1193 /* case SDLK_
1194 return KEY_APPS; */
1195
1196 case SDLK_F1:
1197 return KEY_F1;
1198 case SDLK_F2:
1199 return KEY_F2;
1200 case SDLK_F3:
1201 return KEY_F3;
1202 case SDLK_F4:
1203 return KEY_F4;
1204 case SDLK_F5:
1205 return KEY_F5;
1206 case SDLK_F6:
1207 return KEY_F6;
1208 case SDLK_F7:
1209 return KEY_F7;
1210 case SDLK_F8:
1211 return KEY_F8;
1212 case SDLK_F9:
1213 return KEY_F9;
1214 case SDLK_F10:
1215 return KEY_F10;
1216 case SDLK_F11:
1217 return KEY_F11;
1218 case SDLK_F12:
1219 return KEY_F12;
1220
1221 /* finish foreign keys */
1222
1223 default:
1224 return -1;
1225 }
1226 }
1227
handle_keypress(int key,int unicode,int press)1228 static void handle_keypress(int key, int unicode, int press)
1229 {
1230 if (key == -1)
1231 return;
1232
1233 if (press) {
1234 switch(key) {
1235 case KEY_CR:
1236 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_CHAR('\r');
1237 break;
1238 case KEY_BACKSPACE:
1239 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_BACK);
1240 break;
1241 case KEY_END:
1242 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_END);
1243 break;
1244 case KEY_HOME:
1245 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_HOME);
1246 break;
1247 case KEY_LEFT:
1248 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_LEFT);
1249 break;
1250 case KEY_UP:
1251 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_UP);
1252 break;
1253 case KEY_RIGHT:
1254 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_RIGHT);
1255 break;
1256 case KEY_DOWN:
1257 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_DOWN);
1258 break;
1259 case KEY_INS:
1260 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_INSERT);
1261 break;
1262 case KEY_DEL:
1263 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_DELETE);
1264 break;
1265 case KEY_TAB:
1266 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_KEYDOWN(VK_TAB);
1267 break;
1268 default:
1269 break;
1270 }
1271 }
1272
1273 if (press && !KeyboardInput[key]) {
1274 DebouncedKeyboardInput[key] = 1;
1275 DebouncedGotAnyKey = 1;
1276 }
1277
1278 if (press)
1279 GotAnyKey = 1;
1280 KeyboardInput[key] = press;
1281 }
1282
CheckForWindowsMessages()1283 void CheckForWindowsMessages()
1284 {
1285 SDL_Event event;
1286 int x, y, buttons, wantmouse;
1287
1288 GotAnyKey = 0;
1289 DebouncedGotAnyKey = 0;
1290 memset(DebouncedKeyboardInput, 0, sizeof(DebouncedKeyboardInput));
1291
1292 wantmouse = (SDL_GetRelativeMouseMode() == SDL_TRUE);
1293
1294 // "keyboard" events that don't have an up event
1295 KeyboardInput[KEY_MOUSEWHEELUP] = 0;
1296 KeyboardInput[KEY_MOUSEWHEELDOWN] = 0;
1297
1298 while (SDL_PollEvent(&event)) {
1299 switch(event.type) {
1300 case SDL_MOUSEBUTTONDOWN:
1301 break;
1302 case SDL_MOUSEBUTTONUP:
1303 break;
1304 case SDL_MOUSEWHEEL:
1305 if (wantmouse) {
1306 if (event.wheel.y < 0) {
1307 handle_keypress(KEY_MOUSEWHEELDOWN, 0, 1);
1308 } else if (event.wheel.y > 0) {
1309 handle_keypress(KEY_MOUSEWHEELUP, 0, 1);
1310 }
1311 }
1312 break;
1313 case SDL_TEXTINPUT: {
1314 int unicode = event.text.text[0]; //TODO convert to utf-32
1315 if (unicode && !(unicode & 0xFF80)) {
1316 RE_ENTRANT_QUEUE_WinProc_AddMessage_WM_CHAR(unicode);
1317 KeyboardEntryQueue_Add(unicode);
1318 }
1319 }
1320 break;
1321 case SDL_KEYDOWN:
1322 if (event.key.keysym.sym == SDLK_PRINTSCREEN) {
1323 if (HavePrintScn == 0)
1324 GotPrintScn = 1;
1325 HavePrintScn = 1;
1326 } else {
1327 handle_keypress(KeySymToKey(event.key.keysym.sym), 0, 1);
1328 }
1329 break;
1330 case SDL_KEYUP:
1331 if (event.key.keysym.sym == SDLK_PRINTSCREEN) {
1332 GotPrintScn = 0;
1333 HavePrintScn = 0;
1334 } else {
1335 handle_keypress(KeySymToKey(event.key.keysym.sym), 0, 0);
1336 }
1337 break;
1338 case SDL_WINDOWEVENT:
1339 switch (event.window.event) {
1340 case SDL_WINDOWEVENT_FOCUS_LOST:
1341 // disable mouse grab?
1342 break;
1343 case SDL_WINDOWEVENT_RESIZED:
1344 #if defined(WINDOW_SIZE_DEBUG)
1345 printf("Window Resized %d,%d\n", event.window.data1, event.window.data2);
1346 #endif
1347 WindowWidth = event.window.data1;
1348 WindowHeight = event.window.data2;
1349 if (RenderingMode == RENDERING_MODE_SOFTWARE) {
1350 SetWindowSize(WindowWidth, WindowHeight, 640, 480);
1351 } else {
1352 SetWindowSize(WindowWidth, WindowHeight, WindowWidth, WindowHeight);
1353 }
1354 if (pglViewport != NULL) {
1355 SDL_GL_GetDrawableSize(window, &WindowWidth, &WindowHeight);
1356 pglViewport(0, 0, WindowWidth, WindowHeight);
1357 }
1358 break;
1359 }
1360 break;
1361 case SDL_QUIT:
1362 AvP.MainLoopRunning = 0; /* TODO */
1363 exit(0); //TODO
1364 break;
1365 }
1366 }
1367
1368 buttons = SDL_GetRelativeMouseState(&x, &y);
1369
1370 if (wantmouse) {
1371 if (buttons & SDL_BUTTON(1))
1372 handle_keypress(KEY_LMOUSE, 0, 1);
1373 else
1374 handle_keypress(KEY_LMOUSE, 0, 0);
1375 if (buttons & SDL_BUTTON(2))
1376 handle_keypress(KEY_MMOUSE, 0, 1);
1377 else
1378 handle_keypress(KEY_MMOUSE, 0, 0);
1379 if (buttons & SDL_BUTTON(3))
1380 handle_keypress(KEY_RMOUSE, 0, 1);
1381 else
1382 handle_keypress(KEY_RMOUSE, 0, 0);
1383
1384 MouseVelX = DIV_FIXED(x, NormalFrameTime);
1385 MouseVelY = DIV_FIXED(y, NormalFrameTime);
1386 } else {
1387 KeyboardInput[KEY_LMOUSE] = 0;
1388 KeyboardInput[KEY_MMOUSE] = 0;
1389 KeyboardInput[KEY_RMOUSE] = 0;
1390 MouseVelX = 0;
1391 MouseVelY = 0;
1392 }
1393
1394 if (GotJoystick) {
1395 int numbuttons;
1396
1397 SDL_JoystickUpdate();
1398
1399 numbuttons = SDL_JoystickNumButtons(joy);
1400 if (numbuttons > 16) numbuttons = 16;
1401
1402 for (x = 0; x < numbuttons; x++) {
1403 if (SDL_JoystickGetButton(joy, x)) {
1404 GotAnyKey = 1;
1405 if (!KeyboardInput[KEY_JOYSTICK_BUTTON_1+x]) {
1406 KeyboardInput[KEY_JOYSTICK_BUTTON_1+x] = 1;
1407 DebouncedKeyboardInput[KEY_JOYSTICK_BUTTON_1+x] = 1;
1408 }
1409 } else {
1410 KeyboardInput[KEY_JOYSTICK_BUTTON_1+x] = 0;
1411 }
1412 }
1413 }
1414
1415 //#warning Redo WantX, need to split it out better so fullscreen can temporary set relative without clobbering user setting
1416 if ((KeyboardInput[KEY_LEFTALT]||KeyboardInput[KEY_RIGHTALT]) && DebouncedKeyboardInput[KEY_CR]) {
1417 if (WantFullscreenToggle != 0) {
1418 int displayMode = SDL_GetWindowFlags(window);
1419 //printf("Current window mode:%08x\n", displayMode);
1420 if ((displayMode & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
1421 SDL_SetWindowFullscreen(window, 0);
1422 } else {
1423 SDL_SetWindowFullscreen(window, WantResolutionChange ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP);
1424 }
1425
1426 displayMode = SDL_GetWindowFlags(window);
1427 //printf("New window mode:%08x\n", displayMode);
1428 if ((displayMode & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
1429 SDL_SetRelativeMouseMode(SDL_TRUE);
1430 WantFullscreen = 1;
1431 } else {
1432 SDL_SetRelativeMouseMode(WantMouseGrab ? SDL_TRUE : SDL_FALSE);
1433 WantFullscreen = 0;
1434 }
1435 }
1436 }
1437
1438 if (KeyboardInput[KEY_LEFTCTRL] && DebouncedKeyboardInput[KEY_G]) {
1439 int IsWindowed = (SDL_GetWindowFlags(window) & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) == 0;
1440
1441 if (IsWindowed) {
1442 WantMouseGrab = WantMouseGrab != 0 ? 0 : 1;
1443 if (WantMouseGrab != 0) {
1444 SDL_SetRelativeMouseMode(SDL_TRUE);
1445 } else {
1446 SDL_SetRelativeMouseMode(SDL_FALSE);
1447 }
1448 WantMouseGrab = (SDL_GetRelativeMouseMode() == SDL_TRUE);
1449 }
1450 }
1451
1452 // a second reset of relative mouse state because
1453 // enabling relative mouse mode moves the mouse
1454 SDL_GetRelativeMouseState(NULL, NULL);
1455
1456 if (GotPrintScn) {
1457 GotPrintScn = 0;
1458
1459 ScreenShot();
1460 }
1461 }
1462
InGameFlipBuffers()1463 void InGameFlipBuffers()
1464 {
1465 #if !defined(NDEBUG)
1466 check_for_errors();
1467 #endif
1468
1469 pglBindFramebuffer(GL_FRAMEBUFFER, 0);
1470 pglBindRenderbuffer(GL_RENDERBUFFER, 0);
1471 pglViewport(0, 0, DrawableWidth, DrawableHeight);
1472 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1473
1474 DrawFullscreenTexture(FramebufferTexture);
1475
1476 #if !defined(NDEBUG)
1477 check_for_errors();
1478 #endif
1479
1480 SDL_GL_SwapWindow(window);
1481
1482 pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
1483 pglBindRenderbuffer(GL_RENDERBUFFER, FramebufferDepthObject);
1484 pglViewport(0, 0, FramebufferTextureWidth, FramebufferTextureHeight);
1485 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1486 }
1487
FlipBuffers()1488 void FlipBuffers()
1489 {
1490 pglBindFramebuffer(GL_FRAMEBUFFER, 0);
1491 pglBindRenderbuffer(GL_RENDERBUFFER, 0);
1492
1493 pglViewport(0, 0, DrawableWidth, DrawableHeight);
1494 pglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1495
1496 pglDisable(GL_BLEND);
1497 pglDisable(GL_DEPTH_TEST);
1498
1499 pglBindTexture(GL_TEXTURE_2D, FullscreenTexture);
1500 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1501 pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1502 pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 640, 480, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, surface->pixels);
1503
1504 GLfloat x0;
1505 GLfloat x1;
1506 GLfloat y0;
1507 GLfloat y1;
1508 GLfloat s0;
1509 GLfloat s1;
1510 GLfloat t0;
1511 GLfloat t1;
1512
1513 // figure out the best way to fit the 640x480 virtual window
1514 GLfloat a = DrawableHeight * 640.0f / 480.0f;
1515 GLfloat b = DrawableWidth * 480.0f / 640.0f;
1516
1517 if (a <= DrawableWidth) {
1518 // a x DrawableHeight window
1519 y0 = -1.0f;
1520 y1 = 1.0f;
1521
1522 x1 = 1.0 - (DrawableWidth - a) / DrawableWidth;
1523 x0 = -x1;
1524 } else {
1525 // DrawableWidth x b window
1526 x0 = -1.0f;
1527 x1 = 1.0f;
1528
1529 y1 = 1.0 - (DrawableHeight - b) / DrawableHeight;
1530 y0 = -y1;
1531 }
1532
1533 s0 = 0.0f;
1534 s1 = 640.0f / (float) FullscreenTextureWidth;
1535 t0 = 0.0f;
1536 t1 = 480.0f / (float) FullscreenTextureHeight;
1537
1538 GLfloat v[4*4];
1539 GLshort s[6];
1540
1541 v[0+0*4] = x0;
1542 v[1+0*4] = y0;
1543 v[2+0*4] = s0;
1544 v[3+0*4] = t1;
1545 v[0+1*4] = x1;
1546 v[1+1*4] = y0;
1547 v[2+1*4] = s1;
1548 v[3+1*4] = t1;
1549 v[0+2*4] = x1;
1550 v[1+2*4] = y1;
1551 v[2+2*4] = s1;
1552 v[3+2*4] = t0;
1553 v[0+3*4] = x0;
1554 v[1+3*4] = y1;
1555 v[2+3*4] = s0;
1556 v[3+3*4] = t0;
1557
1558 s[0] = 0;
1559 s[1] = 1;
1560 s[2] = 2;
1561 s[3] = 0;
1562 s[4] = 2;
1563 s[5] = 3;
1564
1565 SelectProgram(AVP_SHADER_PROGRAM_NO_COLOR_NO_DISCARD);
1566
1567 // slow webgl compatibility changes
1568 pglBindBuffer(GL_ARRAY_BUFFER, FullscreenArrayBuffer);
1569 pglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, FullscreenElementArrayBuffer);
1570 pglBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STREAM_DRAW);
1571 pglBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s), s, GL_STREAM_DRAW);
1572
1573 pglVertexAttribPointer(OPENGL_VERTEX_ATTRIB_INDEX, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (const GLvoid*) 0);
1574 pglVertexAttribPointer(OPENGL_TEXCOORD_ATTRIB_INDEX, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (const GLvoid*) 8);
1575
1576 pglDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const GLvoid*) 0);
1577
1578 pglBindTexture(GL_TEXTURE_2D, 0);
1579
1580 #if !defined(NDEBUG)
1581 check_for_errors();
1582 #endif
1583
1584 SDL_GL_SwapWindow(window);
1585 }
1586
1587 char *AvpCDPath = 0;
1588
1589 #if !defined(_MSC_VER)
1590 static const struct option getopt_long_options[] = {
1591 { "help", 0, NULL, 'h' },
1592 { "version", 0, NULL, 'v' },
1593 { "fullscreen", 0, NULL, 'f' },
1594 { "windowed", 0, NULL, 'w' },
1595 { "nosound", 0, NULL, 's' },
1596 { "nocdrom", 0, NULL, 'c' },
1597 { "nojoy", 0, NULL, 'j' },
1598 { "debug", 0, NULL, 'd' },
1599 { "withgl", 1, NULL, 'g' },
1600 /*
1601 { "loadrifs", 1, NULL, 'l' },
1602 { "server", 0, someval, 1 },
1603 { "client", 1, someval, 2 },
1604 */
1605 { NULL, 0, NULL, 0 },
1606 };
1607 #endif
1608
1609 static const char *usage_string =
1610 "Aliens vs Predator Linux - http://www.icculus.org/avp/\n"
1611 "Based on Rebellion Developments AvP Gold source\n"
1612 " [-h | --help] Display this help message\n"
1613 " [-v | --version] Display the game version\n"
1614 " [-f | --fullscreen] Run the game fullscreen\n"
1615 " [-w | --windowed] Run the game in a window\n"
1616 " [-s | --nosound] Do not access the soundcard\n"
1617 " [-c | --nocdrom] Do not access the CD-ROM\n"
1618 " [-j | --nojoy] Do not access the joystick\n"
1619 " [-g | --withgl] [x] Use [x] instead of /usr/lib/libGL.so.1 for OpenGL\n"
1620 ;
1621
1622 static int menusActive = 0;
1623 static int thisLevelHasBeenCompleted = 0;
1624
1625
main(int argc,char * argv[])1626 int main(int argc, char *argv[])
1627 {
1628 #if !defined(_MSC_VER)
1629 int c;
1630
1631 opterr = 0;
1632 while ((c = getopt_long(argc, argv, "hvfwscdg:", getopt_long_options, NULL)) != -1) {
1633 switch(c) {
1634 case 'h':
1635 printf("%s", usage_string);
1636 exit(EXIT_SUCCESS);
1637 case 'v':
1638 printf("%s", AvPVersionString);
1639 exit(EXIT_SUCCESS);
1640 case 'f':
1641 WantFullscreen = 1;
1642 break;
1643 case 'w':
1644 WantFullscreen = 0;
1645 break;
1646 case 's':
1647 WantSound = 0;
1648 break;
1649 case 'c':
1650 WantCDRom = 0;
1651 break;
1652 case 'j':
1653 WantJoystick = 0;
1654 break;
1655 case 'd': {
1656 extern int DebuggingCommandsActive;
1657 DebuggingCommandsActive = 1;
1658 }
1659 break;
1660 case 'g':
1661 opengl_library = optarg;
1662 break;
1663 default:
1664 printf("%s", usage_string);
1665 exit(EXIT_FAILURE);
1666 }
1667 }
1668 #endif
1669
1670 InitGameDirectories(argv[0]);
1671
1672 if (InitSDL() == -1) {
1673 fprintf(stderr, "Could not find a sutable resolution!\n");
1674 fprintf(stderr, "At least 512x384 is needed. Does OpenGL work?\n");
1675 exit(EXIT_FAILURE);
1676 }
1677
1678 LoadCDTrackList();
1679
1680 SetFastRandom();
1681
1682 #if MARINE_DEMO
1683 ffInit("fastfile/mffinfo.txt","fastfile/");
1684 #elif ALIEN_DEMO
1685 ffInit("alienfastfile/ffinfo.txt","alienfastfile/");
1686 #else
1687 ffInit("fastfile/ffinfo.txt","fastfile/");
1688 #endif
1689 InitGame();
1690
1691 WindowWidth = VideoModeList[CurrentVideoMode].w;
1692 WindowHeight = VideoModeList[CurrentVideoMode].h;
1693 SetOGLVideoMode(0, 0);
1694 SetSoftVideoMode(640, 480, 16);
1695
1696 InitialVideoMode();
1697
1698 /* Env_List can probably be removed */
1699 Env_List[0]->main = LevelName;
1700
1701 InitialiseSystem();
1702 InitialiseRenderer();
1703
1704 LoadKeyConfiguration();
1705
1706 SoundSys_Start();
1707 if (WantCDRom) CDDA_Start();
1708
1709 InitTextStrings();
1710
1711 BuildMultiplayerLevelNameArray();
1712
1713 ChangeDirectDrawObject();
1714 AvP.LevelCompleted = 0;
1715 LoadSounds("PLAYER");
1716
1717 /* is this still neccessary? */
1718 AvP.CurrentEnv = AvP.StartingEnv = 0;
1719
1720 #if ALIEN_DEMO
1721 AvP.PlayerType = I_Alien;
1722 SetLevelToLoad(AVP_ENVIRONMENT_INVASION_A);
1723 #elif PREDATOR_DEMO
1724 AvP.PlayerType = I_Predator;
1725 SetLevelToLoad(AVP_ENVIRONMENT_INVASION_P);
1726 #elif MARINE_DEMO
1727 AvP.PlayerType = I_Marine;
1728 SetLevelToLoad(AVP_ENVIRONMENT_INVASION);
1729 #endif
1730
1731 main_loop_state = 1;
1732 return 0;
1733
1734 #if 0
1735 #if !(ALIEN_DEMO|PREDATOR_DEMO|MARINE_DEMO)
1736 while (AvP_MainMenus())
1737 #else
1738 if (AvP_MainMenus())
1739 #endif
1740 {
1741 menusActive = 0;
1742 thisLevelHasBeenCompleted = 0;
1743
1744 /* turn off any special effects */
1745 d3d_light_ctrl.ctrl = LCCM_NORMAL;
1746
1747 SetOGLVideoMode(0, 0);
1748
1749 InitialiseGammaSettings(RequestedGammaSetting);
1750
1751 start_of_loaded_shapes = load_precompiled_shapes();
1752
1753 InitCharacter();
1754
1755 LoadRifFile(); /* sets up a map */
1756
1757 AssignAllSBNames();
1758
1759 StartGame();
1760
1761 ffcloseall();
1762
1763 AvP.MainLoopRunning = 1;
1764
1765 ScanImagesForFMVs();
1766
1767 ResetFrameCounter();
1768
1769 Game_Has_Loaded();
1770
1771 ResetFrameCounter();
1772
1773 if(AvP.Network!=I_No_Network)
1774 {
1775 /*Need to choose a starting position for the player , but first we must look
1776 through the network messages to find out which generator spots are currently clear*/
1777 netGameData.myGameState = NGS_Playing;
1778 MinimalNetCollectMessages();
1779 TeleportNetPlayerToAStartingPosition(Player->ObStrategyBlock,1);
1780 }
1781
1782 IngameKeyboardInput_ClearBuffer();
1783
1784 while(AvP.MainLoopRunning) {
1785 CheckForWindowsMessages();
1786
1787 switch(AvP.GameMode) {
1788 case I_GM_Playing:
1789 if ((!menusActive || (AvP.Network!=I_No_Network && !netGameData.skirmishMode)) && !AvP.LevelCompleted) {
1790 /* TODO: print some debugging stuff */
1791
1792 DoAllShapeAnimations();
1793
1794 UpdateGame();
1795
1796 AvpShowViews();
1797
1798 MaintainHUD();
1799
1800 CheckCDAndChooseTrackIfNeeded();
1801
1802 if(InGameMenusAreRunning() && ( (AvP.Network!=I_No_Network && netGameData.skirmishMode) || (AvP.Network==I_No_Network)) ) {
1803 SoundSys_StopAll();
1804 }
1805 } else {
1806 ReadUserInput();
1807
1808 SoundSys_Management();
1809
1810 FlushD3DZBuffer();
1811
1812 ThisFramesRenderingHasBegun();
1813 }
1814
1815 menusActive = AvP_InGameMenus();
1816 if (AvP.RestartLevel) menusActive=0;
1817
1818 if (AvP.LevelCompleted) {
1819 SoundSys_FadeOutFast();
1820 DoCompletedLevelStatisticsScreen();
1821 thisLevelHasBeenCompleted = 1;
1822 }
1823
1824 ThisFramesRenderingHasFinished();
1825
1826 InGameFlipBuffers();
1827
1828 FrameCounterHandler();
1829 {
1830 PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1831
1832 if (!menusActive && playerStatusPtr->IsAlive && !AvP.LevelCompleted) {
1833 DealWithElapsedTime();
1834 }
1835 }
1836 break;
1837
1838 case I_GM_Menus:
1839 AvP.GameMode = I_GM_Playing;
1840 break;
1841 default:
1842 fprintf(stderr, "AvP.MainLoopRunning: gamemode = %d\n", AvP.GameMode);
1843 exit(EXIT_FAILURE);
1844 }
1845
1846 if (AvP.RestartLevel) {
1847 AvP.RestartLevel = 0;
1848 AvP.LevelCompleted = 0;
1849
1850 FixCheatModesInUserProfile(UserProfilePtr);
1851
1852 RestartLevel();
1853 }
1854 }
1855
1856 AvP.LevelCompleted = thisLevelHasBeenCompleted;
1857
1858 FixCheatModesInUserProfile(UserProfilePtr);
1859
1860 ReleaseAllFMVTextures();
1861
1862 CONSBIND_WriteKeyBindingsToConfigFile();
1863
1864 DeInitialisePlayer();
1865
1866 DeallocatePlayersMirrorImage();
1867
1868 KillHUD();
1869
1870 Destroy_CurrentEnvironment();
1871
1872 DeallocateAllImages();
1873
1874 EndNPCs();
1875
1876 ExitGame();
1877
1878 SoundSys_StopAll();
1879
1880 SoundSys_ResetFadeLevel();
1881
1882 CDDA_Stop();
1883
1884 if (AvP.Network != I_No_Network) {
1885 EndAVPNetGame();
1886 }
1887
1888 ClearMemoryPool();
1889
1890 /* go back to menu mode */
1891 #if !(ALIEN_DEMO|PREDATOR_DEMO|MARINE_DEMO)
1892 SetSoftVideoMode(640, 480, 16);
1893 #endif
1894 }
1895
1896 #if !EMSCRIPTEN
1897 SoundSys_StopAll();
1898 SoundSys_RemoveAll();
1899
1900 ExitSystem();
1901
1902 CDDA_End();
1903 ClearMemoryPool();
1904 #endif
1905 #endif
1906 return 0;
1907 }
1908
1909 int AvP_MainMenus_Init(void);
1910 int AvP_MainMenus_Update(void);
1911 int AvP_MainMenus_Deinit(void);
1912
1913 static int MainGame_Init(void);
1914 static int MainGame_Update(void);
1915 static int MainGame_Deinit(void);
1916
main_loop(void)1917 static void main_loop(void) {
1918 switch (main_loop_state) {
1919 case 0:
1920 return;
1921
1922 case -1:
1923 printf("You can't exit the game!\n");
1924 main_loop_state = 0;
1925 return;
1926
1927 case -999:
1928 printf("Unimplemented!\n");
1929 main_loop_state = 0;
1930 return;
1931
1932 case 1:
1933 AvP_MainMenus_Init();
1934 main_loop_state = 2;
1935 // fallthrough
1936 case 2: {
1937 int cont = AvP_MainMenus_Update();
1938 if (cont != 0) {
1939 return;
1940 }
1941 }
1942 // fallthrough
1943
1944 case 3: {
1945 int cont = AvP_MainMenus_Deinit();
1946 if (cont != 0) {
1947 main_loop_state = 4;
1948 return;
1949 }
1950 }
1951 main_loop_state = -1;
1952 return;
1953
1954 case 4: {
1955 MainGame_Init();
1956 main_loop_state = 5;
1957 // fallthrough
1958 }
1959
1960 case 5: {
1961 int cont = MainGame_Update();
1962 if (cont != 0) {
1963 return;
1964 }
1965 // fallthrough
1966 }
1967
1968 case 6: {
1969 MainGame_Deinit();
1970 main_loop_state = 1;
1971 }
1972
1973 }
1974 }
1975
MainGame_Init(void)1976 static int MainGame_Init(void) {
1977 menusActive = 0;
1978 thisLevelHasBeenCompleted = 0;
1979
1980 /* turn off any special effects */
1981 d3d_light_ctrl.ctrl = LCCM_NORMAL;
1982
1983 SetOGLVideoMode(0, 0);
1984
1985 InitialiseGammaSettings(RequestedGammaSetting);
1986
1987 start_of_loaded_shapes = load_precompiled_shapes();
1988
1989 InitCharacter();
1990
1991 LoadRifFile(); /* sets up a map */
1992
1993 AssignAllSBNames();
1994
1995 StartGame();
1996
1997 ffcloseall();
1998
1999 AvP.MainLoopRunning = 1;
2000
2001 ScanImagesForFMVs();
2002
2003 ResetFrameCounter();
2004
2005 Game_Has_Loaded();
2006
2007 ResetFrameCounter();
2008
2009 if(AvP.Network!=I_No_Network)
2010 {
2011 /*Need to choose a starting position for the player , but first we must look
2012 through the network messages to find out which generator spots are currently clear*/
2013 netGameData.myGameState = NGS_Playing;
2014 MinimalNetCollectMessages();
2015 TeleportNetPlayerToAStartingPosition(Player->ObStrategyBlock,1);
2016 }
2017
2018 IngameKeyboardInput_ClearBuffer();
2019
2020 return 0;
2021 }
2022
MainGame_Update(void)2023 static int MainGame_Update(void) {
2024 if(AvP.MainLoopRunning) {
2025 CheckForWindowsMessages();
2026
2027 switch(AvP.GameMode) {
2028 case I_GM_Playing:
2029 if ((!menusActive || (AvP.Network!=I_No_Network && !netGameData.skirmishMode)) && !AvP.LevelCompleted) {
2030 /* TODO: print some debugging stuff */
2031
2032 DoAllShapeAnimations();
2033
2034 UpdateGame();
2035
2036 AvpShowViews();
2037
2038 MaintainHUD();
2039
2040 CheckCDAndChooseTrackIfNeeded();
2041
2042 if(InGameMenusAreRunning() && ( (AvP.Network!=I_No_Network && netGameData.skirmishMode) || (AvP.Network==I_No_Network)) ) {
2043 SoundSys_StopAll();
2044 }
2045 } else {
2046 ReadUserInput();
2047
2048 SoundSys_Management();
2049
2050 FlushD3DZBuffer();
2051
2052 ThisFramesRenderingHasBegun();
2053 }
2054
2055 menusActive = AvP_InGameMenus();
2056 if (AvP.RestartLevel) menusActive=0;
2057
2058 if (AvP.LevelCompleted) {
2059 SoundSys_FadeOutFast();
2060 DoCompletedLevelStatisticsScreen();
2061 thisLevelHasBeenCompleted = 1;
2062 }
2063
2064 ThisFramesRenderingHasFinished();
2065
2066 InGameFlipBuffers();
2067
2068 FrameCounterHandler();
2069 {
2070 PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
2071
2072 if (!menusActive && playerStatusPtr->IsAlive && !AvP.LevelCompleted) {
2073 DealWithElapsedTime();
2074 }
2075 }
2076 break;
2077
2078 case I_GM_Menus:
2079 AvP.GameMode = I_GM_Playing;
2080 break;
2081 default:
2082 fprintf(stderr, "AvP.MainLoopRunning: gamemode = %d\n", AvP.GameMode);
2083 exit(EXIT_FAILURE);
2084 }
2085
2086 if (AvP.RestartLevel) {
2087 AvP.RestartLevel = 0;
2088 AvP.LevelCompleted = 0;
2089
2090 FixCheatModesInUserProfile(UserProfilePtr);
2091
2092 RestartLevel();
2093 }
2094 }
2095
2096 return AvP.MainLoopRunning;
2097 }
2098
MainGame_Deinit(void)2099 static int MainGame_Deinit(void) {
2100
2101 AvP.LevelCompleted = thisLevelHasBeenCompleted;
2102
2103 FixCheatModesInUserProfile(UserProfilePtr);
2104
2105 ReleaseAllFMVTextures();
2106
2107 CONSBIND_WriteKeyBindingsToConfigFile();
2108
2109 DeInitialisePlayer();
2110
2111 DeallocatePlayersMirrorImage();
2112
2113 KillHUD();
2114
2115 Destroy_CurrentEnvironment();
2116
2117 DeallocateAllImages();
2118
2119 EndNPCs();
2120
2121 ExitGame();
2122
2123 SoundSys_StopAll();
2124
2125 SoundSys_ResetFadeLevel();
2126
2127 CDDA_Stop();
2128
2129 if (AvP.Network != I_No_Network) {
2130 EndAVPNetGame();
2131 }
2132
2133 ClearMemoryPool();
2134
2135 /* go back to menu mode */
2136 #if !(ALIEN_DEMO|PREDATOR_DEMO|MARINE_DEMO)
2137 SetSoftVideoMode(640, 480, 16);
2138 #endif
2139
2140 return 0;
2141 }
2142