CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

MENUS.CPP (29492B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\menus.cpv   2.17   16 Oct 1995 16:50:48   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : MENUS.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Phil W. Gorrow                                               *
     26  *                                                                                             *
     27  *                   Start Date : September 10, 1993                                           *
     28  *                                                                                             *
     29  *                  Last Update : May 17, 1995 [BRR]                                           *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Main_Menu -- Menu processing                                                              *
     34  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     35 
     36 #include "function.h"
     37 #include "ccdde.h"
     38 
     39 /*****************************
     40 **	Function prototypes
     41 ******************************/
     42 
     43 #ifdef SCENARIO_EDITOR
     44 
     45 PRIVATE int Coordinates_In_Region(int x,int y,int inx1,int iny1,int inx2,int iny2);
     46 PRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index);
     47 PRIVATE void Flash_Line(char const *text,int xpix,int ypix,unsigned nfgc,unsigned hfgc,unsigned bgc);
     48 
     49 int UnknownKey;
     50 
     51 PRIVATE int MenuUpdate=1;
     52 PRIVATE int MenuSkip;
     53 
     54 
     55 /*=========================================================================*/
     56 /*	SELECT_TO_ENTRY:																			*/
     57 /*																									*/
     58 /*		This routine converts a selection to the correct string entry. It	   */
     59 /*	does this by search through a long bitfield starting at position index	*/
     60 /*	until it finds the correct conversion to entries.								*/
     61 /*																									*/
     62 /*	INPUTS:	int selection from menu, long the bit field to search, int 	   */
     63 /*				the starting index within the bit field.								*/
     64 /*	RETURNS:	int the index into the table of entries								*/
     65 /*=========================================================================*/
     66 PRIVATE int Select_To_Entry(int select, unsigned long bitfield, int index)
     67 {
     68 	int placement;
     69 
     70 	if (bitfield==0xFFFFFFFFL) 							/* if all bits are set	*/
     71 		return(select);										/*		then it as is		*/
     72 
     73 	placement=0;												/* current pos zero		*/
     74 	while (select) {											/* while still ones		*/
     75 		if (bitfield & (1L<<(placement+index)))			/* if this flagged then	*/
     76 			select--;											/* decrement counter		*/
     77 		placement++;											/* and we moved a place	*/
     78 	}
     79 	while (!(bitfield & (1L<<(placement+index)))) {
     80 		placement++;
     81 	}
     82 
     83 	return(placement);										/* return the position	*/
     84 }
     85 
     86 
     87 /*=========================================================================*/
     88 /*	FLASH_LINE:																					*/
     89 /*																									*/
     90 /*		This routine will flash the line at the desired location for the		*/
     91 /*	menu routine. It is way cool awesome!												*/
     92 /*																									*/
     93 /*	INPUTS:	char *text, int x position on line, int y position, char		   */
     94 /*				normal foreground color, char hilight foreground color, char 	*/
     95 /*				background color																*/
     96 /*	RETURNS:	none																				*/
     97 /*=========================================================================*/
     98 PRIVATE void Flash_Line(char const *text,int xpix,int ypix,unsigned nfgc,unsigned hfgc,unsigned bgc)
     99 {
    100 	int loop;
    101 
    102 	for (loop=0;loop<3;loop++) {
    103 		Hide_Mouse();
    104 		Fancy_Text_Print(text,xpix,ypix,hfgc,bgc, TPF_8POINT|TPF_DROPSHADOW);
    105 		Delay(2);
    106 		Fancy_Text_Print(text,xpix,ypix,nfgc,bgc, TPF_8POINT|TPF_DROPSHADOW);
    107 		Show_Mouse();
    108 		Delay(2);
    109 	}
    110 }
    111 
    112 /*=========================================================================*/
    113 /*	COORDINATES_IN_REGION:																	*/
    114 /*																									*/
    115 /*		Test to see if a given pair of coordinates are within the given 		*/
    116 /*	rectangular region.																		*/
    117 /*																									*/
    118 /*	INPUTS:	int x to be tested, int y to be tested, int left x pos,			*/
    119 /*				int top y pos, int right x pos, int bottom y pos					*/
    120 /*	RETURNS:	none																				*/
    121 /*=========================================================================*/
    122 PRIVATE int Coordinates_In_Region(int x,int y,int inx1,int iny1,int inx2,int iny2)
    123 {
    124 	return((x>=inx1)&&(x<=inx2)&&(y>=iny1)&&(y<=iny2));
    125 }
    126 
    127 #ifdef NEVER
    128 /*=========================================================================*/
    129 /*	FIND_MENU_ITEMS:																			*/
    130 /*																									*/
    131 /*		This routine finds the real total items in a menu when certain items	*/
    132 /*	may be disabled by bit fields and the like. This is done by looping		*/
    133 /*	through the fields, starting at the position passed in index and 			*/
    134 /*	counting the number of bits that are set.											*/
    135 /*																									*/
    136 /*	INPUTS:	int the maximum number of items possible on the menu, long 		*/
    137 /*				the bit field of enabled and disabled items, char the index		*/
    138 /*				point to start at within the list.										*/
    139 /*	RETURNS:	int the total number of items in the menu							*/
    140 /*=========================================================================*/
    141  int Find_Menu_Items(int maxitems, unsigned long field, char index)
    142  {
    143 	int loop,ctr;
    144 
    145 	if (field==0xFFFFFFFFL) 										/* if all bits are set	*/
    146 		return(maxitems);										/* then maxitems set		*/
    147 
    148 	for (loop=ctr=0;loop<maxitems;loop++) {			/* loop through items	*/
    149 		if (field & (1L<<(loop+index))) {				/* if the bit is set		*/
    150 			ctr++;												/*		count the item		*/
    151 		}
    152 	}
    153 	return(ctr);
    154 }
    155 #endif
    156 
    157 
    158 /*=========================================================================*/
    159 /*	SETUP_EOB_MONITOR_MENU:																	*/
    160 /*																									*/
    161 /*		This routine sets up the eye of the beholder monitor menu.				*/
    162 /*																									*/
    163 /*	INPUTS:	int the menu we are using, char *[] the array of text which		*/
    164 /*				makes up the menu commands, long the info field, int the			*/
    165 /*				index into the field, int the number of lines to skip.			*/
    166 /*	RETURNS:	none																				*/
    167 /*=========================================================================*/
    168 void Setup_Menu(int menu,char const *text[], unsigned long field, int index, int skip)
    169 {
    170 	int *menuptr,lp;
    171 	int menuy,menux,idx,item,num,drawy;
    172 
    173 	menuptr=&MenuList[menu][0];							/* get pointer to menu	*/
    174 	menuy=WinY+menuptr[MENUY];								/* get the absolute 		*/
    175 	menux=(WinX+menuptr[MENUX])<<3;						/*		coords of menu		*/
    176 	item=Select_To_Entry(menuptr[MSELECTED],field,index);
    177 	num=menuptr[ITEMSHIGH];
    178 
    179 	Fancy_Text_Print(0, 0, 0, TBLACK, TBLACK, TPF_8POINT|TPF_DROPSHADOW);
    180  	Hide_Mouse();
    181 	for (lp=0;lp<num;lp++) {
    182 		idx=Select_To_Entry(lp,field,index);
    183 		drawy=menuy+(lp*FontHeight)+(lp*skip);
    184 		Fancy_Text_Print(text[idx], menux, drawy, menuptr[((idx==item) && (MenuUpdate )) ? HILITE : NORMCOL], TBLACK, TPF_8POINT|TPF_DROPSHADOW);
    185 //		if ((idx==item) && (MenuUpdate ))
    186 //			Text_Print(text[idx],menux,drawy,menuptr[HILITE],TBLACK);
    187 	}
    188 	MenuSkip=skip;
    189 	Show_Mouse();
    190 	Keyboard::Clear();
    191 }
    192 
    193 
    194 /*=========================================================================*/
    195 /*	CHECK_MENU:																					*/
    196 /*																									*/
    197 /*																									*/
    198 /*																									*/
    199 /*	INPUTS:																						*/
    200 /*	RETURNS:																						*/
    201 /*=========================================================================*/
    202 int Check_Menu(int menu,char const *text[],char *,long field,int index)
    203 {
    204 	int maxitem,select,key,menuy,menux;
    205 	int mx1,mx2,my1,my2,tempy;
    206 	int drawy,menuskip,halfskip;
    207 	int normcol,litcol,item,newitem,idx;
    208 	int *menuptr;
    209 
    210 	//selection++;												/* get rid of warning	*/
    211 
    212 	menuptr = &MenuList[menu][0];							/* get pointer to menu	*/
    213 	maxitem = menuptr[ITEMSHIGH]-1;							/* find max items			*/
    214 	newitem = item = menuptr[MSELECTED]%(maxitem+1);	/* find selected 			*/
    215 	select = -1;													/* no selection made		*/
    216 	menuskip = FontHeight+MenuSkip;							/* calc new font height	*/
    217 	halfskip = MenuSkip>>1;									/* adjustment for menus	*/
    218 
    219 	menuy = WinY+menuptr[MENUY];								/* get the absolute 		*/
    220 	menux = (WinX+menuptr[MENUX])<<3;						/*		coords of menu		*/
    221 	normcol = menuptr[NORMCOL];
    222 	litcol = menuptr[HILITE];
    223 
    224 	/*
    225 	**	Fetch a pending keystroke from the buffer if there is a keystroke
    226 	**	present. If no keystroke is pending then simple mouse tracking will
    227 	**	be done.
    228 	*/
    229 	key = 0;
    230 	UnknownKey = 0;
    231 	if (Keyboard::Check()) {
    232 		key = (Keyboard::Get()&0x18FF);			/* mask off all but release bit	*/
    233 	}
    234 
    235 	/*
    236 	**	if we are using the mouse and it is installed, then find the mouse
    237 	**	coordinates of the menu and if we are not somewhere on the menu get
    238 	**	the heck outta here. If we are somewhere on the menu, then figure
    239 	**	out the new selected item, and continue forward.
    240 	*/
    241 	mx1=(WinX<<3)+(menuptr[MENUX]*FontWidth);		/* get menu coords		*/
    242 	my1=(WinY)+(menuptr[MENUY])-halfskip;			/*		from the menu		*/
    243 	mx2=mx1+(menuptr[ITEMWIDTH]*FontWidth)-1;		/*		structure as		*/
    244 	my2=my1+(menuptr[ITEMSHIGH]*menuskip)-1;		/*		necessary			*/
    245 
    246 		tempy=Get_Mouse_Y();
    247 		if (Coordinates_In_Region(Get_Mouse_X(),tempy,mx1,my1,mx2,my2)&& MenuUpdate) {
    248 			newitem=(tempy-my1)/menuskip;
    249 		}
    250 
    251 	switch (key) {
    252 
    253 		case KN_UP:												/* if the key moves up	*/
    254 			newitem--;											/* 	new item up one	*/
    255 			if (newitem<0) 									/* if invalid new item	*/
    256 				newitem=maxitem;								/* put at list bottom	*/
    257 			break;
    258 		case KN_DOWN:											/* if key moves down		*/
    259 			newitem++;											/*		new item down one	*/
    260 			if (newitem>maxitem) 							/* if new item past 		*/
    261 				newitem=0;										/*		list end, clear	*/
    262 			break;
    263 		case KN_HOME:											/* if top of list key 	*/
    264 		case KN_PGUP:											/*		is selected then	*/
    265 			newitem=0;											/*		new item = top		*/
    266 			break;
    267 		case KN_END:											/* if bottom of list is	*/
    268 		case KN_PGDN:											/*		selected then		*/
    269 			newitem=maxitem;									/*		new item = bottom	*/
    270 			break;
    271 
    272 		/*
    273 		**	Handle mouse button press. Set selection and then fall into the
    274 		**	normal menu item select logic.
    275 		*/
    276 		case KN_RMOUSE:
    277 		case KN_LMOUSE:
    278 			if (Coordinates_In_Region(_Kbd->MouseQX,_Kbd->MouseQY,mx1,my1,mx2,my2)) {
    279 				newitem = (_Kbd->MouseQY - my1) / menuskip;
    280 			} else {
    281 				UnknownKey = key;			//	Pass the unprocessed button click back.
    282 				break;
    283 			}
    284 
    285 		/*
    286 		**	Normal menu item select logic. Will flash line and exit with menu
    287 		**	selection number.
    288 		*/
    289 		case KN_RETURN:										/* if a selection is 	*/
    290 		case KN_SPACE:											/*		made with key		*/
    291 		case KN_CENTER:
    292 			select=newitem;									/*		flag it made.		*/
    293 			break;
    294 
    295 		case 0:
    296 			break;
    297 
    298 		/*
    299 		**	When no key was pressed or an unknown key was pressed, set the
    300 		**	global record of the key and exit normally.
    301 		**	EXCEPTION:	If the key matches the first letter of any of the
    302 		**					menu entries, then presume it as a selection of
    303 		**					that entry.
    304 		*/
    305 		default:
    306 			for (idx = 0; idx < menuptr[ITEMSHIGH]; idx++) {
    307 				if (toupper(*(text[Select_To_Entry(idx,field,index)])) == toupper(Keyboard::To_ASCII((KeyNumType)(key&0x0FF)))) {
    308 					newitem = select = idx;
    309 					break;
    310 				}
    311 			}
    312 			UnknownKey = key;
    313 			break;
    314 	}
    315 
    316 	if (newitem!=item) {
    317 		Hide_Mouse();
    318 		idx=Select_To_Entry(item,field,index);
    319 		drawy=menuy+(item*menuskip);
    320 		Fancy_Text_Print(text[idx],menux,drawy,normcol,TBLACK, TPF_8POINT|TPF_DROPSHADOW);
    321 		idx=Select_To_Entry(newitem,field,index);
    322 		drawy=menuy+(newitem*menuskip);
    323 		Fancy_Text_Print(text[idx],menux,drawy,litcol,TBLACK, TPF_8POINT|TPF_DROPSHADOW);
    324 		Show_Mouse();												/* resurrect the mouse	*/
    325 	}
    326 
    327 	if (select!=-1) {
    328 		idx=Select_To_Entry(select,field,index);
    329 		Hide_Mouse();												/* get rid of the mouse	*/
    330 		drawy=menuy+(newitem*menuskip);
    331 		Flash_Line(text[idx], menux, drawy, normcol, litcol, TBLACK);
    332 		Show_Mouse();
    333 		select=idx;
    334 	}
    335 
    336 	menuptr[MSELECTED]=newitem;							/* update menu select	*/
    337 
    338 	return(select);
    339 }
    340 
    341 
    342 /***************************************************************************
    343  * Do_Menu -- Generic menu processor.                                      *
    344  *                                                                         *
    345  *    This helper function displays a menu of specified entries and waits  *
    346  *    for the player to make a selection. If a selection is made, then     *
    347  *    a whole number (starting at 0) is returned matching the entry        *
    348  *    selected. If ESC is pressed, then -1 is returned.                    *
    349  *                                                                         *
    350  * INPUT:   strings  -- A pointer to an array of pointers to text strings. *
    351  *                      Each entry in the list will be a menu entry that   *
    352  *                      can be selected.                                   *
    353  *                                                                         *
    354  *          blue     -- Should the special blue color be used to display   *
    355  *                      the menu?                                          *
    356  *                                                                         *
    357  * OUTPUT:  Returns with the cardinal number of the selected menu entry.   *
    358  *          If ESC was pressed, then -1 is returned.                       *
    359  *                                                                         *
    360  * WARNINGS:   none                                                        *
    361  *                                                                         *
    362  * HISTORY:                                                                *
    363  *   05/16/1994 JLB : Created.                                             *
    364  *=========================================================================*/
    365 int Do_Menu(char const **strings, bool blue)
    366 {
    367 	int	count;		// Number of entries in this menu.
    368 	int	length;		// The width of the menu (in pixels).
    369 	char	const **ptr;		// Working menu text pointer.
    370 	int	selection;	// Selection from user.
    371 
    372 	if (!strings) return(-1);
    373 	Set_Logic_Page(SeenBuff);
    374 	Keyboard::Clear();
    375 
    376 	/*
    377 	**	Determine the number of entries in this string.
    378 	*/
    379 	ptr = strings;
    380 	count = 0;
    381 	while (*ptr++) {
    382 		count++;
    383 	}
    384 	MenuList[0][ITEMSHIGH] = count;
    385 
    386 	/*
    387 	**	Determine the width of the menu by finding the length of the
    388 	**	longest menu entry.
    389 	*/
    390 	Fancy_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_8POINT|TPF_DROPSHADOW);
    391 	length = 0;
    392 	ptr = strings;
    393 	while (*ptr) {
    394 		length = MAX(length, (int)String_Pixel_Width(*ptr));
    395 		ptr++;
    396 	}
    397 	length += 7;
    398 	MenuList[0][ITEMWIDTH] = length >> 3;
    399 
    400 	/*
    401 	**	Adjust the window values to match the size of the
    402 	**	specified menu.
    403 	*/
    404 	WindowList[WINDOW_MENU][WINDOWWIDTH] = MenuList[0][ITEMWIDTH] + 2;
    405 	WindowList[WINDOW_MENU][WINDOWX] = 19 - (length >> 4);
    406 	WindowList[WINDOW_MENU][WINDOWY] = 174 - (unsigned)(MenuList[0][ITEMSHIGH] * (FontHeight+FontYSpacing));
    407 	WindowList[WINDOW_MENU][WINDOWHEIGHT] = MenuList[0][ITEMSHIGH] * FontHeight + 5 /*11*/;
    408 
    409 	/*
    410 	**	Display the menu.
    411 	*/
    412 	Change_Window((int)WINDOW_MENU);
    413 	Show_Mouse();
    414 	Window_Box(WINDOW_MENU, blue ? BOXSTYLE_BLUE_UP : BOXSTYLE_RAISED);
    415 	Setup_Menu(0, strings, 0xFFFFL, 0, 0);
    416 
    417 	Keyboard::Clear();
    418 	selection = -1;
    419 	UnknownKey = 0;
    420 	while (selection == -1) {
    421 		Call_Back();
    422 		selection = Check_Menu(0, strings, NULL, 0xFFL, 0);
    423 		if (UnknownKey != 0 || UnknownKey == KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) break;
    424 	}
    425 	Keyboard::Clear();
    426 	Hide_Mouse();
    427 
    428 	Blit_Hid_Page_To_Seen_Buff();
    429 	Change_Window((int)WINDOW_MAIN);
    430 	Map.Flag_To_Redraw(true);
    431 	return(selection);
    432 }
    433 #endif
    434 
    435 
    436 /***************************************************************************
    437  * Main_Menu -- Menu processing                                            *
    438  *                                                                         *
    439  * INPUT:                                                                  *
    440  *		none.																						*
    441  *                                                                         *
    442  * OUTPUT:                                                                 *
    443  *		index of item selected, -1 if time out											*
    444  *                                                                         *
    445  * WARNINGS:                                                               *
    446  *		none.																						*
    447  *                                                                         *
    448  * HISTORY:                                                                *
    449  *   05/17/1995 BRR : Created.                                             *
    450  *=========================================================================*/
    451 int Main_Menu(unsigned long timeout)
    452 {
    453 	enum {
    454 		D_DIALOG_W = 152*2,
    455 		D_DIALOG_H = 136*2,
    456 		D_DIALOG_X = 85*2,
    457 		D_DIALOG_Y = 0,
    458 		D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),
    459 
    460 		D_START_W = 125*2,
    461 		D_START_H = 9*2,
    462 		D_START_X = 98*2,
    463 		D_START_Y = 35*2,
    464 
    465 #ifdef BONUS_MISSIONS
    466 		D_BONUS_W = 125*2,
    467 		D_BONUS_H = 9*2,
    468 		D_BONUS_X = 98*2,
    469 		D_BONUS_Y = 0,
    470 #endif	//BONUS_MISSIONS
    471 
    472 		D_INTERNET_W = 125*2,
    473 		D_INTERNET_H = 9*2,
    474 		D_INTERNET_X = 98*2,
    475 		D_INTERNET_Y = 36*2,
    476 
    477 		D_LOAD_W = 125*2,
    478 		D_LOAD_H = 9*2,
    479 		D_LOAD_X = 98*2,
    480 		D_LOAD_Y = 53*2,
    481 
    482 		D_MULTI_W = 125*2,
    483 		D_MULTI_H = 9*2,
    484 		D_MULTI_X = 98*2,
    485 		D_MULTI_Y = 71*2,
    486 
    487 		D_INTRO_W = 125*2,
    488 		D_INTRO_H = 9*2,
    489 		D_INTRO_X = 98*2,
    490 		D_INTRO_Y = 89*2,
    491 #if (GERMAN | FRENCH)
    492 		D_EXIT_W = 83*2,
    493 #else
    494 		D_EXIT_W = 63*2,
    495 #endif
    496 		D_EXIT_H = 9*2,
    497 #if (GERMAN | FRENCH)
    498 		D_EXIT_X = 118*2,
    499 #else
    500 		D_EXIT_X = 128*2,
    501 #endif
    502 		D_EXIT_Y = 111*2,
    503 
    504 	};
    505 
    506 #ifdef NEWMENU
    507 	int starty = 25*2;
    508 #endif
    509 
    510 	enum {
    511 #ifdef NEWMENU
    512 		BUTTON_EXPAND=100*2,
    513 		BUTTON_START,
    514 #ifdef BONUS_MISSIONS
    515 		BUTTON_BONUS,
    516 #endif	//BONUS_MISSIONS
    517 		BUTTON_INTERNET,
    518 #else
    519 		BUTTON_START=100*2,
    520 #endif
    521 		BUTTON_LOAD,
    522 		BUTTON_MULTI,
    523 		BUTTON_INTRO,
    524 		BUTTON_EXIT,
    525 	};
    526 
    527 #ifdef NEWMENU
    528 	bool expansions = Expansion_Present();
    529 #endif
    530 	KeyNumType input;								// input from user
    531 	int retval;										// return value
    532 	int curbutton;
    533 #ifdef NEWMENU
    534 #ifdef BONUS_MISSIONS
    535 	TextButtonClass *buttons[8];
    536 #else
    537 	TextButtonClass *buttons[7];
    538 #endif	//BONUS_MISSIONS
    539 #else
    540 	TextButtonClass *buttons[5];
    541 #endif
    542 //	unsigned long starttime;
    543 
    544 	ControlClass *commands = NULL;				// the button list
    545 
    546 #ifdef NEWMENU
    547 #ifdef BONUS_MISSIONS
    548 	int ystep = 13*2;
    549 #else
    550 	int ystep = 15*2;
    551 #endif	//BONUS_MISSIONS
    552 
    553 	if (expansions) ystep -= 2*2;
    554 	TextButtonClass expandbtn (BUTTON_EXPAND, TXT_NEW_MISSIONS,
    555 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    556 		D_START_X, starty, D_START_W, D_START_H);
    557 	if (expansions) starty += ystep;
    558 
    559 	TextButtonClass startbtn (BUTTON_START, TXT_START_NEW_GAME,
    560 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    561 		D_START_X, starty, D_START_W, D_START_H);
    562 	starty += ystep;
    563 
    564 #ifdef BONUS_MISSIONS
    565 	TextButtonClass bonusbtn (BUTTON_BONUS, TXT_BONUS_MISSIONS,
    566 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    567 		D_BONUS_X, starty, D_BONUS_W, D_BONUS_H);
    568 	starty += ystep;
    569 #endif	//BONUS_MISSIONS
    570 
    571 	TextButtonClass internetbutton(BUTTON_INTERNET, TXT_INTERNET,
    572 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    573 		D_INTERNET_X, starty, D_INTERNET_W, D_INTERNET_H);
    574 	starty += ystep;
    575 
    576 	TextButtonClass loadbtn (BUTTON_LOAD, TXT_LOAD_MISSION,
    577 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    578 		D_LOAD_X, starty, D_LOAD_W, D_LOAD_H);
    579 	starty += ystep;
    580 #else
    581 
    582 	TextButtonClass startbtn (BUTTON_START, TXT_START_NEW_GAME,
    583 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    584 		D_START_X, D_START_Y, D_START_W, D_START_H);
    585 
    586 	TextButtonClass loadbtn (BUTTON_LOAD, TXT_LOAD_MISSION,
    587 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    588 		D_LOAD_X, D_LOAD_Y, D_LOAD_W, D_LOAD_H);
    589 
    590 #endif
    591 
    592 
    593 #ifdef DEMO
    594 	TextButtonClass multibtn (BUTTON_MULTI, TXT_ORDER_INFO,
    595 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    596 		D_MULTI_X, D_MULTI_Y, D_MULTI_W, D_MULTI_H);
    597 #else
    598 
    599 #ifdef NEWMENU
    600 	TextButtonClass multibtn (BUTTON_MULTI, TXT_MULTIPLAYER_GAME,
    601 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    602 		D_MULTI_X, starty, D_MULTI_W, D_MULTI_H);
    603 	starty += ystep;
    604 
    605 	//TextButtonClass internetbutton(BUTTON_INTERNET, TXT_INTERNET,
    606 	//	TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    607 	//	D_INTERNET_X, starty, D_INTERNET_W, D_INTERNET_H);
    608 	//starty += ystep;
    609 #else
    610 	TextButtonClass multibtn (BUTTON_MULTI, TXT_MULTIPLAYER_GAME,
    611 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    612 		D_MULTI_X, D_MULTI_Y, D_MULTI_W, D_MULTI_H);
    613 #endif
    614 #endif
    615 
    616 #ifdef NEWMENU
    617 #ifdef DEMO
    618 	TextButtonClass introbtn (BUTTON_INTRO, TXT_JUST_INTRO,
    619 #else	//DEMO
    620 	TextButtonClass introbtn (BUTTON_INTRO, TXT_INTRO,
    621 #endif	//DEMO
    622 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    623 		D_INTRO_X, starty, D_INTRO_W, D_INTRO_H);
    624 	starty += ystep;
    625 
    626 	TextButtonClass exitbtn (BUTTON_EXIT, TXT_EXIT_GAME,
    627 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    628 #if (GERMAN | FRENCH)
    629 		//D_EXIT_X, starty);
    630 		D_EXIT_X, starty, D_EXIT_W, D_EXIT_H);
    631 #else
    632 		D_EXIT_X, starty, D_EXIT_W, D_EXIT_H);
    633 #endif
    634 	starty += ystep;
    635 
    636 #else
    637 
    638 #ifdef DEMO
    639 	TextButtonClass introbtn (BUTTON_INTRO, TXT_JUST_INTRO,
    640 #else	//DEMO
    641 	TextButtonClass introbtn (BUTTON_INTRO, TXT_INTRO,
    642 #endif	//DEMO
    643 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    644 		D_INTRO_X, D_INTRO_Y, D_INTRO_W, D_INTRO_H);
    645 
    646 	TextButtonClass exitbtn (BUTTON_EXIT, TXT_EXIT_GAME,
    647 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    648 #if (GERMAN | FRENCH)
    649 		//D_EXIT_X, D_EXIT_Y);
    650 		D_EXIT_X, D_EXIT_Y, D_EXIT_W, D_EXIT_H);
    651 #else
    652 		D_EXIT_X, D_EXIT_Y, D_EXIT_W, D_EXIT_H);
    653 #endif
    654 #endif
    655 
    656 	/*
    657 	**	Initialize
    658 	*/
    659 	Set_Logic_Page(SeenBuff);
    660 	Keyboard::Clear();
    661 #if (0)	//PG_TO_FIX
    662 	starttime = TickCount.Time();
    663 #endif
    664 	/*
    665 	**	Create the list
    666 	*/
    667 	commands = &startbtn;
    668 #ifdef NEWMENU
    669 	if (expansions) {
    670 		expandbtn.Add_Tail(*commands);
    671 	}
    672 #endif
    673 #ifdef BONUS_MISSIONS
    674 	bonusbtn.Add_Tail(*commands);
    675 #endif	//BONUS_MISSIONS
    676 
    677 
    678 #ifndef DEMO
    679 	internetbutton.Add_Tail(*commands);
    680 #endif	//DEMO
    681 	loadbtn.Add_Tail(*commands);
    682 	multibtn.Add_Tail(*commands);
    683 	introbtn.Add_Tail(*commands);
    684 	exitbtn.Add_Tail(*commands);
    685 
    686 	/*
    687 	**	Fill array of button ptrs
    688 	*/
    689 #ifdef NEWMENU
    690 	if (expansions) {
    691 		curbutton = 0;
    692 	} else {
    693 		curbutton = 1;
    694 	}
    695 	int butt = 0;
    696 
    697 	buttons[butt++] = &expandbtn;
    698 	buttons[butt++] = &startbtn;
    699 #ifdef BONUS_MISSIONS
    700 	buttons[butt++] = &bonusbtn;
    701 #endif	//BONUS_MISSIONS
    702 	buttons[butt++] = &internetbutton;
    703 	buttons[butt++] = &loadbtn;
    704 	buttons[butt++] = &multibtn;
    705 	buttons[butt++] = &introbtn;
    706 	buttons[butt++] = &exitbtn;
    707 #else
    708 	curbutton = 0;
    709 	buttons[0] = &startbtn;
    710 	buttons[1] = &loadbtn;
    711 	buttons[2] = &multibtn;
    712 	buttons[3] = &introbtn;
    713 	buttons[4] = &exitbtn;
    714 #endif
    715 	buttons[curbutton]->Turn_On();
    716 
    717 	Keyboard::Clear();
    718 
    719 	Fancy_Text_Print(TXT_NONE, 0, 0, CC_GREEN, TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    720 	while (Get_Mouse_State() > 0) Show_Mouse();
    721 
    722 	/*
    723 	**	Main Processing Loop.
    724 	*/
    725 	bool display = true;
    726 	bool process = true;
    727 	while (process) {
    728 
    729 		/*
    730 		** If we have just received input focus again after running in the background then
    731 		** we need to redraw.
    732 		*/
    733 		if (AllSurfaces.SurfacesRestored){
    734 			AllSurfaces.SurfacesRestored=FALSE;
    735 			display=TRUE;
    736 		}
    737 
    738 		/*
    739 		**	If timeout expires, bail
    740 		*/
    741 //PG_TO_FIX
    742 #if (0)
    743 		if (timeout && TickCount.Time() - starttime > timeout) {
    744 			retval = -1;
    745 			process = false;
    746 		}
    747 #endif
    748 		/*
    749 		**	Invoke game callback.
    750 		*/
    751 		Call_Back();
    752 
    753 		/*
    754 		**	Refresh display if needed.
    755 		*/
    756 		if (display) {
    757 
    758 			/*
    759 			**	Load the background picture.
    760 			*/
    761 			Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
    762 			Blit_Hid_Page_To_Seen_Buff();
    763 
    764 			/*
    765 			**	Display the title and text overlay for the menu.
    766 			*/
    767 			Set_Logic_Page(HidPage);
    768 			Dialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);
    769 			Draw_Caption (TXT_NONE, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);
    770 #ifdef VIRGIN_CHEAT_KEYS
    771 #ifdef DEMO
    772 			Version_Number();
    773 			Fancy_Text_Print("Demo%s", D_DIALOG_X+D_DIALOG_W-5*2, D_DIALOG_Y+D_DIALOG_H-10*2, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, VersionText);
    774 #else
    775 			Fancy_Text_Print("V.%d%s", D_DIALOG_X+D_DIALOG_W-5*2, D_DIALOG_Y+D_DIALOG_H-10*2, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
    776 #endif
    777 //			Fancy_Text_Print("V.%d%s%02d", D_DIALOG_X+D_DIALOG_W-5, D_DIALOG_Y+D_DIALOG_H-10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
    778 #else
    779 #ifdef DEMO
    780 			Version_Number();
    781 			Fancy_Text_Print("Demo%s", D_DIALOG_X+D_DIALOG_W-5*2, D_DIALOG_Y+D_DIALOG_H-10*2, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, VersionText);
    782 #else
    783 			Fancy_Text_Print("V.%d%s", D_DIALOG_X+D_DIALOG_W-5*2, D_DIALOG_Y+D_DIALOG_H-10*2, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText);
    784 #endif
    785 #endif
    786 
    787 			/*
    788 			**	Copy the menu to the visible page.
    789 			*/
    790 			Hide_Mouse();
    791 			Blit_Hid_Page_To_Seen_Buff();
    792 			Show_Mouse();
    793 
    794 			Set_Logic_Page(SeenBuff);
    795 			startbtn.Draw_All();
    796 			if (ScreenWidth==320){
    797 				//ST - 1/2/2019 5:27PM
    798 				//ModeX_Blit (SeenBuff.Get_Graphic_Buffer());
    799 			}
    800 			display = false;
    801 		} else {
    802 			if (RunningAsDLL) {
    803 				retval = -1;
    804 				process = false;
    805 			}
    806 		}	
    807 
    808 #ifndef DEMO
    809 		/*
    810 		** Check to see if WChat has told us to start playing an internet game
    811 		*/
    812 		if (DDEServer.Get_MPlayer_Game_Info()){
    813 			retval = BUTTON_INTERNET - BUTTON_EXPAND;
    814 			process = false;
    815 		}
    816 #endif	//DEMO
    817 
    818 		/*
    819 		**	Get and process player input.
    820 		*/
    821 		input = commands->Input();
    822 		switch (input) {
    823 #ifdef NEWMENU
    824 			case (BUTTON_EXPAND | KN_BUTTON):
    825 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    826 				process = false;
    827 				break;
    828 
    829 			case (BUTTON_INTERNET | KN_BUTTON):
    830 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    831 				process = false;
    832 				break;
    833 
    834 #else
    835 #define	BUTTON_EXPAND	BUTTON_START
    836 #endif
    837 
    838 			case (BUTTON_START | KN_BUTTON):
    839 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    840 				process = false;
    841 				break;
    842 
    843 #ifdef BONUS_MISSIONS
    844 			case (BUTTON_BONUS | KN_BUTTON):
    845 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    846 				process = false;
    847 				break;
    848 #endif	//BONUS_MISSIONS
    849 
    850 			case (BUTTON_LOAD | KN_BUTTON):
    851 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    852 #ifdef DEMO
    853 				retval += 1;
    854 #endif	//DEMO
    855 				process = false;
    856 				break;
    857 
    858 			case (BUTTON_MULTI | KN_BUTTON):
    859 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    860 #ifdef DEMO
    861 				retval += 1;
    862 #endif	//DEMO
    863 				process = false;
    864 				break;
    865 
    866 			case (BUTTON_INTRO | KN_BUTTON):
    867 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    868 #ifdef DEMO
    869 				retval += 1;
    870 #endif	//DEMO
    871 				process = false;
    872 				break;
    873 
    874 			case (BUTTON_EXIT | KN_BUTTON):
    875 				retval = (input & 0x7FFF) - BUTTON_EXPAND;
    876 #ifdef DEMO
    877 				retval += 1;
    878 #endif	//DEMO
    879 				process = false;
    880 				break;
    881 
    882 			case KN_UP:
    883 				buttons[curbutton]->Turn_Off();
    884 				buttons[curbutton]->Flag_To_Redraw();
    885 				curbutton--;
    886 #ifdef NEWMENU
    887 				if (expansions) {
    888 					if (curbutton < 0) {
    889 						curbutton = 6;
    890 					}
    891 				} else {
    892 					if (curbutton < 1) {
    893 						curbutton = 6;
    894 					}
    895 				}
    896 #else
    897 				if (curbutton < 0) {
    898 					curbutton = 4;
    899 				}
    900 #endif
    901 				buttons[curbutton]->Turn_On();
    902 				buttons[curbutton]->Flag_To_Redraw();
    903 				break;
    904 
    905 			case KN_DOWN:
    906 				buttons[curbutton]->Turn_Off();
    907 				buttons[curbutton]->Flag_To_Redraw();
    908 				curbutton++;
    909 #ifdef NEWMENU
    910 				if (curbutton > 6) {
    911 					if (expansions) {
    912 						curbutton = 0;
    913 					} else {
    914 						curbutton = 1;
    915 					}
    916 				}
    917 #else
    918 				if (curbutton > 4) {
    919 					curbutton = 0;
    920 				}
    921 #endif
    922 				buttons[curbutton]->Turn_On();
    923 				buttons[curbutton]->Flag_To_Redraw();
    924 				break;
    925 
    926 			case KN_RETURN:
    927 				buttons[curbutton]->IsPressed = true;
    928 				buttons[curbutton]->Draw_Me(true);
    929 				retval = curbutton;
    930 				process = false;
    931 				break;
    932 
    933 			default:
    934 				break;
    935 		}
    936 	}
    937 	return(retval);
    938 }