1 /*
2  * vid_cgx.c -- CyberGraphX video driver for AmigaOS & variants.
3  * Select window size and mode and init CGX in SOFTWARE mode.
4  * $Id: vid_cgx.c 5981 2017-09-25 18:50:30Z sezero $
5  *
6  * Copyright (C) 1996-1997  Id Software, Inc.
7  * Copyright (C) 2004-2005  Steven Atkinson <stevenaaus@yahoo.com>
8  * Copyright (C) 2005-2016  O.Sezer <sezero@users.sourceforge.net>
9  * Copyright (C) 2012-2016  Szil�rd Bir� <col.lawrence@gmail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25  */
26 
27 #include <intuition/intuition.h>
28 #include <intuition/intuitionbase.h>
29 #include <cybergraphx/cybergraphics.h>
30 #include <exec/execbase.h>
31 
32 #include <proto/exec.h>
33 #include <proto/intuition.h>
34 #include <proto/graphics.h>
35 #include <proto/cybergraphics.h>
36 
37 #include <SDI/SDI_compiler.h> /* IPTR */
38 
39 /* WriteLUTPixelArray not included in vbcc_target_m68k-amigaos.lha */
40 #if defined(__VBCC__) && defined(__M68K__) && !defined(WriteLUTPixelArray)
41 ULONG __WriteLUTPixelArray(__reg("a6") void *, __reg("a0") APTR srcRect, __reg("d0") UWORD SrcX, __reg("d1") UWORD SrcY, __reg("d2") UWORD SrcMod, __reg("a1") struct RastPort * a1arg, __reg("a2") APTR a2arg, __reg("d3") UWORD DestX, __reg("d4") UWORD DestY, __reg("d5") UWORD SizeX, __reg("d6") UWORD SizeY, __reg("d7") UBYTE CTFormat)="\tjsr\t-198(a6)";
42 #define WriteLUTPixelArray(srcRect, SrcX, SrcY, SrcMod, a1arg, a2arg, DestX, DestY, SizeX, SizeY, CTFormat) __WriteLUTPixelArray(CyberGfxBase, (srcRect), (SrcX), (SrcY), (SrcMod), (a1arg), (a2arg), (DestX), (DestY), (SizeX), (SizeY), (CTFormat))
43 #endif
44 
45 #include "quakedef.h"
46 #include "d_local.h"
47 #include "cfgfile.h"
48 #include "bgmusic.h"
49 #include "cdaudio.h"
50 
51 #define MIN_WIDTH		320
52 #define MIN_HEIGHT		240
53 #define MAX_DESC		33
54 
55 /* - CGX ----------------------------------- */
56 
57 struct Window *window = NULL; /* used by in_amiga.c */
58 static struct Screen *screen = NULL;
59 static unsigned char ppal[256 * 4];
60 static pixel_t *buffer = NULL;
61 static byte *directbitmap = NULL;
62 #ifdef __CLIB2__
63 struct GfxBase *GfxBase = NULL;
64 #endif
65 #ifdef PLATFORM_AMIGAOS3
66 struct Library *CyberGfxBase = NULL;
67 #ifdef USE_C2P
68 static qboolean use_c2p = false;
69 static int currentBitMap;
70 static struct ScreenBuffer *sbuf[2];
71 
72 #define C2P_BITMAP
73 
74 #ifdef C2P_BITMAP
75 typedef void (*c2p_write_bm_func)(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d2, WORD offsx), REG(d3, WORD offsy), REG(a0, APTR chunkyscreen), REG(a1, struct BitMap *bitmap));
76 static c2p_write_bm_func c2p_write_bm;
77 #else
78 typedef void (*c2p_init_func)(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d3, WORD scroffsy), REG(d5, LONG bplsize));
79 typedef void (*c2p_write_func)(REG(a0, APTR c2pscreen), REG(a1, APTR bitplanes));
80 static c2p_init_func c2p_init;
81 static c2p_write_func c2p_write;
82 #endif
83 
84 ASM_LINKAGE_BEGIN
85 extern void c2p1x1_8_c5_030_smcinit(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d3, WORD scroffsy), REG(d5, LONG bplsize));
86 extern void c2p1x1_8_c5_030(REG(a0, APTR c2pscreen), REG(a1, APTR bitplanes));
87 extern void c2p1x1_8_c5_040_init(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d3, WORD scroffsy), REG(d5, LONG bplsize));
88 extern void c2p1x1_8_c5_040(REG(a0, APTR c2pscreen), REG(a1, APTR bitplanes));
89 extern void c2p1x1_8_c5_bm(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d2, WORD offsx), REG(d3, WORD offsy), REG(a0, APTR chunkyscreen), REG(a1, struct BitMap *bitmap));
90 extern void c2p1x1_8_c5_bm_040(REG(d0, WORD chunkyx), REG(d1, WORD chunkyy), REG(d2, WORD offsx), REG(d3, WORD offsy), REG(a0, APTR chunkyscreen), REG(a1, struct BitMap *bitmap));
91 ASM_LINKAGE_END
92 #endif /* USE_C2P */
93 #endif /* PLATFORM_AMIGAOS3 */
94 
95 /* ----------------------------------------- */
96 
97 static unsigned char	vid_curpal[256*3];	/* save for mode changes */
98 
99 unsigned short	d_8to16table[256];
100 unsigned int	d_8to24table[256];
101 
102 byte globalcolormap[VID_GRADES*256], lastglobalcolor = 0;
103 byte *lastsourcecolormap = NULL;
104 
105 qboolean	in_mode_set;
106 static int	enable_mouse;
107 static qboolean	palette_changed;
108 
109 static int	num_fmodes;
110 static int	num_wmodes;
111 static int	*nummodes;
112 
113 static qboolean	vid_menu_fs;
114 //static qboolean	fs_toggle_works = false;
115 
116 viddef_t	vid;		// global video state
117 // cvar vid_mode must be set before calling VID_SetMode, VID_ChangeVideoMode or VID_Restart_f
118 static cvar_t	vid_mode = {"vid_mode", "0", CVAR_NONE};
119 static cvar_t	vid_config_glx = {"vid_config_glx", "640", CVAR_ARCHIVE};
120 static cvar_t	vid_config_gly = {"vid_config_gly", "480", CVAR_ARCHIVE};
121 static cvar_t	vid_config_swx = {"vid_config_swx", "320", CVAR_ARCHIVE};
122 static cvar_t	vid_config_swy = {"vid_config_swy", "240", CVAR_ARCHIVE};
123 #ifdef PLATFORM_AMIGAOS3
124 static cvar_t	vid_config_fscr= {"vid_config_fscr", "1", CVAR_ARCHIVE};
125 #else
126 static cvar_t	vid_config_fscr= {"vid_config_fscr", "0", CVAR_ARCHIVE};
127 #endif
128 static cvar_t	vid_config_mon = {"vid_config_mon", "0", CVAR_ARCHIVE};
129 
130 static cvar_t	vid_showload = {"vid_showload", "1", CVAR_NONE};
131 
132 cvar_t		_enable_mouse = {"_enable_mouse", "1", CVAR_ARCHIVE};
133 
134 static int	vid_default = -1;	// modenum of 320x240 as a safe default
135 static int	vid_modenum = -1;	// current video mode, set after mode setting succeeds
136 static int	vid_maxwidth = 640, vid_maxheight = 480;
137 modestate_t	modestate = MS_UNINIT;
138 
139 static byte		*vid_surfcache;
140 static int		vid_surfcachesize;
141 static int		VID_highhunkmark;
142 
143 typedef struct {
144 	modestate_t	type;
145 	int			width;
146 	int			height;
147 	int			modenum;
148 	int			fullscreen;
149 	int			bpp;
150 /*	int			halfscreen;*/
151 	ULONG		modeid;
152 #ifdef PLATFORM_AMIGAOS3
153 	qboolean	noadapt;
154 #endif
155 	char		modedesc[MAX_DESC];
156 } vmode_t;
157 
158 typedef struct {
159 	int	width;
160 	int	height;
161 } stdmode_t;
162 
163 #define RES_640X480	3
164 static const stdmode_t	std_modes[] = {
165 // NOTE: keep this list in order
166 	{320, 240},	// 0
167 	{400, 300},	// 1
168 	{512, 384},	// 2
169 	{640, 480},	// 3 == RES_640X480, this is our default, below
170 			//		this is the lowresmodes region.
171 			//		either do not change its order,
172 			//		or change the above define, too
173 	{800,  600},	// 4, RES_640X480 + 1
174 	{1024, 768}	// 5, RES_640X480 + 2
175 };
176 
177 #define MAX_MODE_LIST	64
178 #define MAX_STDMODES	(sizeof(std_modes) / sizeof(std_modes[0]))
179 #define NUM_LOWRESMODES	(RES_640X480)
180 static vmode_t	fmodelist[MAX_MODE_LIST+1];	// list of enumerated fullscreen modes
181 static vmode_t	wmodelist[MAX_STDMODES +1];	// list of standart 4:3 windowed modes
182 static vmode_t	*modelist;	// modelist in use, points to one of the above lists
183 
184 static qboolean VID_SetMode (int modenum, const unsigned char *palette);
185 
186 static void VID_MenuDraw (void);
187 static void VID_MenuKey (int key);
188 
189 // window manager stuff
190 #if defined(H2W)
191 #	define WM_TITLEBAR_TEXT	"HexenWorld"
192 #else
193 #	define WM_TITLEBAR_TEXT	"Hexen II"
194 #endif
195 
196 //====================================
197 
198 /*
199 ================
200 ClearAllStates
201 ================
202 */
ClearAllStates(void)203 static void ClearAllStates (void)
204 {
205 	Key_ClearStates ();
206 	IN_ClearStates ();
207 }
208 
209 
210 /*
211 ================
212 VID_AllocBuffers
213 ================
214 */
VID_AllocBuffers(int width,int height)215 static qboolean VID_AllocBuffers (int width, int height)
216 {
217 	int		tsize, tbuffersize;
218 
219 	tbuffersize = width * height * sizeof (*d_pzbuffer);
220 
221 	tsize = D_SurfaceCacheForRes (width, height);
222 
223 	tbuffersize += tsize;
224 
225 // see if there's enough memory, allowing for the normal mode 0x13 pixel,
226 // z, and surface buffers
227 	//if ((host_parms->memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
228 	//	 0x10000 * 3) < MINIMUM_MEMORY)
229 	// Pa3PyX: using hopefully better estimation now
230 	// if total memory < needed surface cache + (minimum operational memory
231 	// less surface cache for 320x200 and typical hunk state after init)
232 	if (host_parms->memsize < tbuffersize + 0x180000 + 0xC00000)
233 	{
234 		Con_SafePrintf ("Not enough memory for video mode\n");
235 		return false;		// not enough memory for mode
236 	}
237 
238 	vid_surfcachesize = tsize;
239 
240 	if (d_pzbuffer)
241 	{
242 		D_FlushCaches ();
243 		Hunk_FreeToHighMark (VID_highhunkmark);
244 		d_pzbuffer = NULL;
245 	}
246 
247 	VID_highhunkmark = Hunk_HighMark ();
248 
249 	d_pzbuffer = (short *) Hunk_HighAllocName (tbuffersize, "video");
250 
251 	vid_surfcache = (byte *)d_pzbuffer +
252 			width * height * sizeof (*d_pzbuffer);
253 
254 	return true;
255 }
256 
257 /*
258 ================
259 VID_CheckAdequateMem
260 ================
261 */
VID_CheckAdequateMem(int width,int height)262 static qboolean VID_CheckAdequateMem (int width, int height)
263 {
264 	int		tbuffersize;
265 
266 	tbuffersize = width * height * sizeof (*d_pzbuffer);
267 
268 	tbuffersize += D_SurfaceCacheForRes (width, height);
269 
270 // see if there's enough memory, allowing for the normal mode 0x13 pixel,
271 // z, and surface buffers
272 	//if ((host_parms->memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
273 	//	 0x10000 * 3) < MINIMUM_MEMORY)
274 	// Pa3PyX: using hopefully better estimation now
275 	// Experimentation: the heap should have at least 12.0 megs
276 	// remaining (after init) after setting video mode, otherwise
277 	// it's Hunk_Alloc failures and cache thrashes upon level load
278 	if (host_parms->memsize < tbuffersize + 0x180000 + 0xC00000)
279 	{
280 		return false;		// not enough memory for mode
281 	}
282 
283 	return true;
284 }
285 
286 //------------------------------------
sort_modes(const void * arg1,const void * arg2)287 static int sort_modes (const void *arg1, const void *arg2)
288 {
289 	const vmode_t *a1, *a2;
290 	a1 = (const vmode_t *) arg1;
291 	a2 = (const vmode_t *) arg2;
292 
293 	if (a1->width == a2->width)
294 		return a1->height - a2->height;	// lowres-to-highres
295 	//	return a2->height - a1->height;	// highres-to-lowres
296 	else
297 		return a1->width - a2->width;	// lowres-to-highres
298 	//	return a2->width - a1->width;	// highres-to-lowres
299 }
300 
VID_PrepareModes(void)301 static void VID_PrepareModes (void)
302 {
303 	qboolean	have_mem;
304 	ULONG id;
305 	unsigned int i;
306 	APTR handle;
307 	struct DimensionInfo diminfo;
308 #ifdef PLATFORM_AMIGAOS3
309 	ULONG monitorid;
310 	struct DisplayInfo dispinfo;
311 	struct NameInfo nameinfo;
312 #endif
313 
314 	num_fmodes = 0;
315 	num_wmodes = 0;
316 
317 	// standard 4:3 windowed modes
318 	for (i = 0; i < (int)MAX_STDMODES; i++)
319 	{
320 		have_mem = VID_CheckAdequateMem(std_modes[i].width, std_modes[i].height);
321 		if (!have_mem)
322 			break;
323 		wmodelist[num_wmodes].width = std_modes[i].width;
324 		wmodelist[num_wmodes].height = std_modes[i].height;
325 		wmodelist[num_wmodes].fullscreen = 0;
326 		wmodelist[num_wmodes].bpp = 8;
327 		wmodelist[num_wmodes].modeid = INVALID_ID;
328 #ifdef PLATFORM_AMIGAOS3
329 		wmodelist[num_wmodes].noadapt = false;
330 #endif
331 		q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC,
332 				"%d x %d", std_modes[i].width, std_modes[i].height);
333 		num_wmodes++;
334 	}
335 
336 	// fullscreen modes
337 	id = INVALID_ID;
338 	while((id = NextDisplayInfo(id)) != INVALID_ID)
339 	{
340 #ifdef PLATFORM_AMIGAOS3
341 		//if (!IsCyberModeID(id))	continue;
342 		monitorid = id & MONITOR_ID_MASK;
343 		if (monitorid == DEFAULT_MONITOR_ID || monitorid == A2024_MONITOR_ID)
344 			continue;
345 #endif
346 
347 		handle = FindDisplayInfo(id);
348 		if (!handle)
349 			continue;
350 
351 #ifdef PLATFORM_AMIGAOS3
352 		if (!GetDisplayInfoData(handle, (UBYTE *)&dispinfo, sizeof(dispinfo), DTAG_DISP, 0))
353 			continue;
354 		// this is a good way to filter out HAM, EHB, DPF modes
355 		if (!GetDisplayInfoData(handle, (UBYTE *)&nameinfo, sizeof(nameinfo), DTAG_NAME, 0))
356 			continue;
357 		//Con_SafePrintf ("modeid %08x name %s\n", id, nameinfo.Name);
358 #endif
359 
360 		if (!GetDisplayInfoData(handle, (UBYTE *)&diminfo, sizeof(diminfo), DTAG_DIMS, 0))
361 			continue;
362 
363 #ifdef __AROS__
364 		if (diminfo.MaxDepth != 24 || diminfo.Nominal.MaxX + 1 < MIN_WIDTH)	continue;
365 #else
366 		if (diminfo.MaxDepth != 8 || diminfo.Nominal.MaxX + 1 < MIN_WIDTH)	continue;
367 #endif
368 
369 		fmodelist[num_fmodes].width = diminfo.Nominal.MaxX + 1;
370 		fmodelist[num_fmodes].height = diminfo.Nominal.MaxY + 1;
371 #ifdef PLATFORM_AMIGAOS3
372 		// round down PAL resolutions to the nearest multiple of 240
373 		if (fmodelist[num_fmodes].height % 256 == 0)
374 			fmodelist[num_fmodes].height -= fmodelist[num_fmodes].height % MIN_HEIGHT;
375 #endif
376 		fmodelist[num_fmodes].fullscreen = 1;
377 		fmodelist[num_fmodes].bpp = 8; // diminfo.MaxDepth
378 		fmodelist[num_fmodes].modeid = id;
379 		q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%d x %d", (fmodelist[num_fmodes].width), (fmodelist[num_fmodes].height));
380 #ifdef PLATFORM_AMIGAOS3
381 		if (dispinfo.PropertyFlags & DIPF_IS_LACE)
382 			q_strlcat(fmodelist[num_fmodes].modedesc, "i", MAX_DESC);
383 		if (monitorid == PAL_MONITOR_ID)
384 			q_strlcat(fmodelist[num_fmodes].modedesc, " PAL", MAX_DESC);
385 		else if (monitorid == NTSC_MONITOR_ID)
386 			q_strlcat(fmodelist[num_fmodes].modedesc, " NTSC", MAX_DESC);
387 		else if (monitorid == DBLPAL_MONITOR_ID)
388 			q_strlcat(fmodelist[num_fmodes].modedesc, " DblPAL", MAX_DESC);
389 		else if (monitorid == DBLNTSC_MONITOR_ID)
390 			q_strlcat(fmodelist[num_fmodes].modedesc, " DblNTSC", MAX_DESC);
391 		else if (monitorid == EURO36_MONITOR_ID)
392 			q_strlcat(fmodelist[num_fmodes].modedesc, " Euro36", MAX_DESC);
393 		else if (monitorid == EURO72_MONITOR_ID)
394 			q_strlcat(fmodelist[num_fmodes].modedesc, " Euro72", MAX_DESC);
395 		else if (monitorid == SUPER72_MONITOR_ID)
396 			q_strlcat(fmodelist[num_fmodes].modedesc, " Super72", MAX_DESC);
397 		else if (monitorid == VGA_MONITOR_ID)
398 			q_strlcat(fmodelist[num_fmodes].modedesc, " VGA", MAX_DESC);
399 		else
400 			q_strlcat(fmodelist[num_fmodes].modedesc, " RTG", MAX_DESC);
401 
402 		fmodelist[num_fmodes].noadapt = (!CyberGfxBase || !IsCyberModeID(id));
403 #endif
404 		//Con_SafePrintf ("fmodelist[%d].modedesc = %s maxdepth %d id %08x\n", num_fmodes, fmodelist[num_fmodes].modedesc, diminfo.MaxDepth, id);
405 
406 		if (++num_fmodes == MAX_MODE_LIST)
407 			break;
408 	}
409 
410 	if (num_fmodes == 0)
411 	{
412 		Con_SafePrintf ("No fullscreen video modes available\n");
413 		if (num_wmodes > RES_640X480)
414 			num_wmodes = RES_640X480 + 1;
415 		modelist = wmodelist;
416 		nummodes = &num_wmodes;
417 		vid_default = 0;
418 		Cvar_SetValueQuick (&vid_config_swx, modelist[vid_default].width);
419 		Cvar_SetValueQuick (&vid_config_swy, modelist[vid_default].height);
420 		return;
421 	}
422 
423 	if (num_fmodes > 1)
424 		qsort(fmodelist, num_fmodes, sizeof(vmode_t), sort_modes);
425 	nummodes = &num_fmodes;
426 	modelist = fmodelist;
427 
428 	/*vid_maxwidth = fmodelist[num_fmodes-1].width;
429 	vid_maxheight = fmodelist[num_fmodes-1].height;*/
430 	if ((screen = LockPubScreen(NULL)))
431 	{
432 		vid_maxwidth = screen->Width;
433 		vid_maxheight = screen->Height;
434 		UnlockPubScreen(NULL, screen);
435 		screen = NULL;
436 	}
437 
438 	// see if we have 320x240 among the available modes
439 	for (i = 0; i < num_fmodes; i++)
440 	{
441 		if (fmodelist[i].width == 320 && fmodelist[i].height == 240)
442 		{
443 			vid_default = i;
444 			break;
445 		}
446 	}
447 
448 	if (vid_default < 0)
449 	{
450 		// 320x240 not found among the supported dimensions
451 		// set default to the lowest resolution reported
452 		vid_default = 0;
453 	}
454 
455 	// limit the windowed (standard) modes list to desktop dimensions
456 	for (i = 0; i < num_wmodes; i++)
457 	{
458 		if (wmodelist[i].width > vid_maxwidth || wmodelist[i].height > vid_maxheight)
459 			break;
460 	}
461 	if (i < num_wmodes)
462 		num_wmodes = i;
463 
464 	Cvar_SetValueQuick (&vid_config_swx, modelist[vid_default].width);
465 	Cvar_SetValueQuick (&vid_config_swy, modelist[vid_default].height);
466 }
467 
VID_ListModes_f(void)468 static void VID_ListModes_f (void)
469 {
470 	int	i;
471 
472 	Con_Printf ("Maximum allowed mode: %d x %d\n", vid_maxwidth, vid_maxheight);
473 	Con_Printf ("Windowed modes enabled:\n");
474 	for (i = 0; i < num_wmodes; i++)
475 		Con_Printf ("%2d:  %d x %d\n", i, wmodelist[i].width, wmodelist[i].height);
476 	Con_Printf ("Fullscreen modes enumerated:");
477 	if (num_fmodes)
478 	{
479 		Con_Printf ("\n");
480 		for (i = 0; i < num_fmodes; i++)
481 			Con_Printf ("%2d:  %d x %d\n", i, fmodelist[i].width, fmodelist[i].height);
482 	}
483 	else
484 	{
485 		Con_Printf (" None\n");
486 	}
487 }
488 
VID_NumModes_f(void)489 static void VID_NumModes_f (void)
490 {
491 	Con_Printf ("%d video modes in current list\n", *nummodes);
492 }
493 
494 //====================================
495 
496 
VID_DestroyWindow(void)497 static void VID_DestroyWindow (void)
498 {
499 	if (window)
500 	{
501 		CloseWindow(window);
502 		window = NULL;
503 	}
504 
505 	if (buffer)
506 	{
507 		free(buffer);
508 		buffer = NULL;
509 	}
510 
511 	/*if (pointermem)
512 	{
513 		FreeVec(pointermem);
514 		pointermem = NULL;
515 	}*/
516 
517 #if defined(PLATFORM_AMIGAOS3) && defined(USE_C2P)
518 	use_c2p = false;
519 
520 	if (sbuf[0])
521 	{
522 		FreeScreenBuffer(screen, sbuf[0]);
523 		sbuf[0] = NULL;
524 	}
525 
526 	if (sbuf[1])
527 	{
528 		FreeScreenBuffer(screen, sbuf[1]);
529 		sbuf[1] = NULL;
530 	}
531 #endif
532 
533 	if (screen)
534 	{
535 		CloseScreen(screen);
536 		screen = NULL;
537 	}
538 }
539 
VID_SetMode(int modenum,const unsigned char * palette)540 static qboolean VID_SetMode (int modenum, const unsigned char *palette)
541 {
542 	ULONG flags;
543 	qboolean eightbit = false;
544 
545 	in_mode_set = true;
546 
547 	VID_DestroyWindow ();
548 
549 	if (!vid_config_fscr.integer && (screen = LockPubScreen(NULL)))
550 	{
551 		eightbit = (GetBitMapAttr(screen->RastPort.BitMap, BMA_DEPTH) <= 8);
552 		UnlockPubScreen(NULL, screen);
553 		screen = NULL;
554 
555 		if (eightbit)
556 		{
557 			struct EasyStruct es;
558 
559 			es.es_StructSize = sizeof(es);
560 			es.es_Flags = 0;
561 			es.es_Title = (STRPTR) ENGINE_NAME;
562 			es.es_TextFormat = (STRPTR) "Windowed mode requires 15 bit or higher color depth screen\nFalling back to fullscreen.";
563 			es.es_GadgetFormat = (STRPTR) "OK";
564 
565 			EasyRequest(0, &es, 0, 0);
566 
567 			Cvar_SetQuick (&vid_config_fscr, "1");
568 		}
569 	}
570 
571 	flags = WFLG_ACTIVATE | WFLG_RMBTRAP;
572 
573 	if (vid_config_fscr.integer)
574 	{
575 		ULONG ModeID;
576 		#if defined(PLATFORM_AMIGAOS3) && defined(USE_C2P)
577 		struct BitMap *bm;
578 		#endif
579 
580 		/*ModeID = BestCModeIDTags(
581 			CYBRBIDTG_Depth, 8,
582 			CYBRBIDTG_NominalWidth, modelist[modenum].width,
583 			CYBRBIDTG_NominalHeight, modelist[modenum].height,
584 			TAG_DONE);*/
585 		ModeID = modelist[modenum].modeid;
586 
587 		screen = OpenScreenTags(0,
588 			ModeID != INVALID_ID ? SA_DisplayID : TAG_IGNORE, ModeID,
589 			SA_Width, modelist[modenum].width,
590 			SA_Height, modelist[modenum].height,
591 			SA_Depth, 8,
592 			SA_Quiet, TRUE,
593 			TAG_DONE);
594 
595 		#if defined(PLATFORM_AMIGAOS3) && defined(USE_C2P)
596 		currentBitMap = 0;
597 		bm = screen->RastPort.BitMap;
598 
599 		if ((GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD) && (modelist[modenum].width % 32) == 0)
600 		{
601 			if ((sbuf[0] = AllocScreenBuffer(screen, 0, SB_SCREEN_BITMAP)) && (sbuf[1] = AllocScreenBuffer(screen, 0, 0)))
602 			{
603 				use_c2p = true;
604 				#ifndef C2P_BITMAP
605 				c2p_init(modelist[modenum].width, modelist[modenum].height, 0, bm->BytesPerRow*bm->Rows);
606 				#endif
607 				// this fixes some RTG modes which would otherwise display garbage on the 1st buffer swap
608 				//VID_Update(NULL);
609 			}
610 		}
611 		#endif
612 	}
613 
614 	if (screen)
615 	{
616 		flags |= WFLG_BACKDROP | WFLG_BORDERLESS;
617 	}
618 	else
619 	{
620 		if (eightbit) /* shouldn't happen, but.. */
621 			Sys_Error("failed OpenScreen ()");
622 		Cvar_SetQuick (&vid_config_fscr, "0");
623 		flags |=  WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET;
624 	}
625 
626 	window = OpenWindowTags(0,
627 		WA_InnerWidth, modelist[modenum].width,
628 		WA_InnerHeight, modelist[modenum].height,
629 		WA_Title, (IPTR)WM_TITLEBAR_TEXT,
630 		WA_Flags, flags,
631 		screen ? WA_CustomScreen : TAG_IGNORE, (IPTR)screen,
632 		WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW,
633 		TAG_DONE);
634 
635 	if (window)
636 	{
637 		/*pointermem = AllocVec(256, MEMF_ANY | MEMF_CLEAR);
638 		if (pointermem) {*/
639 			vid.height = vid.conheight = modelist[modenum].height;
640 			vid.rowbytes = vid.conrowbytes = vid.width = vid.conwidth = modelist[modenum].width;
641 			buffer = (pixel_t *) malloc(vid.width * vid.height);
642 
643 			if (buffer)
644 			{
645 				vid.buffer = vid.direct = vid.conbuffer = buffer;
646 				vid.numpages = 1;
647 				vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
648 
649 				if (VID_AllocBuffers (vid.width, vid.height))
650 				{
651 					D_InitCaches (vid_surfcache, vid_surfcachesize);
652 
653 					// real success. set vid_modenum properly.
654 					vid_modenum = modenum;
655 					modestate = (screen) ? MS_FULLDIB : MS_WINDOWED;
656 					Cvar_SetValueQuick (&vid_config_swx, modelist[vid_modenum].width);
657 					Cvar_SetValueQuick (&vid_config_swy, modelist[vid_modenum].height);
658 					if (screen)
659 						Cvar_SetValueQuick (&vid_config_mon, (float)(modelist[vid_modenum].modeid & MONITOR_ID_MASK));
660 
661 					//IN_HideMouse ();
662 
663 					ClearAllStates();
664 
665 					VID_SetPalette (palette);
666 
667 					Con_SafePrintf ("Video Mode: %ux%ux%d\n", vid.width, vid.height, modelist[modenum].bpp);
668 
669 					#ifdef PLATFORM_AMIGAOS3
670 					vid.noadapt = modelist[modenum].noadapt;
671 					#endif
672 					in_mode_set = false;
673 					vid.recalc_refdef = 1;
674 
675 					return true;
676 				}
677 				free(buffer);
678 				buffer = NULL;
679 			}
680 		/*	FreeVec(pointermem);
681 			pointermem = NULL;
682 		}*/
683 		CloseWindow(window);
684 		window = NULL;
685 	}
686 
687 	if (screen)
688 	{
689 		CloseScreen(screen);
690 		screen = NULL;
691 	}
692 
693 	in_mode_set = false;
694 	return false;
695 }
696 
697 
VID_ChangeVideoMode(int newmode)698 static void VID_ChangeVideoMode (int newmode)
699 {
700 	int		temp;
701 
702 	temp = scr_disabled_for_loading;
703 	scr_disabled_for_loading = true;
704 	CDAudio_Pause ();
705 	BGM_Pause ();
706 	S_ClearBuffer ();
707 
708 	if (!VID_SetMode (newmode, vid_curpal))
709 	{
710 		if (vid_modenum == newmode)
711 			Sys_Error ("Couldn't set video mode");
712 
713 		// failed setting mode, probably due to insufficient
714 		// memory. go back to previous mode.
715 		Cvar_SetValueQuick (&vid_mode, vid_modenum);
716 		if (!VID_SetMode (vid_modenum, vid_curpal))
717 			Sys_Error ("Couldn't set video mode");
718 	}
719 
720 	CDAudio_Resume ();
721 	BGM_Resume ();
722 	scr_disabled_for_loading = temp;
723 }
724 
VID_Restart_f(void)725 static void VID_Restart_f (void)
726 {
727 	if (vid_mode.integer < 0 || vid_mode.integer >= *nummodes)
728 	{
729 		Con_Printf ("Bad video mode %d\n", vid_mode.integer);
730 		Cvar_SetValueQuick (&vid_mode, vid_modenum);
731 		return;
732 	}
733 
734 	Con_Printf ("Re-initializing video:\n");
735 	VID_ChangeVideoMode (vid_mode.integer);
736 }
737 
VID_LockBuffer(void)738 void VID_LockBuffer(void)
739 {
740 }
741 
VID_UnlockBuffer(void)742 void VID_UnlockBuffer(void)
743 {
744 }
745 
746 
VID_SetPalette(const unsigned char * palette)747 void VID_SetPalette(const unsigned char *palette)
748 {
749 	const unsigned char *p;
750 	unsigned char *pp;
751 	int i;
752 
753 	palette_changed = true;
754 
755 	if (palette != vid_curpal)
756 		memcpy(vid_curpal, palette, sizeof(vid_curpal));
757 
758 	if (screen)
759 	{
760 		ULONG spal[1 + (256 * 3) + 1];
761 		ULONG *sp = spal;
762 
763 		*sp++ = 256 << 16;
764 
765 		for (i = 0, p = palette; i < 256; i++)
766 		{
767 			*sp++ = ((ULONG) *p++) << 24;
768 			*sp++ = ((ULONG) *p++) << 24;
769 			*sp++ = ((ULONG) *p++) << 24;
770 		}
771 
772 		*sp = 0;
773 
774 		LoadRGB32(&screen->ViewPort, spal);
775 	}
776 
777 	for (i = 0, p = palette, pp = ppal; i < 256; i++)
778 	{
779 		if (host_bigendian)
780 		{
781 			*pp++ = 0;
782 			*pp++ = *p++;
783 			*pp++ = *p++;
784 			*pp++ = *p++;
785 		}
786 		else
787 		{
788 			*pp++ = p[2];
789 			*pp++ = p[1];
790 			*pp++ = p[0];
791 			*pp++ = 0;
792 			p += 3;
793 		}
794 	}
795 }
796 
VID_ShiftPalette(const unsigned char * palette)797 void VID_ShiftPalette(const unsigned char *palette)
798 {
799 	VID_SetPalette(palette);
800 }
801 
VID_Init(const unsigned char * palette)802 void VID_Init (const unsigned char *palette)
803 {
804 	int		width, height, i, temp, monitor;
805 	const char	*read_vars[] = {
806 				"vid_config_fscr",
807 				"vid_config_mon",
808 				"vid_config_swx",
809 				"vid_config_swy" };
810 #define num_readvars	( sizeof(read_vars)/sizeof(read_vars[0]) )
811 
812 #ifdef __CLIB2__
813 	GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
814 	if (!GfxBase)
815 		Sys_Error ("Cannot open graphics.library!");
816 #endif
817 
818 #ifdef PLATFORM_AMIGAOS3
819 	CyberGfxBase = OpenLibrary("cybergraphics.library", 0);
820 	/*if (!CyberGfxBase)
821 		Sys_Error ("Cannot open cybergraphics.library!");*/
822 
823 #ifdef USE_C2P
824 	if (SysBase->AttnFlags & AFF_68040)
825 	{
826 #ifdef C2P_BITMAP
827 		c2p_write_bm = c2p1x1_8_c5_bm_040;
828 #else
829 		c2p_init = c2p1x1_8_c5_040_init;
830 		c2p_write = c2p1x1_8_c5_040;
831 #endif
832 	}
833 	else
834 	{
835 #ifdef C2P_BITMAP
836 		c2p_write_bm = c2p1x1_8_c5_bm;
837 #else
838 		c2p_init = c2p1x1_8_c5_030_smcinit;
839 		c2p_write = c2p1x1_8_c5_030;
840 #endif
841 	}
842 #endif
843 #endif
844 
845 	temp = scr_disabled_for_loading;
846 	scr_disabled_for_loading = true;
847 
848 	Cvar_RegisterVariable (&vid_config_fscr);
849 	Cvar_RegisterVariable (&vid_config_mon);
850 	Cvar_RegisterVariable (&vid_config_swy);
851 	Cvar_RegisterVariable (&vid_config_swx);
852 	Cvar_RegisterVariable (&vid_config_gly);
853 	Cvar_RegisterVariable (&vid_config_glx);
854 	Cvar_RegisterVariable (&vid_mode);
855 	Cvar_RegisterVariable (&_enable_mouse);
856 	Cvar_RegisterVariable (&vid_showload);
857 
858 	Cmd_AddCommand ("vid_listmodes", VID_ListModes_f);
859 	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
860 	Cmd_AddCommand ("vid_restart", VID_Restart_f);
861 
862 
863 	// prepare the modelists, find the actual modenum for vid_default
864 	VID_PrepareModes();
865 	//VID_ListModes_f();
866 
867 	// set vid_mode to our safe default first
868 	Cvar_SetValueQuick (&vid_mode, vid_default);
869 
870 	// perform an early read of config.cfg
871 	CFG_ReadCvars (read_vars, num_readvars);
872 
873 	// windowed mode is default
874 	// see if the user wants fullscreen
875 	if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
876 	{
877 		Cvar_SetQuick (&vid_config_fscr, "1");
878 	}
879 	else if (COM_CheckParm("-window") || COM_CheckParm("-w"))
880 	{
881 		Cvar_SetQuick (&vid_config_fscr, "0");
882 	}
883 
884 	if (vid_config_fscr.integer && !num_fmodes) // FIXME: see below, as well
885 		Sys_Error ("No fullscreen modes available at this color depth");
886 
887 	width = vid_config_swx.integer;
888 	height = vid_config_swy.integer;
889 	monitor = vid_config_mon.integer;
890 
891 	// user is always right ...
892 	i = COM_CheckParm("-width");
893 	if (i && i < com_argc-1)
894 	{	// FIXME: this part doesn't know about a disaster case
895 		// like we aren't reported any fullscreen modes.
896 		width = atoi(com_argv[i+1]);
897 
898 		i = COM_CheckParm("-height");
899 		if (i && i < com_argc-1)
900 			height = atoi(com_argv[i+1]);
901 		else	// proceed with 4/3 ratio
902 			height = 3 * width / 4;
903 	}
904 
905 	// pick the appropriate list
906 	if (vid_config_fscr.integer)
907 	{
908 		modelist = fmodelist;
909 		nummodes = &num_fmodes;
910 	}
911 	else
912 	{
913 		modelist = wmodelist;
914 		nummodes = &num_wmodes;
915 	}
916 
917 	// user requested a mode either from the config or from the
918 	// command line
919 	// scan existing modes to see if this is already available
920 	// if not, add this as the last "valid" video mode and set
921 	// vid_mode to it only if it doesn't go beyond vid_maxwidth
922 	i = 0;
923 	if (vid_config_fscr.integer)
924 	{
925 		while (i < *nummodes)
926 		{
927 			if (modelist[i].width == width && modelist[i].height == height && (modelist[i].modeid & MONITOR_ID_MASK) == monitor)
928 				break;
929 			i++;
930 		}
931 	}
932 	if (i == 0 || i == *nummodes)
933 	{
934 		i = 0;
935 		while (i < *nummodes)
936 		{
937 			if (modelist[i].width == width && modelist[i].height == height)
938 				break;
939 			i++;
940 		}
941 	}
942 	if (i < *nummodes)
943 	{
944 		Cvar_SetValueQuick (&vid_mode, i);
945 	}
946 	else if ( (width <= vid_maxwidth && width >= MIN_WIDTH &&
947 		   height <= vid_maxheight && height >= MIN_HEIGHT) ||
948 		  COM_CheckParm("-force") )
949 	{
950 		modelist[*nummodes].width = width;
951 		modelist[*nummodes].height = height;
952 		modelist[*nummodes].fullscreen = 1;
953 		modelist[*nummodes].bpp = 8;
954 		modelist[*nummodes].modeid = INVALID_ID;
955 #ifdef PLATFORM_AMIGAOS3
956 		modelist[*nummodes].noadapt = false;
957 #endif
958 		q_snprintf (modelist[*nummodes].modedesc, MAX_DESC, "%d x %d (user mode)", width, height);
959 		Cvar_SetValueQuick (&vid_mode, *nummodes);
960 		(*nummodes)++;
961 	}
962 	else
963 	{
964 		Con_SafePrintf ("ignoring invalid -width and/or -height arguments\n");
965 	}
966 
967 	vid.maxwarpwidth = WARP_WIDTH;
968 	vid.maxwarpheight = WARP_HEIGHT;
969 	vid.colormap = host_colormap;
970 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
971 
972 	if (!VID_SetMode (vid_mode.integer, palette))
973 	{
974 		if (vid_mode.integer == vid_default)
975 			Sys_Error ("Couldn't set video mode");
976 
977 		// just one more try before dying
978 		Con_SafePrintf ("Couldn't set video mode %d\n"
979 				"Trying the default mode\n", vid_mode.integer);
980 		//Cvar_SetQuick (&vid_config_fscr, "0");
981 		Cvar_SetValueQuick (&vid_mode, vid_default);
982 		if (!VID_SetMode (vid_default, palette))
983 			Sys_Error ("Couldn't set video mode");
984 	}
985 
986 	// lock the early-read cvars until Host_Init is finished
987 	for (i = 0; i < (int)num_readvars; i++)
988 		Cvar_LockVar (read_vars[i]);
989 
990 	scr_disabled_for_loading = temp;
991 
992 	vid_menudrawfn = VID_MenuDraw;
993 	vid_menukeyfn = VID_MenuKey;
994 }
995 
996 
VID_Shutdown(void)997 void VID_Shutdown (void)
998 {
999 	VID_DestroyWindow ();
1000 
1001 #ifdef PLATFORM_AMIGAOS3
1002 	if (CyberGfxBase) {
1003 		CloseLibrary(CyberGfxBase);
1004 		CyberGfxBase = NULL;
1005 	}
1006 #endif
1007 #ifdef __CLIB2__
1008 	if (GfxBase) {
1009 		CloseLibrary((struct Library *)GfxBase);
1010 		GfxBase = NULL;
1011 	}
1012 #endif
1013 }
1014 
1015 
FlipScreen(vrect_t * rects)1016 static void FlipScreen (vrect_t *rects)
1017 {
1018 #ifdef USE_C2P
1019 	if (use_c2p)
1020 	{
1021 		currentBitMap ^= 1;
1022 #ifdef C2P_BITMAP
1023 		c2p_write_bm(vid.width, vid.height, 0, 0, vid.buffer, sbuf[currentBitMap]->sb_BitMap);
1024 #else
1025 		c2p_write(vid.buffer, sbuf[currentBitMap]->sb_BitMap->Planes[0]);
1026 #endif
1027 		ChangeScreenBuffer(screen, sbuf[currentBitMap]);
1028 		return;
1029 	}
1030 #endif
1031 
1032 	while (rects)
1033 	{
1034 #ifdef PLATFORM_AMIGAOS3
1035 		if (!CyberGfxBase)
1036 		{
1037 			WriteChunkyPixels(window->RPort,
1038 							rects->x,
1039 							rects->y,
1040 							rects->width,
1041 							rects->height,
1042 							vid.buffer,
1043 							vid.rowbytes);
1044 		}
1045 		else
1046 #endif
1047 		if (screen)
1048 		{
1049 			WritePixelArray(vid.buffer,
1050 							rects->x,
1051 							rects->y,
1052 							vid.rowbytes,
1053 							window->RPort,
1054 							rects->x,
1055 							rects->y,
1056 							rects->width,
1057 							rects->height,
1058 							RECTFMT_LUT8);
1059 		}
1060 		else
1061 		{
1062 			WriteLUTPixelArray(vid.buffer,
1063 							rects->x,
1064 							rects->y,
1065 							vid.rowbytes,
1066 							window->RPort, ppal,
1067 							window->BorderLeft + rects->x,
1068 							window->BorderTop + rects->y,
1069 							rects->width,
1070 							rects->height,
1071 							CTABFMT_XRGB8);
1072 		}
1073 
1074 		rects = rects->pnext;
1075 	}
1076 }
1077 
VID_Update(vrect_t * rects)1078 void VID_Update(vrect_t *rects)
1079 {
1080 	vrect_t		rect;
1081 
1082 	if (palette_changed)
1083 	{
1084 		palette_changed = false;
1085 		rect.x = 0;
1086 		rect.y = 0;
1087 		rect.width = vid.width;
1088 		rect.height = vid.height;
1089 		rect.pnext = NULL;
1090 		rects = &rect;
1091 	}
1092 
1093 	// We've drawn the frame; copy it to the screen
1094 	FlipScreen (rects);
1095 
1096 	// handle the mouse state when windowed if that's changed
1097 	if (_enable_mouse.integer != enable_mouse /*&& modestate == MS_WINDOWED*/)
1098 	{
1099 		if (_enable_mouse.integer)
1100 			IN_ActivateMouse ();
1101 		else	IN_DeactivateMouse ();
1102 
1103 		enable_mouse = _enable_mouse.integer;
1104 	}
1105 }
1106 
1107 
1108 /*
1109 ================
1110 D_BeginDirectRect
1111 ================
1112 */
D_BeginDirectRect(int x,int y,byte * pbitmap,int width,int height)1113 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
1114 {
1115 	directbitmap = pbitmap;
1116 }
1117 
1118 /*
1119 ================
1120 D_EndDirectRect
1121 ================
1122 */
D_EndDirectRect(int x,int y,int width,int height)1123 void D_EndDirectRect (int x, int y, int width, int height)
1124 {
1125 	if (!window || !directbitmap)
1126 		return;
1127 
1128 	if (x < 0)
1129 		x = vid.width + x - 1;
1130 
1131 	if (screen)
1132 	{
1133 		WritePixelArray(directbitmap, 0, 0, width, window->RPort, x, y, width, height, RECTFMT_LUT8);
1134 	}
1135 	else
1136 	{
1137 		WriteLUTPixelArray(directbitmap, 0, 0, width, window->RPort, ppal, window->BorderLeft + x, window->BorderTop + y, width, height, CTABFMT_XRGB8);
1138 	}
1139 
1140 	directbitmap = NULL;
1141 }
1142 
1143 #ifndef H2W
1144 // unused in hexenworld
D_ShowLoadingSize(void)1145 void D_ShowLoadingSize (void)
1146 {
1147 #if defined(DRAW_PROGRESSBARS)
1148 #error NOT IMPLEMENTED
1149 #endif
1150 }
1151 #endif
1152 
1153 
1154 //==========================================================================
1155 
1156 /*
1157 ================
1158 VID_HandlePause
1159 ================
1160 */
VID_HandlePause(qboolean paused)1161 void VID_HandlePause (qboolean paused)
1162 {
1163 	if (_enable_mouse.integer /*&& (modestate == MS_WINDOWED)*/)
1164 	{
1165 		// for consistency, don't show pointer - S.A
1166 		if (paused)
1167 		{
1168 			IN_DeactivateMouse ();
1169 			//SetPointer(window, pointermem, 16, 16, 0, 0);
1170 		}
1171 		else
1172 		{
1173 			IN_ActivateMouse ();
1174 			//ClearPointer(window);
1175 		}
1176 	}
1177 }
1178 
1179 
1180 /*
1181 ================
1182 VID_ToggleFullscreen
1183 Handles switching between fullscreen/windowed modes
1184 and brings the mouse to a proper state afterwards
1185 ================
1186 */
1187 //extern qboolean menu_disabled_mouse;
VID_ToggleFullscreen(void)1188 void VID_ToggleFullscreen(void)
1189 {
1190 	// implement this...
1191 }
1192 
1193 
1194 //========================================================
1195 // Video menu stuff
1196 //========================================================
1197 
1198 static int	vid_menunum;
1199 static int	vid_cursor;
1200 static vmode_t	*vid_menulist;	// this changes when vid_menu_fs changes
1201 static qboolean	want_fstoggle, need_apply;
1202 static qboolean	vid_menu_firsttime = true;
1203 
1204 enum {
1205 	VID_FULLSCREEN,	// make sure the fullscreen entry (0)
1206 	VID_RESOLUTION,	// is lower than resolution entry (1)
1207 	VID_BLANKLINE,	// spacer line
1208 	VID_RESET,
1209 	VID_APPLY,
1210 	VID_ITEMS
1211 };
1212 
M_DrawYesNo(int x,int y,int on,int white)1213 static void M_DrawYesNo (int x, int y, int on, int white)
1214 {
1215 	if (on)
1216 	{
1217 		if (white)
1218 			M_PrintWhite (x, y, "yes");
1219 		else
1220 			M_Print (x, y, "yes");
1221 	}
1222 	else
1223 	{
1224 		if (white)
1225 			M_PrintWhite (x, y, "no");
1226 		else
1227 			M_Print (x, y, "no");
1228 	}
1229 }
1230 
1231 /*
1232 ================
1233 VID_MenuDraw
1234 ================
1235 */
VID_MenuDraw(void)1236 static void VID_MenuDraw (void)
1237 {
1238 	ScrollTitle("gfx/menu/title7.lmp");
1239 
1240 	if (vid_menu_firsttime)
1241 	{	// settings for entering the menu first time
1242 		vid_menunum = vid_modenum;
1243 		vid_menu_fs = (modestate != MS_WINDOWED);
1244 		vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
1245 		vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1246 		vid_menu_firsttime = false;
1247 	}
1248 
1249 	want_fstoggle = ( ((modestate == MS_WINDOWED) && vid_menu_fs) || ((modestate != MS_WINDOWED) && !vid_menu_fs) );
1250 
1251 	need_apply = (vid_menunum != vid_modenum) || want_fstoggle;
1252 
1253 	M_Print (76, 92 + 8*VID_FULLSCREEN, "Fullscreen: ");
1254 	M_DrawYesNo (76+12*8, 92 + 8*VID_FULLSCREEN, vid_menu_fs, !want_fstoggle);
1255 
1256 	M_Print (76, 92 + 8*VID_RESOLUTION, "Resolution: ");
1257 	if (vid_menunum == vid_modenum)
1258 		M_PrintWhite (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
1259 	else
1260 		M_Print (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
1261 
1262 	if (need_apply)
1263 	{
1264 		M_Print (76, 92 + 8*VID_RESET, "RESET CHANGES");
1265 		M_Print (76, 92 + 8*VID_APPLY, "APPLY CHANGES");
1266 	}
1267 
1268 	M_DrawCharacter (64, 92 + vid_cursor*8, 12+((int)(realtime*4)&1));
1269 }
1270 
match_windowed_fullscr_modes(void)1271 static int match_windowed_fullscr_modes (void)
1272 {
1273 	int	l;
1274 	vmode_t	*tmplist;
1275 	int	*tmpcount;
1276 
1277 	// choose the new mode
1278 	tmplist = (vid_menu_fs) ? fmodelist : wmodelist;
1279 	tmpcount = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
1280 	for (l = 0; l < *tmpcount; l++)
1281 	{
1282 		if (tmplist[l].width == vid_menulist[vid_menunum].width &&
1283 		    tmplist[l].height == vid_menulist[vid_menunum].height)
1284 		{
1285 			return l;
1286 		}
1287 	}
1288 	return 0;
1289 }
1290 
1291 /*
1292 ================
1293 VID_MenuKey
1294 ================
1295 */
VID_MenuKey(int key)1296 static void VID_MenuKey (int key)
1297 {
1298 	int	*tmpnum;
1299 
1300 	switch (key)
1301 	{
1302 	case K_ESCAPE:
1303 		vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1304 		M_Menu_Options_f ();
1305 		return;
1306 
1307 	case K_ENTER:
1308 		switch (vid_cursor)
1309 		{
1310 		case VID_RESET:
1311 			vid_menu_fs = (modestate != MS_WINDOWED);
1312 			vid_menunum = vid_modenum;
1313 			vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
1314 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1315 			break;
1316 		case VID_APPLY:
1317 			if (need_apply)
1318 			{
1319 				Cvar_SetValueQuick(&vid_mode, vid_menunum);
1320 				Cvar_SetValueQuick(&vid_config_fscr, vid_menu_fs);
1321 				modelist = (vid_menu_fs) ? fmodelist : wmodelist;
1322 				nummodes = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
1323 				VID_Restart_f();
1324 			}
1325 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1326 			break;
1327 		}
1328 		return;
1329 
1330 	case K_LEFTARROW:
1331 		switch (vid_cursor)
1332 		{
1333 		case VID_FULLSCREEN:
1334 			vid_menu_fs = !vid_menu_fs;
1335 			vid_menunum = match_windowed_fullscr_modes();
1336 			vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
1337 			/*if (fs_toggle_works)
1338 				VID_ToggleFullscreen();*/
1339 			break;
1340 		case VID_RESOLUTION:
1341 			S_LocalSound ("raven/menu1.wav");
1342 			vid_menunum--;
1343 			if (vid_menunum < 0)
1344 				vid_menunum = 0;
1345 			break;
1346 		}
1347 		return;
1348 
1349 	case K_RIGHTARROW:
1350 		switch (vid_cursor)
1351 		{
1352 		case VID_FULLSCREEN:
1353 			vid_menu_fs = !vid_menu_fs;
1354 			vid_menunum = match_windowed_fullscr_modes();
1355 			vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
1356 			/*if (fs_toggle_works)
1357 				VID_ToggleFullscreen();*/
1358 			break;
1359 		case VID_RESOLUTION:
1360 			S_LocalSound ("raven/menu1.wav");
1361 			tmpnum = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
1362 			vid_menunum++;
1363 			/*if (vid_menunum >= *nummodes)
1364 				vid_menunum = *nummodes - 1;*/
1365 			if (vid_menunum >= *tmpnum)
1366 				vid_menunum--;
1367 			break;
1368 		}
1369 		return;
1370 
1371 	case K_UPARROW:
1372 		S_LocalSound ("raven/menu1.wav");
1373 		vid_cursor--;
1374 		if (vid_cursor < 0)
1375 		{
1376 			vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1;
1377 		}
1378 		else if (vid_cursor == VID_BLANKLINE)
1379 		{
1380 			vid_cursor--;
1381 		}
1382 		break;
1383 
1384 	case K_DOWNARROW:
1385 		S_LocalSound ("raven/menu1.wav");
1386 		vid_cursor++;
1387 		if (vid_cursor >= VID_ITEMS)
1388 		{
1389 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1390 			break;
1391 		}
1392 		if (vid_cursor >= VID_BLANKLINE)
1393 		{
1394 			if (need_apply)
1395 			{
1396 				if (vid_cursor == VID_BLANKLINE)
1397 					vid_cursor++;
1398 			}
1399 			else
1400 			{
1401 				vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
1402 			}
1403 		}
1404 		break;
1405 
1406 	default:
1407 		return;
1408 	}
1409 }
1410 
1411