• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 #include "quakedef.h"
21 #include "winquake.h"
22 
23 void (*vid_menudrawfn)(void);
24 void (*vid_menukeyfn)(int key);
25 
26 enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
27 
28 void M_Menu_Main_f (void);
29 	void M_Menu_SinglePlayer_f (void);
30 		void M_Menu_Load_f (void);
31 		void M_Menu_Save_f (void);
32 	void M_Menu_MultiPlayer_f (void);
33 		void M_Menu_Setup_f (void);
34 		void M_Menu_Net_f (void);
35 	void M_Menu_Options_f (void);
36 		void M_Menu_Keys_f (void);
37 		void M_Menu_Video_f (void);
38 	void M_Menu_Help_f (void);
39 	void M_Menu_Quit_f (void);
40 void M_Menu_SerialConfig_f (void);
41 	void M_Menu_ModemConfig_f (void);
42 void M_Menu_LanConfig_f (void);
43 void M_Menu_GameOptions_f (void);
44 void M_Menu_Search_f (void);
45 void M_Menu_ServerList_f (void);
46 
47 void M_Main_Draw (void);
48 	void M_SinglePlayer_Draw (void);
49 		void M_Load_Draw (void);
50 		void M_Save_Draw (void);
51 	void M_MultiPlayer_Draw (void);
52 		void M_Setup_Draw (void);
53 		void M_Net_Draw (void);
54 	void M_Options_Draw (void);
55 		void M_Keys_Draw (void);
56 		void M_Video_Draw (void);
57 	void M_Help_Draw (void);
58 	void M_Quit_Draw (void);
59 void M_SerialConfig_Draw (void);
60 	void M_ModemConfig_Draw (void);
61 void M_LanConfig_Draw (void);
62 void M_GameOptions_Draw (void);
63 void M_Search_Draw (void);
64 void M_ServerList_Draw (void);
65 
66 void M_Main_Key (int key);
67 	void M_SinglePlayer_Key (int key);
68 		void M_Load_Key (int key);
69 		void M_Save_Key (int key);
70 	void M_MultiPlayer_Key (int key);
71 		void M_Setup_Key (int key);
72 		void M_Net_Key (int key);
73 	void M_Options_Key (int key);
74 		void M_Keys_Key (int key);
75 		void M_Video_Key (int key);
76 	void M_Help_Key (int key);
77 	void M_Quit_Key (int key);
78 void M_SerialConfig_Key (int key);
79 	void M_ModemConfig_Key (int key);
80 void M_LanConfig_Key (int key);
81 void M_GameOptions_Key (int key);
82 void M_Search_Key (int key);
83 void M_ServerList_Key (int key);
84 
85 qboolean	m_entersound;		// play after drawing a frame, so caching
86 								// won't disrupt the sound
87 qboolean	m_recursiveDraw;
88 
89 int			m_return_state;
90 qboolean	m_return_onerror;
91 char		m_return_reason [32];
92 
93 #define StartingGame	(m_multiplayer_cursor == 1)
94 #define JoiningGame		(m_multiplayer_cursor == 0)
95 #define SerialConfig	(m_net_cursor == 0)
96 #define DirectConfig	(m_net_cursor == 1)
97 #define	IPXConfig		(m_net_cursor == 2)
98 #define	TCPIPConfig		(m_net_cursor == 3)
99 
100 void M_ConfigureNetSubsystem(void);
101 
102 //=============================================================================
103 /* Support Routines */
104 
105 /*
106 ================
107 M_DrawCharacter
108 
109 Draws one solid graphics character
110 ================
111 */
M_DrawCharacter(int cx,int line,int num)112 void M_DrawCharacter (int cx, int line, int num)
113 {
114 	Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
115 }
116 
M_Print(int cx,int cy,char * str)117 void M_Print (int cx, int cy, char *str)
118 {
119 	while (*str)
120 	{
121 		M_DrawCharacter (cx, cy, (*str)+128);
122 		str++;
123 		cx += 8;
124 	}
125 }
126 
M_PrintWhite(int cx,int cy,char * str)127 void M_PrintWhite (int cx, int cy, char *str)
128 {
129 	while (*str)
130 	{
131 		M_DrawCharacter (cx, cy, *str);
132 		str++;
133 		cx += 8;
134 	}
135 }
136 
M_DrawTransPic(int x,int y,qpic_t * pic)137 void M_DrawTransPic (int x, int y, qpic_t *pic)
138 {
139 	Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
140 }
141 
M_DrawPic(int x,int y,qpic_t * pic)142 void M_DrawPic (int x, int y, qpic_t *pic)
143 {
144 	Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
145 }
146 
147 byte identityTable[256];
148 byte translationTable[256];
149 
M_BuildTranslationTable(int top,int bottom)150 void M_BuildTranslationTable(int top, int bottom)
151 {
152 	int		j;
153 	byte	*dest, *source;
154 
155 	for (j = 0; j < 256; j++)
156 		identityTable[j] = j;
157 	dest = translationTable;
158 	source = identityTable;
159 	memcpy (dest, source, 256);
160 
161 	if (top < 128)	// the artists made some backwards ranges.  sigh.
162 		memcpy (dest + TOP_RANGE, source + top, 16);
163 	else
164 		for (j=0 ; j<16 ; j++)
165 			dest[TOP_RANGE+j] = source[top+15-j];
166 
167 	if (bottom < 128)
168 		memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
169 	else
170 		for (j=0 ; j<16 ; j++)
171 			dest[BOTTOM_RANGE+j] = source[bottom+15-j];
172 }
173 
174 
M_DrawTransPicTranslate(int x,int y,qpic_t * pic)175 void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
176 {
177 	Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
178 }
179 
180 
M_DrawTextBox(int x,int y,int width,int lines)181 void M_DrawTextBox (int x, int y, int width, int lines)
182 {
183 	qpic_t	*p;
184 	int		cx, cy;
185 	int		n;
186 
187 	// draw left side
188 	cx = x;
189 	cy = y;
190 	p = Draw_CachePic ("gfx/box_tl.lmp");
191 	M_DrawTransPic (cx, cy, p);
192 	p = Draw_CachePic ("gfx/box_ml.lmp");
193 	for (n = 0; n < lines; n++)
194 	{
195 		cy += 8;
196 		M_DrawTransPic (cx, cy, p);
197 	}
198 	p = Draw_CachePic ("gfx/box_bl.lmp");
199 	M_DrawTransPic (cx, cy+8, p);
200 
201 	// draw middle
202 	cx += 8;
203 	while (width > 0)
204 	{
205 		cy = y;
206 		p = Draw_CachePic ("gfx/box_tm.lmp");
207 		M_DrawTransPic (cx, cy, p);
208 		p = Draw_CachePic ("gfx/box_mm.lmp");
209 		for (n = 0; n < lines; n++)
210 		{
211 			cy += 8;
212 			if (n == 1)
213 				p = Draw_CachePic ("gfx/box_mm2.lmp");
214 			M_DrawTransPic (cx, cy, p);
215 		}
216 		p = Draw_CachePic ("gfx/box_bm.lmp");
217 		M_DrawTransPic (cx, cy+8, p);
218 		width -= 2;
219 		cx += 16;
220 	}
221 
222 	// draw right side
223 	cy = y;
224 	p = Draw_CachePic ("gfx/box_tr.lmp");
225 	M_DrawTransPic (cx, cy, p);
226 	p = Draw_CachePic ("gfx/box_mr.lmp");
227 	for (n = 0; n < lines; n++)
228 	{
229 		cy += 8;
230 		M_DrawTransPic (cx, cy, p);
231 	}
232 	p = Draw_CachePic ("gfx/box_br.lmp");
233 	M_DrawTransPic (cx, cy+8, p);
234 }
235 
236 //=============================================================================
237 
238 int m_save_demonum;
239 
240 /*
241 ================
242 M_ToggleMenu_f
243 ================
244 */
M_ToggleMenu_f(void)245 void M_ToggleMenu_f (void)
246 {
247 	m_entersound = true;
248 
249 	if (key_dest == key_menu)
250 	{
251 		if (m_state != m_main)
252 		{
253 			M_Menu_Main_f ();
254 			return;
255 		}
256 		key_dest = key_game;
257 		m_state = m_none;
258 		return;
259 	}
260 	if (key_dest == key_console)
261 	{
262 		Con_ToggleConsole_f ();
263 	}
264 	else
265 	{
266 		M_Menu_Main_f ();
267 	}
268 }
269 
270 
271 //=============================================================================
272 /* MAIN MENU */
273 
274 int	m_main_cursor;
275 #define	MAIN_ITEMS	5
276 
277 
M_Menu_Main_f(void)278 void M_Menu_Main_f (void)
279 {
280 	if (key_dest != key_menu)
281 	{
282 		m_save_demonum = cls.demonum;
283 		cls.demonum = -1;
284 	}
285 	key_dest = key_menu;
286 	m_state = m_main;
287 	m_entersound = true;
288 }
289 
290 
M_Main_Draw(void)291 void M_Main_Draw (void)
292 {
293 	int		f;
294 	qpic_t	*p;
295 
296 	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
297 	p = Draw_CachePic ("gfx/ttl_main.lmp");
298 	M_DrawPic ( (320-p->width)/2, 4, p);
299 	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
300 
301 	f = (int)(realtime * 10)%6;
302 
303 	M_DrawTransPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
304 }
305 
306 
M_Main_Key(int key)307 void M_Main_Key (int key)
308 {
309 	switch (key)
310 	{
311 	case K_ESCAPE:
312 		key_dest = key_game;
313 		m_state = m_none;
314 		cls.demonum = m_save_demonum;
315 		if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected)
316 			CL_NextDemo ();
317 		break;
318 
319 	case K_DOWNARROW:
320 		S_LocalSound ("misc/menu1.wav");
321 		if (++m_main_cursor >= MAIN_ITEMS)
322 			m_main_cursor = 0;
323 		break;
324 
325 	case K_UPARROW:
326 		S_LocalSound ("misc/menu1.wav");
327 		if (--m_main_cursor < 0)
328 			m_main_cursor = MAIN_ITEMS - 1;
329 		break;
330 
331 	case K_ENTER:
332 		m_entersound = true;
333 
334 		switch (m_main_cursor)
335 		{
336 		case 0:
337 			M_Menu_SinglePlayer_f ();
338 			break;
339 
340 		case 1:
341 			M_Menu_MultiPlayer_f ();
342 			break;
343 
344 		case 2:
345 			M_Menu_Options_f ();
346 			break;
347 
348 		case 3:
349 			M_Menu_Help_f ();
350 			break;
351 
352 		case 4:
353 			M_Menu_Quit_f ();
354 			break;
355 		}
356 	}
357 }
358 
359 
360 //=============================================================================
361 /* OPTIONS MENU */
362 
363 #define	OPTIONS_ITEMS	16
364 
365 #define	SLIDER_RANGE	10
366 
367 int		options_cursor;
368 
M_Menu_Options_f(void)369 void M_Menu_Options_f (void)
370 {
371 	key_dest = key_menu;
372 	m_state = m_options;
373 	m_entersound = true;
374 }
375 
376 
M_AdjustSliders(int dir)377 void M_AdjustSliders (int dir)
378 {
379 	S_LocalSound ("misc/menu3.wav");
380 
381 	switch (options_cursor)
382 	{
383 	case 3:	// screen size
384 		scr_viewsize.value += dir * 10;
385 		if (scr_viewsize.value < 30)
386 			scr_viewsize.value = 30;
387 		if (scr_viewsize.value > 120)
388 			scr_viewsize.value = 120;
389 		Cvar_SetValue ("viewsize", scr_viewsize.value);
390 		break;
391 	case 4:	// gamma
392 		v_gamma.value -= dir * 0.05;
393 		if (v_gamma.value < 0.5)
394 			v_gamma.value = 0.5;
395 		if (v_gamma.value > 1)
396 			v_gamma.value = 1;
397 		Cvar_SetValue ("gamma", v_gamma.value);
398 		break;
399 	case 5:	// mouse speed
400 		sensitivity.value += dir * 0.5;
401 		if (sensitivity.value < 1)
402 			sensitivity.value = 1;
403 		if (sensitivity.value > 11)
404 			sensitivity.value = 11;
405 		Cvar_SetValue ("sensitivity", sensitivity.value);
406 		break;
407 	case 6:	// music volume
408 #ifdef _WIN32
409 		bgmvolume.value += dir * 1.0;
410 #else
411 		bgmvolume.value += dir * 0.1;
412 #endif
413 		if (bgmvolume.value < 0)
414 			bgmvolume.value = 0;
415 		if (bgmvolume.value > 1)
416 			bgmvolume.value = 1;
417 		Cvar_SetValue ("bgmvolume", bgmvolume.value);
418 		break;
419 	case 7:	// sfx volume
420 		volume.value += dir * 0.1;
421 		if (volume.value < 0)
422 			volume.value = 0;
423 		if (volume.value > 1)
424 			volume.value = 1;
425 		Cvar_SetValue ("volume", volume.value);
426 		break;
427 
428 	case 8:	// allways run
429 		if (cl_forwardspeed.value > 200)
430 		{
431 			Cvar_SetValue ("cl_forwardspeed", 200);
432 			Cvar_SetValue ("cl_backspeed", 200);
433 		}
434 		else
435 		{
436 			Cvar_SetValue ("cl_forwardspeed", 400);
437 			Cvar_SetValue ("cl_backspeed", 400);
438 		}
439 		break;
440 
441 	case 9:	// invert mouse
442 		Cvar_SetValue ("m_pitch", -m_pitch.value);
443 		break;
444 
445 	case 10:	// lookspring
446 		Cvar_SetValue ("lookspring", !lookspring.value);
447 		break;
448 
449 	case 11:	// lookstrafe
450 		Cvar_SetValue ("lookstrafe", !lookstrafe.value);
451 		break;
452 
453 	case 12:
454 		Cvar_SetValue ("cl_sbar", !cl_sbar.value);
455 		break;
456 
457 	case 13:
458 		Cvar_SetValue ("cl_hudswap", !cl_hudswap.value);
459 
460 	case 15:	// _windowed_mouse
461 		Cvar_SetValue ("_windowed_mouse", !_windowed_mouse.value);
462 		break;
463 	}
464 }
465 
466 
M_DrawSlider(int x,int y,float range)467 void M_DrawSlider (int x, int y, float range)
468 {
469 	int	i;
470 
471 	if (range < 0)
472 		range = 0;
473 	if (range > 1)
474 		range = 1;
475 	M_DrawCharacter (x-8, y, 128);
476 	for (i=0 ; i<SLIDER_RANGE ; i++)
477 		M_DrawCharacter (x + i*8, y, 129);
478 	M_DrawCharacter (x+i*8, y, 130);
479 	M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
480 }
481 
M_DrawCheckbox(int x,int y,int on)482 void M_DrawCheckbox (int x, int y, int on)
483 {
484 #if 0
485 	if (on)
486 		M_DrawCharacter (x, y, 131);
487 	else
488 		M_DrawCharacter (x, y, 129);
489 #endif
490 	if (on)
491 		M_Print (x, y, "on");
492 	else
493 		M_Print (x, y, "off");
494 }
495 
M_Options_Draw(void)496 void M_Options_Draw (void)
497 {
498 	float		r;
499 	qpic_t	*p;
500 
501 	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
502 	p = Draw_CachePic ("gfx/p_option.lmp");
503 	M_DrawPic ( (320-p->width)/2, 4, p);
504 
505 	M_Print (16, 32, "    Customize controls");
506 	M_Print (16, 40, "         Go to console");
507 	M_Print (16, 48, "     Reset to defaults");
508 
509 	M_Print (16, 56, "           Screen size");
510 	r = (scr_viewsize.value - 30) / (120 - 30);
511 	M_DrawSlider (220, 56, r);
512 
513 	M_Print (16, 64, "            Brightness");
514 	r = (1.0 - v_gamma.value) / 0.5;
515 	M_DrawSlider (220, 64, r);
516 
517 	M_Print (16, 72, "           Mouse Speed");
518 	r = (sensitivity.value - 1)/10;
519 	M_DrawSlider (220, 72, r);
520 
521 	M_Print (16, 80, "       CD Music Volume");
522 	r = bgmvolume.value;
523 	M_DrawSlider (220, 80, r);
524 
525 	M_Print (16, 88, "          Sound Volume");
526 	r = volume.value;
527 	M_DrawSlider (220, 88, r);
528 
529 	M_Print (16, 96,  "            Always Run");
530 	M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
531 
532 	M_Print (16, 104, "          Invert Mouse");
533 	M_DrawCheckbox (220, 104, m_pitch.value < 0);
534 
535 	M_Print (16, 112, "            Lookspring");
536 	M_DrawCheckbox (220, 112, lookspring.value);
537 
538 	M_Print (16, 120, "            Lookstrafe");
539 	M_DrawCheckbox (220, 120, lookstrafe.value);
540 
541 	M_Print (16, 128, "    Use old status bar");
542 	M_DrawCheckbox (220, 128, cl_sbar.value);
543 
544 	M_Print (16, 136, "      HUD on left side");
545 	M_DrawCheckbox (220, 136, cl_hudswap.value);
546 
547 	if (vid_menudrawfn)
548 		M_Print (16, 144, "         Video Options");
549 
550 #ifdef _WIN32
551 	if (modestate == MS_WINDOWED)
552 	{
553 #endif
554 		M_Print (16, 152, "             Use Mouse");
555 		M_DrawCheckbox (220, 152, _windowed_mouse.value);
556 #ifdef _WIN32
557 	}
558 #endif
559 
560 // cursor
561 	M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
562 }
563 
564 
M_Options_Key(int k)565 void M_Options_Key (int k)
566 {
567 	switch (k)
568 	{
569 	case K_ESCAPE:
570 		M_Menu_Main_f ();
571 		break;
572 
573 	case K_ENTER:
574 		m_entersound = true;
575 		switch (options_cursor)
576 		{
577 		case 0:
578 			M_Menu_Keys_f ();
579 			break;
580 		case 1:
581 			m_state = m_none;
582 			Con_ToggleConsole_f ();
583 			break;
584 		case 2:
585 			Cbuf_AddText ("exec default.cfg\n");
586 			break;
587 		case 14:
588 			M_Menu_Video_f ();
589 			break;
590 		default:
591 			M_AdjustSliders (1);
592 			break;
593 		}
594 		return;
595 
596 	case K_UPARROW:
597 		S_LocalSound ("misc/menu1.wav");
598 		options_cursor--;
599 		if (options_cursor < 0)
600 			options_cursor = OPTIONS_ITEMS-1;
601 		break;
602 
603 	case K_DOWNARROW:
604 		S_LocalSound ("misc/menu1.wav");
605 		options_cursor++;
606 		if (options_cursor >= OPTIONS_ITEMS)
607 			options_cursor = 0;
608 		break;
609 
610 	case K_LEFTARROW:
611 		M_AdjustSliders (-1);
612 		break;
613 
614 	case K_RIGHTARROW:
615 		M_AdjustSliders (1);
616 		break;
617 	}
618 
619 	if (options_cursor == 14 && vid_menudrawfn == NULL)
620 	{
621 		if (k == K_UPARROW)
622 			options_cursor = 13;
623 		else
624 			options_cursor = 0;
625 	}
626 
627 	if ((options_cursor == 15)
628 #ifdef _WIN32
629 	&& (modestate != MS_WINDOWED)
630 #endif
631 	)
632 	{
633 		if (k == K_UPARROW)
634 			options_cursor = 14;
635 		else
636 			options_cursor = 0;
637 	}
638 }
639 
640 
641 //=============================================================================
642 /* KEYS MENU */
643 
644 char *bindnames[][2] =
645 {
646 {"+attack", 		"attack"},
647 {"impulse 10", 		"change weapon"},
648 {"+jump", 			"jump / swim up"},
649 {"+forward", 		"walk forward"},
650 {"+back", 			"backpedal"},
651 {"+left", 			"turn left"},
652 {"+right", 			"turn right"},
653 {"+speed", 			"run"},
654 {"+moveleft", 		"step left"},
655 {"+moveright", 		"step right"},
656 {"+strafe", 		"sidestep"},
657 {"+lookup", 		"look up"},
658 {"+lookdown", 		"look down"},
659 {"centerview", 		"center view"},
660 {"+mlook", 			"mouse look"},
661 {"+klook", 			"keyboard look"},
662 {"+moveup",			"swim up"},
663 {"+movedown",		"swim down"}
664 };
665 
666 #define	NUMCOMMANDS	(sizeof(bindnames)/sizeof(bindnames[0]))
667 
668 int		keys_cursor;
669 int		bind_grab;
670 
M_Menu_Keys_f(void)671 void M_Menu_Keys_f (void)
672 {
673 	key_dest = key_menu;
674 	m_state = m_keys;
675 	m_entersound = true;
676 }
677 
678 
M_FindKeysForCommand(char * command,int * twokeys)679 void M_FindKeysForCommand (char *command, int *twokeys)
680 {
681 	int		count;
682 	int		j;
683 	int		l;
684 	char	*b;
685 
686 	twokeys[0] = twokeys[1] = -1;
687 	l = strlen(command);
688 	count = 0;
689 
690 	for (j=0 ; j<256 ; j++)
691 	{
692 		b = keybindings[j];
693 		if (!b)
694 			continue;
695 		if (!strncmp (b, command, l) )
696 		{
697 			twokeys[count] = j;
698 			count++;
699 			if (count == 2)
700 				break;
701 		}
702 	}
703 }
704 
M_UnbindCommand(char * command)705 void M_UnbindCommand (char *command)
706 {
707 	int		j;
708 	int		l;
709 	char	*b;
710 
711 	l = strlen(command);
712 
713 	for (j=0 ; j<256 ; j++)
714 	{
715 		b = keybindings[j];
716 		if (!b)
717 			continue;
718 		if (!strncmp (b, command, l) )
719 			Key_SetBinding (j, "");
720 	}
721 }
722 
723 
M_Keys_Draw(void)724 void M_Keys_Draw (void)
725 {
726 	int		i, l;
727 	int		keys[2];
728 	char	*name;
729 	int		x, y;
730 	qpic_t	*p;
731 
732 	p = Draw_CachePic ("gfx/ttl_cstm.lmp");
733 	M_DrawPic ( (320-p->width)/2, 4, p);
734 
735 	if (bind_grab)
736 		M_Print (12, 32, "Press a key or button for this action");
737 	else
738 		M_Print (18, 32, "Enter to change, backspace to clear");
739 
740 // search for known bindings
741 	for (i=0 ; i< (int) NUMCOMMANDS ; i++)
742 	{
743 		y = 48 + 8*i;
744 
745 		M_Print (16, y, bindnames[i][1]);
746 
747 		l = strlen (bindnames[i][0]);
748 
749 		M_FindKeysForCommand (bindnames[i][0], keys);
750 
751 		if (keys[0] == -1)
752 		{
753 			M_Print (140, y, "???");
754 		}
755 		else
756 		{
757 			name = Key_KeynumToString (keys[0]);
758 			M_Print (140, y, name);
759 			x = strlen(name) * 8;
760 			if (keys[1] != -1)
761 			{
762 				M_Print (140 + x + 8, y, "or");
763 				M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
764 			}
765 		}
766 	}
767 
768 	if (bind_grab)
769 		M_DrawCharacter (130, 48 + keys_cursor*8, '=');
770 	else
771 		M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
772 }
773 
774 
M_Keys_Key(int k)775 void M_Keys_Key (int k)
776 {
777 	char	cmd[80];
778 	int		keys[2];
779 
780 	if (bind_grab)
781 	{	// defining a key
782 		S_LocalSound ("misc/menu1.wav");
783 		if (k == K_ESCAPE)
784 		{
785 			bind_grab = false;
786 		}
787 		else if (k != '`')
788 		{
789 			sprintf (cmd, "bind %s \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);
790 			Cbuf_InsertText (cmd);
791 		}
792 
793 		bind_grab = false;
794 		return;
795 	}
796 
797 	switch (k)
798 	{
799 	case K_ESCAPE:
800 		M_Menu_Options_f ();
801 		break;
802 
803 	case K_LEFTARROW:
804 	case K_UPARROW:
805 		S_LocalSound ("misc/menu1.wav");
806 		keys_cursor--;
807 		if (keys_cursor < 0)
808 			keys_cursor = NUMCOMMANDS-1;
809 		break;
810 
811 	case K_DOWNARROW:
812 	case K_RIGHTARROW:
813 		S_LocalSound ("misc/menu1.wav");
814 		keys_cursor++;
815 		if (keys_cursor >= (int) NUMCOMMANDS)
816 			keys_cursor = 0;
817 		break;
818 
819 	case K_ENTER:		// go into bind mode
820 		M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
821 		S_LocalSound ("misc/menu2.wav");
822 		if (keys[1] != -1)
823 			M_UnbindCommand (bindnames[keys_cursor][0]);
824 		bind_grab = true;
825 		break;
826 
827 	case K_BACKSPACE:		// delete bindings
828 	case K_DEL:				// delete bindings
829 		S_LocalSound ("misc/menu2.wav");
830 		M_UnbindCommand (bindnames[keys_cursor][0]);
831 		break;
832 	}
833 }
834 
835 //=============================================================================
836 /* VIDEO MENU */
837 
M_Menu_Video_f(void)838 void M_Menu_Video_f (void)
839 {
840 	key_dest = key_menu;
841 	m_state = m_video;
842 	m_entersound = true;
843 }
844 
845 
M_Video_Draw(void)846 void M_Video_Draw (void)
847 {
848 	(*vid_menudrawfn) ();
849 }
850 
851 
M_Video_Key(int key)852 void M_Video_Key (int key)
853 {
854 	(*vid_menukeyfn) (key);
855 }
856 
857 //=============================================================================
858 /* HELP MENU */
859 
860 int		help_page;
861 #define	NUM_HELP_PAGES	6
862 
863 
M_Menu_Help_f(void)864 void M_Menu_Help_f (void)
865 {
866 	key_dest = key_menu;
867 	m_state = m_help;
868 	m_entersound = true;
869 	help_page = 0;
870 }
871 
872 
873 
M_Help_Draw(void)874 void M_Help_Draw (void)
875 {
876 	M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) );
877 }
878 
879 
M_Help_Key(int key)880 void M_Help_Key (int key)
881 {
882 	switch (key)
883 	{
884 	case K_ESCAPE:
885 		M_Menu_Main_f ();
886 		break;
887 
888 	case K_UPARROW:
889 	case K_RIGHTARROW:
890 		m_entersound = true;
891 		if (++help_page >= NUM_HELP_PAGES)
892 			help_page = 0;
893 		break;
894 
895 	case K_DOWNARROW:
896 	case K_LEFTARROW:
897 		m_entersound = true;
898 		if (--help_page < 0)
899 			help_page = NUM_HELP_PAGES-1;
900 		break;
901 	}
902 
903 }
904 
905 //=============================================================================
906 /* QUIT MENU */
907 
908 int		msgNumber;
909 int		m_quit_prevstate;
910 qboolean	wasInMenus;
911 
912 char *quitMessage [] =
913 {
914 /* .........1.........2.... */
915   "  Are you gonna quit    ",
916   "  this game just like   ",
917   "   everything else?     ",
918   "                        ",
919 
920   " Milord, methinks that  ",
921   "   thou art a lowly     ",
922   " quitter. Is this true? ",
923   "                        ",
924 
925   " Do I need to bust your ",
926   "  face open for trying  ",
927   "        to quit?        ",
928   "                        ",
929 
930   " Man, I oughta smack you",
931   "   for trying to quit!  ",
932   "     Press Y to get     ",
933   "      smacked out.      ",
934 
935   " Press Y to quit like a ",
936   "   big loser in life.   ",
937   "  Press N to stay proud ",
938   "    and successful!     ",
939 
940   "   If you press Y to    ",
941   "  quit, I will summon   ",
942   "  Satan all over your   ",
943   "      hard drive!       ",
944 
945   "  Um, Asmodeus dislikes ",
946   " his children trying to ",
947   " quit. Press Y to return",
948   "   to your Tinkertoys.  ",
949 
950   "  If you quit now, I'll ",
951   "  throw a blanket-party ",
952   "   for you next time!   ",
953   "                        "
954 };
955 
M_Menu_Quit_f(void)956 void M_Menu_Quit_f (void)
957 {
958 	if (m_state == m_quit)
959 		return;
960 	wasInMenus = (key_dest == key_menu);
961 	key_dest = key_menu;
962 	m_quit_prevstate = m_state;
963 	m_state = m_quit;
964 	m_entersound = true;
965 	msgNumber = rand()&7;
966 }
967 
968 
M_Quit_Key(int key)969 void M_Quit_Key (int key)
970 {
971 	switch (key)
972 	{
973 	case K_ESCAPE:
974 	case 'n':
975 	case 'N':
976 		if (wasInMenus)
977 		{
978 			m_state = m_quit_prevstate;
979 			m_entersound = true;
980 		}
981 		else
982 		{
983 			key_dest = key_game;
984 			m_state = m_none;
985 		}
986 		break;
987 
988 	case 'Y':
989 	case 'y':
990 		key_dest = key_console;
991 		CL_Disconnect ();
992 		Sys_Quit ();
993 		break;
994 
995 	default:
996 		break;
997 	}
998 
999 }
1000 
M_Menu_SinglePlayer_f(void)1001 void M_Menu_SinglePlayer_f (void) {
1002 	m_state = m_singleplayer;
1003 }
1004 
M_SinglePlayer_Draw(void)1005 void M_SinglePlayer_Draw (void) {
1006 	qpic_t	*p;
1007 
1008 	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1009 //	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1010 	p = Draw_CachePic ("gfx/ttl_sgl.lmp");
1011 	M_DrawPic ( (320-p->width)/2, 4, p);
1012 //	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
1013 
1014 	M_DrawTextBox (60, 10*8, 23, 4);
1015 	M_PrintWhite (92, 12*8, "QuakeWorld is for");
1016 	M_PrintWhite (88, 13*8, "Internet play only");
1017 
1018 }
1019 
M_SinglePlayer_Key(int key)1020 void M_SinglePlayer_Key (int key) {
1021 	if (key == K_ESCAPE || key==K_ENTER)
1022 		m_state = m_main;
1023 }
1024 
M_Menu_MultiPlayer_f(void)1025 void M_Menu_MultiPlayer_f (void) {
1026 	m_state = m_multiplayer;
1027 }
1028 
M_MultiPlayer_Draw(void)1029 void M_MultiPlayer_Draw (void) {
1030 	qpic_t	*p;
1031 
1032 	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1033 //	M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
1034 	p = Draw_CachePic ("gfx/p_multi.lmp");
1035 	M_DrawPic ( (320-p->width)/2, 4, p);
1036 //	M_DrawTransPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") );
1037 
1038 	M_DrawTextBox (46, 8*8, 27, 9);
1039 	M_PrintWhite (72, 10*8, "If you want to find QW  ");
1040 	M_PrintWhite (72, 11*8, "games, head on over to: ");
1041 	     M_Print (72, 12*8, "   www.quakeworld.net   ");
1042 	M_PrintWhite (72, 13*8, "          or            ");
1043 	     M_Print (72, 14*8, "   www.quakespy.com     ");
1044 	M_PrintWhite (72, 15*8, "For pointers on getting ");
1045 	M_PrintWhite (72, 16*8, "        started!        ");
1046 }
1047 
M_MultiPlayer_Key(int key)1048 void M_MultiPlayer_Key (int key) {
1049 	if (key == K_ESCAPE || key==K_ENTER)
1050 		m_state = m_main;
1051 }
1052 
M_Quit_Draw(void)1053 void M_Quit_Draw (void)
1054 {
1055 #define VSTR(x) #x
1056 #define VSTR2(x) VSTR(x)
1057 	char *cmsg[] = {
1058 //    0123456789012345678901234567890123456789
1059 	"0            QuakeWorld",
1060 	"1    version " VSTR2(VERSION) " by id Software",
1061 	"0Programming",
1062 	"1 John Carmack    Michael Abrash",
1063 	"1 John Cash       Christian Antkow",
1064 	"0Additional Programming",
1065 	"1 Dave 'Zoid' Kirsch",
1066 	"1 Jack 'morbid' Mathews",
1067 	"0Id Software is not responsible for",
1068     "0providing technical support for",
1069 	"0QUAKEWORLD(tm). (c)1996 Id Software,",
1070 	"0Inc.  All Rights Reserved.",
1071 	"0QUAKEWORLD(tm) is a trademark of Id",
1072 	"0Software, Inc.",
1073 	"1NOTICE: THE COPYRIGHT AND TRADEMARK",
1074 	"1NOTICES APPEARING  IN YOUR COPY OF",
1075 	"1QUAKE(r) ARE NOT MODIFIED BY THE USE",
1076 	"1OF QUAKEWORLD(tm) AND REMAIN IN FULL",
1077 	"1FORCE.",
1078 	"0NIN(r) is a registered trademark",
1079 	"0licensed to Nothing Interactive, Inc.",
1080 	"0All rights reserved. Press y to exit",
1081 	NULL };
1082 	char **p;
1083 	int y;
1084 
1085 	if (wasInMenus)
1086 	{
1087 		m_state = m_quit_prevstate;
1088 		m_recursiveDraw = true;
1089 		M_Draw ();
1090 		m_state = m_quit;
1091 	}
1092 #if 1
1093 	M_DrawTextBox (0, 0, 38, 23);
1094 	y = 12;
1095 	for (p = cmsg; *p; p++, y += 8) {
1096 		if (**p == '0')
1097 			M_PrintWhite (16, y, *p + 1);
1098 		else
1099 			M_Print (16, y,	*p + 1);
1100 	}
1101 #else
1102 	M_DrawTextBox (56, 76, 24, 4);
1103 	M_Print (64, 84,  quitMessage[msgNumber*4+0]);
1104 	M_Print (64, 92,  quitMessage[msgNumber*4+1]);
1105 	M_Print (64, 100, quitMessage[msgNumber*4+2]);
1106 	M_Print (64, 108, quitMessage[msgNumber*4+3]);
1107 #endif
1108 }
1109 
1110 
1111 
1112 //=============================================================================
1113 /* Menu Subsystem */
1114 
1115 
M_Init(void)1116 void M_Init (void)
1117 {
1118 	Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
1119 
1120 	Cmd_AddCommand ("menu_main", M_Menu_Main_f);
1121 	Cmd_AddCommand ("menu_options", M_Menu_Options_f);
1122 	Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
1123 	Cmd_AddCommand ("menu_video", M_Menu_Video_f);
1124 	Cmd_AddCommand ("help", M_Menu_Help_f);
1125 	Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
1126 }
1127 
1128 
M_Draw(void)1129 void M_Draw (void)
1130 {
1131 	if (m_state == m_none || key_dest != key_menu)
1132 		return;
1133 
1134 	if (!m_recursiveDraw)
1135 	{
1136 		scr_copyeverything = 1;
1137 
1138 		if (scr_con_current)
1139 		{
1140 			Draw_ConsoleBackground (vid.height);
1141 			VID_UnlockBuffer ();
1142 			S_ExtraUpdate ();
1143 			VID_LockBuffer ();
1144 		}
1145 		else
1146 			Draw_FadeScreen ();
1147 
1148 		scr_fullupdate = 0;
1149 	}
1150 	else
1151 	{
1152 		m_recursiveDraw = false;
1153 	}
1154 
1155 	switch (m_state)
1156 	{
1157 	case m_none:
1158 		break;
1159 
1160 	case m_main:
1161 		M_Main_Draw ();
1162 		break;
1163 
1164 	case m_singleplayer:
1165 		M_SinglePlayer_Draw ();
1166 		break;
1167 
1168 	case m_load:
1169 //		M_Load_Draw ();
1170 		break;
1171 
1172 	case m_save:
1173 //		M_Save_Draw ();
1174 		break;
1175 
1176 	case m_multiplayer:
1177 		M_MultiPlayer_Draw ();
1178 		break;
1179 
1180 	case m_setup:
1181 //		M_Setup_Draw ();
1182 		break;
1183 
1184 	case m_net:
1185 //		M_Net_Draw ();
1186 		break;
1187 
1188 	case m_options:
1189 		M_Options_Draw ();
1190 		break;
1191 
1192 	case m_keys:
1193 		M_Keys_Draw ();
1194 		break;
1195 
1196 	case m_video:
1197 		M_Video_Draw ();
1198 		break;
1199 
1200 	case m_help:
1201 		M_Help_Draw ();
1202 		break;
1203 
1204 	case m_quit:
1205 		M_Quit_Draw ();
1206 		break;
1207 
1208 	case m_serialconfig:
1209 //		M_SerialConfig_Draw ();
1210 		break;
1211 
1212 	case m_modemconfig:
1213 //		M_ModemConfig_Draw ();
1214 		break;
1215 
1216 	case m_lanconfig:
1217 //		M_LanConfig_Draw ();
1218 		break;
1219 
1220 	case m_gameoptions:
1221 //		M_GameOptions_Draw ();
1222 		break;
1223 
1224 	case m_search:
1225 //		M_Search_Draw ();
1226 		break;
1227 
1228 	case m_slist:
1229 //		M_ServerList_Draw ();
1230 		break;
1231 	}
1232 
1233 	if (m_entersound)
1234 	{
1235 		S_LocalSound ("misc/menu2.wav");
1236 		m_entersound = false;
1237 	}
1238 
1239 	VID_UnlockBuffer ();
1240 	S_ExtraUpdate ();
1241 	VID_LockBuffer ();
1242 }
1243 
1244 
M_Keydown(int key)1245 void M_Keydown (int key)
1246 {
1247 	switch (m_state)
1248 	{
1249 	case m_none:
1250 		return;
1251 
1252 	case m_main:
1253 		M_Main_Key (key);
1254 		return;
1255 
1256 	case m_singleplayer:
1257 		M_SinglePlayer_Key (key);
1258 		return;
1259 
1260 	case m_load:
1261 //		M_Load_Key (key);
1262 		return;
1263 
1264 	case m_save:
1265 //		M_Save_Key (key);
1266 		return;
1267 
1268 	case m_multiplayer:
1269 		M_MultiPlayer_Key (key);
1270 		return;
1271 
1272 	case m_setup:
1273 //		M_Setup_Key (key);
1274 		return;
1275 
1276 	case m_net:
1277 //		M_Net_Key (key);
1278 		return;
1279 
1280 	case m_options:
1281 		M_Options_Key (key);
1282 		return;
1283 
1284 	case m_keys:
1285 		M_Keys_Key (key);
1286 		return;
1287 
1288 	case m_video:
1289 		M_Video_Key (key);
1290 		return;
1291 
1292 	case m_help:
1293 		M_Help_Key (key);
1294 		return;
1295 
1296 	case m_quit:
1297 		M_Quit_Key (key);
1298 		return;
1299 
1300 	case m_serialconfig:
1301 //		M_SerialConfig_Key (key);
1302 		return;
1303 
1304 	case m_modemconfig:
1305 //		M_ModemConfig_Key (key);
1306 		return;
1307 
1308 	case m_lanconfig:
1309 //		M_LanConfig_Key (key);
1310 		return;
1311 
1312 	case m_gameoptions:
1313 //		M_GameOptions_Key (key);
1314 		return;
1315 
1316 	case m_search:
1317 //		M_Search_Key (key);
1318 		break;
1319 
1320 	case m_slist:
1321 //		M_ServerList_Key (key);
1322 		return;
1323 	}
1324 }
1325 
1326 
1327