1 /*
2 ** videomenu.cpp
3 ** The video modes menu
4 **
5 **---------------------------------------------------------------------------
6 ** Copyright 2001-2010 Randy Heit
7 ** Copyright 2010 Christoph Oelckers
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
12 ** are met:
13 **
14 ** 1. Redistributions of source code must retain the above copyright
15 **    notice, this list of conditions and the following disclaimer.
16 ** 2. Redistributions in binary form must reproduce the above copyright
17 **    notice, this list of conditions and the following disclaimer in the
18 **    documentation and/or other materials provided with the distribution.
19 ** 3. The name of the author may not be used to endorse or promote products
20 **    derived from this software without specific prior written permission.
21 **
22 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 **---------------------------------------------------------------------------
33 **
34 */
35 
36 #include <float.h>
37 
38 #include "menu/menu.h"
39 #include "c_dispatch.h"
40 #include "w_wad.h"
41 #include "sc_man.h"
42 #include "v_font.h"
43 #include "g_level.h"
44 #include "d_player.h"
45 #include "v_video.h"
46 #include "gi.h"
47 #include "i_system.h"
48 #include "c_bind.h"
49 #include "v_palette.h"
50 #include "d_event.h"
51 #include "d_gui.h"
52 #include "i_music.h"
53 #include "m_joy.h"
54 #include "sbar.h"
55 #include "hardware.h"
56 
57 #define NO_IMP
58 #include "optionmenuitems.h"
59 
60 
61 /*=======================================
62  *
63  * Video Modes Menu
64  *
65  *=======================================*/
66 static void BuildModesList (int hiwidth, int hiheight, int hi_id);
67 static bool GetSelectedSize (int *width, int *height);
68 static void SetModesMenu (int w, int h, int bits);
69 FOptionMenuDescriptor *GetVideoModeMenu();
70 
71 extern bool setmodeneeded;
72 extern int NewWidth, NewHeight, NewBits;
73 extern int DisplayBits;
74 
75 EXTERN_CVAR (Int, vid_defwidth)
76 EXTERN_CVAR (Int, vid_defheight)
77 EXTERN_CVAR (Int, vid_defbits)
78 EXTERN_CVAR (Bool, fullscreen)
79 EXTERN_CVAR (Bool, vid_tft)		// Defined below
80 
81 int testingmode;		// Holds time to revert to old mode
82 int OldWidth, OldHeight, OldBits;
83 static FIntCVar DummyDepthCvar (NULL, 0, 0);
84 static BYTE BitTranslate[32];
85 
86 CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE)
87 {
88 	if (self < -1 || self > 4)
89 	{
90 		self = -1;
91 	}
92 	else if (self == 4 && !vid_tft)
93 	{
94 		self = 0;
95 	}
96 	else
97 	{
98 		BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
99 	}
100 }
101 
102 CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
103 {
104 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
105 	if (opt != NULL)
106 	{
107 		FOptionMenuItem *it = opt->GetItem("menu_screenratios");
108 		if (it != NULL)
109 		{
110 			if (self)
111 			{
112 				it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "RatiosTFT");
113 			}
114 			else
115 			{
116 				it->SetString(FOptionMenuItemOptionBase::OP_VALUES, "Ratios");
117 			}
118 		}
119 	}
120 	setsizeneeded = true;
121 	if (StatusBar != NULL)
122 	{
123 		StatusBar->ScreenSizeChanged();
124 	}
125 }
126 
127 
128 //=============================================================================
129 //
130 //
131 //
132 //=============================================================================
133 
134 class DVideoModeMenu : public DOptionMenu
135 {
136 	DECLARE_CLASS(DVideoModeMenu, DOptionMenu)
137 
138 public:
139 
DVideoModeMenu()140 	DVideoModeMenu()
141 	{
142 		SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
143 	}
144 
MenuEvent(int mkey,bool fromcontroller)145 	bool MenuEvent(int mkey, bool fromcontroller)
146 	{
147 		if ((mkey == MKEY_Up || mkey == MKEY_Down) && mDesc->mSelectedItem >= 0 &&
148 			mDesc->mSelectedItem < (int)mDesc->mItems.Size())
149 		{
150 			int sel;
151 			bool selected = mDesc->mItems[mDesc->mSelectedItem]->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &sel);
152 			bool res = Super::MenuEvent(mkey, fromcontroller);
153 			if (selected) mDesc->mItems[mDesc->mSelectedItem]->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, sel);
154 			return res;
155 		}
156 		return Super::MenuEvent(mkey, fromcontroller);
157 	}
158 
Responder(event_t * ev)159 	bool Responder(event_t *ev)
160 	{
161 		if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown &&
162 			(ev->data1 == 't' || ev->data1 == 'T'))
163 		{
164 			if (!GetSelectedSize (&NewWidth, &NewHeight))
165 			{
166 				NewWidth = SCREENWIDTH;
167 				NewHeight = SCREENHEIGHT;
168 			}
169 			else
170 			{
171 				OldWidth = SCREENWIDTH;
172 				OldHeight = SCREENHEIGHT;
173 				OldBits = DisplayBits;
174 				NewBits = BitTranslate[DummyDepthCvar];
175 				setmodeneeded = true;
176 				testingmode = I_GetTime(false) + 5 * TICRATE;
177 				S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
178 				SetModesMenu (NewWidth, NewHeight, NewBits);
179 				return true;
180 			}
181 		}
182 		return Super::Responder(ev);
183 	}
184 };
185 
IMPLEMENT_CLASS(DVideoModeMenu)186 IMPLEMENT_CLASS(DVideoModeMenu)
187 
188 
189 //=============================================================================
190 //
191 //
192 //
193 //=============================================================================
194 
195 FOptionMenuDescriptor *GetVideoModeMenu()
196 {
197 	FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_VideoModeMenu);
198 	if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu)
199 	{
200 		return (FOptionMenuDescriptor *)*desc;
201 	}
202 	return NULL;
203 }
204 
205 //=============================================================================
206 //
207 //		Set some stuff up for the video modes menu
208 //
209 //=============================================================================
210 
BuildModesList(int hiwidth,int hiheight,int hi_bits)211 static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
212 {
213 	char strtemp[32];
214 	int	 i, c;
215 	int	 width, height, showbits;
216 	bool letterbox=false;
217 	int  ratiomatch;
218 
219 	if (menu_screenratios >= 0 && menu_screenratios <= 4)
220 	{
221 		ratiomatch = menu_screenratios;
222 	}
223 	else
224 	{
225 		ratiomatch = -1;
226 	}
227 	showbits = BitTranslate[DummyDepthCvar];
228 
229 	if (Video != NULL)
230 	{
231 		Video->StartModeIterator (showbits, screen->IsFullscreen());
232 	}
233 
234 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
235 	if (opt != NULL)
236 	{
237 		for (i = NAME_res_0; i<= NAME_res_9; i++)
238 		{
239 			FOptionMenuItem *it = opt->GetItem((ENamedName)i);
240 			if (it != NULL)
241 			{
242 				it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, -1);
243 				for (c = 0; c < 3; c++)
244 				{
245 					bool haveMode = false;
246 
247 					if (Video != NULL)
248 					{
249 						while ((haveMode = Video->NextMode (&width, &height, &letterbox)) &&
250 							ratiomatch >= 0)
251 						{
252 							int ratio;
253 							CheckRatio (width, height, &ratio);
254 							if (ratio == ratiomatch)
255 								break;
256 						}
257 					}
258 
259 					if (haveMode)
260 					{
261 						if (width == hiwidth && height == hiheight)
262 						{
263 							it->SetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, c);
264 							it->SetValue(FOptionMenuScreenResolutionLine::SRL_HIGHLIGHT, c);
265 						}
266 
267 						mysnprintf (strtemp, countof(strtemp), "%dx%d%s", width, height, letterbox?TEXTCOLOR_BROWN" LB":"");
268 						it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, strtemp);
269 					}
270 					else
271 					{
272 						it->SetString(FOptionMenuScreenResolutionLine::SRL_INDEX+c, "");
273 					}
274 				}
275 			}
276 		}
277 	}
278 }
279 
280 
281 //=============================================================================
282 //
283 //
284 //
285 //=============================================================================
286 
M_RestoreMode()287 void M_RestoreMode ()
288 {
289 	NewWidth = OldWidth;
290 	NewHeight = OldHeight;
291 	NewBits = OldBits;
292 	setmodeneeded = true;
293 	testingmode = 0;
294 	SetModesMenu (OldWidth, OldHeight, OldBits);
295 }
296 
M_SetDefaultMode()297 void M_SetDefaultMode ()
298 {
299 	// Make current resolution the default
300 	vid_defwidth = SCREENWIDTH;
301 	vid_defheight = SCREENHEIGHT;
302 	vid_defbits = DisplayBits;
303 	testingmode = 0;
304 	SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
305 }
306 
307 
308 
309 //=============================================================================
310 //
311 //
312 //
313 //=============================================================================
314 
M_RefreshModesList()315 void M_RefreshModesList ()
316 {
317 	BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits);
318 }
319 
M_InitVideoModesMenu()320 void M_InitVideoModesMenu ()
321 {
322 	int dummy1, dummy2;
323 	size_t currval = 0;
324 
325 	M_RefreshModesList();
326 	vid_tft.Callback();
327 
328 	for (unsigned int i = 1; i <= 32 && currval < countof(BitTranslate); i++)
329 	{
330 		Video->StartModeIterator (i, screen->IsFullscreen());
331 		if (Video->NextMode (&dummy1, &dummy2, NULL))
332 		{
333 			BitTranslate[currval++] = i;
334 		}
335 	}
336 
337 	/* It doesn't look like this can be anything but DISPLAY_Both, regardless of any other settings.
338 	switch (Video->GetDisplayType ())
339 	{
340 	case DISPLAY_FullscreenOnly:
341 	case DISPLAY_WindowOnly:
342 		// todo: gray out fullscreen option
343 	default:
344 		break;
345 	}
346 	*/
347 }
348 
349 //=============================================================================
350 //
351 //
352 //
353 //=============================================================================
354 
GetSelectedSize(int * width,int * height)355 static bool GetSelectedSize (int *width, int *height)
356 {
357 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
358 	if (opt != NULL && (unsigned)opt->mSelectedItem < opt->mItems.Size())
359 	{
360 		int line = opt->mSelectedItem;
361 		int hsel;
362 		FOptionMenuItem *it = opt->mItems[line];
363 		if (it->GetValue(FOptionMenuScreenResolutionLine::SRL_SELECTION, &hsel))
364 		{
365 			char buffer[32];
366 			char *breakpt;
367 			if (it->GetString(FOptionMenuScreenResolutionLine::SRL_INDEX+hsel, buffer, sizeof(buffer)))
368 			{
369 				*width = strtol (buffer, &breakpt, 10);
370 				*height = strtol (breakpt+1, NULL, 10);
371 				return true;
372 			}
373 		}
374 	}
375 	return false;
376 }
377 
378 //=============================================================================
379 //
380 //
381 //
382 //=============================================================================
383 
M_SetVideoMode()384 void M_SetVideoMode()
385 {
386 	if (!GetSelectedSize (&NewWidth, &NewHeight))
387 	{
388 		NewWidth = SCREENWIDTH;
389 		NewHeight = SCREENHEIGHT;
390 	}
391 	else
392 	{
393 		testingmode = 1;
394 		setmodeneeded = true;
395 		NewBits = BitTranslate[DummyDepthCvar];
396 	}
397 	SetModesMenu (NewWidth, NewHeight, NewBits);
398 }
399 
400 //=============================================================================
401 //
402 //
403 //
404 //=============================================================================
405 
FindBits(int bits)406 static int FindBits (int bits)
407 {
408 	int i;
409 
410 	for (i = 0; i < 22; i++)
411 	{
412 		if (BitTranslate[i] == bits)
413 			return i;
414 	}
415 
416 	return 0;
417 }
418 
SetModesMenu(int w,int h,int bits)419 static void SetModesMenu (int w, int h, int bits)
420 {
421 	DummyDepthCvar = FindBits (bits);
422 
423 	FOptionMenuDescriptor *opt = GetVideoModeMenu();
424 	if (opt != NULL)
425 	{
426 		FOptionMenuItem *it;
427 		if (testingmode <= 1)
428 		{
429 			it = opt->GetItem(NAME_VMEnterText);
430 			if (it != NULL) it->SetValue(0, 0);
431 			it = opt->GetItem(NAME_VMTestText);
432 			if (it != NULL) it->SetValue(0, 0);
433 		}
434 		else
435 		{
436 
437 			it = opt->GetItem(NAME_VMTestText);
438 			if (it != NULL) it->SetValue(0, 1);
439 			it = opt->GetItem(NAME_VMEnterText);
440 			if (it != NULL)
441 			{
442 				char strtemp[64];
443 				mysnprintf (strtemp, countof(strtemp), "TESTING %dx%dx%d", w, h, bits);
444 				it->SetValue(0, 1);
445 				it->SetString(0, strtemp);
446 			}
447 		}
448 	}
449 	BuildModesList (w, h, bits);
450 }
451