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