summaryrefslogtreecommitdiff
path: root/src/strife/m_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/strife/m_menu.c')
-rw-r--r--src/strife/m_menu.c2039
1 files changed, 2039 insertions, 0 deletions
diff --git a/src/strife/m_menu.c b/src/strife/m_menu.c
new file mode 100644
index 00000000..a0d66dd4
--- /dev/null
+++ b/src/strife/m_menu.c
@@ -0,0 +1,2039 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// DOOM selection menu, options, episode etc.
+// Sliders and icons. Kinda widget stuff.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include <ctype.h>
+
+
+#include "doomdef.h"
+#include "doomkeys.h"
+#include "dstrings.h"
+
+#include "d_main.h"
+#include "deh_main.h"
+
+#include "i_swap.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "z_zone.h"
+#include "v_video.h"
+#include "w_wad.h"
+
+#include "r_local.h"
+
+
+#include "hu_stuff.h"
+
+#include "g_game.h"
+
+#include "m_argv.h"
+#include "m_controls.h"
+#include "p_saveg.h"
+
+#include "s_sound.h"
+
+#include "doomstat.h"
+
+// Data.
+#include "sounds.h"
+
+#include "m_menu.h"
+
+
+extern void M_QuitDOOM(int);
+
+extern patch_t* hu_font[HU_FONTSIZE];
+extern boolean message_dontfuckwithme;
+
+extern boolean chat_on; // in heads-up code
+
+//
+// defaulted values
+//
+int mouseSensitivity = 5;
+
+// Show messages has default, 0 = off, 1 = on
+int showMessages = 1;
+
+
+// Blocky mode, has default, 0 = high, 1 = normal
+int detailLevel = 0;
+int screenblocks = 9;
+
+// temp for screenblocks (0-9)
+int screenSize;
+
+// -1 = no quicksave slot picked!
+int quickSaveSlot;
+
+ // 1 = message to be printed
+int messageToPrint;
+// ...and here is the message string!
+char* messageString;
+
+// message x & y
+int messx;
+int messy;
+int messageLastMenuActive;
+
+// timed message = no input from user
+boolean messageNeedsInput;
+
+void (*messageRoutine)(int response);
+
+char gammamsg[5][26] =
+{
+ GAMMALVL0,
+ GAMMALVL1,
+ GAMMALVL2,
+ GAMMALVL3,
+ GAMMALVL4
+};
+
+// we are going to be entering a savegame string
+int saveStringEnter;
+int saveSlot; // which slot to save in
+int saveCharIndex; // which char we're editing
+// old save description before edit
+char saveOldString[SAVESTRINGSIZE];
+
+boolean inhelpscreens;
+boolean menuactive;
+
+#define SKULLXOFF -32
+#define LINEHEIGHT 16
+
+extern boolean sendpause;
+char savegamestrings[10][SAVESTRINGSIZE];
+
+char endstring[160];
+
+
+//
+// MENU TYPEDEFS
+//
+typedef struct
+{
+ // 0 = no cursor here, 1 = ok, 2 = arrows ok
+ short status;
+
+ char name[10];
+
+ // choice = menu item #.
+ // if status = 2,
+ // choice=0:leftarrow,1:rightarrow
+ void (*routine)(int choice);
+
+ // hotkey in menu
+ char alphaKey;
+} menuitem_t;
+
+
+
+typedef struct menu_s
+{
+ short numitems; // # of menu items
+ struct menu_s* prevMenu; // previous menu
+ menuitem_t* menuitems; // menu items
+ void (*routine)(); // draw routine
+ short x;
+ short y; // x,y of menu
+ short lastOn; // last item user was on in menu
+} menu_t;
+
+short itemOn; // menu item skull is on
+short skullAnimCounter; // skull animation counter
+short whichSkull; // which skull to draw
+
+// graphic name of skulls
+// warning: initializer-string for array of chars is too long
+char *skullName[2] = {"M_SKULL1","M_SKULL2"};
+
+// current menudef
+menu_t* currentMenu;
+
+//
+// PROTOTYPES
+//
+void M_NewGame(int choice);
+void M_Episode(int choice);
+void M_ChooseSkill(int choice);
+void M_LoadGame(int choice);
+void M_SaveGame(int choice);
+void M_Options(int choice);
+void M_EndGame(int choice);
+void M_ReadThis(int choice);
+void M_ReadThis2(int choice);
+void M_QuitDOOM(int choice);
+
+void M_ChangeMessages(int choice);
+void M_ChangeSensitivity(int choice);
+void M_SfxVol(int choice);
+void M_MusicVol(int choice);
+void M_ChangeDetail(int choice);
+void M_SizeDisplay(int choice);
+void M_StartGame(int choice);
+void M_Sound(int choice);
+
+void M_FinishReadThis(int choice);
+void M_LoadSelect(int choice);
+void M_SaveSelect(int choice);
+void M_ReadSaveStrings(void);
+void M_QuickSave(void);
+void M_QuickLoad(void);
+
+void M_DrawMainMenu(void);
+void M_DrawReadThis1(void);
+void M_DrawReadThis2(void);
+void M_DrawNewGame(void);
+void M_DrawEpisode(void);
+void M_DrawOptions(void);
+void M_DrawSound(void);
+void M_DrawLoad(void);
+void M_DrawSave(void);
+
+void M_DrawSaveLoadBorder(int x,int y);
+void M_SetupNextMenu(menu_t *menudef);
+void M_DrawThermo(int x,int y,int thermWidth,int thermDot);
+void M_DrawEmptyCell(menu_t *menu,int item);
+void M_DrawSelCell(menu_t *menu,int item);
+void M_WriteText(int x, int y, char *string);
+int M_StringWidth(char *string);
+int M_StringHeight(char *string);
+void M_StartControlPanel(void);
+void M_StartMessage(char *string,void *routine,boolean input);
+void M_StopMessage(void);
+void M_ClearMenus (void);
+
+
+
+
+//
+// DOOM MENU
+//
+enum
+{
+ newgame = 0,
+ options,
+ loadgame,
+ savegame,
+ readthis,
+ quitdoom,
+ main_end
+} main_e;
+
+menuitem_t MainMenu[]=
+{
+ {1,"M_NGAME",M_NewGame,'n'},
+ {1,"M_OPTION",M_Options,'o'},
+ {1,"M_LOADG",M_LoadGame,'l'},
+ {1,"M_SAVEG",M_SaveGame,'s'},
+ // Another hickup with Special edition.
+ {1,"M_RDTHIS",M_ReadThis,'r'},
+ {1,"M_QUITG",M_QuitDOOM,'q'}
+};
+
+menu_t MainDef =
+{
+ main_end,
+ NULL,
+ MainMenu,
+ M_DrawMainMenu,
+ 97,64,
+ 0
+};
+
+
+//
+// EPISODE SELECT
+//
+enum
+{
+ ep1,
+ ep2,
+ ep3,
+ ep4,
+ ep_end
+} episodes_e;
+
+menuitem_t EpisodeMenu[]=
+{
+ {1,"M_EPI1", M_Episode,'k'},
+ {1,"M_EPI2", M_Episode,'t'},
+ {1,"M_EPI3", M_Episode,'i'},
+ {1,"M_EPI4", M_Episode,'t'}
+};
+
+menu_t EpiDef =
+{
+ ep_end, // # of menu items
+ &MainDef, // previous menu
+ EpisodeMenu, // menuitem_t ->
+ M_DrawEpisode, // drawing routine ->
+ 48,63, // x,y
+ ep1 // lastOn
+};
+
+//
+// NEW GAME
+//
+enum
+{
+ killthings,
+ toorough,
+ hurtme,
+ violence,
+ nightmare,
+ newg_end
+} newgame_e;
+
+menuitem_t NewGameMenu[]=
+{
+ {1,"M_JKILL", M_ChooseSkill, 'i'},
+ {1,"M_ROUGH", M_ChooseSkill, 'h'},
+ {1,"M_HURT", M_ChooseSkill, 'h'},
+ {1,"M_ULTRA", M_ChooseSkill, 'u'},
+ {1,"M_NMARE", M_ChooseSkill, 'n'}
+};
+
+menu_t NewDef =
+{
+ newg_end, // # of menu items
+ &EpiDef, // previous menu
+ NewGameMenu, // menuitem_t ->
+ M_DrawNewGame, // drawing routine ->
+ 48,63, // x,y
+ hurtme // lastOn
+};
+
+
+
+//
+// OPTIONS MENU
+//
+enum
+{
+ endgame,
+ messages,
+ detail,
+ scrnsize,
+ option_empty1,
+ mousesens,
+ option_empty2,
+ soundvol,
+ opt_end
+} options_e;
+
+menuitem_t OptionsMenu[]=
+{
+ {1,"M_ENDGAM", M_EndGame,'e'},
+ {1,"M_MESSG", M_ChangeMessages,'m'},
+ {1,"M_DETAIL", M_ChangeDetail,'g'},
+ {2,"M_SCRNSZ", M_SizeDisplay,'s'},
+ {-1,"",0,'\0'},
+ {2,"M_MSENS", M_ChangeSensitivity,'m'},
+ {-1,"",0,'\0'},
+ {1,"M_SVOL", M_Sound,'s'}
+};
+
+menu_t OptionsDef =
+{
+ opt_end,
+ &MainDef,
+ OptionsMenu,
+ M_DrawOptions,
+ 60,37,
+ 0
+};
+
+//
+// Read This! MENU 1 & 2
+//
+enum
+{
+ rdthsempty1,
+ read1_end
+} read_e;
+
+menuitem_t ReadMenu1[] =
+{
+ {1,"",M_ReadThis2,0}
+};
+
+menu_t ReadDef1 =
+{
+ read1_end,
+ &MainDef,
+ ReadMenu1,
+ M_DrawReadThis1,
+ 280,185,
+ 0
+};
+
+enum
+{
+ rdthsempty2,
+ read2_end
+} read_e2;
+
+menuitem_t ReadMenu2[]=
+{
+ {1,"",M_FinishReadThis,0}
+};
+
+menu_t ReadDef2 =
+{
+ read2_end,
+ &ReadDef1,
+ ReadMenu2,
+ M_DrawReadThis2,
+ 330,175,
+ 0
+};
+
+//
+// SOUND VOLUME MENU
+//
+enum
+{
+ sfx_vol,
+ sfx_empty1,
+ music_vol,
+ sfx_empty2,
+ sound_end
+} sound_e;
+
+menuitem_t SoundMenu[]=
+{
+ {2,"M_SFXVOL",M_SfxVol,'s'},
+ {-1,"",0,'\0'},
+ {2,"M_MUSVOL",M_MusicVol,'m'},
+ {-1,"",0,'\0'}
+};
+
+menu_t SoundDef =
+{
+ sound_end,
+ &OptionsDef,
+ SoundMenu,
+ M_DrawSound,
+ 80,64,
+ 0
+};
+
+//
+// LOAD GAME MENU
+//
+enum
+{
+ load1,
+ load2,
+ load3,
+ load4,
+ load5,
+ load6,
+ load_end
+} load_e;
+
+menuitem_t LoadMenu[]=
+{
+ {1,"", M_LoadSelect,'1'},
+ {1,"", M_LoadSelect,'2'},
+ {1,"", M_LoadSelect,'3'},
+ {1,"", M_LoadSelect,'4'},
+ {1,"", M_LoadSelect,'5'},
+ {1,"", M_LoadSelect,'6'}
+};
+
+menu_t LoadDef =
+{
+ load_end,
+ &MainDef,
+ LoadMenu,
+ M_DrawLoad,
+ 80,54,
+ 0
+};
+
+//
+// SAVE GAME MENU
+//
+menuitem_t SaveMenu[]=
+{
+ {1,"", M_SaveSelect,'1'},
+ {1,"", M_SaveSelect,'2'},
+ {1,"", M_SaveSelect,'3'},
+ {1,"", M_SaveSelect,'4'},
+ {1,"", M_SaveSelect,'5'},
+ {1,"", M_SaveSelect,'6'}
+};
+
+menu_t SaveDef =
+{
+ load_end,
+ &MainDef,
+ SaveMenu,
+ M_DrawSave,
+ 80,54,
+ 0
+};
+
+
+//
+// M_ReadSaveStrings
+// read the strings from the savegame files
+//
+void M_ReadSaveStrings(void)
+{
+ FILE *handle;
+ int count;
+ int i;
+ char name[256];
+
+ for (i = 0;i < load_end;i++)
+ {
+ strcpy(name, P_SaveGameFile(i));
+
+ handle = fopen(name, "rb");
+ if (handle == NULL)
+ {
+ strcpy(&savegamestrings[i][0], EMPTYSTRING);
+ LoadMenu[i].status = 0;
+ continue;
+ }
+ count = fread(&savegamestrings[i], 1, SAVESTRINGSIZE, handle);
+ fclose(handle);
+ LoadMenu[i].status = 1;
+ }
+}
+
+
+//
+// M_LoadGame & Cie.
+//
+void M_DrawLoad(void)
+{
+ int i;
+
+ V_DrawPatchDirect(72, 28,
+ W_CacheLumpName(DEH_String("M_LOADG"), PU_CACHE));
+
+ for (i = 0;i < load_end; i++)
+ {
+ M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
+ M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
+ }
+}
+
+
+
+//
+// Draw border for the savegame description
+//
+void M_DrawSaveLoadBorder(int x,int y)
+{
+ int i;
+
+ V_DrawPatchDirect(x - 8, y + 7,
+ W_CacheLumpName(DEH_String("M_LSLEFT"), PU_CACHE));
+
+ for (i = 0;i < 24;i++)
+ {
+ V_DrawPatchDirect(x, y + 7,
+ W_CacheLumpName(DEH_String("M_LSCNTR"), PU_CACHE));
+ x += 8;
+ }
+
+ V_DrawPatchDirect(x, y + 7,
+ W_CacheLumpName(DEH_String("M_LSRGHT"), PU_CACHE));
+}
+
+
+
+//
+// User wants to load this game
+//
+void M_LoadSelect(int choice)
+{
+ char name[256];
+
+ strcpy(name, P_SaveGameFile(choice));
+
+ G_LoadGame (name);
+ M_ClearMenus ();
+}
+
+//
+// Selected from DOOM menu
+//
+void M_LoadGame (int choice)
+{
+ if (netgame)
+ {
+ M_StartMessage(DEH_String(LOADNET),NULL,false);
+ return;
+ }
+
+ M_SetupNextMenu(&LoadDef);
+ M_ReadSaveStrings();
+}
+
+
+//
+// M_SaveGame & Cie.
+//
+void M_DrawSave(void)
+{
+ int i;
+
+ V_DrawPatchDirect(72, 28, W_CacheLumpName(DEH_String("M_SAVEG"), PU_CACHE));
+ for (i = 0;i < load_end; i++)
+ {
+ M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i);
+ M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]);
+ }
+
+ if (saveStringEnter)
+ {
+ i = M_StringWidth(savegamestrings[saveSlot]);
+ M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_");
+ }
+}
+
+//
+// M_Responder calls this when user is finished
+//
+void M_DoSave(int slot)
+{
+ G_SaveGame (slot,savegamestrings[slot]);
+ M_ClearMenus ();
+
+ // PICK QUICKSAVE SLOT YET?
+ if (quickSaveSlot == -2)
+ quickSaveSlot = slot;
+}
+
+//
+// User wants to save. Start string input for M_Responder
+//
+void M_SaveSelect(int choice)
+{
+ // we are going to be intercepting all chars
+ saveStringEnter = 1;
+
+ saveSlot = choice;
+ strcpy(saveOldString,savegamestrings[choice]);
+ if (!strcmp(savegamestrings[choice],EMPTYSTRING))
+ savegamestrings[choice][0] = 0;
+ saveCharIndex = strlen(savegamestrings[choice]);
+}
+
+//
+// Selected from DOOM menu
+//
+void M_SaveGame (int choice)
+{
+ if (!usergame)
+ {
+ M_StartMessage(DEH_String(SAVEDEAD),NULL,false);
+ return;
+ }
+
+ if (gamestate != GS_LEVEL)
+ return;
+
+ M_SetupNextMenu(&SaveDef);
+ M_ReadSaveStrings();
+}
+
+
+
+//
+// M_QuickSave
+//
+char tempstring[80];
+
+void M_QuickSaveResponse(int key)
+{
+ if (key == key_menu_confirm)
+ {
+ M_DoSave(quickSaveSlot);
+ S_StartSound(NULL,sfx_swtchx);
+ }
+}
+
+void M_QuickSave(void)
+{
+ if (!usergame)
+ {
+ S_StartSound(NULL,sfx_oof);
+ return;
+ }
+
+ if (gamestate != GS_LEVEL)
+ return;
+
+ if (quickSaveSlot < 0)
+ {
+ M_StartControlPanel();
+ M_ReadSaveStrings();
+ M_SetupNextMenu(&SaveDef);
+ quickSaveSlot = -2; // means to pick a slot now
+ return;
+ }
+ sprintf(tempstring,DEH_String(QSPROMPT),savegamestrings[quickSaveSlot]);
+ M_StartMessage(tempstring,M_QuickSaveResponse,true);
+}
+
+
+
+//
+// M_QuickLoad
+//
+void M_QuickLoadResponse(int key)
+{
+ if (key == key_menu_confirm)
+ {
+ M_LoadSelect(quickSaveSlot);
+ S_StartSound(NULL,sfx_swtchx);
+ }
+}
+
+
+void M_QuickLoad(void)
+{
+ if (netgame)
+ {
+ M_StartMessage(DEH_String(QLOADNET),NULL,false);
+ return;
+ }
+
+ if (quickSaveSlot < 0)
+ {
+ M_StartMessage(DEH_String(QSAVESPOT),NULL,false);
+ return;
+ }
+ sprintf(tempstring,DEH_String(QLPROMPT),savegamestrings[quickSaveSlot]);
+ M_StartMessage(tempstring,M_QuickLoadResponse,true);
+}
+
+
+
+
+//
+// Read This Menus
+// Had a "quick hack to fix romero bug"
+//
+void M_DrawReadThis1(void)
+{
+ char *lumpname = "CREDIT";
+ int skullx = 330, skully = 175;
+
+ inhelpscreens = true;
+
+ // Different versions of Doom 1.9 work differently
+
+ switch (gameversion)
+ {
+ case exe_doom_1_9:
+ if (gamemode == commercial)
+ {
+ // Doom 2
+
+ lumpname = "HELP";
+
+ skullx = 330;
+ skully = 165;
+ }
+ else
+ {
+ // Doom 1
+ // HELP2 is the first screen shown in Doom 1
+
+ lumpname = "HELP2";
+
+ skullx = 280;
+ skully = 185;
+ }
+ break;
+
+ case exe_ultimate:
+ case exe_chex:
+
+ // Ultimate Doom always displays "HELP1".
+
+ // Chex Quest version also uses "HELP1", even though it is based
+ // on Final Doom.
+
+ lumpname = "HELP1";
+
+ break;
+
+ case exe_final:
+
+ // Final Doom always displays "HELP".
+
+ lumpname = "HELP";
+
+ break;
+
+ default:
+ I_Error("Unhandled game version");
+ break;
+ }
+
+ lumpname = DEH_String(lumpname);
+
+ V_DrawPatchDirect (0, 0, W_CacheLumpName(lumpname, PU_CACHE));
+
+ ReadDef1.x = skullx;
+ ReadDef1.y = skully;
+}
+
+
+
+//
+// Read This Menus - optional second page.
+//
+void M_DrawReadThis2(void)
+{
+ inhelpscreens = true;
+
+ // We only ever draw the second page if this is
+ // gameversion == exe_doom_1_9 and gamemode == registered
+
+ V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE));
+}
+
+
+//
+// Change Sfx & Music volumes
+//
+void M_DrawSound(void)
+{
+ V_DrawPatchDirect (60, 38, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE));
+
+ M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1),
+ 16,sfxVolume);
+
+ M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1),
+ 16,musicVolume);
+}
+
+void M_Sound(int choice)
+{
+ M_SetupNextMenu(&SoundDef);
+}
+
+void M_SfxVol(int choice)
+{
+ switch(choice)
+ {
+ case 0:
+ if (sfxVolume)
+ sfxVolume--;
+ break;
+ case 1:
+ if (sfxVolume < 15)
+ sfxVolume++;
+ break;
+ }
+
+ S_SetSfxVolume(sfxVolume * 8);
+}
+
+void M_MusicVol(int choice)
+{
+ switch(choice)
+ {
+ case 0:
+ if (musicVolume)
+ musicVolume--;
+ break;
+ case 1:
+ if (musicVolume < 15)
+ musicVolume++;
+ break;
+ }
+
+ S_SetMusicVolume(musicVolume * 8);
+}
+
+
+
+
+//
+// M_DrawMainMenu
+//
+void M_DrawMainMenu(void)
+{
+ V_DrawPatchDirect(94, 2,
+ W_CacheLumpName(DEH_String("M_DOOM"), PU_CACHE));
+}
+
+
+
+
+//
+// M_NewGame
+//
+void M_DrawNewGame(void)
+{
+ V_DrawPatchDirect(96, 14, W_CacheLumpName(DEH_String("M_NEWG"), PU_CACHE));
+ V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_SKILL"), PU_CACHE));
+}
+
+void M_NewGame(int choice)
+{
+ if (netgame && !demoplayback)
+ {
+ M_StartMessage(DEH_String(NEWGAME),NULL,false);
+ return;
+ }
+
+ // Chex Quest disabled the episode select screen, as did Doom II.
+
+ if (gamemode == commercial || gameversion == exe_chex)
+ M_SetupNextMenu(&NewDef);
+ else
+ M_SetupNextMenu(&EpiDef);
+}
+
+
+//
+// M_Episode
+//
+int epi;
+
+void M_DrawEpisode(void)
+{
+ V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE));
+}
+
+void M_VerifyNightmare(int key)
+{
+ if (key != key_menu_confirm)
+ return;
+
+ G_DeferedInitNew(nightmare,epi+1,1);
+ M_ClearMenus ();
+}
+
+void M_ChooseSkill(int choice)
+{
+ if (choice == nightmare)
+ {
+ M_StartMessage(DEH_String(NIGHTMARE),M_VerifyNightmare,true);
+ return;
+ }
+
+ G_DeferedInitNew(choice,epi+1,1);
+ M_ClearMenus ();
+}
+
+void M_Episode(int choice)
+{
+ if ( (gamemode == shareware)
+ && choice)
+ {
+ M_StartMessage(DEH_String(SWSTRING),NULL,false);
+ M_SetupNextMenu(&ReadDef1);
+ return;
+ }
+
+ // Yet another hack...
+ if ( (gamemode == registered)
+ && (choice > 2))
+ {
+ fprintf( stderr,
+ "M_Episode: 4th episode requires UltimateDOOM\n");
+ choice = 0;
+ }
+
+ epi = choice;
+ M_SetupNextMenu(&NewDef);
+}
+
+
+
+//
+// M_Options
+//
+char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"};
+char msgNames[2][9] = {"M_MSGOFF","M_MSGON"};
+
+
+void M_DrawOptions(void)
+{
+ V_DrawPatchDirect(108, 15, W_CacheLumpName(DEH_String("M_OPTTTL"),
+ PU_CACHE));
+
+ V_DrawPatchDirect(OptionsDef.x + 175, OptionsDef.y + LINEHEIGHT * detail,
+ W_CacheLumpName(DEH_String(detailNames[detailLevel]),
+ PU_CACHE));
+
+ V_DrawPatchDirect(OptionsDef.x + 120, OptionsDef.y + LINEHEIGHT * messages,
+ W_CacheLumpName(DEH_String(msgNames[showMessages]),
+ PU_CACHE));
+
+ M_DrawThermo(OptionsDef.x, OptionsDef.y + LINEHEIGHT * (mousesens + 1),
+ 10, mouseSensitivity);
+
+ M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1),
+ 9,screenSize);
+}
+
+void M_Options(int choice)
+{
+ M_SetupNextMenu(&OptionsDef);
+}
+
+
+
+//
+// Toggle messages on/off
+//
+void M_ChangeMessages(int choice)
+{
+ // warning: unused parameter `int choice'
+ choice = 0;
+ showMessages = 1 - showMessages;
+
+ if (!showMessages)
+ players[consoleplayer].message = DEH_String(MSGOFF);
+ else
+ players[consoleplayer].message = DEH_String(MSGON);
+
+ message_dontfuckwithme = true;
+}
+
+
+//
+// M_EndGame
+//
+void M_EndGameResponse(int key)
+{
+ if (key != key_menu_confirm)
+ return;
+
+ currentMenu->lastOn = itemOn;
+ M_ClearMenus ();
+ D_StartTitle ();
+}
+
+void M_EndGame(int choice)
+{
+ choice = 0;
+ if (!usergame)
+ {
+ S_StartSound(NULL,sfx_oof);
+ return;
+ }
+
+ if (netgame)
+ {
+ M_StartMessage(DEH_String(NETEND),NULL,false);
+ return;
+ }
+
+ M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true);
+}
+
+
+
+
+//
+// M_ReadThis
+//
+void M_ReadThis(int choice)
+{
+ choice = 0;
+ M_SetupNextMenu(&ReadDef1);
+}
+
+void M_ReadThis2(int choice)
+{
+ // Doom 1.9 had two menus when playing Doom 1
+ // All others had only one
+
+ if (gameversion == exe_doom_1_9 && gamemode != commercial)
+ {
+ choice = 0;
+ M_SetupNextMenu(&ReadDef2);
+ }
+ else
+ {
+ // Close the menu
+
+ M_FinishReadThis(0);
+ }
+}
+
+void M_FinishReadThis(int choice)
+{
+ choice = 0;
+ M_SetupNextMenu(&MainDef);
+}
+
+
+
+
+//
+// M_QuitDOOM
+//
+int quitsounds[8] =
+{
+ sfx_pldeth,
+ sfx_dmpain,
+ sfx_popain,
+ sfx_slop,
+ sfx_telept,
+ sfx_posit1,
+ sfx_posit3,
+ sfx_sgtatk
+};
+
+int quitsounds2[8] =
+{
+ sfx_vilact,
+ sfx_getpow,
+ sfx_boscub,
+ sfx_slop,
+ sfx_skeswg,
+ sfx_kntdth,
+ sfx_bspact,
+ sfx_sgtatk
+};
+
+
+
+void M_QuitResponse(int key)
+{
+ if (key != key_menu_confirm)
+ return;
+ if (!netgame)
+ {
+ if (gamemode == commercial)
+ S_StartSound(NULL,quitsounds2[(gametic>>2)&7]);
+ else
+ S_StartSound(NULL,quitsounds[(gametic>>2)&7]);
+ I_WaitVBL(105);
+ }
+ I_Quit ();
+}
+
+
+static char *M_SelectEndMessage(void)
+{
+ char **endmsg;
+
+ if (gamemission == doom)
+ {
+ // Doom 1
+
+ endmsg = doom1_endmsg;
+ }
+ else
+ {
+ // Doom 2
+
+ endmsg = doom2_endmsg;
+ }
+
+ return endmsg[gametic % NUM_QUITMESSAGES];
+}
+
+
+void M_QuitDOOM(int choice)
+{
+ sprintf(endstring,
+ DEH_String("%s\n\n" DOSY),
+ DEH_String(M_SelectEndMessage()));
+
+ M_StartMessage(endstring,M_QuitResponse,true);
+}
+
+
+
+
+void M_ChangeSensitivity(int choice)
+{
+ switch(choice)
+ {
+ case 0:
+ if (mouseSensitivity)
+ mouseSensitivity--;
+ break;
+ case 1:
+ if (mouseSensitivity < 9)
+ mouseSensitivity++;
+ break;
+ }
+}
+
+
+
+
+void M_ChangeDetail(int choice)
+{
+ choice = 0;
+ detailLevel = 1 - detailLevel;
+
+ R_SetViewSize (screenblocks, detailLevel);
+
+ if (!detailLevel)
+ players[consoleplayer].message = DEH_String(DETAILHI);
+ else
+ players[consoleplayer].message = DEH_String(DETAILLO);
+}
+
+
+
+
+void M_SizeDisplay(int choice)
+{
+ switch(choice)
+ {
+ case 0:
+ if (screenSize > 0)
+ {
+ screenblocks--;
+ screenSize--;
+ }
+ break;
+ case 1:
+ if (screenSize < 8)
+ {
+ screenblocks++;
+ screenSize++;
+ }
+ break;
+ }
+
+
+ R_SetViewSize (screenblocks, detailLevel);
+}
+
+
+
+
+//
+// Menu Functions
+//
+void
+M_DrawThermo
+( int x,
+ int y,
+ int thermWidth,
+ int thermDot )
+{
+ int xx;
+ int i;
+
+ xx = x;
+ V_DrawPatchDirect(xx, y, W_CacheLumpName(DEH_String("M_THERML"), PU_CACHE));
+ xx += 8;
+ for (i=0;i<thermWidth;i++)
+ {
+ V_DrawPatchDirect(xx, y, W_CacheLumpName(DEH_String("M_THERMM"), PU_CACHE));
+ xx += 8;
+ }
+ V_DrawPatchDirect(xx, y, W_CacheLumpName(DEH_String("M_THERMR"), PU_CACHE));
+
+ V_DrawPatchDirect((x + 8) + thermDot * 8, y,
+ W_CacheLumpName(DEH_String("M_THERMO"), PU_CACHE));
+}
+
+
+
+void
+M_DrawEmptyCell
+( menu_t* menu,
+ int item )
+{
+ V_DrawPatchDirect(menu->x - 10, menu->y + item * LINEHEIGHT - 1,
+ W_CacheLumpName(DEH_String("M_CELL1"), PU_CACHE));
+}
+
+void
+M_DrawSelCell
+( menu_t* menu,
+ int item )
+{
+ V_DrawPatchDirect(menu->x - 10, menu->y + item * LINEHEIGHT - 1,
+ W_CacheLumpName(DEH_String("M_CELL2"), PU_CACHE));
+}
+
+
+void
+M_StartMessage
+( char* string,
+ void* routine,
+ boolean input )
+{
+ messageLastMenuActive = menuactive;
+ messageToPrint = 1;
+ messageString = string;
+ messageRoutine = routine;
+ messageNeedsInput = input;
+ menuactive = true;
+ return;
+}
+
+
+
+void M_StopMessage(void)
+{
+ menuactive = messageLastMenuActive;
+ messageToPrint = 0;
+}
+
+
+
+//
+// Find string width from hu_font chars
+//
+int M_StringWidth(char* string)
+{
+ size_t i;
+ int w = 0;
+ int c;
+
+ for (i = 0;i < strlen(string);i++)
+ {
+ c = toupper(string[i]) - HU_FONTSTART;
+ if (c < 0 || c >= HU_FONTSIZE)
+ w += 4;
+ else
+ w += SHORT (hu_font[c]->width);
+ }
+
+ return w;
+}
+
+
+
+//
+// Find string height from hu_font chars
+//
+int M_StringHeight(char* string)
+{
+ size_t i;
+ int h;
+ int height = SHORT(hu_font[0]->height);
+
+ h = height;
+ for (i = 0;i < strlen(string);i++)
+ if (string[i] == '\n')
+ h += height;
+
+ return h;
+}
+
+
+//
+// Write a string using the hu_font
+//
+void
+M_WriteText
+( int x,
+ int y,
+ char* string)
+{
+ int w;
+ char* ch;
+ int c;
+ int cx;
+ int cy;
+
+
+ ch = string;
+ cx = x;
+ cy = y;
+
+ while(1)
+ {
+ c = *ch++;
+ if (!c)
+ break;
+ if (c == '\n')
+ {
+ cx = x;
+ cy += 12;
+ continue;
+ }
+
+ c = toupper(c) - HU_FONTSTART;
+ if (c < 0 || c>= HU_FONTSIZE)
+ {
+ cx += 4;
+ continue;
+ }
+
+ w = SHORT (hu_font[c]->width);
+ if (cx+w > SCREENWIDTH)
+ break;
+ V_DrawPatchDirect(cx, cy, hu_font[c]);
+ cx+=w;
+ }
+}
+
+
+
+//
+// CONTROL PANEL
+//
+
+//
+// M_Responder
+//
+boolean M_Responder (event_t* ev)
+{
+ int ch;
+ int key;
+ int i;
+ static int joywait = 0;
+ static int mousewait = 0;
+ static int mousey = 0;
+ static int lasty = 0;
+ static int mousex = 0;
+ static int lastx = 0;
+
+ // "close" button pressed on window?
+ if (ev->type == ev_quit)
+ {
+ S_StartSound(NULL,sfx_swtchn);
+ M_QuitDOOM(0);
+ return true;
+ }
+
+ // key is the key pressed, ch is the actual character typed
+
+ ch = 0;
+ key = -1;
+
+ if (ev->type == ev_joystick && joywait < I_GetTime())
+ {
+ if (ev->data3 == -1)
+ {
+ key = key_menu_up;
+ joywait = I_GetTime() + 5;
+ }
+ else if (ev->data3 == 1)
+ {
+ key = key_menu_down;
+ joywait = I_GetTime() + 5;
+ }
+
+ if (ev->data2 == -1)
+ {
+ key = key_menu_left;
+ joywait = I_GetTime() + 2;
+ }
+ else if (ev->data2 == 1)
+ {
+ key = key_menu_right;
+ joywait = I_GetTime() + 2;
+ }
+
+ if (ev->data1&1)
+ {
+ key = key_menu_forward;
+ joywait = I_GetTime() + 5;
+ }
+ if (ev->data1&2)
+ {
+ key = key_menu_back;
+ joywait = I_GetTime() + 5;
+ }
+ }
+ else
+ {
+ if (ev->type == ev_mouse && mousewait < I_GetTime())
+ {
+ mousey += ev->data3;
+ if (mousey < lasty-30)
+ {
+ key = key_menu_down;
+ mousewait = I_GetTime() + 5;
+ mousey = lasty -= 30;
+ }
+ else if (mousey > lasty+30)
+ {
+ key = key_menu_up;
+ mousewait = I_GetTime() + 5;
+ mousey = lasty += 30;
+ }
+
+ mousex += ev->data2;
+ if (mousex < lastx-30)
+ {
+ key = key_menu_left;
+ mousewait = I_GetTime() + 5;
+ mousex = lastx -= 30;
+ }
+ else if (mousex > lastx+30)
+ {
+ key = key_menu_right;
+ mousewait = I_GetTime() + 5;
+ mousex = lastx += 30;
+ }
+
+ if (ev->data1&1)
+ {
+ key = key_menu_forward;
+ mousewait = I_GetTime() + 15;
+ }
+
+ if (ev->data1&2)
+ {
+ key = key_menu_back;
+ mousewait = I_GetTime() + 15;
+ }
+ }
+ else
+ {
+ if (ev->type == ev_keydown)
+ {
+ key = ev->data1;
+ ch = ev->data2;
+ }
+ }
+ }
+
+ if (key == -1)
+ return false;
+
+ // In testcontrols mode, none of the function keys should do anything
+ // - the only key is escape to quit.
+
+ if (testcontrols)
+ {
+ if (key == key_menu_activate || key == key_menu_quit)
+ {
+ I_Quit();
+ return true;
+ }
+
+ return false;
+ }
+
+ // Save Game string input
+ if (saveStringEnter)
+ {
+ switch(key)
+ {
+ case KEY_BACKSPACE:
+ if (saveCharIndex > 0)
+ {
+ saveCharIndex--;
+ savegamestrings[saveSlot][saveCharIndex] = 0;
+ }
+ break;
+
+ case KEY_ESCAPE:
+ saveStringEnter = 0;
+ strcpy(&savegamestrings[saveSlot][0],saveOldString);
+ break;
+
+ case KEY_ENTER:
+ saveStringEnter = 0;
+ if (savegamestrings[saveSlot][0])
+ M_DoSave(saveSlot);
+ break;
+
+ default:
+ // Entering a character - use the 'ch' value, not the key
+
+ ch = toupper(ch);
+
+ if (ch != ' '
+ && (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE))
+ {
+ break;
+ }
+
+ if (ch >= 32 && ch <= 127 &&
+ saveCharIndex < SAVESTRINGSIZE-1 &&
+ M_StringWidth(savegamestrings[saveSlot]) <
+ (SAVESTRINGSIZE-2)*8)
+ {
+ savegamestrings[saveSlot][saveCharIndex++] = ch;
+ savegamestrings[saveSlot][saveCharIndex] = 0;
+ }
+ break;
+ }
+ return true;
+ }
+
+ // Take care of any messages that need input
+ if (messageToPrint)
+ {
+ if (messageNeedsInput)
+ {
+ if (key != ' ' && key != KEY_ESCAPE
+ && key != key_menu_confirm && key != key_menu_abort)
+ {
+ return false;
+ }
+ }
+
+ menuactive = messageLastMenuActive;
+ messageToPrint = 0;
+ if (messageRoutine)
+ messageRoutine(key);
+
+ menuactive = false;
+ S_StartSound(NULL,sfx_swtchx);
+ return true;
+ }
+
+ if (devparm && key == key_menu_help)
+ {
+ G_ScreenShot ();
+ return true;
+ }
+
+ // F-Keys
+ if (!menuactive)
+ {
+ if (key == key_menu_decscreen) // Screen size down
+ {
+ if (automapactive || chat_on)
+ return false;
+ M_SizeDisplay(0);
+ S_StartSound(NULL,sfx_stnmov);
+ return true;
+ }
+ else if (key == key_menu_incscreen) // Screen size up
+ {
+ if (automapactive || chat_on)
+ return false;
+ M_SizeDisplay(1);
+ S_StartSound(NULL,sfx_stnmov);
+ return true;
+ }
+ else if (key == key_menu_help) // Help key
+ {
+ M_StartControlPanel ();
+
+ if ( gamemode == retail )
+ currentMenu = &ReadDef2;
+ else
+ currentMenu = &ReadDef1;
+
+ itemOn = 0;
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ else if (key == key_menu_save) // Save
+ {
+ M_StartControlPanel();
+ S_StartSound(NULL,sfx_swtchn);
+ M_SaveGame(0);
+ return true;
+ }
+ else if (key == key_menu_load) // Load
+ {
+ M_StartControlPanel();
+ S_StartSound(NULL,sfx_swtchn);
+ M_LoadGame(0);
+ return true;
+ }
+ else if (key == key_menu_volume) // Sound Volume
+ {
+ M_StartControlPanel ();
+ currentMenu = &SoundDef;
+ itemOn = sfx_vol;
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ else if (key == key_menu_detail) // Detail toggle
+ {
+ M_ChangeDetail(0);
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ else if (key == key_menu_qsave) // Quicksave
+ {
+ S_StartSound(NULL,sfx_swtchn);
+ M_QuickSave();
+ return true;
+ }
+ else if (key == key_menu_endgame) // End game
+ {
+ S_StartSound(NULL,sfx_swtchn);
+ M_EndGame(0);
+ return true;
+ }
+ else if (key == key_menu_messages) // Toggle messages
+ {
+ M_ChangeMessages(0);
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ else if (key == key_menu_qload) // Quickload
+ {
+ S_StartSound(NULL,sfx_swtchn);
+ M_QuickLoad();
+ return true;
+ }
+ else if (key == key_menu_quit) // Quit DOOM
+ {
+ S_StartSound(NULL,sfx_swtchn);
+ M_QuitDOOM(0);
+ return true;
+ }
+ else if (key == key_menu_gamma) // gamma toggle
+ {
+ usegamma++;
+ if (usegamma > 4)
+ usegamma = 0;
+ players[consoleplayer].message = DEH_String(gammamsg[usegamma]);
+ I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
+ return true;
+ }
+ }
+
+ // Pop-up menu?
+ if (!menuactive)
+ {
+ if (key == key_menu_activate)
+ {
+ M_StartControlPanel ();
+ S_StartSound(NULL,sfx_swtchn);
+ return true;
+ }
+ return false;
+ }
+
+
+ // Keys usable within menu
+
+ if (key == key_menu_down)
+ {
+ // Move down to next item
+
+ do
+ {
+ if (itemOn+1 > currentMenu->numitems-1)
+ itemOn = 0;
+ else itemOn++;
+ S_StartSound(NULL,sfx_pstop);
+ } while(currentMenu->menuitems[itemOn].status==-1);
+
+ return true;
+ }
+ else if (key == key_menu_up)
+ {
+ // Move back up to previous item
+
+ do
+ {
+ if (!itemOn)
+ itemOn = currentMenu->numitems-1;
+ else itemOn--;
+ S_StartSound(NULL,sfx_pstop);
+ } while(currentMenu->menuitems[itemOn].status==-1);
+
+ return true;
+ }
+ else if (key == key_menu_left)
+ {
+ // Slide slider left
+
+ if (currentMenu->menuitems[itemOn].routine &&
+ currentMenu->menuitems[itemOn].status == 2)
+ {
+ S_StartSound(NULL,sfx_stnmov);
+ currentMenu->menuitems[itemOn].routine(0);
+ }
+ return true;
+ }
+ else if (key == key_menu_right)
+ {
+ // Slide slider right
+
+ if (currentMenu->menuitems[itemOn].routine &&
+ currentMenu->menuitems[itemOn].status == 2)
+ {
+ S_StartSound(NULL,sfx_stnmov);
+ currentMenu->menuitems[itemOn].routine(1);
+ }
+ return true;
+ }
+ else if (key == key_menu_forward)
+ {
+ // Activate menu item
+
+ if (currentMenu->menuitems[itemOn].routine &&
+ currentMenu->menuitems[itemOn].status)
+ {
+ currentMenu->lastOn = itemOn;
+ if (currentMenu->menuitems[itemOn].status == 2)
+ {
+ currentMenu->menuitems[itemOn].routine(1); // right arrow
+ S_StartSound(NULL,sfx_stnmov);
+ }
+ else
+ {
+ currentMenu->menuitems[itemOn].routine(itemOn);
+ S_StartSound(NULL,sfx_pistol);
+ }
+ }
+ return true;
+ }
+ else if (key == key_menu_activate)
+ {
+ // Deactivate menu
+
+ currentMenu->lastOn = itemOn;
+ M_ClearMenus ();
+ S_StartSound(NULL,sfx_swtchx);
+ return true;
+ }
+ else if (key == key_menu_back)
+ {
+ // Go back to previous menu
+
+ currentMenu->lastOn = itemOn;
+ if (currentMenu->prevMenu)
+ {
+ currentMenu = currentMenu->prevMenu;
+ itemOn = currentMenu->lastOn;
+ S_StartSound(NULL,sfx_swtchn);
+ }
+ return true;
+ }
+ else if (ch != 0)
+ {
+ // Keyboard shortcut?
+
+ for (i = itemOn+1;i < currentMenu->numitems;i++)
+ {
+ if (currentMenu->menuitems[i].alphaKey == ch)
+ {
+ itemOn = i;
+ S_StartSound(NULL,sfx_pstop);
+ return true;
+ }
+ }
+
+ for (i = 0;i <= itemOn;i++)
+ {
+ if (currentMenu->menuitems[i].alphaKey == ch)
+ {
+ itemOn = i;
+ S_StartSound(NULL,sfx_pstop);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+//
+// M_StartControlPanel
+//
+void M_StartControlPanel (void)
+{
+ // intro might call this repeatedly
+ if (menuactive)
+ return;
+
+ menuactive = 1;
+ currentMenu = &MainDef; // JDC
+ itemOn = currentMenu->lastOn; // JDC
+}
+
+
+//
+// M_Drawer
+// Called after the view has been rendered,
+// but before it has been blitted.
+//
+void M_Drawer (void)
+{
+ static short x;
+ static short y;
+ unsigned int i;
+ unsigned int max;
+ char string[80];
+ char *name;
+ int start;
+
+ inhelpscreens = false;
+
+ // Horiz. & Vertically center string and print it.
+ if (messageToPrint)
+ {
+ start = 0;
+ y = 100 - M_StringHeight(messageString) / 2;
+ while (messageString[start] != '\0')
+ {
+ int foundnewline = 0;
+
+ for (i = 0; i < strlen(messageString + start); i++)
+ if (messageString[start + i] == '\n')
+ {
+ memset(string, 0, sizeof(string));
+ strncpy(string, messageString + start, i);
+ foundnewline = 1;
+ start += i + 1;
+ break;
+ }
+
+ if (!foundnewline)
+ {
+ strcpy(string, messageString + start);
+ start += strlen(string);
+ }
+
+ x = 160 - M_StringWidth(string) / 2;
+ M_WriteText(x, y, string);
+ y += SHORT(hu_font[0]->height);
+ }
+
+ return;
+ }
+
+ if (!menuactive)
+ return;
+
+ if (currentMenu->routine)
+ currentMenu->routine(); // call Draw routine
+
+ // DRAW MENU
+ x = currentMenu->x;
+ y = currentMenu->y;
+ max = currentMenu->numitems;
+
+ for (i=0;i<max;i++)
+ {
+ name = DEH_String(currentMenu->menuitems[i].name);
+
+ if (name[0])
+ {
+ V_DrawPatchDirect (x, y, W_CacheLumpName(name, PU_CACHE));
+ }
+ y += LINEHEIGHT;
+ }
+
+
+ // DRAW SKULL
+ V_DrawPatchDirect(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,
+ W_CacheLumpName(DEH_String(skullName[whichSkull]),
+ PU_CACHE));
+
+}
+
+
+//
+// M_ClearMenus
+//
+void M_ClearMenus (void)
+{
+ menuactive = 0;
+ // if (!netgame && usergame && paused)
+ // sendpause = true;
+}
+
+
+
+
+//
+// M_SetupNextMenu
+//
+void M_SetupNextMenu(menu_t *menudef)
+{
+ currentMenu = menudef;
+ itemOn = currentMenu->lastOn;
+}
+
+
+//
+// M_Ticker
+//
+void M_Ticker (void)
+{
+ if (--skullAnimCounter <= 0)
+ {
+ whichSkull ^= 1;
+ skullAnimCounter = 8;
+ }
+}
+
+
+//
+// M_Init
+//
+void M_Init (void)
+{
+ currentMenu = &MainDef;
+ menuactive = 0;
+ itemOn = currentMenu->lastOn;
+ whichSkull = 0;
+ skullAnimCounter = 10;
+ screenSize = screenblocks - 3;
+ messageToPrint = 0;
+ messageString = NULL;
+ messageLastMenuActive = menuactive;
+ quickSaveSlot = -1;
+
+ // Here we could catch other version dependencies,
+ // like HELP1/2, and four episodes.
+
+
+ switch ( gamemode )
+ {
+ case commercial:
+ // Commercial has no "read this" entry.
+ MainMenu[readthis] = MainMenu[quitdoom];
+ MainDef.numitems--;
+ MainDef.y += 8;
+ NewDef.prevMenu = &MainDef;
+ break;
+ case shareware:
+ // Episode 2 and 3 are handled,
+ // branching to an ad screen.
+ case registered:
+ // We need to remove the fourth episode.
+ EpiDef.numitems--;
+ break;
+ case retail:
+ // We are fine.
+ default:
+ break;
+ }
+
+}
+