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