]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/mn_menu.c
Round 1: $HOME/.hhexen/ for configs and savegames.
[theoddone33/hhexen.git] / base / mn_menu.c
1 //**************************************************************************
2 //**
3 //** mn_menu.c : Heretic 2 : Raven Software, Corp.
4 //**
5 //** $RCSfile$
6 //** $Revision$
7 //** $Date$
8 //** $Author$
9 //**
10 //**************************************************************************
11
12 // HEADER FILES ------------------------------------------------------------
13
14 #include <ctype.h>
15 #include "h2def.h"
16 #include "p_local.h"
17 #include "r_local.h"
18 #include "soundst.h"
19
20 #ifdef RENDER3D
21 #include "ogl_def.h"
22 #endif
23
24 // MACROS ------------------------------------------------------------------
25
26 #define LEFT_DIR 0
27 #define RIGHT_DIR 1
28 #define ITEM_HEIGHT 20
29 #define SMALL_ITEM_HEIGHT 9
30 #define MENU_MAX_MOUSE_SENS 50
31
32 #define KEY_INS         (0x80+0x52)
33 #define KEY_DEL         (0x80+0x53)
34 #define KEY_PGUP        (0x80+0x49)
35 #define KEY_PGDN        (0x80+0x51)
36 #define KEY_HOME        (0x80+0x47)
37 #define KEY_END         (0x80+0x4f)
38 #define SELECTOR_XOFFSET (-28)
39 #define SELECTOR_YOFFSET (-1)
40 #define SLOTTEXTLEN     16
41 #define ASCII_CURSOR '['
42
43 // TYPES -------------------------------------------------------------------
44
45 typedef enum
46 {
47         ITT_EMPTY,
48         ITT_EFUNC,
49         ITT_LRFUNC,
50         ITT_SETMENU,
51         ITT_INERT,
52         ITT_SETKEY
53 } ItemType_t;
54
55 typedef enum
56 {
57         MENU_MAIN,
58         MENU_CLASS,
59         MENU_SKILL,
60         MENU_OPTIONS,
61         MENU_OPTIONS2,
62         MENU_OPTIONS3,
63         MENU_FILES,
64         MENU_LOAD,
65         MENU_SAVE,
66         MENU_NONE
67 } MenuType_t;
68
69 typedef struct
70 {
71         ItemType_t type;
72         char *text;
73         void (*func)(int option);
74         int option;
75         MenuType_t menu;
76 } MenuItem_t;
77
78 typedef struct
79 {
80         int x;
81         int y;
82         void (*drawFunc)(void);
83         int itemCount;
84         MenuItem_t *items;
85         int oldItPos;
86         int step;
87         MenuType_t prevMenu;
88
89 #ifdef RENDER3D
90 #if 0
91     void (*textDrawer)(char*,int,int);
92     int itemHeight;
93 #endif
94 #endif
95
96 } Menu_t;
97
98 char *mlooktext[] =
99 {
100         "OFF",
101         "NORMAL",
102         "INVERSE"
103 };
104
105 boolean cdaudio;
106
107 extern int alwaysrun;
108 extern boolean i_CDMusic;
109 extern int I_CDMusInit( void );
110 extern int I_CDMusStop( void );
111
112 extern int mouselook;
113
114 extern int key_right,key_left,key_up,key_down;
115 extern int key_straferight,key_strafeleft,key_jump;
116 extern int key_fire, key_use, key_strafe, key_speed;
117 extern int key_flyup, key_flydown, key_flycenter;
118 extern int key_lookup, key_lookdown, key_lookcenter;
119 extern int key_invleft, key_invright, key_useartifact;
120
121 char *stupidtable[] = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N",
122 "O","P","Q","R","S","T","U","V","W","X","Y","Z"};
123
124 extern default_t defaults[];
125 int FirstKey = 0;
126
127 boolean askforkey = false;
128 int keyaskedfor;
129 int *mbone, *mbtwo, *mbthree;
130
131 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
132
133 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
134
135 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
136
137 char *Key2String(int key);
138 void ClearControls(int key);
139 static void InitFonts(void);
140 static void SetMenu(MenuType_t menu);
141 static void SCQuitGame(int option);
142 static void SCClass(int option);
143 static void SCSkill(int option);
144 static void SCMouseSensi(int option);
145 static void SCSfxVolume(int option);
146 static void SCMusicVolume(int option);
147 static void SCScreenSize(int option);
148 static boolean SCNetCheck(int option);
149 static void SCNetCheck2(int option);
150 static void SCLoadGame(int option);
151 static void SCSaveGame(int option);
152 static void SCMessages(int option);
153 static void SCEndGame(int option);
154 static void SCInfo(int option);
155 static void SCSetKey(int option);
156 static void SCMouselook(int option);
157 static void SCAlwaysRun(int option);
158 static void SCCDAudio(int option);
159 static void DrawMainMenu(void);
160 static void DrawClassMenu(void);
161 static void DrawSkillMenu(void);
162 static void DrawOptionsMenu(void);
163 static void DrawOptions2Menu(void);
164 static void DrawOptions3Menu(void);
165 static void DrawFileSlots(Menu_t *menu);
166 static void DrawFilesMenu(void);
167 static void MN_DrawInfo(void);
168 static void DrawLoadMenu(void);
169 static void DrawSaveMenu(void);
170 static void DrawSlider(Menu_t *menu, int item, int width, int slot);
171 void MN_LoadSlotText(void);
172
173 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
174
175 extern int detailLevel;
176 extern int screenblocks;
177 extern char *basePath;
178 extern int key_speed, key_strafe;
179 extern boolean gamekeydown[256]; // The NUMKEYS macro is local to g_game
180
181 // PUBLIC DATA DEFINITIONS -------------------------------------------------
182
183 boolean MenuActive;
184 int InfoType;
185 boolean messageson;
186 boolean mn_SuicideConsole;
187
188 // PRIVATE DATA DEFINITIONS ------------------------------------------------
189
190 static int FontABaseLump;
191 static int FontAYellowBaseLump;
192 static int FontBBaseLump;
193 static int MauloBaseLump;
194 static Menu_t *CurrentMenu;
195 static int CurrentItPos;
196 static int MenuPClass;
197 static int MenuTime;
198 static boolean soundchanged;
199
200 #ifdef RENDER3D
201 static float bgAlpha = 0;
202 static float outFade = 0;
203 static boolean fadingOut = false;
204 static int menuDarkTicks = 15;
205 static int slamInTicks = 9;
206 #endif
207
208 boolean askforquit;
209 boolean typeofask;
210 static boolean FileMenuKeySteal;
211 static boolean slottextloaded;
212 static char SlotText[6][SLOTTEXTLEN+2];
213 static char oldSlotText[SLOTTEXTLEN+2];
214 static int SlotStatus[6];
215 static int slotptr;
216 static int currentSlot;
217 static int quicksave;
218 static int quickload;
219
220 static MenuItem_t MainItems[] =
221 {
222         { ITT_SETMENU, "NEW GAME", SCNetCheck2, 1, MENU_CLASS },
223         { ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS },
224         { ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES },
225         { ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE },
226         { ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE }
227 };
228
229 static Menu_t MainMenu =
230 {
231         110, 56,
232         DrawMainMenu,
233         5, MainItems,
234         0,
235         ITEM_HEIGHT,
236         MENU_NONE
237 };
238
239 static MenuItem_t ClassItems[] =
240 {
241         { ITT_EFUNC, "FIGHTER", SCClass, 0, MENU_NONE },
242         { ITT_EFUNC, "CLERIC", SCClass, 1, MENU_NONE },
243         { ITT_EFUNC, "MAGE", SCClass, 2, MENU_NONE }
244 #ifdef ASSASSIN 
245         ,{ ITT_EFUNC, "ASSASSIN", SCClass, 3, MENU_NONE }
246 #endif
247 };
248
249 static Menu_t ClassMenu =
250 {
251         66, 66,
252         DrawClassMenu,
253 #ifdef ASSASSIN 
254         4
255 #else 
256         3
257 #endif
258         , ClassItems,
259         0,
260         ITEM_HEIGHT,
261         MENU_MAIN
262 };
263
264 static MenuItem_t FilesItems[] =
265 {
266         { ITT_SETMENU, "LOAD GAME", SCNetCheck2, 2, MENU_LOAD },
267         { ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE }
268 };
269
270 static Menu_t FilesMenu =
271 {
272         110, 60,
273         DrawFilesMenu,
274         2, FilesItems,
275         0,
276         ITEM_HEIGHT,
277         MENU_MAIN
278 };
279
280 static MenuItem_t LoadItems[] =
281 {
282         { ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE },
283         { ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE },
284         { ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE },
285         { ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE },
286         { ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE },
287         { ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE }
288 };
289
290 static Menu_t LoadMenu =
291 {
292         70, 30,
293         DrawLoadMenu,
294         6, LoadItems,
295         0,
296         ITEM_HEIGHT,
297         MENU_FILES
298 };
299
300 static MenuItem_t SaveItems[] =
301 {
302         { ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE },
303         { ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE },
304         { ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE },
305         { ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE },
306         { ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE },
307         { ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE }
308 };
309
310 static Menu_t SaveMenu =
311 {
312         70, 30,
313         DrawSaveMenu,
314         6, SaveItems,
315         0,
316         ITEM_HEIGHT,
317         MENU_FILES
318 };
319
320 static MenuItem_t SkillItems[] =
321 {
322         { ITT_EFUNC, NULL, SCSkill, sk_baby, MENU_NONE },
323         { ITT_EFUNC, NULL, SCSkill, sk_easy, MENU_NONE },
324         { ITT_EFUNC, NULL, SCSkill, sk_medium, MENU_NONE },
325         { ITT_EFUNC, NULL, SCSkill, sk_hard, MENU_NONE },
326         { ITT_EFUNC, NULL, SCSkill, sk_nightmare, MENU_NONE }
327 };
328
329 static Menu_t SkillMenu =
330 {
331         120, 44,
332         DrawSkillMenu,
333         5, SkillItems,
334         2,
335         ITEM_HEIGHT,
336         MENU_CLASS
337 };
338
339 static MenuItem_t OptionsItems[] =
340 {
341         { ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE },
342         { ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE },
343         { ITT_LRFUNC, "MOUSE SENSITIVITY :", SCMouseSensi, 0, MENU_NONE },
344         { ITT_SETMENU, "CONTROL SETUP", NULL, 0, MENU_OPTIONS3 },
345         { ITT_LRFUNC, "MOUSELOOK : ", SCMouselook, 0, MENU_NONE },
346         { ITT_EFUNC, "ALWAYS RUN : ", SCAlwaysRun, 0, MENU_NONE },
347         { ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2 }
348 };
349
350 static Menu_t OptionsMenu =
351 {
352         88, 30,
353         DrawOptionsMenu,
354         7,
355         OptionsItems,
356         0,
357         ITEM_HEIGHT,
358         MENU_MAIN
359 };
360
361 static MenuItem_t Options2Items[] =
362 {
363         { ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE },
364         { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
365         { ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE },
366         { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
367         { ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE },
368         { ITT_EMPTY, NULL, NULL, 0, MENU_NONE },
369         { ITT_EFUNC, "CD AUDIO :", SCCDAudio, 0, MENU_NONE }
370 };
371
372 static Menu_t Options2Menu =
373 {
374         90, 20,
375         DrawOptions2Menu,
376         7,
377         Options2Items,
378         0,
379         ITEM_HEIGHT,
380         MENU_OPTIONS
381 };
382
383 static MenuItem_t Options3Items[] =
384 {
385         { ITT_SETKEY, "TURN RIGHT :", SCSetKey, 0, MENU_NONE },
386         { ITT_SETKEY, "TURN LEFT :", SCSetKey, 1, MENU_NONE },
387         { ITT_SETKEY, "MOVE FORWARD :", SCSetKey, 2, MENU_NONE },
388         { ITT_SETKEY, "MOVE BACK :" , SCSetKey, 3, MENU_NONE },
389         { ITT_SETKEY, "STRAFE LEFT :", SCSetKey, 4, MENU_NONE },
390         { ITT_SETKEY, "STRAFE RIGHT :", SCSetKey, 5, MENU_NONE },
391         { ITT_SETKEY, "FLY UP :", SCSetKey, 6, MENU_NONE },
392         { ITT_SETKEY, "FLY DOWN :", SCSetKey, 7, MENU_NONE },
393         { ITT_SETKEY, "FLY CENTER :", SCSetKey, 8, MENU_NONE },
394         { ITT_SETKEY, "JUMP :", SCSetKey, 9, MENU_NONE },
395         { ITT_SETKEY, "LOOK UP :", SCSetKey, 10, MENU_NONE },
396         { ITT_SETKEY, "LOOK DOWN :", SCSetKey, 11, MENU_NONE },
397         { ITT_SETKEY, "LOOK CENTER :", SCSetKey, 12, MENU_NONE },
398         { ITT_SETKEY, "INVETORY LEFT :", SCSetKey, 13, MENU_NONE },
399         { ITT_SETKEY, "INVENTORY RIGHT :", SCSetKey, 14, MENU_NONE },
400         { ITT_SETKEY, "USE ARTIFACT :", SCSetKey, 15, MENU_NONE },
401         { ITT_SETKEY, "FIRE :", SCSetKey, 16, MENU_NONE },
402         { ITT_SETKEY, "USE :", SCSetKey, 17, MENU_NONE },
403         { ITT_SETKEY, "STRAFE :", SCSetKey, 18, MENU_NONE },
404         { ITT_SETKEY, "SPEED :", SCSetKey, 19, MENU_NONE }
405 };
406 static Menu_t Options3Menu = 
407 {
408         70,20,
409         DrawOptions3Menu,
410         15, Options3Items,
411         0,
412         SMALL_ITEM_HEIGHT,
413         MENU_OPTIONS
414 };
415
416 static Menu_t *Menus[] =
417 {
418         &MainMenu,
419         &ClassMenu,
420         &SkillMenu,
421         &OptionsMenu,
422         &Options2Menu,
423         &Options3Menu,
424         &FilesMenu,
425         &LoadMenu,
426         &SaveMenu
427 };
428
429 #if defined(__linux)
430 static char *GammaText[] = 
431 {
432         TXT_GAMMA_LEVEL_OFF,
433         TXT_GAMMA_LEVEL_1,
434         TXT_GAMMA_LEVEL_2,
435         TXT_GAMMA_LEVEL_3,
436         TXT_GAMMA_LEVEL_4
437 };
438 #endif
439         
440 // CODE --------------------------------------------------------------------
441 char *Key2String(int key)
442 {
443   switch(key) {
444         case KEY_RIGHTARROW:
445         return "RIGHT ARROW";
446         case KEY_LEFTARROW:
447         return "LEFT ARROW";
448         case KEY_DOWNARROW:
449         return "DOWN ARROW";
450         case KEY_UPARROW:
451         return "UP ARROW";
452         case KEY_ENTER:
453         return "ENTER";
454         case KEY_PGUP:
455         return "PAGE UP";
456         case KEY_PGDN:
457         return "PAGE DOWN";
458         case KEY_INS:
459         return "INSERT";
460         case KEY_HOME:
461         return "HOME";
462         case KEY_END:
463         return "END";
464         case KEY_DEL:
465         return "DELETE";
466         case ' ':
467         return "SPACE";
468         case KEY_RSHIFT:
469         return "SHIFT";
470         case KEY_RALT:
471         return "ALT";
472         case KEY_RCTRL:
473         return "CTRL";
474   }
475   //Handle letter keys
476   if(key >= 'a' && key <= 'z') return stupidtable[(key - 'a')];
477   //Everything else
478   return " ";
479 }
480
481 void ClearControls(int key)
482 {
483         int i;
484
485         for(i=3;i<24;i++)
486         {
487                 if(*defaults[i].location == key) *defaults[i].location = 0;
488         }
489 }
490
491 //---------------------------------------------------------------------------
492 //
493 // PROC MN_Init
494 //
495 //---------------------------------------------------------------------------
496
497 void MN_Init(void)
498 {
499         InitFonts();
500         MenuActive = false;
501 //      messageson = true;              // Set by defaults in .CFG
502         MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00");
503 }
504
505 //---------------------------------------------------------------------------
506 //
507 // PROC InitFonts
508 //
509 //---------------------------------------------------------------------------
510
511 static void InitFonts(void)
512 {
513         FontABaseLump = W_GetNumForName("FONTA_S")+1;
514         FontAYellowBaseLump = W_GetNumForName("FONTAY_S")+1;
515         FontBBaseLump = W_GetNumForName("FONTB_S")+1;
516 }
517
518 //---------------------------------------------------------------------------
519 //
520 // PROC MN_DrTextA
521 //
522 // Draw text using font A.
523 //
524 //---------------------------------------------------------------------------
525
526 void MN_DrTextA(char *text, int x, int y)
527 {
528         char c;
529         patch_t *p;
530
531 #ifdef RENDER3D
532     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
533 #endif
534
535         while((c = *text++) != 0)
536         {
537                 if(c < 33)
538                 {
539                         x += 5;
540                 }
541                 else
542                 {
543                         p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
544 #ifdef RENDER3D
545             OGL_DrawPatch_CS(x, y, FontABaseLump+c-33);
546 #else
547                         V_DrawPatch(x, y, p);
548 #endif
549                         x += p->width-1;
550                 }
551         }
552 }
553
554 //==========================================================================
555 //
556 // MN_DrTextAYellow
557 //
558 //==========================================================================
559
560 void MN_DrTextAYellow(char *text, int x, int y)
561 {
562         char c;
563         patch_t *p;
564
565 #ifdef RENDER3D
566     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
567 #endif
568
569         while((c = *text++) != 0)
570         {
571                 if(c < 33)
572                 {
573                         x += 5;
574                 }
575                 else
576                 {
577                         p = W_CacheLumpNum(FontAYellowBaseLump+c-33, PU_CACHE);
578 #ifdef RENDER3D
579             OGL_DrawPatch_CS(x, y, FontAYellowBaseLump+c-33);
580 #else
581                         V_DrawPatch(x, y, p);
582 #endif
583                         x += p->width-1;
584                 }
585         }
586 }
587
588 //---------------------------------------------------------------------------
589 //
590 // FUNC MN_TextAWidth
591 //
592 // Returns the pixel width of a string using font A.
593 //
594 //---------------------------------------------------------------------------
595
596 int MN_TextAWidth(char *text)
597 {
598         char c;
599         int width;
600         patch_t *p;
601
602         width = 0;
603         while((c = *text++) != 0)
604         {
605                 if(c < 33)
606                 {
607                         width += 5;
608                 }
609                 else
610                 {
611                         p = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
612                         width += p->width-1;
613                 }
614         }
615         return(width);
616 }
617
618 //---------------------------------------------------------------------------
619 //
620 // PROC MN_DrTextB
621 //
622 // Draw text using font B.
623 //
624 //---------------------------------------------------------------------------
625
626 void MN_DrTextB(char *text, int x, int y)
627 {
628         char c;
629         patch_t *p;
630
631 #ifdef RENDER3D
632     OGL_SetColorAndAlpha( 1, 1, 1, 1 );
633 #endif
634
635         while((c = *text++) != 0)
636         {
637                 if(c < 33)
638                 {
639                         x += 8;
640                 }
641                 else
642                 {
643                         p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
644 #ifdef RENDER3D
645             OGL_DrawPatch_CS(x, y, FontBBaseLump+c-33);
646 #else
647                         V_DrawPatch(x, y, p);
648 #endif
649                         x += p->width-1;
650                 }
651         }
652 }
653
654 //---------------------------------------------------------------------------
655 //
656 // FUNC MN_TextBWidth
657 //
658 // Returns the pixel width of a string using font B.
659 //
660 //---------------------------------------------------------------------------
661
662 int MN_TextBWidth(char *text)
663 {
664         char c;
665         int width;
666         patch_t *p;
667
668         width = 0;
669         while((c = *text++) != 0)
670         {
671                 if(c < 33)
672                 {
673                         width += 5;
674                 }
675                 else
676                 {
677                         p = W_CacheLumpNum(FontBBaseLump+c-33, PU_CACHE);
678                         width += p->width-1;
679                 }
680         }
681         return(width);
682 }
683
684 //---------------------------------------------------------------------------
685 //
686 // PROC MN_Ticker
687 //
688 //---------------------------------------------------------------------------
689
690 void MN_Ticker(void)
691 {
692         if(MenuActive == false)
693         {
694 #ifdef RENDER3D
695         if(bgAlpha > 0)
696         {
697             bgAlpha -= .5/(float)menuDarkTicks;
698             if(bgAlpha < 0) bgAlpha = 0;
699         }
700         if(fadingOut)
701         {
702             outFade += 1/(float)slamInTicks;
703             if(outFade > 1) fadingOut = false;
704         }
705 #endif
706                 return;
707         }
708         MenuTime++;
709 }
710
711
712 #ifdef RENDER3D
713 void MN_OGL_SetupState(float time)
714 {
715     glMatrixMode(GL_MODELVIEW);
716     glPushMatrix();
717  
718     if(time > 1 && time <= 2)
719     {
720         time = 2-time;
721         glTranslatef(160, 100, 0);
722         glScalef(.9+time*.1, .9+time*.1, 1);
723         glTranslatef(-160, -100, 0);
724         glColor4f(1, 1, 1, time);
725         return;
726     }
727  
728     glTranslatef(160, 100, 0);
729     glScalef(2-time, 2-time, 1);
730     glTranslatef(-160, -100, 0);
731     glColor4f(1, 1, 1, time*time);
732 }
733  
734 void MN_OGL_RestoreState()
735 {
736     glMatrixMode(GL_MODELVIEW);
737     glPopMatrix();                                                              
738 }
739 #endif
740
741
742 //---------------------------------------------------------------------------
743 //
744 // PROC MN_Drawer
745 //
746 //---------------------------------------------------------------------------
747
748 char *QuitEndMsg[] =
749 {
750         "ARE YOU SURE YOU WANT TO QUIT?",
751         "ARE YOU SURE YOU WANT TO END THE GAME?",
752         "DO YOU WANT TO QUICKSAVE THE GAME NAMED",
753         "DO YOU WANT TO QUICKLOAD THE GAME NAMED",
754         "ARE YOU SURE YOU WANT TO SUICIDE?"
755 };
756
757
758 #define BETA_FLASH_TEXT "BETA"
759
760 void MN_Drawer(void)
761 {
762         int i;
763         int x;
764         int y;
765         MenuItem_t *item;
766         char *selName;
767
768
769         if(MenuActive == false)
770         {
771 #ifdef RENDER3D
772         if(bgAlpha > 0)
773         {
774             UpdateState |= I_FULLSCRN;
775             BorderNeedRefresh = true;
776             //OGL_SetNoTexture();
777             glDisable( GL_TEXTURE_2D );
778             OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
779             glEnable( GL_TEXTURE_2D );
780         }
781 #endif
782                 if(askforquit)
783                 {
784                         MN_DrTextA(QuitEndMsg[typeofask-1], 160-
785                                 MN_TextAWidth(QuitEndMsg[typeofask-1])/2, 80);
786                         if(typeofask == 3)
787                         {
788                                 MN_DrTextA(SlotText[quicksave-1], 160-
789                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
790                                 MN_DrTextA("?", 160+
791                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
792                         }
793                         if(typeofask == 4)
794                         {
795                                 MN_DrTextA(SlotText[quickload-1], 160-
796                                         MN_TextAWidth(SlotText[quickload-1])/2, 90);
797                                 MN_DrTextA("?", 160+
798                                         MN_TextAWidth(SlotText[quicksave-1])/2, 90);
799                         }
800                         UpdateState |= I_FULLSCRN;
801                 }
802         }
803 #ifdef RENDER3D
804     if( MenuActive || fadingOut )
805     {
806         int effTime = (MenuTime>menuDarkTicks)? menuDarkTicks : MenuTime;
807         float temp = .5 * effTime/(float)menuDarkTicks;
808  
809         UpdateState |= I_FULLSCRN;
810  
811         if(!fadingOut)
812         {
813             if(temp > bgAlpha) bgAlpha = temp;
814             effTime = (MenuTime>slamInTicks)? slamInTicks : MenuTime;
815             temp = effTime / (float)slamInTicks;
816  
817             // Draw a dark background. It makes it easier to read the menus.
818             //OGL_SetNoTexture();
819             glDisable( GL_TEXTURE_2D );
820             OGL_DrawRect(0,0,320,200,0,0,0,bgAlpha);
821             glEnable( GL_TEXTURE_2D );
822         }
823         else temp = outFade+1;
824         MN_OGL_SetupState(temp);
825  
826         if(InfoType)
827         {
828             MN_DrawInfo();
829             MN_OGL_RestoreState();
830             return;
831         }
832         //if(screenblocks < 10)
833         //{
834         BorderNeedRefresh = true;
835         //}
836         if(CurrentMenu->drawFunc != NULL)
837         {
838             CurrentMenu->drawFunc();
839         }
840         x = CurrentMenu->x;
841         y = CurrentMenu->y;
842         item = CurrentMenu->items;
843         if(item->type == ITT_SETKEY)
844                 item += FirstKey;
845         for(i = 0; i < CurrentMenu->itemCount; i++)
846         {
847                         switch(item->type)
848                         {
849                                 case (ITT_EMPTY):
850                                         break;
851                                 case (ITT_SETKEY):
852                                         if(item->text) 
853                                                 MN_DrTextA(item->text, x, y+6);
854                                         break;
855                                 default:
856                                         if(item->text)
857                                                 MN_DrTextB(item->text, x, y);
858                         }
859                         y += CurrentMenu->step;
860             item++;
861         }
862                 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
863         selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
864         OGL_DrawPatch_CS(x+SELECTOR_XOFFSET, y, W_GetNumForName(selName));
865  
866         MN_OGL_RestoreState();
867     }
868 #else
869         else
870         {
871                 UpdateState |= I_FULLSCRN;
872                 if(InfoType)
873                 {
874                         MN_DrawInfo();
875                         return;
876                 }
877                 if(screenblocks < 10)
878                 {
879                         BorderNeedRefresh = true;
880                 }
881                 if(CurrentMenu->drawFunc != NULL)
882                 {
883                         CurrentMenu->drawFunc();
884                 }
885                 x = CurrentMenu->x;
886                 y = CurrentMenu->y;
887                 item = CurrentMenu->items;
888                 if(item->type == ITT_SETKEY)
889                         item += FirstKey;
890                 for(i = 0; i < CurrentMenu->itemCount; i++)
891                 {
892                         switch(item->type)
893                         {
894                                 case (ITT_EMPTY):
895                                         break;
896                                 case (ITT_SETKEY):
897                                         if(item->text) 
898                                                 MN_DrTextA(item->text, x, y+6);
899                                         break;
900                                 default:
901                                         if(item->text)
902                                                 MN_DrTextB(item->text, x, y);
903                         }
904                         y += CurrentMenu->step;
905                         item++;
906                 }
907                 y = CurrentMenu->y+(CurrentItPos*CurrentMenu->step)+SELECTOR_YOFFSET;
908                 selName = MenuTime&16 ? "M_SLCTR1" : "M_SLCTR2";
909                 V_DrawPatch(x+SELECTOR_XOFFSET, y,
910                         W_CacheLumpName(selName, PU_CACHE));
911         }
912 #endif
913 }
914
915 //---------------------------------------------------------------------------
916 //
917 // PROC DrawMainMenu
918 //
919 //---------------------------------------------------------------------------
920
921 static void DrawMainMenu(void)
922 {
923         int frame;
924
925         frame = (MenuTime/5)%7;
926
927 #ifdef RENDER3D
928     OGL_DrawPatch_CS( 88, 0, W_GetNumForName("M_HTIC") );
929     OGL_DrawPatch_CS( 37, 80, MauloBaseLump+(frame+2)%7 );
930     OGL_DrawPatch_CS( 278, 80, MauloBaseLump+frame );
931 #else
932         V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
933 // Old Gold skull positions: (40, 10) and (232, 10)
934         V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump+(frame+2)%7, 
935                 PU_CACHE));
936         V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump+frame, PU_CACHE));
937 #endif
938 }
939
940 //==========================================================================
941 //
942 // DrawClassMenu
943 //
944 //==========================================================================
945
946 static void DrawClassMenu(void)
947 {
948         pclass_t class;
949         static char *boxLumpName[4] =
950         {
951                 "m_fbox",
952                 "m_cbox",
953                 "m_mbox",
954                 "m_abox"
955         };
956         static char *walkLumpName[4] =
957         {
958                 "m_fwalk1",
959                 "m_cwalk1",
960                 "m_mwalk1",
961                 "m_awalk1"
962         };
963
964         MN_DrTextB("CHOOSE CLASS:", 34, 24);
965         class = (pclass_t)CurrentMenu->items[CurrentItPos].option;
966 #ifdef RENDER3D
967     OGL_DrawPatch_CS(174, 8, W_GetNumForName(boxLumpName[class]));
968     OGL_DrawPatch_CS(174+24, 8+12,
969             W_GetNumForName(walkLumpName[class])+((MenuTime>>3)&3));
970 #else
971         V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE));
972         V_DrawPatch(174+24, 8+12,
973                 W_CacheLumpNum(W_GetNumForName(walkLumpName[class])
974                 +((MenuTime>>3)&3), PU_CACHE));
975 #endif
976 }
977
978 //---------------------------------------------------------------------------
979 //
980 // PROC DrawSkillMenu
981 //
982 //---------------------------------------------------------------------------
983
984 static void DrawSkillMenu(void)
985 {
986         MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16);
987 }
988
989 //---------------------------------------------------------------------------
990 //
991 // PROC DrawFilesMenu
992 //
993 //---------------------------------------------------------------------------
994
995 static void DrawFilesMenu(void)
996 {
997 // clear out the quicksave/quickload stuff
998         quicksave = 0;
999         quickload = 0;
1000         P_ClearMessage(&players[consoleplayer]);
1001 }
1002
1003 //---------------------------------------------------------------------------
1004 //
1005 // PROC DrawLoadMenu
1006 //
1007 //---------------------------------------------------------------------------
1008
1009 static void DrawLoadMenu(void)
1010 {
1011         MN_DrTextB("LOAD GAME", 160-MN_TextBWidth("LOAD GAME")/2, 10);
1012         if(!slottextloaded)
1013         {
1014                 MN_LoadSlotText();
1015         }
1016         DrawFileSlots(&LoadMenu);
1017 }
1018
1019 //---------------------------------------------------------------------------
1020 //
1021 // PROC DrawSaveMenu
1022 //
1023 //---------------------------------------------------------------------------
1024
1025 static void DrawSaveMenu(void)
1026 {
1027         MN_DrTextB("SAVE GAME", 160-MN_TextBWidth("SAVE GAME")/2, 10);
1028         if(!slottextloaded)
1029         {
1030                 MN_LoadSlotText();
1031         }
1032         DrawFileSlots(&SaveMenu);
1033 }
1034
1035 //===========================================================================
1036 //
1037 // MN_LoadSlotText
1038 //
1039 // For each slot, looks for save games and reads the description field.
1040 //
1041 //===========================================================================
1042
1043 void MN_LoadSlotText(void)
1044 {
1045         int slot;
1046         FILE *fp;
1047         char name[100];
1048         char versionText[HXS_VERSION_TEXT_LENGTH];
1049         char description[HXS_DESCRIPTION_LENGTH];
1050         boolean found;
1051
1052         for(slot = 0; slot < 6; slot++)
1053         {
1054                 found = false;
1055                 snprintf(name, 100, "%shex%d.hxs", basePath, slot);
1056                 fp = fopen(name, "rb");
1057                 if(fp)
1058                 {
1059                         fread(description, HXS_DESCRIPTION_LENGTH, 1, fp);
1060                         fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp);
1061                         fclose(fp);
1062                         if(!strcmp(versionText, HXS_VERSION_TEXT))
1063                         {
1064                                 found = true;
1065                         }
1066                 }
1067                 if(found)
1068                 {
1069                         memcpy(SlotText[slot], description, SLOTTEXTLEN);
1070                         SlotStatus[slot] = 1;
1071                 }
1072                 else
1073                 {
1074                         memset(SlotText[slot], 0, SLOTTEXTLEN);
1075                         SlotStatus[slot] = 0;
1076                 }
1077         }
1078         slottextloaded = true;
1079 }
1080
1081 //---------------------------------------------------------------------------
1082 //
1083 // PROC DrawFileSlots
1084 //
1085 //---------------------------------------------------------------------------
1086
1087 static void DrawFileSlots(Menu_t *menu)
1088 {
1089         int i;
1090         int x;
1091         int y;
1092
1093         x = menu->x;
1094         y = menu->y;
1095         for(i = 0; i < 6; i++)
1096         {
1097 #ifdef RENDER3D
1098         OGL_DrawPatch_CS(x, y, W_GetNumForName("M_FSLOT"));
1099 #else
1100                 V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
1101 #endif
1102                 if(SlotStatus[i])
1103                 {
1104                         MN_DrTextA(SlotText[i], x+5, y+5);
1105                 }
1106                 y += ITEM_HEIGHT;
1107         }
1108 }
1109
1110 //---------------------------------------------------------------------------
1111 //
1112 // PROC DrawOptionsMenu
1113 //
1114 //---------------------------------------------------------------------------
1115
1116 static void DrawOptionsMenu(void)
1117 {
1118 char num[5];
1119         if(messageson)
1120         {
1121                 MN_DrTextB("ON", 196, 50);
1122         }
1123         else
1124         {
1125                 MN_DrTextB("OFF", 196, 50);
1126         }
1127         MN_DrTextB(mlooktext[mouselook], 208, 110);
1128
1129         sprintf(num,"%d",mouseSensitivity);
1130         MN_DrTextB(num,265, 71); 
1131
1132         if(alwaysrun)
1133         {
1134                 MN_DrTextB("ON", 208, 130);
1135         }
1136         else
1137         {
1138                 MN_DrTextB("OFF", 208,130);
1139         }
1140 }
1141
1142 //---------------------------------------------------------------------------
1143 //
1144 // PROC DrawOptions2Menu
1145 //
1146 //---------------------------------------------------------------------------
1147
1148 static void DrawOptions2Menu(void)
1149 {
1150         DrawSlider(&Options2Menu, 1, 9, screenblocks-3);
1151         DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume);
1152         DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume);
1153         if(cdaudio == true)
1154         {
1155                 MN_DrTextB("ON", 196, 140);
1156         }
1157         else
1158         {
1159                 MN_DrTextB("OFF", 196, 140);
1160         }
1161 }
1162
1163
1164 static void DrawOptions3Menu(void)
1165 {
1166         int i;
1167
1168         for(i=0;i<15;i++)
1169         {
1170                 if(askforkey && keyaskedfor == i) {
1171                         MN_DrTextAYellow("???", 195, (i*SMALL_ITEM_HEIGHT+26));
1172                 }
1173                 else {
1174                         MN_DrTextA(Key2String(*defaults[i+FirstKey+3].location),
1175                                 195, (i*SMALL_ITEM_HEIGHT+26));
1176                 }
1177         }
1178
1179 }
1180
1181 //---------------------------------------------------------------------------
1182 //
1183 // PROC SCQuitGame
1184 //
1185 //---------------------------------------------------------------------------
1186
1187 static void SCQuitGame(int option)
1188 {
1189         MenuActive = false;
1190         askforquit = true;
1191         typeofask = 1; //quit game
1192         if(!netgame && !demoplayback)
1193         {
1194                 paused = true;
1195         }
1196 }
1197
1198 //---------------------------------------------------------------------------
1199 //
1200 // PROC SCEndGame
1201 //
1202 //---------------------------------------------------------------------------
1203
1204 static void SCEndGame(int option)
1205 {
1206         if(demoplayback)
1207         {
1208                 return;
1209         }
1210         if(SCNetCheck(3))
1211         {
1212                 MenuActive = false;
1213                 askforquit = true;
1214                 typeofask = 2; //endgame
1215                 if(!netgame && !demoplayback)
1216                 {
1217                         paused = true;
1218                 }
1219         }
1220 }
1221
1222 //---------------------------------------------------------------------------
1223 //
1224 // PROC SCMessages
1225 //
1226 //---------------------------------------------------------------------------
1227
1228 static void SCMessages(int option)
1229 {
1230         messageson ^= 1;
1231         if(messageson)
1232         {
1233                 P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
1234         }
1235         else
1236         {
1237                 P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
1238         }
1239         S_StartSound(NULL, SFX_CHAT);
1240 }
1241
1242 //===========================================================================
1243 //
1244 // SCNetCheck
1245 //
1246 //===========================================================================
1247
1248 static boolean SCNetCheck(int option)
1249 {
1250         if(!netgame)
1251         {
1252                 return true;
1253         }
1254         switch(option)
1255         {
1256                 case 1: // new game
1257                         P_SetMessage(&players[consoleplayer],
1258                                 "YOU CAN'T START A NEW GAME IN NETPLAY!", true);
1259                         break;
1260                 case 2: // load game
1261                         P_SetMessage(&players[consoleplayer],
1262                                 "YOU CAN'T LOAD A GAME IN NETPLAY!", true);
1263                         break;
1264                 case 3: // end game
1265                         P_SetMessage(&players[consoleplayer],
1266                                 "YOU CAN'T END A GAME IN NETPLAY!", true);
1267                         break;
1268         }
1269         MenuActive = false;
1270         S_StartSound(NULL, SFX_CHAT);
1271         return false;
1272 }
1273
1274 //===========================================================================
1275 //
1276 // SCNetCheck2
1277 //
1278 //===========================================================================
1279
1280 static void SCNetCheck2(int option)
1281 {
1282         SCNetCheck(option);
1283         return;
1284 }
1285
1286 //---------------------------------------------------------------------------
1287 //
1288 // PROC SCLoadGame
1289 //
1290 //---------------------------------------------------------------------------
1291
1292 static void SCLoadGame(int option)
1293 {
1294         if(!SlotStatus[option])
1295         { // Don't try to load from an empty slot
1296                 return;
1297         }
1298         G_LoadGame(option);
1299         MN_DeactivateMenu();
1300         BorderNeedRefresh = true;
1301         if(quickload == -1)
1302         {
1303                 quickload = option+1;
1304                 P_ClearMessage(&players[consoleplayer]);
1305         }
1306 }
1307
1308 //---------------------------------------------------------------------------
1309 //
1310 // PROC SCSaveGame
1311 //
1312 //---------------------------------------------------------------------------
1313
1314 static void SCSaveGame(int option)
1315 {
1316         char *ptr;
1317
1318         if(!FileMenuKeySteal)
1319         {
1320                 FileMenuKeySteal = true;
1321                 strcpy(oldSlotText, SlotText[option]);
1322                 ptr = SlotText[option];
1323                 while(*ptr)
1324                 {
1325                         ptr++;
1326                 }
1327                 *ptr = '[';
1328                 *(ptr+1) = 0;
1329                 SlotStatus[option]++;
1330                 currentSlot = option;
1331                 slotptr = ptr-SlotText[option];
1332                 return;
1333         }
1334         else
1335         {
1336                 G_SaveGame(option, SlotText[option]);
1337                 FileMenuKeySteal = false;
1338                 MN_DeactivateMenu();
1339         }
1340         BorderNeedRefresh = true;
1341         if(quicksave == -1)
1342         {
1343                 quicksave = option+1;
1344                 P_ClearMessage(&players[consoleplayer]);
1345         }
1346 }
1347
1348 //==========================================================================
1349 //
1350 // SCClass
1351 //
1352 //==========================================================================
1353
1354 static void SCClass(int option)
1355 {
1356         if(netgame)
1357         {
1358                 P_SetMessage(&players[consoleplayer],
1359                         "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", true);
1360                 return;
1361         }
1362         MenuPClass = option;
1363         switch(MenuPClass)
1364         {
1365                 case PCLASS_FIGHTER:
1366                         SkillMenu.x = 120;
1367                         SkillItems[0].text = "SQUIRE";
1368                         SkillItems[1].text = "KNIGHT";
1369                         SkillItems[2].text = "WARRIOR";
1370                         SkillItems[3].text = "BERSERKER";
1371                         SkillItems[4].text = "TITAN";
1372                         break;
1373                 case PCLASS_CLERIC:
1374                         SkillMenu.x = 116;
1375                         SkillItems[0].text = "ALTAR BOY";
1376                         SkillItems[1].text = "ACOLYTE";
1377                         SkillItems[2].text = "PRIEST";
1378                         SkillItems[3].text = "CARDINAL";
1379                         SkillItems[4].text = "POPE";
1380                         break;
1381                 case PCLASS_MAGE:
1382                         SkillMenu.x = 112;
1383                         SkillItems[0].text = "APPRENTICE";
1384                         SkillItems[1].text = "ENCHANTER";
1385                         SkillItems[2].text = "SORCERER";
1386                         SkillItems[3].text = "WARLOCK";
1387                         SkillItems[4].text = "ARCHIMAGE";
1388                         break;
1389                 case PCLASS_ASS:
1390                         SkillMenu.x = 116;
1391                         SkillItems[0].text = "KNAVE";
1392                         SkillItems[1].text = "ROUGE";
1393                         SkillItems[2].text = "CUTTHROAT";
1394                         SkillItems[3].text = "EXECUTIONER";
1395                         SkillItems[4].text = "WIDOW MAKER";
1396                         break;
1397         }
1398         SetMenu(MENU_SKILL);
1399 }
1400
1401 //---------------------------------------------------------------------------
1402 //
1403 // PROC SCSkill
1404 //
1405 //---------------------------------------------------------------------------
1406
1407 static void SCSkill(int option)
1408 {
1409         extern int SB_state;
1410
1411         PlayerClass[consoleplayer] = MenuPClass;
1412         G_DeferredNewGame(option);
1413         SB_SetClassData();
1414         SB_state = -1;
1415         MN_DeactivateMenu();
1416 }
1417
1418 //---------------------------------------------------------------------------
1419 //
1420 // PROC SCMouseSensi
1421 //
1422 //---------------------------------------------------------------------------
1423
1424 static void SCMouseSensi(int option)
1425 {
1426         if(option == RIGHT_DIR)
1427         {
1428                 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1429                 {
1430                         mouseSensitivity++;
1431                 }
1432         }
1433         else if(mouseSensitivity)
1434         {
1435                 mouseSensitivity--;
1436         }
1437 }
1438
1439 //---------------------------------------------------------------------------
1440 //
1441 // PROC SCSfxVolume
1442 //
1443 //---------------------------------------------------------------------------
1444
1445 static void SCSfxVolume(int option)
1446 {
1447         if(option == RIGHT_DIR)
1448         {
1449                 if(snd_MaxVolume < 15)
1450                 {
1451                         snd_MaxVolume++;
1452                 }
1453         }
1454         else if(snd_MaxVolume)
1455         {
1456                 snd_MaxVolume--;
1457         }
1458         soundchanged = true; // we'll set it when we leave the menu
1459 }
1460
1461 //---------------------------------------------------------------------------
1462 //
1463 // PROC SCMusicVolume
1464 //
1465 //---------------------------------------------------------------------------
1466
1467 static void SCMusicVolume(int option)
1468 {
1469         if(option == RIGHT_DIR)
1470         {
1471                 if(snd_MusicVolume < 15)
1472                 {
1473                         snd_MusicVolume++;
1474                 }
1475         }
1476         else if(snd_MusicVolume)
1477         {
1478                 snd_MusicVolume--;
1479         }
1480         S_SetMusicVolume();
1481 }
1482
1483 //---------------------------------------------------------------------------
1484 //
1485 // PROC SCScreenSize
1486 //
1487 //---------------------------------------------------------------------------
1488
1489 static void SCScreenSize(int option)
1490 {
1491         if(option == RIGHT_DIR)
1492         {
1493                 if(screenblocks < 11)
1494                 {
1495                         screenblocks++;
1496                 }
1497         }
1498         else if(screenblocks > 3)
1499         {
1500                 screenblocks--;
1501         }
1502         R_SetViewSize(screenblocks, detailLevel);
1503 }
1504
1505 //---------------------------------------------------------------------------
1506 //
1507 // PROC SCInfo
1508 //
1509 //---------------------------------------------------------------------------
1510
1511 static void SCInfo(int option)
1512 {
1513         InfoType = 1;
1514         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1515         if(!netgame && !demoplayback)
1516         {
1517                 paused = true;
1518         }
1519 }
1520
1521 //---------------------------------------------------------------------------
1522 //
1523 // PROC SCSetKey
1524 //
1525 //---------------------------------------------------------------------------
1526 static void SCSetKey(int option)
1527 {
1528         askforkey = true;
1529         keyaskedfor = option;
1530         if(!netgame && !demoplayback)
1531         {
1532                 paused = true;
1533         }
1534 }
1535
1536 //---------------------------------------------------------------------------
1537 //
1538 // PROC SCMouslook(int option)
1539 //
1540 //---------------------------------------------------------------------------
1541 static void SCMouselook(int option)
1542 {
1543         if(option == RIGHT_DIR)
1544         {
1545                 if(mouselook < 2) mouselook++;
1546                 
1547         }
1548         else if(mouselook) mouselook--;
1549 }
1550
1551 static void SCAlwaysRun(int option)
1552 {
1553         if(alwaysrun) alwaysrun=0;
1554         else alwaysrun=1;
1555 }
1556 static void SCCDAudio(int option)
1557 {
1558         if(cdaudio == true)
1559         {
1560                 cdaudio = false;
1561                 I_CDMusStop();
1562                 i_CDMusic = false;
1563         }
1564         else
1565         {
1566                 cdaudio = true;
1567                 ST_Message("Attempting to initialize CD Music: ");
1568                 if(!cdrom)
1569                 {
1570                         i_CDMusic = (I_CDMusInit() != -1);
1571                 }
1572                 else
1573                 { // The user is trying to use the cdrom for both game and music
1574                         i_CDMusic = false;
1575                 }
1576                 if(i_CDMusic)
1577                 {
1578                         ST_Message("initialized.\n");
1579                 }
1580                 else
1581                 {
1582                         ST_Message("failed.\n");
1583                 }
1584         }
1585 }
1586
1587 //---------------------------------------------------------------------------
1588 //
1589 // FUNC MN_Responder
1590 //
1591 //---------------------------------------------------------------------------
1592
1593 boolean MN_Responder(event_t *event)
1594 {
1595         int key;
1596         int i;
1597         MenuItem_t *item;
1598         extern boolean automapactive;
1599         static boolean shiftdown;
1600         extern void H2_StartTitle(void);
1601         extern void G_CheckDemoStatus(void);
1602         char *textBuffer;
1603
1604         if(askforkey && event->type == ev_keydown)
1605         {
1606                 ClearControls(event->data1);
1607                 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1608                 askforkey = false;
1609                 return(true);
1610         }
1611         if(askforkey && event->type == ev_mouse)
1612         {
1613                 if(event->data1&1)
1614                         mbone = defaults[keyaskedfor+3+FirstKey].location;
1615                 if(event->data1&2)
1616                         mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1617                 if(event->data1&4)
1618                         mbthree = defaults[keyaskedfor+3+FirstKey].location;
1619                 else return(false);
1620                 return(true);
1621         }
1622         if(event->data1 == KEY_RSHIFT)
1623         {
1624                 shiftdown = (event->type == ev_keydown);
1625         }
1626         if(event->type != ev_keydown)
1627         {
1628                 return(false);
1629         }
1630         key = event->data1;
1631         if(InfoType)
1632         {
1633                 if(shareware)
1634                 {
1635                         InfoType = (InfoType+1)%5;
1636                 }
1637                 else
1638                 {
1639                         InfoType = (InfoType+1)%4;
1640                 }
1641                 if(key == KEY_ESCAPE)
1642                 {
1643                         InfoType = 0;
1644                 }
1645                 if(!InfoType)
1646                 {
1647                         if(!netgame && !demoplayback)
1648                         {
1649                                 paused = false;
1650                         }
1651                         MN_DeactivateMenu();
1652                         SB_state = -1; //refresh the statbar
1653                         BorderNeedRefresh = true;
1654                 }
1655                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1656                 return(true); //make the info screen eat the keypress
1657         }
1658
1659         if(ravpic && key == KEY_F1)
1660         {
1661                 G_ScreenShot();
1662                 return(true);
1663         }
1664
1665         if(askforquit)
1666         {
1667                 switch(key)
1668                 {
1669                         case 'y':
1670                                 if(askforquit)
1671                                 {
1672                                         switch(typeofask)
1673                                         {
1674                                                 case 1:
1675                                                         G_CheckDemoStatus(); 
1676                                                         I_Quit();
1677                                                         break;
1678                                                 case 2:
1679                                                         P_ClearMessage(&players[consoleplayer]);
1680                                                         typeofask = 0;
1681                                                         askforquit = false;
1682                                                         paused = false;
1683                                                         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1684                                                         H2_StartTitle(); // go to intro/demo mode.
1685                                                         break;
1686                                                 case 3:
1687                                                         P_SetMessage(&players[consoleplayer], 
1688                                                                 "QUICKSAVING....", false);
1689                                                         FileMenuKeySteal = true;
1690                                                         SCSaveGame(quicksave-1);
1691                                                         askforquit = false;
1692                                                         typeofask = 0;
1693                                                         BorderNeedRefresh = true;
1694                                                         return true;
1695                                                 case 4:
1696                                                         P_SetMessage(&players[consoleplayer], 
1697                                                                 "QUICKLOADING....", false);
1698                                                         SCLoadGame(quickload-1);
1699                                                         askforquit = false;
1700                                                         typeofask = 0;
1701                                                         BorderNeedRefresh = true;
1702                                                         return true;
1703                                                 case 5:
1704                                                         askforquit = false;
1705                                                         typeofask = 0;  
1706                                                         BorderNeedRefresh = true;
1707                                                         mn_SuicideConsole = true;
1708                                                         return true;
1709                                                         break;
1710                                                 default:
1711                                                         return true; // eat the 'y' keypress
1712                                         }
1713                                 }
1714                                 return false;
1715                         case 'n':
1716                         case KEY_ESCAPE:
1717                                 if(askforquit)
1718                                 {
1719                                         players[consoleplayer].messageTics = 0;
1720                                         askforquit = false;
1721                                         typeofask = 0;
1722                                         paused = false;
1723                                         UpdateState |= I_FULLSCRN;
1724                                         BorderNeedRefresh = true;
1725                                         return true;
1726                                 }
1727                                 return false;
1728                 }
1729                 return false; // don't let the keys filter thru
1730         }
1731         if(MenuActive == false && !chatmodeon)
1732         {
1733                 switch(key)
1734                 {
1735                         case KEY_MINUS:
1736                                 if(automapactive)
1737                                 { // Don't screen size in automap
1738                                         return(false);
1739                                 }
1740                                 SCScreenSize(LEFT_DIR);
1741                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1742                                 BorderNeedRefresh = true;
1743                                 UpdateState |= I_FULLSCRN;
1744                                 return(true);
1745                         case KEY_EQUALS:
1746                                 if(automapactive)
1747                                 { // Don't screen size in automap
1748                                         return(false);
1749                                 }
1750                                 SCScreenSize(RIGHT_DIR);
1751                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1752                                 BorderNeedRefresh = true;
1753                                 UpdateState |= I_FULLSCRN;
1754                                 return(true);
1755 #ifdef __NeXT__
1756                         case 'q':
1757                                 MenuActive = false;
1758                                 askforquit = true;
1759                                 typeofask = 5; // suicide
1760                                 return true;
1761 #endif
1762 #ifndef __NeXT__
1763                         case KEY_F1: // help screen
1764                                 SCInfo(0); // start up info screens
1765                                 MenuActive = true;
1766                                 return(true);
1767                         case KEY_F2: // save game
1768                                 if(gamestate == GS_LEVEL && !demoplayback)
1769                                 {
1770                                         MenuActive = true;
1771                                         FileMenuKeySteal = false;
1772                                         MenuTime = 0;
1773                                         CurrentMenu = &SaveMenu;
1774                                         CurrentItPos = CurrentMenu->oldItPos;
1775                                         if(!netgame && !demoplayback)
1776                                         {
1777                                                 paused = true;
1778                                         }
1779                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1780                                         slottextloaded = false; //reload the slot text, when needed
1781                                 }
1782                                 return true;
1783                         case KEY_F3: // load game
1784                                 if(SCNetCheck(2))
1785                                 {
1786                                         MenuActive = true;
1787                                         FileMenuKeySteal = false;
1788                                         MenuTime = 0;
1789                                         CurrentMenu = &LoadMenu;
1790                                         CurrentItPos = CurrentMenu->oldItPos;
1791                                         if(!netgame && !demoplayback)
1792                                         {
1793                                                 paused = true;
1794                                         }
1795                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1796                                         slottextloaded = false; //reload the slot text, when needed
1797                                 }
1798                                 return true;
1799                         case KEY_F4: // volume
1800                                 MenuActive = true;
1801                                 FileMenuKeySteal = false;
1802                                 MenuTime = 0;
1803                                 CurrentMenu = &Options2Menu;
1804                                 CurrentItPos = CurrentMenu->oldItPos;
1805                                 if(!netgame && !demoplayback)
1806                                 {
1807                                         paused = true;
1808                                 }
1809                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1810                                 slottextloaded = false; //reload the slot text, when needed
1811                                 return true;
1812                         case KEY_F5:
1813                                 MenuActive = false;
1814                                 askforquit = true;
1815                                 typeofask = 5; // suicide
1816                                 return true;
1817                         case KEY_F6: // quicksave
1818                                 if(gamestate == GS_LEVEL && !demoplayback)
1819                                 {
1820                                         if(!quicksave || quicksave == -1)
1821                                         {
1822                                                 MenuActive = true;
1823                                                 FileMenuKeySteal = false;
1824                                                 MenuTime = 0;
1825                                                 CurrentMenu = &SaveMenu;
1826                                                 CurrentItPos = CurrentMenu->oldItPos;
1827                                                 if(!netgame && !demoplayback)
1828                                                 {
1829                                                         paused = true;
1830                                                 }
1831                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1832                                                 slottextloaded = false; //reload the slot text
1833                                                 quicksave = -1;
1834                                                 P_SetMessage(&players[consoleplayer],
1835                                                         "CHOOSE A QUICKSAVE SLOT", true);
1836                                         }
1837                                         else
1838                                         {
1839                                                 askforquit = true;
1840                                                 typeofask = 3;
1841                                                 if(!netgame && !demoplayback)
1842                                                 {
1843                                                         paused = true;
1844                                                 }
1845                                                 S_StartSound(NULL, SFX_CHAT);
1846                                         }
1847                                 }
1848                                 return true;
1849                         case KEY_F7: // endgame
1850                                 if(SCNetCheck(3))
1851                                 {
1852                                         if(gamestate == GS_LEVEL && !demoplayback)
1853                                         {
1854                                                 S_StartSound(NULL, SFX_CHAT);
1855                                                 SCEndGame(0);
1856                                         }
1857                                 }
1858                                 return true;
1859                         case KEY_F8: // toggle messages
1860                                 SCMessages(0);
1861                                 return true;
1862                         case KEY_F9: // quickload
1863                                 if(SCNetCheck(2))
1864                                 {
1865                                         if(!quickload || quickload == -1)
1866                                         {
1867                                                 MenuActive = true;
1868                                                 FileMenuKeySteal = false;
1869                                                 MenuTime = 0;
1870                                                 CurrentMenu = &LoadMenu;
1871                                                 CurrentItPos = CurrentMenu->oldItPos;
1872                                                 if(!netgame && !demoplayback)
1873                                                 {
1874                                                         paused = true;
1875                                                 }
1876                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1877                                                 slottextloaded = false; // reload the slot text
1878                                                 quickload = -1;
1879                                                 P_SetMessage(&players[consoleplayer],
1880                                                         "CHOOSE A QUICKLOAD SLOT", true);
1881                                         }
1882                                         else
1883                                         {
1884                                                 askforquit = true;
1885                                                 if(!netgame && !demoplayback)
1886                                                 {
1887                                                         paused = true;
1888                                                 }
1889                                                 typeofask = 4;
1890                                                 S_StartSound(NULL, SFX_CHAT);
1891                                         }
1892                                 }
1893                                 return true;
1894                         case KEY_F10: // quit
1895                                 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1896                                 {
1897                                         SCQuitGame(0);
1898                                         S_StartSound(NULL, SFX_CHAT);
1899                                 }
1900                                 return true;
1901                         case KEY_F11: // F11 - gamma mode correction
1902                                 usegamma++;
1903                                 if(usegamma > 4)
1904                                 {
1905                                         usegamma = 0;
1906                                 }
1907                                 SB_PaletteFlash(true); // force change
1908                                 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1909                                         false);
1910                                 return true;
1911                         case KEY_F12: // F12 - reload current map (devmaps mode)
1912                                 if(netgame || DevMaps == false)
1913                                 {
1914                                         return false;
1915                                 }
1916                                 if(gamekeydown[key_speed])
1917                                 { // Monsters ON
1918                                         nomonsters = false;
1919                                 }
1920                                 if(gamekeydown[key_strafe])
1921                                 { // Monsters OFF
1922                                         nomonsters = true;
1923                                 }
1924                                 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1925                                 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1926                                         false);
1927                                 return true;
1928 #endif
1929                 }
1930
1931         }
1932
1933         if(MenuActive == false)
1934         {
1935                 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1936                 {
1937                         MN_ActivateMenu();
1938                         return(true);
1939                 }
1940                 return(false);
1941         }
1942         if(!FileMenuKeySteal)
1943         {
1944                 item = &CurrentMenu->items[CurrentItPos];
1945                 switch(key)
1946                 {
1947                         case KEY_DOWNARROW:
1948                                 do
1949                                 {
1950 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1951         {
1952                 if(FirstKey == 5) 
1953                 {
1954                         CurrentItPos = 0;  //End of Key menu
1955                         FirstKey = 0;
1956                 }
1957                 else
1958                 {
1959                         FirstKey++;
1960                 }       
1961         }
1962         else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1963         {
1964                 CurrentItPos = 0;
1965         }
1966         else
1967         {
1968                 CurrentItPos++;
1969         }
1970 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1971 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1972 return(true);
1973 break;
1974 case KEY_UPARROW:
1975         do
1976         {
1977         if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1978         {
1979                 if(FirstKey == 0) 
1980                 {
1981                         CurrentItPos = 14;  //End of Key menu
1982                         FirstKey = 5;
1983                 }
1984                 else
1985                 {
1986                         FirstKey--;
1987                 }       
1988         }
1989         else if(CurrentItPos == 0)
1990                                         {
1991                                                 CurrentItPos = CurrentMenu->itemCount-1;
1992                                         }
1993                                         else
1994                                         {
1995                                                 CurrentItPos--;
1996                                         }
1997                                 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1998                                 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1999                                 return(true);
2000                                 break;
2001                         case KEY_LEFTARROW:
2002                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2003                                 {
2004                                         item->func(LEFT_DIR);
2005                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2006                                 }
2007                                 return(true);
2008                                 break;
2009                         case KEY_RIGHTARROW:
2010                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2011                                 {
2012                                         item->func(RIGHT_DIR);
2013                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2014                                 }
2015                                 return(true);
2016                                 break;
2017                         case KEY_ENTER:
2018                                 if(item->type == ITT_SETMENU)
2019                                 {
2020                                         if(item->func != NULL)  
2021                                         {
2022                                                 item->func(item->option);
2023                                         }
2024                                         SetMenu(item->menu);
2025                                 }
2026                                 else if(item->func != NULL)
2027                                 {
2028                                         CurrentMenu->oldItPos = CurrentItPos;
2029                                         if(item->type == ITT_LRFUNC)
2030                                         {
2031                                                 item->func(RIGHT_DIR);
2032                                         }
2033                                         else if(item->type == ITT_EFUNC)
2034                                         {
2035                                                 item->func(item->option);
2036                                         }
2037                                         else if(item->type == ITT_SETKEY)
2038                                         {
2039                                                 item->func(item->option);
2040                                         }
2041                                 }
2042                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2043                                 return(true);
2044                                 break;
2045                         case KEY_ESCAPE:
2046                                 MN_DeactivateMenu();
2047                                 return(true);
2048                         case KEY_BACKSPACE:
2049                                 S_StartSound(NULL, SFX_PICKUP_KEY);
2050                                 if(CurrentMenu->prevMenu == MENU_NONE)
2051                                 {
2052                                         MN_DeactivateMenu();
2053                                 }
2054                                 else
2055                                 {
2056                                         SetMenu(CurrentMenu->prevMenu);
2057                                 }
2058                                 return(true);
2059                         default:
2060                                 for(i = 0; i < CurrentMenu->itemCount; i++)
2061                                 {
2062                                         if(CurrentMenu->items[i].text)
2063                                         {
2064                                                 if(toupper(key)
2065                                                         == toupper(CurrentMenu->items[i].text[0]))
2066                                                 {
2067                                                         CurrentItPos = i;
2068                                                         return(true);
2069                                                 }
2070                                         }
2071                                 }
2072                                 break;
2073                 }
2074                 return(false);
2075         }
2076         else
2077         { // Editing file names
2078                 textBuffer = &SlotText[currentSlot][slotptr];
2079                 if(key == KEY_BACKSPACE)
2080                 {
2081                         if(slotptr)
2082                         {
2083                                 *textBuffer-- = 0;
2084                                 *textBuffer = ASCII_CURSOR;
2085                                 slotptr--;
2086                         }
2087                         return(true);
2088                 }
2089                 if(key == KEY_ESCAPE)
2090                 {
2091                         memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2092                         strcpy(SlotText[currentSlot], oldSlotText);
2093                         SlotStatus[currentSlot]--;
2094                         MN_DeactivateMenu();
2095                         return(true);
2096                 }
2097                 if(key == KEY_ENTER)
2098                 {
2099                         SlotText[currentSlot][slotptr] = 0; // clear the cursor
2100                         item = &CurrentMenu->items[CurrentItPos];
2101                         CurrentMenu->oldItPos = CurrentItPos;
2102                         if(item->type == ITT_EFUNC)
2103                         {
2104                                 item->func(item->option);
2105                                 if(item->menu != MENU_NONE)
2106                                 {
2107                                         SetMenu(item->menu);
2108                                 }
2109                         }
2110                         return(true);
2111                 }
2112                 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2113                 {
2114                         if((key >= 'a' && key <= 'z'))
2115                         {
2116                                 *textBuffer++ = key-32;
2117                                 *textBuffer = ASCII_CURSOR;
2118                                 slotptr++;
2119                                 return(true);
2120                         }
2121                         if(((key >= '0' && key <= '9') || key == ' '
2122                                 || key == ',' || key == '.' || key == '-')
2123                                 && !shiftdown)
2124                         {
2125                                 *textBuffer++ = key;
2126                                 *textBuffer = ASCII_CURSOR;
2127                                 slotptr++;
2128                                 return(true);
2129                         }
2130                         if(shiftdown && key == '1')
2131                         {
2132                                 *textBuffer++ = '!';
2133                                 *textBuffer = ASCII_CURSOR;
2134                                 slotptr++;
2135                                 return(true);
2136                         }
2137                 }
2138                 return(true);
2139         }
2140         return(false);
2141 }
2142
2143 //---------------------------------------------------------------------------
2144 //
2145 // PROC MN_ActivateMenu
2146 //
2147 //---------------------------------------------------------------------------
2148
2149 void MN_ActivateMenu(void)
2150 {
2151         if(MenuActive)
2152         {
2153                 return;
2154         }
2155         if(paused)
2156         {
2157                 S_ResumeSound();
2158         }
2159         MenuActive = true;
2160         FileMenuKeySteal = false;
2161         MenuTime = 0;
2162         CurrentMenu = &MainMenu;
2163         CurrentItPos = CurrentMenu->oldItPos;
2164         if(!netgame && !demoplayback)
2165         {
2166                 paused = true;
2167         }
2168         S_StartSound(NULL, SFX_PLATFORM_STOP);
2169         slottextloaded = false; //reload the slot text, when needed
2170 }
2171
2172 //---------------------------------------------------------------------------
2173 //
2174 // PROC MN_DeactivateMenu
2175 //
2176 //---------------------------------------------------------------------------
2177
2178 void MN_DeactivateMenu(void)
2179 {
2180         CurrentMenu->oldItPos = CurrentItPos;
2181         MenuActive = false;
2182         if(!netgame)
2183         {
2184                 paused = false;
2185         }
2186         S_StartSound(NULL, SFX_PLATFORM_STOP);
2187         P_ClearMessage(&players[consoleplayer]);
2188 }
2189
2190 //---------------------------------------------------------------------------
2191 //
2192 // PROC MN_DrawInfo
2193 //
2194 //---------------------------------------------------------------------------
2195
2196 void MN_DrawInfo(void)
2197 {
2198 #ifdef RENDER3D
2199     OGL_SetFilter( 0 );
2200     OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2201 #else
2202         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2203         memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2204                 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2205 //      V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2206 //              PU_CACHE));
2207 #endif
2208 }
2209
2210
2211 //---------------------------------------------------------------------------
2212 //
2213 // PROC SetMenu
2214 //
2215 //---------------------------------------------------------------------------
2216
2217 static void SetMenu(MenuType_t menu)
2218 {
2219         CurrentMenu->oldItPos = CurrentItPos;
2220         CurrentMenu = Menus[menu];
2221         CurrentItPos = CurrentMenu->oldItPos;
2222 }
2223
2224 //---------------------------------------------------------------------------
2225 //
2226 // PROC DrawSlider
2227 //
2228 //---------------------------------------------------------------------------
2229
2230 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2231 {
2232         int x;
2233         int y;
2234         int x2;
2235         int count;
2236
2237         x = menu->x+24;
2238         y = menu->y+2+(item*ITEM_HEIGHT);
2239
2240 #ifdef RENDER3D
2241     OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2242     for(x2 = x, count = width; count--; x2 += 8)
2243     {
2244         OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2245                           "M_SLDMD2") );
2246     }
2247     OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2248     OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2249 #else
2250         V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2251         for(x2 = x, count = width; count--; x2 += 8)
2252         {
2253                 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2254                         : "M_SLDMD2", PU_CACHE));
2255         }
2256         V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2257         V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));
2258 #endif
2259 }