1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 1993-1996 by id Software, Inc.
4 // Copyright (C) 1998-2000 by DooM Legacy Team.
5 // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh.
6 // Copyright (C) 1999-2020 by Sonic Team Junior.
7 //
8 // This program is free software distributed under the
9 // terms of the GNU General Public License, version 2.
10 // See the 'LICENSE' file for more details.
11 //-----------------------------------------------------------------------------
12 /// \file  m_menu.h
13 /// \brief Menu widget stuff, selection and such
14 
15 #ifndef __X_MENU__
16 #define __X_MENU__
17 
18 #include "doomstat.h" // for NUMGAMETYPES
19 #include "d_event.h"
20 #include "command.h"
21 #include "f_finale.h" // for ttmode_enum
22 #include "i_threads.h"
23 #include "mserv.h"
24 #include "r_things.h" // for SKINNAMESIZE
25 
26 // Compatibility with old-style named NiGHTS replay files.
27 #define OLDNREPLAYNAME
28 
29 //
30 // MENUS
31 //
32 
33 // If menu hierarchies go deeper, change this up to 5.
34 // Zero-based, inclusive.
35 #define NUMMENULEVELS 3
36 #define MENUBITS 6
37 
38 // Menu IDs sectioned by numeric places to signify hierarchy
39 /**
40  * IF YOU MODIFY THIS, MODIFY MENUTYPES_LIST[] IN dehacked.c TO MATCH.
41  */
42 typedef enum
43 {
44 	MN_NONE,
45 
46 	MN_MAIN,
47 
48 	// Single Player
49 	MN_SP_MAIN,
50 
51 	MN_SP_LOAD,
52 	MN_SP_PLAYER,
53 
54 	MN_SP_LEVELSELECT,
55 	MN_SP_LEVELSTATS,
56 
57 	MN_SP_TIMEATTACK,
58 	MN_SP_TIMEATTACK_LEVELSELECT,
59 	MN_SP_GUESTREPLAY,
60 	MN_SP_REPLAY,
61 	MN_SP_GHOST,
62 
63 	MN_SP_NIGHTSATTACK,
64 	MN_SP_NIGHTS_LEVELSELECT,
65 	MN_SP_NIGHTS_GUESTREPLAY,
66 	MN_SP_NIGHTS_REPLAY,
67 	MN_SP_NIGHTS_GHOST,
68 
69 	MN_SP_MARATHON,
70 
71 	// Multiplayer
72 	MN_MP_MAIN,
73 	MN_MP_SPLITSCREEN, // SplitServer
74 	MN_MP_SERVER,
75 	MN_MP_CONNECT,
76 	MN_MP_ROOM,
77 	MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
78 	MN_MP_SERVER_OPTIONS,
79 
80 	// Options
81 	MN_OP_MAIN,
82 
83 	MN_OP_P1CONTROLS,
84 	MN_OP_CHANGECONTROLS, // OP_ChangeControlsDef shared with P2
85 	MN_OP_P1MOUSE,
86 	MN_OP_P1JOYSTICK,
87 	MN_OP_JOYSTICKSET, // OP_JoystickSetDef shared with P2
88 	MN_OP_P1CAMERA,
89 
90 	MN_OP_P2CONTROLS,
91 	MN_OP_P2MOUSE,
92 	MN_OP_P2JOYSTICK,
93 	MN_OP_P2CAMERA,
94 
95 	MN_OP_PLAYSTYLE,
96 
97 	MN_OP_VIDEO,
98 	MN_OP_VIDEOMODE,
99 	MN_OP_COLOR,
100 	MN_OP_OPENGL,
101 	MN_OP_OPENGL_LIGHTING,
102 
103 	MN_OP_SOUND,
104 
105 	MN_OP_SERVER,
106 	MN_OP_MONITORTOGGLE,
107 
108 	MN_OP_DATA,
109 	MN_OP_ADDONS,
110 	MN_OP_SCREENSHOTS,
111 	MN_OP_ERASEDATA,
112 
113 	// Extras
114 	MN_SR_MAIN,
115 	MN_SR_PANDORA,
116 	MN_SR_LEVELSELECT,
117 	MN_SR_UNLOCKCHECKLIST,
118 	MN_SR_EMBLEMHINT,
119 	MN_SR_PLAYER,
120 	MN_SR_SOUNDTEST,
121 
122 	// Addons (Part of MISC, but let's make it our own)
123 	MN_AD_MAIN,
124 
125 	// MISC
126 	// MN_MESSAGE,
127 	// MN_SPAUSE,
128 
129 	// MN_MPAUSE,
130 	// MN_SCRAMBLETEAM,
131 	// MN_CHANGETEAM,
132 	// MN_CHANGELEVEL,
133 
134 	// MN_MAPAUSE,
135 	// MN_HELP,
136 
137 	MN_SPECIAL,
138 	NUMMENUTYPES,
139 } menutype_t; // up to 63; MN_SPECIAL = 53
140 #define MTREE2(a,b) (a | (b<<MENUBITS))
141 #define MTREE3(a,b,c) MTREE2(a, MTREE2(b,c))
142 #define MTREE4(a,b,c,d) MTREE2(a, MTREE3(b,c,d))
143 
144 typedef struct
145 {
146 	char bgname[8]; // name for background gfx lump; lays over titlemap if this is set
147 	SINT8 fadestrength;  // darken background when displaying this menu, strength 0-31 or -1 for undefined
148 	INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules.
149 	INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting
150 	INT32 titlescrollyspeed; // y scroll
151 	boolean bghide; // for titlemaps, hide the background.
152 
153 	SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting
154 	ttmode_enum ttmode; // title wing animation mode; default TTMODE_OLD
155 	UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting
156 	char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx)
157 	INT16 ttx; // X position of title wing
158 	INT16 tty; // Y position of title wing
159 	INT16 ttloop; // # frame to loop; -1 means dont loop
160 	UINT16 tttics; // # of tics per frame
161 
162 	char musname[7]; ///< Music track to play. "" for no music.
163 	UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
164 	boolean muslooping; ///< Loop the music
165 	boolean musstop; ///< Don't play any music
166 	boolean musignore; ///< Let the current music keep playing
167 
168 	boolean enterbubble; // run all entrance line execs after common ancestor and up to child. If false, only run the child's exec
169 	boolean exitbubble; // run all exit line execs from child and up to before common ancestor. If false, only run the child's exec
170 	INT32 entertag; // line exec to run on menu enter, if titlemap
171 	INT32 exittag; // line exec to run on menu exit, if titlemap
172 	INT16 enterwipe; // wipe type to run on menu enter, -1 means default
173 	INT16 exitwipe; // wipe type to run on menu exit, -1 means default
174 } menupres_t;
175 
176 extern menupres_t menupres[NUMMENUTYPES];
177 extern UINT32 prevMenuId;
178 extern UINT32 activeMenuId;
179 
180 void M_InitMenuPresTables(void);
181 UINT8 M_GetYoungestChildMenu(void);
182 void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping);
183 void M_SetMenuCurBackground(const char *defaultname);
184 void M_SetMenuCurFadeValue(UINT8 defaultvalue);
185 void M_SetMenuCurTitlePics(void);
186 
187 // Called by main loop,
188 // saves config file and calls I_Quit when user exits.
189 // Even when the menu is not displayed,
190 // this can resize the view and change game parameters.
191 // Does all the real work of the menu interaction.
192 boolean M_Responder(event_t *ev);
193 
194 // Called by main loop, only used for menu (skull cursor) animation.
195 void M_Ticker(void);
196 
197 // Called by main loop, draws the menus directly into the screen buffer.
198 void M_Drawer(void);
199 
200 // Called by D_SRB2Main, loads the config file.
201 void M_Init(void);
202 
203 // Called by D_SRB2Main also, sets up the playermenu and description tables.
204 void M_InitCharacterTables(void);
205 
206 // Called by intro code to force menu up upon a keypress,
207 // does nothing if menu is already up.
208 void M_StartControlPanel(void);
209 
210 // Called upon end of a mode attack run
211 void M_EndModeAttackRun(void);
212 
213 // Called on new server add, or other reasons
214 void M_SortServerList(void);
215 
216 // Draws a box with a texture inside as background for messages
217 void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);
218 
219 // the function to show a message box typing with the string inside
220 // string must be static (not in the stack)
221 // routine is a function taking a INT32 in parameter
222 typedef enum
223 {
224 	MM_NOTHING = 0, // is just displayed until the user do someting
225 	MM_YESNO,       // routine is called with only 'y' or 'n' in param
226 	MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction
227 	                // and routine is void routine(event_t *) (ex: set control)
228 } menumessagetype_t;
229 void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
230 
231 typedef enum
232 {
233 	M_NOT_WAITING,
234 
235 	M_WAITING_VERSION,
236 	M_WAITING_ROOMS,
237 	M_WAITING_SERVERS,
238 }
239 M_waiting_mode_t;
240 
241 extern M_waiting_mode_t m_waiting_mode;
242 
243 // Called by linux_x/i_video_xshm.c
244 void M_QuitResponse(INT32 ch);
245 
246 // Determines whether to show a level in the list (platter version does not need to be exposed)
247 boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
248 
249 // flags for items in the menu
250 // menu handle (what we do when key is pressed
251 #define IT_TYPE             15     // (1+2+4+8)
252 #define IT_CALL              0     // call the function
253 #define IT_SPACE             1     // no handling
254 #define IT_ARROWS            2     // call function with 0 for left arrow and 1 for right arrow in param
255 #define IT_KEYHANDLER        4     // call with the key in param
256 #define IT_SUBMENU           6     // go to sub menu
257 #define IT_CVAR              8     // handle as a cvar
258 #define IT_PAIR             11     // no handling, define both sides of text
259 #define IT_MSGHANDLER       12     // same as key but with event and sometime can handle y/n key (special for message)
260 
261 #define IT_DISPLAY   (48+64+128)    // 16+32+64+128
262 #define IT_NOTHING            0     // space
263 #define IT_PATCH             16     // a patch or a string with big font
264 #define IT_STRING            32     // little string (spaced with 10)
265 #define IT_WHITESTRING       48     // little string in white
266 #define IT_DYBIGSPACE        64     // same as noting
267 #define IT_DYLITLSPACE   (16+64)    // little space
268 #define IT_STRING2       (32+64)    // a simple string
269 #define IT_GRAYPATCH     (16+32+64) // grayed patch or big font string
270 #define IT_BIGSLIDER        128     // volume sound use this
271 #define IT_TRANSTEXT     (16+128)   // Transparent text
272 #define IT_TRANSTEXT2    (32+128)   // used for control names
273 #define IT_HEADERTEXT    (48+128)   // Non-selectable header option, displays in yellow offset to the left a little
274 #define IT_QUESTIONMARKS (64+128)   // Displays as question marks, used for secrets
275 #define IT_CENTER           256     // if IT_PATCH, center it on screen
276 
277 //consvar specific
278 #define IT_CVARTYPE   (512+1024+2048)
279 #define IT_CV_NORMAL         0
280 #define IT_CV_SLIDER       512
281 #define IT_CV_STRING      1024
282 #define IT_CV_NOPRINT     1536
283 #define IT_CV_NOMOD       2048
284 #define IT_CV_INVISSLIDER 2560
285 #define IT_CV_INTEGERSTEP 4096      // if IT_CV_NORMAL and cvar is CV_FLOAT, modify it by 1 instead of 0.0625
286 #define IT_CV_FLOATSLIDER 4608      // IT_CV_SLIDER, value modified by 0.0625 instead of 1 (for CV_FLOAT cvars)
287 
288 //call/submenu specific
289 // There used to be a lot more here but ...
290 // A lot of them became redundant with the advent of the Pause menu, so they were removed
291 #define IT_CALLTYPE   (512+1024)
292 #define IT_CALL_NORMAL          0
293 #define IT_CALL_NOTMODIFIED   512
294 
295 // in INT16 for some common use
296 #define IT_BIGSPACE    (IT_SPACE  +IT_DYBIGSPACE)
297 #define IT_LITLSPACE   (IT_SPACE  +IT_DYLITLSPACE)
298 #define IT_CONTROL     (IT_STRING2+IT_CALL)
299 #define IT_CVARMAX     (IT_CVAR   +IT_CV_NOMOD)
300 #define IT_DISABLED    (IT_SPACE  +IT_GRAYPATCH)
301 #define IT_GRAYEDOUT   (IT_SPACE  +IT_TRANSTEXT)
302 #define IT_GRAYEDOUT2  (IT_SPACE  +IT_TRANSTEXT2)
303 #define IT_HEADER      (IT_SPACE  +IT_HEADERTEXT)
304 #define IT_SECRET      (IT_SPACE  +IT_QUESTIONMARKS)
305 
306 #define MAXSTRINGLENGTH 32
307 
308 typedef union
309 {
310 	struct menu_s *submenu;      // IT_SUBMENU
311 	consvar_t *cvar;             // IT_CVAR
312 	void (*routine)(INT32 choice); // IT_CALL, IT_KEYHANDLER, IT_ARROWS
313 } itemaction_t;
314 
315 //
316 // MENU TYPEDEFS
317 //
318 typedef struct menuitem_s
319 {
320 	// show IT_xxx
321 	UINT16 status;
322 
323 	const char *patch;
324 	const char *text; // used when FONTBxx lump is found
325 
326 // FIXME: should be itemaction_t
327 	void *itemaction;
328 
329 	// hotkey in menu or y of the item
330 	UINT16 alphaKey;
331 } menuitem_t;
332 
333 extern menuitem_t MP_RoomMenu[];
334 extern UINT32     roomIds[NUM_LIST_ROOMS];
335 
336 typedef struct menu_s
337 {
338 	UINT32         menuid;             // ID to encode menu type and hierarchy
339 	const char    *menutitlepic;
340 	INT16          numitems;           // # of menu items
341 	struct menu_s *prevMenu;           // previous menu
342 	menuitem_t    *menuitems;          // menu items
343 	void         (*drawroutine)(void); // draw routine
344 	INT16          x, y;               // x, y of menu
345 	INT16          lastOn;             // last item user was on in menu
346 	boolean      (*quitroutine)(void); // called before quit a menu return true if we can
347 } menu_t;
348 
349 void M_SetupNextMenu(menu_t *menudef);
350 void M_ClearMenus(boolean callexitmenufunc);
351 
352 // Maybe this goes here????? Who knows.
353 boolean M_MouseNeeded(void);
354 
355 #ifdef HAVE_THREADS
356 extern I_mutex m_menu_mutex;
357 #endif
358 
359 extern menu_t *currentMenu;
360 
361 extern menu_t MainDef;
362 extern menu_t SP_LoadDef;
363 
364 // Call upon joystick hotplug
365 void M_SetupJoystickMenu(INT32 choice);
366 extern menu_t OP_JoystickSetDef;
367 
368 // Stuff for customizing the player select screen
369 typedef struct
370 {
371 	boolean used;
372 	char notes[441];
373 	char picname[8];
374 	char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
375 	patch_t *charpic;
376 	UINT8 prev;
377 	UINT8 next;
378 
379 	// new character select
380 	char displayname[SKINNAMESIZE+1];
381 	SINT8 skinnum[2];
382 	UINT16 oppositecolor;
383 	char nametag[8];
384 	patch_t *namepic;
385 	UINT16 tagtextcolor;
386 	UINT16 tagoutlinecolor;
387 } description_t;
388 
389 // level select platter
390 typedef struct
391 {
392 	char header[22+5]; // mapheader_t lvltttl max length + " ZONE"
393 	INT32 maplist[3];
394 	char mapnames[3][17+1];
395 	boolean mapavailable[4]; // mapavailable[3] == wide or not
396 } levelselectrow_t;
397 
398 typedef struct
399 {
400 	UINT8 numrows;
401 	levelselectrow_t *rows;
402 } levelselect_t;
403 // experimental level select end
404 
405 // descriptions for gametype select screen
406 typedef struct
407 {
408 	UINT8 col[2];
409 	char notes[441];
410 } gtdesc_t;
411 extern gtdesc_t gametypedesc[NUMGAMETYPES];
412 
413 // mode descriptions for video mode menu
414 typedef struct
415 {
416 	INT32 modenum; // video mode number in the vidmodes list
417 	const char *desc;  // XXXxYYY
418 	UINT8 goodratio; // aspect correct if 1
419 } modedesc_t;
420 
421 // savegame struct for save game menu
422 typedef struct
423 {
424 	char levelname[32];
425 	UINT8 skinnum;
426 	UINT8 botskin;
427 	UINT8 numemeralds;
428 	UINT8 numgameovers;
429 	INT32 lives;
430 	INT32 continuescore;
431 	INT32 gamemap;
432 } saveinfo_t;
433 
434 extern description_t description[MAXSKINS];
435 
436 extern consvar_t cv_showfocuslost;
437 extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
438 extern CV_PossibleValue_t gametype_cons_t[];
439 
440 extern INT16 startmap;
441 extern INT32 ultimate_selectable;
442 extern INT16 char_on, startchar;
443 
444 #define MAXSAVEGAMES 31
445 #define NOSAVESLOT 0 //slot where Play Without Saving appears
446 #define MARATHONSLOT 420 // just has to be nonzero, but let's use one that'll show up as an obvious error if something goes wrong while not using our existing saves
447 
448 #define BwehHehHe() S_StartSound(NULL, sfx_bewar1+M_RandomKey(4)) // Bweh heh he
449 
450 void M_TutorialSaveControlResponse(INT32 ch);
451 
452 void M_ForceSaveSlotSelected(INT32 sslot);
453 
454 void M_CheatActivationResponder(INT32 ch);
455 
456 void M_ModeAttackRetry(INT32 choice);
457 
458 // Level select updating
459 void Nextmap_OnChange(void);
460 
461 // Screenshot menu updating
462 void Moviemode_mode_Onchange(void);
463 void Screenshot_option_Onchange(void);
464 
465 // Addons menu updating
466 void Addons_option_Onchange(void);
467 
468 // Moviemode menu updating
469 void Moviemode_option_Onchange(void);
470 
471 // Player Setup menu colors linked list
472 typedef struct menucolor_s {
473 	struct menucolor_s *next;
474 	struct menucolor_s *prev;
475 	UINT16 color;
476 } menucolor_t;
477 
478 extern menucolor_t *menucolorhead, *menucolortail;
479 
480 void M_AddMenuColor(UINT16 color);
481 void M_MoveColorBefore(UINT16 color, UINT16 targ);
482 void M_MoveColorAfter(UINT16 color, UINT16 targ);
483 UINT16 M_GetColorBefore(UINT16 color);
484 UINT16 M_GetColorAfter(UINT16 color);
485 void M_InitPlayerSetupColors(void);
486 void M_FreePlayerSetupColors(void);
487 
488 // These defines make it a little easier to make menus
489 #define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\
490 {\
491 	id,\
492 	header,\
493 	sizeof(source)/sizeof(menuitem_t),\
494 	prev,\
495 	source,\
496 	M_DrawGenericMenu,\
497 	x, y,\
498 	0,\
499 	NULL\
500 }
501 
502 #define DEFAULTSCROLLMENUSTYLE(id, header, source, prev, x, y)\
503 {\
504 	id,\
505 	header,\
506 	sizeof(source)/sizeof(menuitem_t),\
507 	prev,\
508 	source,\
509 	M_DrawGenericScrollMenu,\
510 	x, y,\
511 	0,\
512 	NULL\
513 }
514 
515 #define PAUSEMENUSTYLE(source, x, y)\
516 {\
517 	MN_SPECIAL,\
518 	NULL,\
519 	sizeof(source)/sizeof(menuitem_t),\
520 	NULL,\
521 	source,\
522 	M_DrawPauseMenu,\
523 	x, y,\
524 	0,\
525 	NULL\
526 }
527 
528 #define CENTERMENUSTYLE(id, header, source, prev, y)\
529 {\
530 	id,\
531 	header,\
532 	sizeof(source)/sizeof(menuitem_t),\
533 	prev,\
534 	source,\
535 	M_DrawCenteredMenu,\
536 	BASEVIDWIDTH/2, y,\
537 	0,\
538 	NULL\
539 }
540 
541 #define MAPPLATTERMENUSTYLE(id, header, source)\
542 {\
543 	id,\
544 	header,\
545 	sizeof (source)/sizeof (menuitem_t),\
546 	&MainDef,\
547 	source,\
548 	M_DrawLevelPlatterMenu,\
549 	0,0,\
550 	0,\
551 	NULL\
552 }
553 
554 #define CONTROLMENUSTYLE(id, source, prev)\
555 {\
556 	id,\
557 	"M_CONTRO",\
558 	sizeof (source)/sizeof (menuitem_t),\
559 	prev,\
560 	source,\
561 	M_DrawControl,\
562 	24, 40,\
563 	0,\
564 	NULL\
565 }
566 
567 #define IMAGEDEF(source)\
568 {\
569 	MN_SPECIAL,\
570 	NULL,\
571 	sizeof (source)/sizeof (menuitem_t),\
572 	NULL,\
573 	source,\
574 	M_DrawImageDef,\
575 	0, 0,\
576 	0,\
577 	NULL\
578 }
579 
580 #endif //__X_MENU__
581