]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/mn_menu.c
osezer patch 001
[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) || #defined(__FreeBSD__)
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 #ifdef ASSASSIN
1390                 case PCLASS_ASS:
1391                         SkillMenu.x = 116;
1392                         SkillItems[0].text = "KNAVE";
1393                         SkillItems[1].text = "ROUGE";
1394                         SkillItems[2].text = "CUTTHROAT";
1395                         SkillItems[3].text = "EXECUTIONER";
1396                         SkillItems[4].text = "WIDOW MAKER";
1397                         break;
1398 #endif
1399         }
1400         SetMenu(MENU_SKILL);
1401 }
1402
1403 //---------------------------------------------------------------------------
1404 //
1405 // PROC SCSkill
1406 //
1407 //---------------------------------------------------------------------------
1408
1409 static void SCSkill(int option)
1410 {
1411         extern int SB_state;
1412
1413         PlayerClass[consoleplayer] = MenuPClass;
1414         G_DeferredNewGame(option);
1415         SB_SetClassData();
1416         SB_state = -1;
1417         MN_DeactivateMenu();
1418 }
1419
1420 //---------------------------------------------------------------------------
1421 //
1422 // PROC SCMouseSensi
1423 //
1424 //---------------------------------------------------------------------------
1425
1426 static void SCMouseSensi(int option)
1427 {
1428         if(option == RIGHT_DIR)
1429         {
1430                 if(mouseSensitivity < MENU_MAX_MOUSE_SENS)
1431                 {
1432                         mouseSensitivity++;
1433                 }
1434         }
1435         else if(mouseSensitivity)
1436         {
1437                 mouseSensitivity--;
1438         }
1439 }
1440
1441 //---------------------------------------------------------------------------
1442 //
1443 // PROC SCSfxVolume
1444 //
1445 //---------------------------------------------------------------------------
1446
1447 static void SCSfxVolume(int option)
1448 {
1449         if(option == RIGHT_DIR)
1450         {
1451                 if(snd_MaxVolume < 15)
1452                 {
1453                         snd_MaxVolume++;
1454                 }
1455         }
1456         else if(snd_MaxVolume)
1457         {
1458                 snd_MaxVolume--;
1459         }
1460         soundchanged = true; // we'll set it when we leave the menu
1461 }
1462
1463 //---------------------------------------------------------------------------
1464 //
1465 // PROC SCMusicVolume
1466 //
1467 //---------------------------------------------------------------------------
1468
1469 static void SCMusicVolume(int option)
1470 {
1471         if(option == RIGHT_DIR)
1472         {
1473                 if(snd_MusicVolume < 15)
1474                 {
1475                         snd_MusicVolume++;
1476                 }
1477         }
1478         else if(snd_MusicVolume)
1479         {
1480                 snd_MusicVolume--;
1481         }
1482         S_SetMusicVolume();
1483 }
1484
1485 //---------------------------------------------------------------------------
1486 //
1487 // PROC SCScreenSize
1488 //
1489 //---------------------------------------------------------------------------
1490
1491 static void SCScreenSize(int option)
1492 {
1493         if(option == RIGHT_DIR)
1494         {
1495                 if(screenblocks < 11)
1496                 {
1497                         screenblocks++;
1498                 }
1499         }
1500         else if(screenblocks > 3)
1501         {
1502                 screenblocks--;
1503         }
1504         R_SetViewSize(screenblocks, detailLevel);
1505 }
1506
1507 //---------------------------------------------------------------------------
1508 //
1509 // PROC SCInfo
1510 //
1511 //---------------------------------------------------------------------------
1512
1513 static void SCInfo(int option)
1514 {
1515         InfoType = 1;
1516         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1517         if(!netgame && !demoplayback)
1518         {
1519                 paused = true;
1520         }
1521 }
1522
1523 //---------------------------------------------------------------------------
1524 //
1525 // PROC SCSetKey
1526 //
1527 //---------------------------------------------------------------------------
1528 static void SCSetKey(int option)
1529 {
1530         askforkey = true;
1531         keyaskedfor = option;
1532         if(!netgame && !demoplayback)
1533         {
1534                 paused = true;
1535         }
1536 }
1537
1538 //---------------------------------------------------------------------------
1539 //
1540 // PROC SCMouslook(int option)
1541 //
1542 //---------------------------------------------------------------------------
1543 static void SCMouselook(int option)
1544 {
1545         if(option == RIGHT_DIR)
1546         {
1547                 if(mouselook < 2) mouselook++;
1548                 
1549         }
1550         else if(mouselook) mouselook--;
1551 }
1552
1553 static void SCAlwaysRun(int option)
1554 {
1555         if(alwaysrun) alwaysrun=0;
1556         else alwaysrun=1;
1557 }
1558 static void SCCDAudio(int option)
1559 {
1560         if(cdaudio == true)
1561         {
1562                 cdaudio = false;
1563                 I_CDMusStop();
1564                 i_CDMusic = false;
1565         }
1566         else
1567         {
1568                 cdaudio = true;
1569                 ST_Message("Attempting to initialize CD Music: ");
1570                 if(!cdrom)
1571                 {
1572                         i_CDMusic = (I_CDMusInit() != -1);
1573                 }
1574                 else
1575                 { // The user is trying to use the cdrom for both game and music
1576                         i_CDMusic = false;
1577                 }
1578                 if(i_CDMusic)
1579                 {
1580                         ST_Message("initialized.\n");
1581                 }
1582                 else
1583                 {
1584                         ST_Message("failed.\n");
1585                 }
1586         }
1587 }
1588
1589 //---------------------------------------------------------------------------
1590 //
1591 // FUNC MN_Responder
1592 //
1593 //---------------------------------------------------------------------------
1594
1595 boolean MN_Responder(event_t *event)
1596 {
1597         int key;
1598         int i;
1599         MenuItem_t *item;
1600         extern boolean automapactive;
1601         static boolean shiftdown;
1602         extern void H2_StartTitle(void);
1603         extern void G_CheckDemoStatus(void);
1604         char *textBuffer;
1605
1606         if(askforkey && event->type == ev_keydown)
1607         {
1608                 ClearControls(event->data1);
1609                 *defaults[keyaskedfor+3+FirstKey].location = event->data1;
1610                 askforkey = false;
1611                 return(true);
1612         }
1613         if(askforkey && event->type == ev_mouse)
1614         {
1615                 if(event->data1&1)
1616                         mbone = defaults[keyaskedfor+3+FirstKey].location;
1617                 if(event->data1&2)
1618                         mbtwo = defaults[keyaskedfor+3+FirstKey].location;
1619                 if(event->data1&4)
1620                         mbthree = defaults[keyaskedfor+3+FirstKey].location;
1621                 else return(false);
1622                 return(true);
1623         }
1624         if(event->data1 == KEY_RSHIFT)
1625         {
1626                 shiftdown = (event->type == ev_keydown);
1627         }
1628         if(event->type != ev_keydown)
1629         {
1630                 return(false);
1631         }
1632         key = event->data1;
1633         if(InfoType)
1634         {
1635                 if(shareware)
1636                 {
1637                         InfoType = (InfoType+1)%5;
1638                 }
1639                 else
1640                 {
1641                         InfoType = (InfoType+1)%4;
1642                 }
1643                 if(key == KEY_ESCAPE)
1644                 {
1645                         InfoType = 0;
1646                 }
1647                 if(!InfoType)
1648                 {
1649                         if(!netgame && !demoplayback)
1650                         {
1651                                 paused = false;
1652                         }
1653                         MN_DeactivateMenu();
1654                         SB_state = -1; //refresh the statbar
1655                         BorderNeedRefresh = true;
1656                 }
1657                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1658                 return(true); //make the info screen eat the keypress
1659         }
1660
1661         if(ravpic && key == KEY_F1)
1662         {
1663                 G_ScreenShot();
1664                 return(true);
1665         }
1666
1667         if(askforquit)
1668         {
1669                 switch(key)
1670                 {
1671                         case 'y':
1672                                 if(askforquit)
1673                                 {
1674                                         switch(typeofask)
1675                                         {
1676                                                 case 1:
1677                                                         G_CheckDemoStatus(); 
1678                                                         I_Quit();
1679                                                         break;
1680                                                 case 2:
1681                                                         P_ClearMessage(&players[consoleplayer]);
1682                                                         typeofask = 0;
1683                                                         askforquit = false;
1684                                                         paused = false;
1685                                                         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1686                                                         H2_StartTitle(); // go to intro/demo mode.
1687                                                         break;
1688                                                 case 3:
1689                                                         P_SetMessage(&players[consoleplayer], 
1690                                                                 "QUICKSAVING....", false);
1691                                                         FileMenuKeySteal = true;
1692                                                         SCSaveGame(quicksave-1);
1693                                                         askforquit = false;
1694                                                         typeofask = 0;
1695                                                         BorderNeedRefresh = true;
1696                                                         return true;
1697                                                 case 4:
1698                                                         P_SetMessage(&players[consoleplayer], 
1699                                                                 "QUICKLOADING....", false);
1700                                                         SCLoadGame(quickload-1);
1701                                                         askforquit = false;
1702                                                         typeofask = 0;
1703                                                         BorderNeedRefresh = true;
1704                                                         return true;
1705                                                 case 5:
1706                                                         askforquit = false;
1707                                                         typeofask = 0;  
1708                                                         BorderNeedRefresh = true;
1709                                                         mn_SuicideConsole = true;
1710                                                         return true;
1711                                                         break;
1712                                                 default:
1713                                                         return true; // eat the 'y' keypress
1714                                         }
1715                                 }
1716                                 return false;
1717                         case 'n':
1718                         case KEY_ESCAPE:
1719                                 if(askforquit)
1720                                 {
1721                                         players[consoleplayer].messageTics = 0;
1722                                         askforquit = false;
1723                                         typeofask = 0;
1724                                         paused = false;
1725                                         UpdateState |= I_FULLSCRN;
1726                                         BorderNeedRefresh = true;
1727                                         return true;
1728                                 }
1729                                 return false;
1730                 }
1731                 return false; // don't let the keys filter thru
1732         }
1733         if(MenuActive == false && !chatmodeon)
1734         {
1735                 switch(key)
1736                 {
1737                         case KEY_MINUS:
1738                                 if(automapactive)
1739                                 { // Don't screen size in automap
1740                                         return(false);
1741                                 }
1742                                 SCScreenSize(LEFT_DIR);
1743                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1744                                 BorderNeedRefresh = true;
1745                                 UpdateState |= I_FULLSCRN;
1746                                 return(true);
1747                         case KEY_EQUALS:
1748                                 if(automapactive)
1749                                 { // Don't screen size in automap
1750                                         return(false);
1751                                 }
1752                                 SCScreenSize(RIGHT_DIR);
1753                                 S_StartSound(NULL, SFX_PICKUP_KEY);
1754                                 BorderNeedRefresh = true;
1755                                 UpdateState |= I_FULLSCRN;
1756                                 return(true);
1757 #ifdef __NeXT__
1758                         case 'q':
1759                                 MenuActive = false;
1760                                 askforquit = true;
1761                                 typeofask = 5; // suicide
1762                                 return true;
1763 #endif
1764 #ifndef __NeXT__
1765                         case KEY_F1: // help screen
1766                                 SCInfo(0); // start up info screens
1767                                 MenuActive = true;
1768                                 return(true);
1769                         case KEY_F2: // save game
1770                                 if(gamestate == GS_LEVEL && !demoplayback)
1771                                 {
1772                                         MenuActive = true;
1773                                         FileMenuKeySteal = false;
1774                                         MenuTime = 0;
1775                                         CurrentMenu = &SaveMenu;
1776                                         CurrentItPos = CurrentMenu->oldItPos;
1777                                         if(!netgame && !demoplayback)
1778                                         {
1779                                                 paused = true;
1780                                         }
1781                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1782                                         slottextloaded = false; //reload the slot text, when needed
1783                                 }
1784                                 return true;
1785                         case KEY_F3: // load game
1786                                 if(SCNetCheck(2))
1787                                 {
1788                                         MenuActive = true;
1789                                         FileMenuKeySteal = false;
1790                                         MenuTime = 0;
1791                                         CurrentMenu = &LoadMenu;
1792                                         CurrentItPos = CurrentMenu->oldItPos;
1793                                         if(!netgame && !demoplayback)
1794                                         {
1795                                                 paused = true;
1796                                         }
1797                                         S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1798                                         slottextloaded = false; //reload the slot text, when needed
1799                                 }
1800                                 return true;
1801                         case KEY_F4: // volume
1802                                 MenuActive = true;
1803                                 FileMenuKeySteal = false;
1804                                 MenuTime = 0;
1805                                 CurrentMenu = &Options2Menu;
1806                                 CurrentItPos = CurrentMenu->oldItPos;
1807                                 if(!netgame && !demoplayback)
1808                                 {
1809                                         paused = true;
1810                                 }
1811                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1812                                 slottextloaded = false; //reload the slot text, when needed
1813                                 return true;
1814                         case KEY_F5:
1815                                 MenuActive = false;
1816                                 askforquit = true;
1817                                 typeofask = 5; // suicide
1818                                 return true;
1819                         case KEY_F6: // quicksave
1820                                 if(gamestate == GS_LEVEL && !demoplayback)
1821                                 {
1822                                         if(!quicksave || quicksave == -1)
1823                                         {
1824                                                 MenuActive = true;
1825                                                 FileMenuKeySteal = false;
1826                                                 MenuTime = 0;
1827                                                 CurrentMenu = &SaveMenu;
1828                                                 CurrentItPos = CurrentMenu->oldItPos;
1829                                                 if(!netgame && !demoplayback)
1830                                                 {
1831                                                         paused = true;
1832                                                 }
1833                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1834                                                 slottextloaded = false; //reload the slot text
1835                                                 quicksave = -1;
1836                                                 P_SetMessage(&players[consoleplayer],
1837                                                         "CHOOSE A QUICKSAVE SLOT", true);
1838                                         }
1839                                         else
1840                                         {
1841                                                 askforquit = true;
1842                                                 typeofask = 3;
1843                                                 if(!netgame && !demoplayback)
1844                                                 {
1845                                                         paused = true;
1846                                                 }
1847                                                 S_StartSound(NULL, SFX_CHAT);
1848                                         }
1849                                 }
1850                                 return true;
1851                         case KEY_F7: // endgame
1852                                 if(SCNetCheck(3))
1853                                 {
1854                                         if(gamestate == GS_LEVEL && !demoplayback)
1855                                         {
1856                                                 S_StartSound(NULL, SFX_CHAT);
1857                                                 SCEndGame(0);
1858                                         }
1859                                 }
1860                                 return true;
1861                         case KEY_F8: // toggle messages
1862                                 SCMessages(0);
1863                                 return true;
1864                         case KEY_F9: // quickload
1865                                 if(SCNetCheck(2))
1866                                 {
1867                                         if(!quickload || quickload == -1)
1868                                         {
1869                                                 MenuActive = true;
1870                                                 FileMenuKeySteal = false;
1871                                                 MenuTime = 0;
1872                                                 CurrentMenu = &LoadMenu;
1873                                                 CurrentItPos = CurrentMenu->oldItPos;
1874                                                 if(!netgame && !demoplayback)
1875                                                 {
1876                                                         paused = true;
1877                                                 }
1878                                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
1879                                                 slottextloaded = false; // reload the slot text
1880                                                 quickload = -1;
1881                                                 P_SetMessage(&players[consoleplayer],
1882                                                         "CHOOSE A QUICKLOAD SLOT", true);
1883                                         }
1884                                         else
1885                                         {
1886                                                 askforquit = true;
1887                                                 if(!netgame && !demoplayback)
1888                                                 {
1889                                                         paused = true;
1890                                                 }
1891                                                 typeofask = 4;
1892                                                 S_StartSound(NULL, SFX_CHAT);
1893                                         }
1894                                 }
1895                                 return true;
1896                         case KEY_F10: // quit
1897                                 if(gamestate == GS_LEVEL || gamestate == GS_FINALE)
1898                                 {
1899                                         SCQuitGame(0);
1900                                         S_StartSound(NULL, SFX_CHAT);
1901                                 }
1902                                 return true;
1903                         case KEY_F11: // F11 - gamma mode correction
1904                                 usegamma++;
1905                                 if(usegamma > 4)
1906                                 {
1907                                         usegamma = 0;
1908                                 }
1909                                 SB_PaletteFlash(true); // force change
1910                                 P_SetMessage(&players[consoleplayer], GammaText[usegamma],
1911                                         false);
1912                                 return true;
1913                         case KEY_F12: // F12 - reload current map (devmaps mode)
1914                                 if(netgame || DevMaps == false)
1915                                 {
1916                                         return false;
1917                                 }
1918                                 if(gamekeydown[key_speed])
1919                                 { // Monsters ON
1920                                         nomonsters = false;
1921                                 }
1922                                 if(gamekeydown[key_strafe])
1923                                 { // Monsters OFF
1924                                         nomonsters = true;
1925                                 }
1926                                 G_DeferedInitNew(gameskill, gameepisode, gamemap);
1927                                 P_SetMessage(&players[consoleplayer], TXT_CHEATWARP,
1928                                         false);
1929                                 return true;
1930 #endif
1931                 }
1932
1933         }
1934
1935         if(MenuActive == false)
1936         {
1937                 if(key == KEY_ESCAPE || gamestate == GS_DEMOSCREEN || demoplayback)
1938                 {
1939                         MN_ActivateMenu();
1940                         return(true);
1941                 }
1942                 return(false);
1943         }
1944         if(!FileMenuKeySteal)
1945         {
1946                 item = &CurrentMenu->items[CurrentItPos];
1947                 switch(key)
1948                 {
1949                         case KEY_DOWNARROW:
1950                                 do
1951                                 {
1952 if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos+1 > CurrentMenu->itemCount-1)
1953         {
1954                 if(FirstKey == 5) 
1955                 {
1956                         CurrentItPos = 0;  //End of Key menu
1957                         FirstKey = 0;
1958                 }
1959                 else
1960                 {
1961                         FirstKey++;
1962                 }       
1963         }
1964         else if(CurrentItPos+1 > CurrentMenu->itemCount-1)
1965         {
1966                 CurrentItPos = 0;
1967         }
1968         else
1969         {
1970                 CurrentItPos++;
1971         }
1972 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
1973 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
1974 return(true);
1975 break;
1976 case KEY_UPARROW:
1977         do
1978         {
1979         if(CurrentMenu->items[CurrentItPos].type == ITT_SETKEY && CurrentItPos==0)
1980         {
1981                 if(FirstKey == 0) 
1982                 {
1983                         CurrentItPos = 14;  //End of Key menu
1984                         FirstKey = 5;
1985                 }
1986                 else
1987                 {
1988                         FirstKey--;
1989                 }       
1990         }
1991         else if(CurrentItPos == 0)
1992                                         {
1993                                                 CurrentItPos = CurrentMenu->itemCount-1;
1994                                         }
1995                                         else
1996                                         {
1997                                                 CurrentItPos--;
1998                                         }
1999                                 } while(CurrentMenu->items[CurrentItPos].type == ITT_EMPTY);
2000                                 S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL);
2001                                 return(true);
2002                                 break;
2003                         case KEY_LEFTARROW:
2004                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2005                                 {
2006                                         item->func(LEFT_DIR);
2007                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2008                                 }
2009                                 return(true);
2010                                 break;
2011                         case KEY_RIGHTARROW:
2012                                 if(item->type == ITT_LRFUNC && item->func != NULL)
2013                                 {
2014                                         item->func(RIGHT_DIR);
2015                                         S_StartSound(NULL, SFX_PICKUP_KEY);
2016                                 }
2017                                 return(true);
2018                                 break;
2019                         case KEY_ENTER:
2020                                 if(item->type == ITT_SETMENU)
2021                                 {
2022                                         if(item->func != NULL)  
2023                                         {
2024                                                 item->func(item->option);
2025                                         }
2026                                         SetMenu(item->menu);
2027                                 }
2028                                 else if(item->func != NULL)
2029                                 {
2030                                         CurrentMenu->oldItPos = CurrentItPos;
2031                                         if(item->type == ITT_LRFUNC)
2032                                         {
2033                                                 item->func(RIGHT_DIR);
2034                                         }
2035                                         else if(item->type == ITT_EFUNC)
2036                                         {
2037                                                 item->func(item->option);
2038                                         }
2039                                         else if(item->type == ITT_SETKEY)
2040                                         {
2041                                                 item->func(item->option);
2042                                         }
2043                                 }
2044                                 S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE);
2045                                 return(true);
2046                                 break;
2047                         case KEY_ESCAPE:
2048                                 MN_DeactivateMenu();
2049                                 return(true);
2050                         case KEY_BACKSPACE:
2051                                 S_StartSound(NULL, SFX_PICKUP_KEY);
2052                                 if(CurrentMenu->prevMenu == MENU_NONE)
2053                                 {
2054                                         MN_DeactivateMenu();
2055                                 }
2056                                 else
2057                                 {
2058                                         SetMenu(CurrentMenu->prevMenu);
2059                                 }
2060                                 return(true);
2061                         default:
2062                                 for(i = 0; i < CurrentMenu->itemCount; i++)
2063                                 {
2064                                         if(CurrentMenu->items[i].text)
2065                                         {
2066                                                 if(toupper(key)
2067                                                         == toupper(CurrentMenu->items[i].text[0]))
2068                                                 {
2069                                                         CurrentItPos = i;
2070                                                         return(true);
2071                                                 }
2072                                         }
2073                                 }
2074                                 break;
2075                 }
2076                 return(false);
2077         }
2078         else
2079         { // Editing file names
2080                 textBuffer = &SlotText[currentSlot][slotptr];
2081                 if(key == KEY_BACKSPACE)
2082                 {
2083                         if(slotptr)
2084                         {
2085                                 *textBuffer-- = 0;
2086                                 *textBuffer = ASCII_CURSOR;
2087                                 slotptr--;
2088                         }
2089                         return(true);
2090                 }
2091                 if(key == KEY_ESCAPE)
2092                 {
2093                         memset(SlotText[currentSlot], 0, SLOTTEXTLEN+2);
2094                         strcpy(SlotText[currentSlot], oldSlotText);
2095                         SlotStatus[currentSlot]--;
2096                         MN_DeactivateMenu();
2097                         return(true);
2098                 }
2099                 if(key == KEY_ENTER)
2100                 {
2101                         SlotText[currentSlot][slotptr] = 0; // clear the cursor
2102                         item = &CurrentMenu->items[CurrentItPos];
2103                         CurrentMenu->oldItPos = CurrentItPos;
2104                         if(item->type == ITT_EFUNC)
2105                         {
2106                                 item->func(item->option);
2107                                 if(item->menu != MENU_NONE)
2108                                 {
2109                                         SetMenu(item->menu);
2110                                 }
2111                         }
2112                         return(true);
2113                 }
2114                 if(slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE)
2115                 {
2116                         if((key >= 'a' && key <= 'z'))
2117                         {
2118                                 *textBuffer++ = key-32;
2119                                 *textBuffer = ASCII_CURSOR;
2120                                 slotptr++;
2121                                 return(true);
2122                         }
2123                         if(((key >= '0' && key <= '9') || key == ' '
2124                                 || key == ',' || key == '.' || key == '-')
2125                                 && !shiftdown)
2126                         {
2127                                 *textBuffer++ = key;
2128                                 *textBuffer = ASCII_CURSOR;
2129                                 slotptr++;
2130                                 return(true);
2131                         }
2132                         if(shiftdown && key == '1')
2133                         {
2134                                 *textBuffer++ = '!';
2135                                 *textBuffer = ASCII_CURSOR;
2136                                 slotptr++;
2137                                 return(true);
2138                         }
2139                 }
2140                 return(true);
2141         }
2142         return(false);
2143 }
2144
2145 //---------------------------------------------------------------------------
2146 //
2147 // PROC MN_ActivateMenu
2148 //
2149 //---------------------------------------------------------------------------
2150
2151 void MN_ActivateMenu(void)
2152 {
2153         if(MenuActive)
2154         {
2155                 return;
2156         }
2157         if(paused)
2158         {
2159                 S_ResumeSound();
2160         }
2161         MenuActive = true;
2162         FileMenuKeySteal = false;
2163         MenuTime = 0;
2164         CurrentMenu = &MainMenu;
2165         CurrentItPos = CurrentMenu->oldItPos;
2166         if(!netgame && !demoplayback)
2167         {
2168                 paused = true;
2169         }
2170         S_StartSound(NULL, SFX_PLATFORM_STOP);
2171         slottextloaded = false; //reload the slot text, when needed
2172 }
2173
2174 //---------------------------------------------------------------------------
2175 //
2176 // PROC MN_DeactivateMenu
2177 //
2178 //---------------------------------------------------------------------------
2179
2180 void MN_DeactivateMenu(void)
2181 {
2182         CurrentMenu->oldItPos = CurrentItPos;
2183         MenuActive = false;
2184         if(!netgame)
2185         {
2186                 paused = false;
2187         }
2188         S_StartSound(NULL, SFX_PLATFORM_STOP);
2189         P_ClearMessage(&players[consoleplayer]);
2190 }
2191
2192 //---------------------------------------------------------------------------
2193 //
2194 // PROC MN_DrawInfo
2195 //
2196 //---------------------------------------------------------------------------
2197
2198 void MN_DrawInfo(void)
2199 {
2200 #ifdef RENDER3D
2201     OGL_SetFilter( 0 );
2202     OGL_DrawRawScreen( W_GetNumForName("TITLE")+InfoType );
2203 #else
2204         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
2205         memcpy(screen, (byte *)W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2206                 PU_CACHE), SCREENWIDTH*SCREENHEIGHT);
2207 //      V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType,
2208 //              PU_CACHE));
2209 #endif
2210 }
2211
2212
2213 //---------------------------------------------------------------------------
2214 //
2215 // PROC SetMenu
2216 //
2217 //---------------------------------------------------------------------------
2218
2219 static void SetMenu(MenuType_t menu)
2220 {
2221         CurrentMenu->oldItPos = CurrentItPos;
2222         CurrentMenu = Menus[menu];
2223         CurrentItPos = CurrentMenu->oldItPos;
2224 }
2225
2226 //---------------------------------------------------------------------------
2227 //
2228 // PROC DrawSlider
2229 //
2230 //---------------------------------------------------------------------------
2231
2232 static void DrawSlider(Menu_t *menu, int item, int width, int slot)
2233 {
2234         int x;
2235         int y;
2236         int x2;
2237         int count;
2238
2239         x = menu->x+24;
2240         y = menu->y+2+(item*ITEM_HEIGHT);
2241
2242 #ifdef RENDER3D
2243     OGL_DrawPatch_CS(x-32, y, W_GetNumForName("M_SLDLT"));
2244     for(x2 = x, count = width; count--; x2 += 8)
2245     {
2246         OGL_DrawPatch_CS( x2, y, W_GetNumForName(count&1 ? "M_SLDMD1" :
2247                           "M_SLDMD2") );
2248     }
2249     OGL_DrawPatch_CS(x2, y, W_GetNumForName("M_SLDRT"));
2250     OGL_DrawPatch_CS(x+4+slot*8, y+7, W_GetNumForName("M_SLDKB"));
2251 #else
2252         V_DrawPatch(x-32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
2253         for(x2 = x, count = width; count--; x2 += 8)
2254         {
2255                 V_DrawPatch(x2, y, W_CacheLumpName(count&1 ? "M_SLDMD1"
2256                         : "M_SLDMD2", PU_CACHE));
2257         }
2258         V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
2259         V_DrawPatch(x+4+slot*8, y+7, W_CacheLumpName("M_SLDKB", PU_CACHE));
2260 #endif
2261 }
2262