shithub: rott

ref: 69f062a7028f072a24712cf3034f208677cd7079
dir: /src/rt_menu.c/

View raw version
/*
Copyright (C) 1994-1995  Apogee Software, Ltd.
Copyright (C) 2002-2015  icculus.org, GNU/Linux port
Copyright (C) 2017-2018  Steven LeVesque

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.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
//******************************************************************************
//
// RT_MENU.C
//    Contains the menu stuff!
//
//******************************************************************************


#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>

#include <unistd.h>
#include "SDL2/SDL.h"

#include <sys/types.h>
#include <sys/stat.h>

#include "rt_def.h"
#include "_rt_menu.h"
#include "rt_menu.h"
#include "rt_sound.h"
#include "fx_man.h"
#include "rt_build.h"
#include "rt_in.h"
#include "isr.h"
#include "z_zone.h"
#include "w_wad.h"
#include "rt_util.h"
#include "rt_main.h"
#include "rt_playr.h"
#include "rt_rand.h"
#include "rt_game.h"
#include "rt_floor.h"
#include "rt_draw.h"
#include "rt_view.h"
#include "rt_str.h"
#include "rt_vid.h"
#include "rt_ted.h"
#include "rt_com.h"
#include "lumpy.h"
#include "rt_cfg.h"
#include "version.h"
#include "modexlib.h"
#include "rt_msg.h"
#include "rt_net.h"
#include "rt_scale.h"

#include "rt_battl.h"
#include "develop.h"


//******************************************************************************
//
// GLOBALS
//
//******************************************************************************

#define DELAYAMT  2

#define SNDCARDS  12

#define CP_NO     0
#define CP_ESC    -1
#define CP_YES    1

int CP_Acknowledge;

boolean POK = false;
char    pword[ 13 ];

boolean ingame    = false;
boolean inmenu    = false;
boolean pickquick = false;
boolean NewGame   = false;

//
// Global window coords
//
int PrintX;
int PrintY;
int WindowX;
int WindowY;
int WindowH = 160;
int WindowW;

int px;
int py;
int bufferheight;
int bufferwidth;

extern SDL_Window *window;

cfont_t *IFont;
font_t  *CurrentFont;
font_t  *newfont1;
font_t  *smallfont;
font_t  *bigfont;
font_t  *tinyfont;

boolean loadedgame = false;

battle_type BATTLE_Options[ battle_NumBattleModes ];

int quicksaveslot=-1;

//******************************************************************************
//
// LOCALS
//
//******************************************************************************

char order[ 21 ] = {
    di_west, di_east, di_north, di_south, bt_run, bt_use, bt_attack,
    bt_strafe, bt_strafeleft, bt_straferight, bt_lookup, bt_lookdown,
    bt_aimbutton, bt_horizonup, bt_horizondown, bt_swapweapon, bt_dropweapon,
    bt_turnaround, bt_autorun, bt_message, bt_directmsg
};

// bt_pistol, bt_dualpistol, bt_mp40, bt_missileweapon, bt_recordsound,

#define RETURNVAL    100

static boolean loadsavesound = false;
static int numdone;

static char *endStrings[ 7 ] =
{
    "Press Y to reformat \nand install Windows.\0\0",
    "Press Y to activate \nguillotine.\0\0",
    "Press Y to release \nthe cyanide gas.\0\0",
    "Press Y to open \ntrap door.\0\0",
    "Press Y to drive your \ncar off the cliff.\0\0",
    "Press Y to pull \nyour plug.\0\0",
    "Press Y to activate \nelectric chair.\0\0"
};

static char *BattleModeDescriptions[ battle_NumBattleModes - 1 ] =
{
    "Kill your enemies!  Don't get killed!  Kill some more!",
    "Score more points for more difficult kills.",
    "Collect the most triads to win the game.  Whoopee!",
    "Collect triads to win the game--this time with weapons!",
    "Armed hunters vs. unarmed prey--then the tables are turned!",
    "Tag your enemies.  Run away.  Lowest points wins.",
    "Chase roving 'Eluders'--tag them for points.",
    "Use weapons to destroy roving Eluder triads for points.",
    "Capture the opposing team's triad while guarding your own."
};

static char *BattleOptionDescriptions[ 9 ] =
{
    "Adjust the Gravitational Constant of the game universe!",
    "Adjust the top speed for all players in the game",
    "Adjust the amount of ammo in all missile weapons",
    "Adjust the hit points of all players in the game",
    "Radically change the way the game plays",
    "Adjust the light characteristics of the game",
    "Adjust the point goal of the game",
    "Adjust the damage done by environment dangers",
    "Adjust the time limit for the game"
};

static char *GravityOptionDescriptions[ 3 ] =
{
    "Similar to gravity on the moon",
    "Normal Gravity (9.81 m/s^2 !)",
    "Similar to gravity on Jupiter"
};

static char *SpeedOptionDescriptions[ 2 ] =
{
    "Player speeds are determined by character",
    "All players can move at the fastest possible speed"
};

static char *AmmoOptionDescriptions[ 3 ] =
{
    "One piece of ammo per missile weapon",
    "Normal ammo for all missile weapons",
    "Infinite ammo for all missile weapons"
};

static char *HitPointsOptionDescriptions[ 7 ] =
{
    "One hit point for each player",
    "25 hit points for each player",
    "Hit points determined by character",
    "100 hit points for each player",
    "250 hit points for each player (default)",
    "500 hit points for each player",
    "4000 hit points for each player",
};

static char *RadicalOptionDescriptions[ 8 ] =
{
    "Control spawning of environment dangers",
    "Control spawning of health items",
    "Control spawning of missile weapons",
    "Spawn mines instead of health items",
    "Objects reappear a short time after being picked up",
    "Missile weapons remain when picked up",
    "Weapons are chosen randomly at the start of the game",
    "Killing yourself or a team member counts as a suicide"
};

static char *LightLevelOptionDescriptions[ 6 ] =
{
    "Very dark, cave-like",
    "Lighting determined by level design",
    "Full brightness",
    "Bright with fog",
    "Periodic lighting (voobing)",
    "Dark with lightning"
};

static char *PointGoalOptionDescriptions[ 9 ] =
{
    "One Point/Kill",
    "5 Points/Kills",
    "11 Points/Kills",
    "21 Points/Kills",
    "50 Points/Kills",
    "100 Points/Kills",
    "Random Points/Kills",
    "Random Points/Kills but goal is not revealed",
    "Infinite Points/Kills"
};

static char *DangerDamageOptionDescriptions[ 3 ] =
{
    "Environmental dangers' damage is relatively low",
    "Environmental dangers' damage normal",
    "One touch and you are dead!"
};

static char *TimeLimitOptionDescriptions[ 8 ] =
{
    "One Minute",
    "2 Minutes",
    "5 Minutes",
    "10 Minutes",
    "21 Minutes",
    "30 Minutes",
    "99 Minutes",
    "No Time Limit"
};


static char *BattleModeNames[ battle_NumBattleModes - 1 ] =
{
    "NORMAL COMM-BAT", "SCORE MORE", "COLLECTOR", "SCAVENGER",
    "HUNTER", "TAG", "ELUDER", "DELUDER", "CAPTURE THE TRIAD"
};

static int OptionNums[ 12 ] =
{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};

static int HitPointNums[ 7 ] =
{
    1, 25, bo_character_hitpoints, 100, 250, 500, 4000
};

static int KillNums[ 9 ] =
{
    1, 5, 11, 21, 50, 100, bo_kills_random,
    bo_kills_blind, bo_kills_infinite
};

static int GravityNums[ 3 ] =
{
    LOW_GRAVITY, NORMAL_GRAVITY, HIGH_GRAVITY
};

static int TimeLimitNums[ 8 ] =
{
    1, 2, 5, 10, 21, 30, 99, bo_time_infinite
};

static int DangerNums[ 3 ] =
{
    bo_danger_low, bo_danger_normal, bo_danger_kill
};

static int MenuNum = 0;
static int handlewhich;
static int CSTactive = 0;
static boolean INFXSETUP = false;

//
// MENU CURSOR SHAPES
//

#define MAXCURSORNUM 24

static int cursorwidth;
static int cursorheight;
static int yinc;

static char *FontNames[] = { "itnyfont", "ifnt", "sifont", "lifont" };
static int   FontSize[]  = { 6, 7, 9, 14 };
static char *SmallCursor = "smallc01";
static char *LargeCursor = "cursor01";
static char *CursorLump  = "cursor01";
static int CursorNum = 0;
static int CursorFrame[ MAXCURSORNUM ] =
{
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3,
    4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1
};

typedef enum
{
    MOUSEENABLE,
    JOYENABLE,
    USEPORT2,
    PADENABLE,
    THRESSENS,
    MOUSESENS,
    CUSTOMIZE
} controltypes;


static char *playerwadname[] =
{
    "cass1", "bars1", "wens1", "lnis1", "ipfs1"
};

char *colorname[] =
{
    "Gray", "Brown", "Black", "Tan", "Red", "Olive",
    "Blue", "White", "Green", "Purple", "Orange"
};

//
// MENU ITEMS
//
CP_MenuNames MainMenuNames[] =
{
    "NEW GAME",
    "COMM-BAT� GAME",
    "RESTORE GAME",
    "SAVE GAME",
    "OPTIONS",
    "ORDERING INFO",
    "VIEW SCORES", //"END GAME"
    "BACK TO DEMO", //"BACK TO GAME"
    "QUIT"
};

CP_iteminfo MainItems  = { MENU_X, MENU_Y + 1, 9, STARTITEM, 32, MainMenuNames, mn_largefont };
CP_itemtype MainMenu[] =
{
    { CP_CursorLocation, "mm_opt1\0",  'N', (menuptr)CP_NewGame },
    { CP_Active,         "battle\0",   'C', (menuptr)CP_BattleModes },
    { CP_Active,         "mm_opt2\0",  'R', (menuptr)CP_LoadGame },
    { CP_Inactive,       "mm_opt3\0",  'S', (menuptr)CP_SaveGame },
    { CP_Active,         "mm_opt5\0",  'O', (menuptr)CP_ControlMenu },
    { CP_Active,         "ordrinfo\0", 'O', (menuptr)CP_OrderInfo },
    { CP_Active,         "mm_opt7\0",  'V', (menuptr)CP_ViewScores },
    { CP_Active,         "mm_opt8\0",  'B', (menuptr)NULL },
    { CP_Active,         "mm_opt9\0",  'Q', (menuptr)CP_Quit }
};


CP_iteminfo LSItems  = { LSM_X, LSM_Y, NUMSAVEGAMES, 0, 10, NULL, mn_largefont };
CP_itemtype LSMenu[] =
{
    { CP_Active, "", 'a', NULL },
    { CP_Active, "", 'b', NULL },
    { CP_Active, "", 'c', NULL },
    { CP_Active, "", 'd', NULL },
    { CP_Active, "", 'e', NULL },
    { CP_Active, "", 'f', NULL },
    { CP_Active, "", 'g', NULL },
    { CP_Active, "", 'h', NULL },
    { CP_Active, "", 'i', NULL },
    { CP_Active, "", 'j', NULL },
    { CP_Active, "", 'k', NULL },
    { CP_Active, "", 'l', NULL },
    { CP_Active, "", 'm', NULL },
    { CP_Active, "", 'n', NULL },
    { CP_Active, "", 'o', NULL }
};

CP_MenuNames CtlMenuNames[] =
{
    "MOUSE ENABLED",
    "JOYSTICK ENABLED",
    "USE JOYSTICK PORT 2",
    "GAMEPAD ENABLED",
    "ADJUST THRESHOLD",
    "MOUSE SENSITIVITY",
    "CUSTOMIZE CONTROLS"
};

CP_iteminfo CtlItems  = { CTL_X, MENU_Y, 7, -1, 36, CtlMenuNames, mn_largefont };
CP_itemtype CtlMenu[] =
{
    { CP_Inactive, "ctl_mic\0", 'M', NULL },
    { CP_Inactive, "ctl_jen\0", 'J', NULL },
    { CP_Inactive, "ctl_jp2\0", 'U', NULL },
    { CP_Inactive, "ctl_gpd\0", 'G', NULL },
    { CP_Inactive, "ctl_thr\0", 'A', (menuptr)DoThreshold },
    { CP_Inactive, "ctl_mse\0", 'M', (menuptr)MouseSensitivity },
    { CP_Active,   "ctl_cus\0", 'C', (menuptr)CP_Custom }
};

CP_iteminfo CusItems  = { 32, CST_Y + 13 * 2, 9, -1, 0, NULL, mn_largefont };
CP_itemtype CusMenu[] =
{
    { CP_Active,   "ctl_mic\0", 'a', NULL },
    { CP_Inactive, "ctl_mic\0", 'a', NULL },
    { CP_Inactive, "ctl_mic\0", 'a', NULL },
    { CP_Active,   "ctl_mic\0", 'a', NULL },
    { CP_Inactive, "ctl_mic\0", 'a', NULL },
    { CP_Inactive, "ctl_mic\0", 'a', NULL },
    { CP_Active,   "ctl_mic\0", 'a', NULL },
    { CP_Inactive, "ctl_mic\0", 'a', NULL },
    { CP_Active,   "ctl_mic\0", 'a', NULL }
};


CP_iteminfo TufItems = { TUF_X, TUF_Y, 7, 0, 80, NULL, mn_largefont };
CP_itemtype TufMenu[ 4 ][ 7 ] =
{
    {
        { 2, "new11\0", 'a', NULL },
        { 3, "new11\0", 'a', NULL },
        { 1, "new12\0", 'a', NULL },
        { 3, "new12\0", 'a', NULL },
        { 1, "new13\0", 'a', NULL },
        { 3, "new13\0", 'a', NULL },
        { 1, "new14\0", 'a', NULL },
    },

    {
        { 2, "new21\0", 'a', NULL },
        { 3, "new21\0", 'a', NULL },
        { 1, "new22\0", 'a', NULL },
        { 3, "new22\0", 'a', NULL },
        { 1, "new23\0", 'a', NULL },
        { 3, "new23\0", 'a', NULL },
        { 1, "new24\0", 'a', NULL },
    },

    {
        { 2, "new31\0", 'a', NULL },
        { 3, "new31\0", 'a', NULL },
        { 1, "new32\0", 'a', NULL },
        { 3, "new32\0", 'a', NULL },
        { 1, "new33\0", 'a', NULL },
        { 3, "new33\0", 'a', NULL },
        { 1, "new34\0", 'a', NULL },
    },

    {
        { 2, "stk_1\0", 'a', NULL },
        { 3, "stk_1\0", 'a', NULL },
        { 1, "stk_2\0", 'a', NULL },
        { 3, "stk_2\0", 'a', NULL },
        { 1, "stk_3\0", 'a', NULL },
        { 3, "stk_3\0", 'a', NULL },
        { 1, "stk_4\0", 'a', NULL },
    }
};

CP_MenuNames CustomMenuNames[] =
{
    "CUSTOMIZE KEYBOARD",
    "CUSTOMIZE MOUSE",
    "CUSTOMIZE JOYSTICK"
};

CP_iteminfo CustomItems = {32, 64, 3, 0, 24, CustomMenuNames, mn_largefont };

CP_itemtype CustomMenu[] =
{
    {2, "custom1\0", 'C', (menuptr)CP_Keyboard},
    {1, "custom2\0", 'C', (menuptr)CP_Mouse},
    {1, "custom3\0", 'C', (menuptr)CP_Joystick}
};

#define KEYNAMEINDEX 21

CP_MenuNames NormalKeyNames[] =
{
    "LEFT               \x9      ",
    "RIGHT              \x9      ",
    "FORWARD            \x9      ",
    "BACKWARD           \x9      ",
    "RUN                \x9      ",
    "OPEN               \x9      ",
    "FIRE               \x9      ",
    "STRAFE             \x9      ",
    "STRAFE LEFT        \x9      ",
    "STRAFE RIGHT       \x9      ",
    "LOOK/FLY UP        \x9      ",
    "LOOK/FLY DOWN      \x9      ",
    "AIM                \x9      ",
    "AIM UP             \x9      ",
    "AIM DOWN           \x9      ",
    "TOGGLE WEAPON      \x9      ",
    "DROP WEAPON        \x9      ",
    "VOLTE-FACE         \x9      ",
    "AUTORUN            \x9      ",
    "SEND MESSAGE       \x9      ",
    "DIRECT MESSAGE     \x9      "
};

#define NORMALKEY_X  74
#define NORMALKEY_Y  16
CP_iteminfo NormalKeyItems = { NORMALKEY_X, 17, 21, 0, 16, NormalKeyNames, mn_tinyfont };

CP_itemtype NormalKeyMenu[] =
{
    { 2, "\0", 'L', (menuptr)DefineKey },
    { 1, "\0", 'R', (menuptr)DefineKey },
    { 1, "\0", 'F', (menuptr)DefineKey },
    { 1, "\0", 'B', (menuptr)DefineKey },
    { 1, "\0", 'R', (menuptr)DefineKey },
    { 1, "\0", 'O', (menuptr)DefineKey },
    { 1, "\0", 'F', (menuptr)DefineKey },
    { 1, "\0", 'S', (menuptr)DefineKey },
    { 1, "\0", 'S', (menuptr)DefineKey },
    { 1, "\0", 'S', (menuptr)DefineKey },
    { 1, "\0", 'L', (menuptr)DefineKey },
    { 1, "\0", 'L', (menuptr)DefineKey },
    { 1, "\0", 'A', (menuptr)DefineKey },
    { 1, "\0", 'A', (menuptr)DefineKey },
    { 1, "\0", 'T', (menuptr)DefineKey },
    { 1, "\0", 'D', (menuptr)DefineKey },
    { 1, "\0", 'V', (menuptr)DefineKey },
    { 1, "\0", 'A', (menuptr)DefineKey },
    { 1, "\0", 'A', (menuptr)DefineKey },
    { 1, "\0", 'S', (menuptr)DefineKey },
    { 1, "\0", 'D', (menuptr)DefineKey }
};

#define NUMCONTROLNAMES 21

CP_MenuNames ControlNames[] =
{
    "NONE",
    "LEFT",
    "RIGHT",
    "FORWARD",
    "BACKWARD",
    "RUN",
    "OPEN",
    "FIRE",
    "STRAFE",
    "STRAFE LEFT",
    "STRAFE RIGHT",
    "LOOK/FLY UP",
    "LOOK/FLY DOWN",
    "AIM",
    "AIM UP",
    "AIM DOWN",
    "TOGGLE WEAPON",
    "DROP WEAPON",
    "VOLTE-FACE",
    "AUTORUN",
    "MAP"
};

int controlorder[ NUMCONTROLNAMES ] = {
    bt_nobutton, di_west, di_east, di_north, di_south, bt_run, bt_use,
    bt_attack, bt_strafe, bt_strafeleft, bt_straferight, bt_lookup,
    bt_lookdown, bt_aimbutton, bt_horizonup, bt_horizondown,
    bt_swapweapon, bt_dropweapon, bt_turnaround, bt_autorun, bt_map
};

#define CONTROLSELECT_X  106
CP_iteminfo ControlSelectItems = { CONTROLSELECT_X, 17, NUMCONTROLNAMES, 0, 16, ControlNames, mn_tinyfont };

CP_itemtype ControlSelectMenu[] =
{
    { 2, "\0", 'N', NULL },
    { 1, "\0", 'L', NULL },
    { 1, "\0", 'R', NULL },
    { 1, "\0", 'F', NULL },
    { 1, "\0", 'B', NULL },
    { 1, "\0", 'R', NULL },
    { 1, "\0", 'O', NULL },
    { 1, "\0", 'F', NULL },
    { 1, "\0", 'S', NULL },
    { 1, "\0", 'S', NULL },
    { 1, "\0", 'S', NULL },
    { 1, "\0", 'L', NULL },
    { 1, "\0", 'L', NULL },
    { 1, "\0", 'A', NULL },
    { 1, "\0", 'A', NULL },
    { 1, "\0", 'A', NULL },
    { 1, "\0", 'T', NULL },
    { 1, "\0", 'D', NULL },
    { 1, "\0", 'V', NULL },
    { 1, "\0", 'A', NULL },
    { 1, "\0", 'M', NULL }
};

#define MOUSEBTNINDEX 17

CP_MenuNames MouseBtnNames[] =
{
    "             B0  \x9             ",
    "             B1  \x9             ",
    "             B2  \x9             ",
    "DOUBLE-CLICK B0  \x9             ",
    "DOUBLE-CLICK B1  \x9             ",
    "DOUBLE-CLICK B2  \x9             "
};

CP_iteminfo MouseBtnItems = { 19, 52, 6, 0, 11, MouseBtnNames, mn_8x8font };

CP_itemtype MouseBtnMenu[] =
{
    { 2, "\0", 'B', (menuptr)DefineMouseBtn },
    { 1, "\0", 'B', (menuptr)DefineMouseBtn },
    { 1, "\0", 'B', (menuptr)DefineMouseBtn },
    { 1, "\0", 'D', (menuptr)DefineMouseBtn },
    { 1, "\0", 'D', (menuptr)DefineMouseBtn },
    { 1, "\0", 'D', (menuptr)DefineMouseBtn }
};


#define JOYBTNINDEX 17

CP_MenuNames JoyBtnNames[] =
{
    "             B0  \x9             ",
    "             B1  \x9             ",
    "             B2  \x9             ",
    "             B3  \x9             ",
    "DOUBLE-CLICK B0  \x9             ",
    "DOUBLE-CLICK B1  \x9             ",
    "DOUBLE-CLICK B2  \x9             ",
    "DOUBLE-CLICK B3  \x9             "
};

CP_iteminfo JoyBtnItems = { 19, 48, 8, 0, 11, JoyBtnNames, mn_8x8font };

CP_itemtype JoyBtnMenu[] =
{
    { 2, "\0", 'B', (menuptr)DefineJoyBtn },
    { 1, "\0", 'B', (menuptr)DefineJoyBtn },
    { 1, "\0", 'B', (menuptr)DefineJoyBtn },
    { 1, "\0", 'B', (menuptr)DefineJoyBtn },
    { 1, "\0", 'D', (menuptr)DefineJoyBtn },
    { 1, "\0", 'D', (menuptr)DefineJoyBtn },
    { 1, "\0", 'D', (menuptr)DefineJoyBtn },
    { 1, "\0", 'D', (menuptr)DefineJoyBtn }
};

CP_MenuNames PlayerMenuNames[] =
{
    "TARADINO CASSATT",
    "THI BARRETT",
    "DOUG WENDT",
    "LORELEI NI",
    "IAN PAUL FREELEY"
};

CP_iteminfo PlayerItems = {TUF_X, 48, 5, 0, 80, PlayerMenuNames, mn_largefont };

CP_itemtype PlayerMenu[] =
{
    {2, "name1\0", 'T', NULL},
    {1, "name2\0", 'T', NULL},
    {1, "name3\0", 'D', NULL},
    {1, "name4\0", 'L', NULL},
    {1, "name5\0", 'I', NULL},
};

CP_MenuNames ControlMMenuNames[] =
{
    "VISUAL OPTIONS",
    "CONTROLS",
    "USER OPTIONS",
    "EXT USER OPTIONS",//bna added
    "EXT GAME OPTIONS", //added by LT
    "MUSIC VOLUME",
    "SOUND FX VOLUME"

};
CP_iteminfo ControlMItems = {32, 48-8, 7, 0, 32, ControlMMenuNames, mn_largefont };//bna added
//CP_iteminfo ControlMItems = {32, 48, 4, 0, 32, ControlMMenuNames, mn_largefont };
void CP_VisualsMenu(void);
CP_itemtype ControlMMenu[] =
{
    {1, "adjfwid\0", 'W', (menuptr)CP_VisualsMenu},
    {2, "cntl\0",     'C', (menuptr)CP_Control},
    {1, "uopt\0",     'U', (menuptr)CP_OptionsMenu},
    {1, "euopt\0", 'E', (menuptr)CP_ExtOptionsMenu},//bna added
    {1, "eaopt\0", 'A', (menuptr)CP_ExtGameOptionsMenu},
    {1, "muvolumn\0", 'M', (menuptr)MusicVolume},
    {1, "fxvolumn\0", 'S', (menuptr)FXVolume}
};

CP_MenuNames OptionsNames[] =
{
    "AUTO DETAIL ADJUST",
    "LIGHT DIMINISHING",
    "BOBBIN'",
    "FLOOR AND CEILING",
    "DOUBLE-CLICK SPEED",
    "MENU FLIP SPEED",
    "DETAIL LEVELS",
    "VIOLENCE LEVEL",
    "SCREEN SIZE"
};
//bna added
CP_MenuNames ExtOptionsNames[] =
{
    "MOUSELOOK",
    "INVERSE MOUSE",
    "ALLOW Y AXIS MOUSE",
    "CROSS HAIR",
    "JUMPING",
    "AUTOAIM MISSILE WEPS",
    "ENABLE AUTOAIM"
};

CP_MenuNames ExtGameOptionsNames[] =
{
    "BLITZ RANDOM WEPS",
    "ENABLE AMMO PICKUP",
    "EXTRA PISTOL DROPS",
    "ENABLE ZOMROTT"
}; //LT added

CP_MenuNames VisualOptionsNames[] = 
{
    "SCREEN RESOLUTION",
    "ADJUST FOCAL WIDTH",
    "HUD SCALING",
    "DISPLAY OPTIONS"
};

typedef struct
{
    int width;
    int height;
    char *extraMenuText;
    int hudScale;
} ValidResolution;

ValidResolution AvailableResolutions[] =
{
    {320, 200, NULL, 1},
    {640, 400, NULL, 2},
    {640, 480, NULL, 2},
    {800, 600, NULL, 2},
    {1024, 768, NULL, 2},
    {1152, 864, NULL, 2},
    {1280, 720, NULL, 2},
    {1280, 768, NULL, 2},
    {1280, 800, NULL, 2},
    {1280, 960, NULL, 2},
    {1280, 1024, NULL, 2},
    {1400, 1050, NULL, 2},
    {1440, 900, NULL, 2},
    {1600, 900, NULL, 2},
    {1680, 1050, NULL, 2},
    {1920, 1080, NULL, 2},
    {2560, 1080, NULL, 2},
    {2560, 1440, NULL, 2},
    {3840, 2160, NULL, 2},
};

CP_MenuNames *ScreenResolutions = NULL;

CP_itemtype *ScreenResolutionMenu = NULL;

CP_MenuNames DisplayOptionsNames[] = {
    "Fullscreen",
    "Bordered Window",
    "Borderless Window",
};

CP_itemtype DisplayOptionsItems[] = {
    {1, "", 'F', NULL},
    {1, "", 'B', NULL},
    {1, "", 'B', NULL}
};


CP_iteminfo VisualOptionsItems = { 20, MENU_Y, 4, 0, 43, VisualOptionsNames, mn_largefont };

CP_iteminfo ScreenResolutionItems; // This gets filled in at run time

CP_iteminfo ExtOptionsItems = { 20, MENU_Y, 7, 0, 43, ExtOptionsNames, mn_largefont };

CP_iteminfo ExtGameOptionsItems = { 20, MENU_Y, 4, 0, 43, ExtGameOptionsNames, mn_largefont }; //LT added

CP_iteminfo DisplayOptionsMenu = { 20, MENU_Y, 3, 0, 43, DisplayOptionsNames, mn_largefont }; //LT added

void CP_ScreenResolution(void);

void CP_DisplayOptions(void);
void DoAdjustHudScale(void);

CP_itemtype VisualsOptionsMenu[] = 
{
    {1, "", 'S', (menuptr)CP_ScreenResolution},
    {1, "", 'F', (menuptr)DoAdjustFocalWidth},
    {1, "", 'H', (menuptr)DoAdjustHudScale},
    {1, "", 'D', (menuptr)CP_DisplayOptions}
};

CP_itemtype ExtOptionsMenu[] =
{
    {1, "", 'M', NULL},
    {1, "", 'I', NULL},
    {1, "", 'D', NULL},
    {1, "", 'C', NULL},
    {1, "", 'J', NULL},
    {1, "", 'A', NULL},
    {1, "", 'U', NULL},
};

CP_itemtype ExtGameMenu[] =
{
    {1, "", 'A', NULL},
    {1, "", 'P', NULL},
    {1, "", 'E', NULL},
    {1, "", 'Z', NULL},
}; //LT added

//bna added end

CP_iteminfo OptionsItems = { 20, MENU_Y, 9, 0, 43, OptionsNames, mn_largefont };

CP_itemtype OptionsMenu[] =
{
    {2, "autoadj\0", 'A', NULL},
    {1, "lightdim\0",'L', NULL},
    {1, "bobbin\0",  'B', NULL},
    {1, "fandc\0",   'F', NULL},
    {1, "double\0",  'D', (menuptr)CP_DoubleClickSpeed},
    {1, "menuspd\0", 'M', (menuptr)MenuFlipSpeed},
    {1, "detail\0",  'D', (menuptr)CP_DetailMenu},
    {1, "vlevel\0",  'V', (menuptr)CP_ViolenceMenu},
    {1, "\0",        'S', (menuptr)CP_ScreenSize}
};

CP_MenuNames DetailMenuNames[] =
{
    "LOW DETAIL",
    "MEDIUM DETAIL",
    "HIGH DETAIL"
};

CP_iteminfo DetailItems = { 32, 64, 3, 0, 43, DetailMenuNames, mn_largefont };

CP_itemtype DetailMenu[] =
{
    {2, "lowdtl\0", 'L', NULL},
    {1, "meddtl\0", 'M', NULL},
    {1, "hidtl\0",  'H', NULL}
};

CP_MenuNames BattleMenuNames[] =
{
    "PLAY GAME",
    "PLAY TEAM GAME",
    "COMM-BAT OPTIONS"
};

CP_iteminfo BattleItems = { 32, 19, 3, 0, 24, BattleMenuNames, mn_largefont };

CP_itemtype BattleMenu[] =
{
    {2, "bplay\0",    'P', (menuptr)BattleNoTeams},
    {1, "playteam\0", 'P', (menuptr)BattleTeams},
    {1, "comopt\0",   'C', (menuptr)CP_BattleOptions}
};

CP_MenuNames ViolenceMenuNames[] =
{
    "NONE",
    "SOME",
    "A LOT",
    "EXCESSIVE"
};

CP_iteminfo ViolenceItems = { 32, 64, 4, 0, 45, ViolenceMenuNames, mn_largefont };

CP_itemtype ViolenceMenu[] =
{
    {2, "vnone\0",   'N', NULL},
    {1, "vsome\0",   'S', NULL},
    {1, "valot\0",   'A', NULL},
    {1, "vexcess\0", 'E', NULL}
};

CP_MenuNames VMenuNames[] =
{
    "SET VIOLENCE LEVEL",
    "" // "ENTER PASSWORD" // "CHANGE PASSWORD"
};

CP_iteminfo VItems = { 32, MP_Y, 2, 0, 24, VMenuNames, mn_largefont };

CP_itemtype VMenu[] =
{
    {2, "msetv\0",  'S',  (menuptr)CP_ViolenceLevel},
    {1, "mepass\0", 'E', (menuptr)CP_PWMenu}
};

CP_MenuNames ModeMenuNames[] =
{
    "NORMAL",
    "SCORE MORE",
    "COLLECTOR",
    "SCAVENGER",
    "HUNTER",
    "TAG",
    "ELUDER",
    "DELUDER",
    "CAPTURE THE TRIAD"
};

CP_iteminfo ModeItems = { MENU_X, MENU_Y + 1, 9, 0, 24, ModeMenuNames, mn_largefont };

CP_itemtype ModeMenu[] =
{
    {CP_CursorLocation, "normal\0",   'N', (menuptr)CP_BattleMenu},
    {CP_Active,         "scorem\0",   'S', (menuptr)CP_BattleMenu},
    {CP_Active,         "collect\0",  'C', (menuptr)CP_BattleMenu},
    {CP_Active,         "scaven\0",   'S', (menuptr)CP_BattleMenu},
    {CP_Active,         "hunter\0",   'H', (menuptr)CP_BattleMenu},
    {CP_Active,         "tag\0",      'T', (menuptr)CP_BattleMenu},
    {CP_Active,         "eluder\0",   'E', (menuptr)CP_BattleMenu},
    {CP_Active,         "deluder\0",  'D', (menuptr)CP_BattleMenu},
    {CP_Active,         "captriad\0", 'C', (menuptr)CP_BattleMenu}
};

CP_MenuNames BOptNames[] =
{
    "GRAVITY",
    "SPEED",
    "AMMO PER WEAPON",
    "HIT POINTS",
    "RADICAL OPTIONS",
    "LIGHT LEVELS",
    "POINT GOAL",
    "DANGER DAMAGE",
    "TIME LIMIT"
};

CP_iteminfo BOptItems = { MENU_X, MENU_Y + 1, 9, 0, 24, BOptNames, mn_largefont };

CP_itemtype BOptMenu[] =
{
    {2, "gravity\0",  'G', (menuptr)CP_GravityOptions},
    {1, "speed\0",    'S', (menuptr)CP_SpeedOptions},
    {1, "ammoper\0",  'A', (menuptr)CP_AmmoPerWeaponOptions},
    {1, "hitp\0",     'H', (menuptr)CP_HitPointsOptions},
    {1, "radical\0",  'R', (menuptr)CP_SpawnControlOptions},
    {1, "lightl\0",   'L', (menuptr)CP_LightLevelOptions},
    {1, "pntgoal\0",  'P', (menuptr)CP_PointGoalOptions},
    {1, "danger\0",   'D', (menuptr)CP_DangerOptions},
    {1, "timel\0",    'T', (menuptr)CP_TimeLimitOptions}
};

CP_MenuNames GravityMenuNames[] =
{
    "LOW",
    "NORMAL",
    "HIGH"
};

CP_iteminfo GravityItems = { 32, 26, 3, 0, 45, GravityMenuNames, mn_largefont };

CP_itemtype GravityMenu[] =
{
    {2, "b_low\0",    'L', NULL},
    {1, "b_normal\0", 'N', NULL},
    {1, "b_high\0",   'H', NULL}
};

CP_MenuNames SpeedMenuNames[] =
{
    "NORMAL",
    "FAST"
};

CP_iteminfo SpeedItems = { 32, MP_Y, 2, 0, 45, SpeedMenuNames, mn_largefont };

CP_itemtype SpeedMenu[] =
{
    {2, "b_normal\0", 'N', NULL},
    {1, "b_fast\0",   'F', NULL}
};

CP_MenuNames AmmoPerWeaponMenuNames[] =
{
    "ONE",
    "NORMAL",
    "GUNFINITY"
};

CP_iteminfo AmmoPerWeaponItems = { 32, 26, 3, 0, 45, AmmoPerWeaponMenuNames, mn_largefont };

CP_itemtype AmmoPerWeaponMenu[] =
{
    {2, "b_one\0",    'O', NULL},
    {1, "b_normal\0", 'N', NULL},
    {1, "b_gunf\0",   'G', NULL}
};

CP_MenuNames HitPointMenuNames[] =
{
    "ONE",
    "25",
    "BY CHARACTER",
    "100",
    "250",
    "500",
    "4000"
};

CP_iteminfo HitPointItems = { 32, 32, 7, 0, 45, HitPointMenuNames, mn_largefont };

CP_itemtype HitPointMenu[] =
{
    {2, "b_one\0",  'O', NULL},
    {1, "b_25\0",   'a', NULL},
    {1, "b_char\0", 'C', NULL},
    {1, "b_100\0",  'a', NULL},
    {1, "b_250\0",  'a', NULL},
    {1, "b_500\0",  'a', NULL},
    {1, "b_4000\0", 'a', NULL}
};

CP_MenuNames SpawnMenuNames[] =
{
    "SPAWN DANGERS",
    "SPAWN HEALTH",
    "SPAWN WEAPONS",
    "SPAWN MINES",
    "RESPAWN ITEMS",
    "WEAPON PERSISTENCE",
    "RANDOM WEAPONS",
    "FRIENDLY FIRE"
};

CP_iteminfo SpawnItems = { 20, 24, 8, 0, 35, SpawnMenuNames, mn_largefont };

CP_itemtype SpawnMenu[] =
{
    {2, "b_danger\0", 'S', NULL},
    {1, "b_health\0", 'S', NULL},
    {1, "b_weap\0",   'S', NULL},
    {1, "b_mines\0",  'S', NULL},
    {1, "b_rpawn\0",  'R', NULL},
    {1, "b_persis\0", 'W', NULL},
    {1, "b_rndwpn\0", 'R', NULL},
    {1, "b_friend\0", 'F', NULL}
};

CP_MenuNames LightLevelMenuNames[] =
{
    "DARK",
    "NORMAL",
    "BRIGHT",
    "FOG",
    "PERIODIC",
    "LIGHTNING"
};

CP_iteminfo LightLevelItems = { 32, 40, 6, 0, 45, LightLevelMenuNames, mn_largefont };

CP_itemtype LightLevelMenu[] =
{
    {2, "b_dark\0",   'D', NULL},
    {1, "b_normal\0", 'N', NULL},
    {1, "b_bright\0", 'B', NULL},
    {1, "b_fog\0",    'F', NULL},
    {1, "b_period\0", 'P', NULL},
    {1, "b_light\0",  'L', NULL}
};

CP_MenuNames PointGoalMenuNames[] =
{
    "1",
    "5",
    "11",
    "21",
    "50",
    "100",
    "RANDOM",
    "RANDOM BLIND",
    "INFINITE"
};

CP_iteminfo PointGoalItems = { 32, 16, 9, 0, 45, PointGoalMenuNames, mn_largefont };

CP_itemtype PointGoalMenu[] =
{
    {2, "b_1\0",      'a', NULL},
    {1, "b_5\0",      'a', NULL},
    {1, "b_11\0",     'a', NULL},
    {1, "b_21\0",     'a', NULL},
    {1, "b_50\0",     'a', NULL},
    {1, "b_100\0",    'a', NULL},
    {1, "b_random\0", 'R', NULL},
    {1, "b_randb\0",  'R', NULL},
    {1, "b_inf\0",    'I', NULL}
};

CP_MenuNames DangerMenuNames[] =
{
    "LOW",
    "NORMAL",
    "KILL"
};

CP_iteminfo DangerItems = { 32, 56, 3, 0, 45, DangerMenuNames, mn_largefont };

CP_itemtype DangerMenu[] =
{
    {2, "b_low\0",    'L', NULL},
    {1, "b_normal\0", 'N', NULL},
    {1, "b_kill\0",   'K', NULL}
};

CP_MenuNames TimeLimitMenuNames[] =
{
    "1",
    "2",
    "5",
    "10",
    "21",
    "30",
    "99",
    "NONE"
};

CP_iteminfo TimeLimitItems = { 32, 24, 8, 0, 45, TimeLimitMenuNames, mn_largefont };

CP_itemtype TimeLimitMenu[] =
{
    {2, "b_1\0",    'a', NULL},
    {1, "b_2\0",    'a', NULL},
    {1, "b_5\0",    'a', NULL},
    {1, "b_10\0",   'a', NULL},
    {1, "b_21\0",   'a', NULL},
    {1, "b_30\0",   'a', NULL},
    {1, "b_99\0",   'a', NULL},
    {1, "vnone\0",  'N', NULL}
};

CP_MenuNames MultiPageCustomNames[ MAXCUSTOM + 2 ] =
{
    "NEXT PAGE",
    "PREVIOUS PAGE"
};

CP_iteminfo MultiPageCustomItems = { 18, 17, 0, 0, 12, MultiPageCustomNames, mn_smallfont };
CP_itemtype MultiPageCustomMenu[] =
{
    {1, "", 'N', NULL},
    {1, "", 'P', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
    {1, "", 'a', NULL},
};

#define COLORX 113
#define COLORY 43
#define COLORW 60
#define COLORH 96

// Custom menu stuff
static int CUSTOM_y[ 7 ] = { 31, 0, 63, 0, 94, 0, 126 };

//
// Save globals
//
static boolean StartGame = false;

static int  SaveGamesAvail[ NUMSAVEGAMES ];
static char SaveGameNames[ NUMSAVEGAMES ][ 32 ];
static char SaveName[ 13 ] = "rottgam?.rot\0";

static byte *savedscreen;
static mapfileinfo_t * mapinfo;

static void HideCursor
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int x,
    int y,
    int which
);
static void ShowCursor
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int x,
    int *y,
    int which,
    int basey
);
void CP_DrawSelectedGame (int w);
int HandleMenu (CP_iteminfo *item_i, CP_itemtype *items, void (*routine)(int w));
void DrawStoredGame ( byte * pic, int episode, int area );
void DrawCustomKeyboard (void);
void DrawBattleModeName( int which );
void DrawBattleModeDescription( int w );
void DrawSoundSetupMainMenu( void );
int ColorMenu(void);

//******************************************************************************
//
// MN_DrawButtons
//
//******************************************************************************

void MN_DrawButtons
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int check,
    int *nums
)

{
    int i;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName( "snd_on" );
    button_off = W_GetNumForName( "snd_off" );

    for( i = 0; i < item_i->amount; i++ )
    {
        if ( items[ i ].active != CP_Active3 )
        {
            if ( nums[ i ] == check )
            {
                DrawMenuBufItem( item_i->x + 27, item_i->y + i *
                                 FontSize[ item_i->fontsize ] - 1, button_on);
            }
            else
            {
                DrawMenuBufItem( item_i->x + 27, item_i->y + i *
                                 FontSize[ item_i->fontsize ] - 1, button_off);
            }
        }
    }
}


//****************************************************************************
//
// MN_GetCursorLocation()
//
//****************************************************************************

void MN_GetCursorLocation
(
    CP_iteminfo *item_i,
    CP_itemtype *items
)

{
    int i;
    int position;

    position = -1;
    for( i = 0; i < item_i->amount; i++ )
    {
        if ( items[ i ].active == CP_CursorLocation )
        {
            position = i;
            break;
        }

        if ( ( items[ i ].active == CP_Active ) && ( position == -1 ) )
        {
            position = i;
        }
    }

    if ( position != -1 )
    {
        item_i->curpos = position;
        items[ position ].active = CP_CursorLocation;
    }
}


//****************************************************************************
//
// MN_GetActive ()
//
//****************************************************************************

int MN_GetActive
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int check,
    int *nums
)

{
    int i;
    int returnval;

    returnval = 0;
    for( i = 0; i < item_i->amount; i++ )
    {
        items[ i ].active = CP_Active;
        if ( nums[ i ] == check )
        {
            item_i->curpos    = i;
            items[ i ].active = CP_CursorLocation;
            returnval = i;
        }
    }

    return( returnval );
}


//****************************************************************************
//
// MN_MakeActive ()
//
//****************************************************************************

void MN_MakeActive
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int which
)

{
    int i;

    for( i = 0; i < item_i->amount; i++ )
        if (i == which)
        {
            items[i].active = CP_CursorLocation;
            item_i->curpos    = i;
        }
        else
            items[i].active = CP_Active;
}


//******************************************************************************
//
// DrawMenu ()
//
// Purpose - Draws a menu
//
//******************************************************************************
void DrawMenu
(
    CP_iteminfo *item_i,
    CP_itemtype *items
)

{
    int i;
    int active;
    int color;
    int posx;
    int posy;

    posx = item_i->x + item_i->indent;
    posy = item_i->y;
    WindowX = posx;
    WindowY = posy;
    WindowW = 320;
    WindowH = 200;

    for ( i = 0; i < item_i->amount; i++ )
    {
        posy   = item_i->y + i * FontSize[ item_i->fontsize ];
        active = items[ i ].active;

        color = -1;
        switch( active )
        {
        case CP_CursorLocation :
            color = ACTIVECOLOR;
            break;

        case CP_Inactive :
            color = NOTAVAILABLECOLOR;
            break;

        case CP_Active :
            color = NORMALCOLOR;
            break;

        case CP_SemiActive :
            color = DIMMEDCOLOR;
            break;

        case CP_Highlight :
            color = HIGHLIGHTCOLOR;
            break;
        }

        if ( color != -1 )
        {
            if ( item_i->names == NULL )
            {
                DrawIMenuBufItem( posx, posy, W_GetNumForName( items[ i ].texture ),
                                  color );
            }
            else
            {
                IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
                                                      PU_CACHE, Cvt_cfont_t, 1 );
                if ( item_i->fontsize == mn_tinyfont )
                {
                    DrawMenuBufIString( posx + 1, posy, item_i->names[ i ], 0 );
                }
                DrawMenuBufIString( posx, posy - 1, item_i->names[ i ], color );
            }
        }
    }
}


//******************************************************************************
//
// getASCII () - Gets info from Keyboard.
//
//******************************************************************************

int getASCII ( void )
{
    int i;
    int LS;
    int RS;
    int returnvalue = 0;
    int scancode = 0;

    IN_UpdateKeyboard ();

    LS = Keyboard[sc_LShift];
    RS = Keyboard[sc_RShift];

    Keyboard[sc_LShift] = Keyboard[sc_RShift] = 0;

    scancode = 0;

    for (i = 0; i < 127; i++)
        if (Keyboard[i])
        {
            scancode = i;
            break;
        }

    if (scancode)
    {
        if (LS || RS)
            returnvalue = ShiftNames[scancode];
        else
            returnvalue = ASCIINames[scancode];
    }

    Keyboard[sc_LShift] = LS;
    Keyboard[sc_RShift] = RS;

    return (returnvalue);
}


//******************************************************************************
//
// ScanForSavedGames ()
//
//******************************************************************************

void ScanForSavedGames (void)
{
    struct find_t f;
    char filename[256];
    char str[45];
    int which;
    boolean found = false;
    char *pathsave;

    //
    // SEE WHICH SAVE GAME FILES ARE AVAILABLE & READ STRING IN
    //
    memset (&SaveGamesAvail[0], 0, sizeof (SaveGamesAvail));
#if PLATFORM_WIN32
    GetPathFromEnvironment( filename, ApogeePath, SaveName );
#elif defined(__plan9__)
    strncpy(filename, SaveName, 256);
#else
    strncpy (filename, SaveName, 256);
    pathsave = getcwd (NULL, 0);
    chdir (ApogeePath);
#endif

    if (!_dos_findfirst (filename, 0, &f))
        do
        {
            strcpy(str,&f.name[7]);
            sscanf((const char *)&str[0],"%x",&which);

            if (which < NUMSAVEGAMES)
            {
                found = true;
                SaveGamesAvail[which] = 1;
                GetSavedMessage (which, &SaveGameNames[which][0]);
            }

        } while (!_dos_findnext (&f));

    if (found)
    {
        if (MainMenu[loadgame].active == CP_Inactive)
            MainMenu[loadgame].active = CP_Active;
    }
    else
        MainMenu[loadgame].active = CP_Inactive;
#if !PLATFORM_WIN32 && !defined(__plan9__)
    chdir (pathsave);
    free (pathsave);
#endif
}


//******************************************************************************
//
// SetUpControlPanel ()
//
//******************************************************************************

void SetUpControlPanel (void)
{
    int i;
    int j;
    byte * b;
    byte * s;

//   int Xres = 320;//org
//   int Yres = 200;//org
    int Xres = 640;
    int Yres = 400;

    //dont work in 800x600 until we get a better screen schrinker
    //  int Xres = iGLOBAL_SCREENWIDTH;//640;
//  int Yres = iGLOBAL_SCREENHEIGHT;//400;

    Xres = 640;
    Yres = 400;



    // Save the current game screen

    //bna--savedscreen = SafeMalloc (16000);
    savedscreen = SafeMalloc (16000*8);

    // Copy the current save game screen (� size) to this buffer

    if (RefreshPause==false)
    {
        GamePaused=false;
        ThreeDRefresh();
        FlipPage();
        FlipPage();
        GamePaused=true;
    }


    s=savedscreen;



    if (iGLOBAL_SCREENWIDTH == 320) {
        for (i=0; i<Xres; i+=2)	{
            b=(byte *)bufferofs+i;
            for (j=0; j<100; j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1))
                *s=*b;
        }
    }
    if (iGLOBAL_SCREENWIDTH >= 640) {
        for (i=0; i<Xres; i+=4)	{
            b=(byte *)bufferofs+i;//schrink screen to 1/2 size
            for (j=0; j<(Yres/4); j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1)*2)
                *s=*b;
        }
    }/*
      if (iGLOBAL_SCREENWIDTH == 800) {
		  for (i=0;i<Xres;i+=8)		{
			  b=(byte *)bufferofs+i;//schrink screen to 1/3 size
			  for (j=0;j<(Yres/8);j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1)*3)
				 *s=*b;
		  }

      }*/

    ScanForSavedGames ();



    if (modemgame == true)
    {
        // Make battle mode active
        //
        MainMenu[battlemode].active = CP_Active;

        // No save or load game in modem game
        //
        MainMenu[newgame].active    = CP_Inactive;
        MainMenu[backtodemo].active = CP_Inactive;
        MainMenu[loadgame].active   = CP_Inactive;
        MainMenu[savegame].active   = CP_Inactive;

        if ( MainMenu[ MainItems.curpos ].active == CP_Inactive )
        {
            MainItems.curpos = battlemode;
        }

        MainMenu[MainItems.curpos].active = CP_CursorLocation;

        if ( consoleplayer != 0 )
        {
            MainMenu[battlemode].routine = ( void (*)(int) )BattleGamePlayerSetup;
        }
    }
}

//******************************************************************************
//
// GetMenuInfo ()
//
// Gets the user's password
//
//******************************************************************************

void GetMenuInfo (void)
{
    ConvertPasswordStringToPassword ();

    POK=true;
    if (pword[0]==0)
        POK=false;
}


//******************************************************************************
//
// WriteMenuInfo ()
//
// Writes out password
//
//******************************************************************************

void WriteMenuInfo (void)
{
    ConvertPasswordToPasswordString ();
}

//******************************************************************************
//
// AllocateSavedScreenPtr ()
//
//******************************************************************************

void AllocateSavedScreenPtr (void)
{
    // Save the current game screen

    savedscreen = SafeMalloc(16000);
    inmenu  = true;
    numdone = 0;
}


//******************************************************************************
//
// FreeSavedScreenPtr ()
//
//******************************************************************************

void FreeSavedScreenPtr (void)
{
    SafeFree (savedscreen);
    inmenu  = false;
}


//******************************************************************************
//
// CleanUpControlPanel ()
//
//******************************************************************************

void CleanUpControlPanel (void)
{
    int   joyx, joyy;

    if ((playstate==ex_resetgame) || (loadedgame==true))
        ShutdownClientControls();

    // Free up saved screen image

    FreeSavedScreenPtr ();

    WriteConfig ();
    
    //change the focal width if modified
    
    RecalculateFocalWidth();

    INL_GetJoyDelta (joystickport, &joyx, &joyy);

    if (mouseenabled)
        PollMouseMove ();    // Trying to kill movement

    RefreshPause = true;
}


//******************************************************************************
//
// CP_CheckQuick ()
//
//******************************************************************************
boolean CP_CheckQuick
(
    byte scancode
)

{
    if (demoplayback==true)
    {
        switch ( scancode )
        {
        case sc_Escape:
            inmenu = true;
            return( true );
            break;
        }
    }
    else
    {
        switch ( scancode )
        {
        case sc_Escape:
        case sc_F1:
        case sc_F2:
        case sc_F3:
        case sc_F4:
        case sc_F8:
        case sc_F9:
        case sc_F10:
            inmenu = true;
            return( true );
            break;
        }
    }

    return( false );
}


//******************************************************************************
//
// ControlPanel
//
//    ROTT Control Panel!
//
//******************************************************************************
void ControlPanel
(
    byte scancode
)

{
    if ( scancode == sc_Escape )
    {
        CP_MainMenu();
        if ( ( playstate == ex_stillplaying ) && ( loadedgame == false ) )
        {
            fizzlein = true;
        }
        return;
    }

    SetupMenuBuf();

    numdone = 0;
    StartGame = false;

    SetUpControlPanel();
    EnableScreenStretch();
    //
    // F-KEYS FROM WITHIN GAME
    //
    switch( scancode )
    {
    case sc_F1:
        CP_F1Help();
        break;

    case sc_F2:
        CP_SaveGame();
        break;

    case sc_F3:
        CP_LoadGame( 0, 0 );
        break;

    case sc_F4:
        CP_ControlMenu();
        break;

    case sc_F8:
        LastScan          = 0;
        Keyboard[ sc_F8 ] = 0;
        CP_EndGame();
        break;

    case sc_F9:
        LastScan          = 0;
        Keyboard[ sc_F9 ] = 0;

        CP_LoadGame(1, 0);
        loadsavesound = true;
        break;

    case sc_F10:
        SetMenuTitle ("Quit");

        LastScan           = 0;
        Keyboard[ sc_F10 ] = 0;
        CP_Quit( -1 );
        break;

    }
    
    if (playstate == ex_stillplaying)
    {
        DisableScreenStretch();
    }

    CleanUpControlPanel();
    ShutdownMenuBuf();

    if ( loadedgame == false )
    {
        SetupScreen( false );
        fizzlein = true;
        inmenu = false;
    }

    loadsavesound = false;
}


//******************************************************************************
//
// CP_MainMenu
//
//******************************************************************************
menuitems CP_MainMenu
(
    void
)

{
    int which;

    SetupMenuBuf();

    numdone = 0;

    SetUpControlPanel();

    DrawMainMenu();

    //
    // Main menu loop.  "Exit options" or "New game" exits
    //
    StartGame = false;
    EnableScreenStretch();

    while( !StartGame )
    {
        StartGame = false;

        IN_ClearKeysDown();

        which = HandleMenu( &MainItems, &MainMenu[ 0 ], NULL );

        switch( which )
        {
        case backtodemo:
            if ( !ingame )
            {
                playstate = ex_titles;
            }

            StartGame = true;
            DisableScreenStretch();//bna++ shut off streech mode
            break;

        case -1:
            CP_Quit( 0 );
            break;

        default:
            if ( !StartGame )
            {
                DoMainMenu();
            }
        }
    }

    // Deallocate everything
    CleanUpControlPanel();
    ShutdownMenuBuf();

    return( which );
}


//******************************************************************************
//
// DrawMainMenu ()
//
//******************************************************************************

void DrawMainMenu(void)
{

    MenuNum = 1;
    EnableScreenStretch();//bna++ shut off streech mode
    //
    // CHANGE "GAME" AND "DEMO"
    //
    if ( ingame )
    {
        MainMenu[ backtodemo ].texture[ 6 ] = '1';
        MainMenu[ backtodemo ].texture[ 7 ] = '1';
        MainMenu[ backtodemo ].texture[ 8 ] = '\0';
        strcpy (MainMenuNames[ backtodemo ], "BACK TO GAME");
    }
    else
    {
        MainMenu[ backtodemo ].texture[ 6 ] = '8';
        MainMenu[ backtodemo ].texture[ 7 ] = '\0';
        strcpy (MainMenuNames[ backtodemo ], "BACK TO DEMO");
    }

    MN_GetCursorLocation( &MainItems, &MainMenu[ 0 ] );
    SetMenuTitle ("Main Menu");
    DrawMenu (&MainItems, &MainMenu[0]);

    numdone ++;
    DisplayInfo (0);
}


//******************************************************************************
//
// Handle moving triad around a menu
//
//******************************************************************************

int HandleMenu (CP_iteminfo *item_i, CP_itemtype *items, void (*routine)(int w))
{

    char        key;
    int         i,
                x,
                y,
                basey,
                exit,
                numactive,
                count;
    int         newpos;
    volatile int timer;
    ControlInfo ci;
    boolean     playsnd = false;

    handlewhich = item_i->curpos;
    x     = item_i->x;
    if ((MenuNum == 4) || (MenuNum == 6) ||
            ( item_i->fontsize == mn_smallfont ) )
    {
        basey = item_i->y;

        CursorLump = SmallCursor;
        yinc = 9;
        cursorwidth = cursorheight = 8;
    }
    else if ( item_i->fontsize == mn_8x8font )
    {
        basey = item_i->y - 1;

        CursorLump = SmallCursor;
        yinc = 7;
        cursorwidth = cursorheight = 8;
    }
    else if ( item_i->fontsize == mn_tinyfont )
    {
        basey = item_i->y - 2;

        CursorLump = SmallCursor;
        yinc = 6;
        cursorwidth = cursorheight = 8;
    }
    else
    {
        basey = item_i->y-2;

        CursorLump = LargeCursor;
        yinc = 14;
        cursorwidth = cursorheight = 16;
    }


    if (MenuNum)
        y = basey + handlewhich*yinc;
    else
        y = CUSTOM_y[handlewhich];


    if (MenuNum != 5)
        DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
                         CursorFrame[ CursorNum ] );

    if (routine)
        routine (handlewhich);

    count    = 2;
    exit     = 0;
    timer    = GetTicCount();
    IN_ClearKeysDown ();

    numactive = GetNumActive (item_i, items);

    do
    {
        ReadAnyControl (&ci);
        RefreshMenuBuf (0);
        // Change Cursor Shape
        if ((GetTicCount() > (timer+count)) && (MenuNum != 5))
        {
            timer = GetTicCount();

            CursorNum++;
            if (CursorNum > (MAXCURSORNUM-1))
                CursorNum = 0;

            EraseMenuBufRegion(x, y, cursorwidth, cursorheight);
            DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
                             CursorFrame[ CursorNum ] );

        }

        // Initial char - pass 1
        key = getASCII ();
        if (key)
        {
            int ok = 0;

            key = toupper (key);

            for (i = (handlewhich + 1); i < item_i->amount; i++)
                if ((items+i)->active && (items+i)->letter == key)
                {
                    HideCursor (item_i, items, x, y, handlewhich);
                    MN_PlayMenuSnd (SD_MOVECURSORSND);
                    handlewhich = i;


                    if (routine)
                        routine (handlewhich);

                    ShowCursor (item_i, items, x, &y, handlewhich, basey);
                    ok = 1;
                    IN_ClearKeysDown();
                    break;
                }

            // Initial char - pass 2
            if (!ok)
            {
                for (i = 0; i < handlewhich; i++)
                    if ((items+i)->active && (items+i)->letter == key)
                    {
                        HideCursor (item_i, items, x, y, handlewhich);
                        MN_PlayMenuSnd (SD_MOVECURSORSND);
                        handlewhich = i;


                        if (routine)
                            routine (handlewhich);

                        ShowCursor (item_i, items, x,& y, handlewhich, basey);
                        IN_ClearKeysDown ();
                        break;
                    }
            }
        }

        ReadAnyControl (&ci);

        if (numactive > 1)
        {
            switch (ci.dir)
            {
            case dir_North:
                HideCursor (item_i, items, x, y, handlewhich);


                CursorNum++;
                if (CursorNum > (MAXCURSORNUM-1))
                    CursorNum = 0;


                // Do a half step if possible
                if ((handlewhich) &&
                        (((items+handlewhich-1)->active == CP_CursorLocation) ||
                         ((items+handlewhich-1)->active == CP_Active)))
                {
                    y -= 6;
                    DrawHalfStep (x, y);
                    playsnd = false;

                    RefreshMenuBuf (0);

                    CursorNum++;
                    if (CursorNum > (MAXCURSORNUM-1))
                        CursorNum = 0;
                }
                else
                {
                    playsnd = true;
                    RefreshMenuBuf (0);
                }

                do
                {
                    if (!handlewhich)
                        handlewhich = item_i->amount-1;
                    else
                        handlewhich--;
                } while (((items+handlewhich)->active == CP_Inactive) || ((items+handlewhich)->active == CP_Active3));

                if (playsnd)
                    MN_PlayMenuSnd (SD_MOVECURSORSND);
                ShowCursor (item_i, items, x, &y, handlewhich, basey);

                if (routine)
                    routine (handlewhich);

                RefreshMenuBuf(0);
                break;

            case dir_South:
                HideCursor (item_i, items, x, y, handlewhich);

                CursorNum++;
                if (CursorNum > (MAXCURSORNUM-1))
                    CursorNum = 0;

                // Do a half step if possible
                if ((handlewhich != item_i->amount-1) &&
                        (((items+handlewhich+1)->active == CP_CursorLocation) ||
                         ((items+handlewhich+1)->active == CP_Active)))
                {
                    y += 6;
                    DrawHalfStep(x,y);
                    playsnd = false;

                    RefreshMenuBuf (0);

                    CursorNum++;
                    if (CursorNum > (MAXCURSORNUM-1))
                        CursorNum = 0;
                }
                else
                {
                    playsnd = true;
                    RefreshMenuBuf (0);
                }

                do
                {
                    if (handlewhich==item_i->amount-1)
                        handlewhich=0;
                    else
                        handlewhich++;
                } while (((items+handlewhich)->active == CP_Inactive) || ((items+handlewhich)->active == CP_Active3));

                if (playsnd)
                    MN_PlayMenuSnd (SD_MOVECURSORSND);
                ShowCursor(item_i,items,x,&y,handlewhich,basey);

                if (routine)
                    routine (handlewhich);

                RefreshMenuBuf (0);
                break;
            default:
                ;
            }
        }

        ReadAnyControl (&ci);
        if (ci.button0 || Keyboard[sc_Space] || Keyboard[sc_Enter])
        {
            exit = 1;
            WaitKeyUp ();
            MN_PlayMenuSnd (SD_SELECTSND);
        }

        if (ci.button1 || Keyboard[sc_Escape])
        {
            WaitKeyUp ();
            exit = 2;
        }

        if ( ( Keyboard[ sc_Home ] ) && ( numactive > 1 ) )
        {
            newpos = 0;
            while( ( items[ newpos ].active == CP_Inactive ) ||
                    ( items[ newpos ].active == CP_Active3 ) )
            {
                newpos++;
            }

            if ( newpos != handlewhich )
            {
                HideCursor( item_i, items, x, y, handlewhich );

                CursorNum++;
                if ( CursorNum > ( MAXCURSORNUM - 1 ) )
                {
                    CursorNum = 0;
                }

                RefreshMenuBuf( 0 );

                handlewhich = newpos;

                MN_PlayMenuSnd( SD_MOVECURSORSND );

                ShowCursor( item_i, items, x, &y, handlewhich, basey );

                if ( routine )
                {
                    routine( handlewhich );
                }

                RefreshMenuBuf( 0 );
            }
        }
        else if ( ( Keyboard[ sc_End ] ) && ( numactive > 1 ) )
        {
            newpos = item_i->amount - 1;
            while( ( items[ newpos ].active == CP_Inactive ) ||
                    ( items[ newpos ].active == CP_Active3 ) )
            {
                newpos--;
            }

            if ( newpos != handlewhich )
            {
                HideCursor( item_i, items, x, y, handlewhich );

                CursorNum++;
                if ( CursorNum > ( MAXCURSORNUM - 1 ) )
                {
                    CursorNum = 0;
                }

                RefreshMenuBuf( 0 );

                handlewhich = newpos;

                MN_PlayMenuSnd( SD_MOVECURSORSND );

                ShowCursor( item_i, items, x, &y, handlewhich, basey );

                if ( routine )
                {
                    routine( handlewhich );
                }

                RefreshMenuBuf( 0 );
            }
        }

        // Page Up/Down
        if ( MenuNum == 11 )
        {
            if ( ( Keyboard[ sc_PgUp ] ) &&
                    ( ( items + 1 )->active != CP_Inactive ) )
            {
                item_i->curpos = handlewhich;
                handlewhich = PAGEUP;
                exit = 3;
                MN_PlayMenuSnd( SD_SELECTSND );
            }
            else if ( ( Keyboard[ sc_PgDn ] ) &&
                      ( ( items + 0 )->active != CP_Inactive ) )
            {
                item_i->curpos = handlewhich;
                handlewhich = PAGEDOWN;
                exit = 3;
                MN_PlayMenuSnd( SD_SELECTSND );
            }
        }

        // Delete save games
        if ((MenuNum == 4) || (MenuNum == 6))
        {
            if (Keyboard[sc_Delete] && SaveGamesAvail[handlewhich])
            {
                if (CP_DisplayMsg ("Delete saved game?\nAre you sure?", 12) == true)
                {
                    char loadname[45] = "rottgam0.rot";
                    char filename[128];

                    // Create the proper file name
                    itoa (handlewhich, &loadname[7], 16);
                    loadname[8]='.';

                    GetPathFromEnvironment( filename, ApogeePath, loadname );

                    // Delete the file

                    unlink (filename);

                    memset (&SaveGameNames[handlewhich][0], 0, 32);
                    SaveGamesAvail[handlewhich] = 0;
                    if (handlewhich==quicksaveslot)
                        quicksaveslot=-1;

                    PrintX = LSM_X+LSItems.indent+2;
                    PrintY = LSM_Y+handlewhich*9+2;
                }
                ScanForSavedGames ();

                LSItems.curpos = handlewhich;
                if (MenuNum == 4)
                    DrawLoadSaveScreenAlt (1);
                else
                    DrawLoadSaveScreenAlt (0);
                CP_DrawSelectedGame (handlewhich);
            }
        }


#if SAVE_SCREEN
        if (Keyboard[sc_CapsLock] && Keyboard[sc_C])
        {
            inhmenu=true;
            SaveScreen (true);
            inhmenu=false;
        }
        else if (Keyboard[sc_CapsLock] && Keyboard[sc_X])
        {
            inhmenu=true;
            SaveScreen (false);
            inhmenu=false;
        }
        else if (Keyboard[sc_CapsLock] && Keyboard[sc_Q])
            Error ("Insta-Menu Quit!\n");
#endif

    } while (!exit);


    IN_ClearKeysDown();

    if (routine)
        routine (handlewhich);

    if ( exit != 3 )
    {
        item_i->curpos = handlewhich;
    }

    if (MenuNum == 3)
    {
        if (exit != 2)
            CSTactive = handlewhich;
        else
            CSTactive = -1;
    }

    switch (exit)
    {
    case 1:
        if ((items+handlewhich)->routine!=NULL)
            (items+handlewhich)->routine(0);
        return (handlewhich);

    case 2:
        MN_PlayMenuSnd (SD_ESCPRESSEDSND);
        return (-1);

    case 3:
        return( handlewhich );
    }


    return (0);
}

//******************************************************************************
//
// HideCursor
//
//******************************************************************************
void HideCursor
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int x,
    int y,
    int which
)

{
    int time = GetTicCount();
    int color;
    int delay;
    int posx;
    int posy;

    if ( MenuNum != 5 )
    {
        EraseMenuBufRegion( x, y, cursorwidth, cursorheight );
    }

    if ( MenuNum && ( MenuNum != 4 ) && ( MenuNum != 6 ) )
    {
        posx = item_i->x + item_i->indent;
        posy = item_i->y + ( which * yinc );

        color = -1;
        switch( items[ which ].active )
        {
        case CP_Inactive :
            color = NOTAVAILABLECOLOR;
            break;

        case CP_CursorLocation :
        case CP_Active :
            color = NORMALCOLOR;
            break;

        case CP_SemiActive :
            color = DIMMEDCOLOR;
            break;

        case CP_Highlight :
            color = HIGHLIGHTCOLOR;
            break;
        }

        if ( color != -1 )
        {
            if ( item_i->names == NULL )
            {
                DrawIMenuBufItem( posx, posy,
                                  W_GetNumForName( items[ which ].texture ), color );
            }
            else
            {
                IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
                                                      PU_CACHE, Cvt_cfont_t, 1 );
                if ( item_i->fontsize == mn_tinyfont )
                {
                    DrawMenuBufIString( posx + 1, posy, item_i->names[ which ], 0 );
                }
                DrawMenuBufIString( posx, posy - 1, item_i->names[ which ],
                                    color );
            }
        }
    }

    if ( ( items[ which ].active != CP_Inactive ) &&
            ( items[ which ].active != CP_SemiActive ) )
    {
        items[ which ].active = CP_Active;
    }

    delay = DELAYAMT - tics;
    while( ( time + delay ) > GetTicCount() )
    {
        RefreshMenuBuf (0);
    }
}


//******************************************************************************
//
// DrawHalfStep
//
//******************************************************************************

void DrawHalfStep (int x, int y)
{
    MN_PlayMenuSnd (SD_MOVECURSORSND);
    if (MenuNum == 5)
        return;

    DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
                     CursorFrame[ CursorNum ] );
}


//******************************************************************************
//
// GetNumActive ()
//
//******************************************************************************

int GetNumActive (CP_iteminfo *item_i, CP_itemtype *items)
{
    int cnt;
    int num = 0;

    for (cnt = 0; cnt < item_i->amount; cnt ++)
    {
        if ((items+cnt)->active != CP_Inactive)
            num++;
    }

    return (num);
}


//******************************************************************************
//
// ShowCursor
//    Draw triad at new position.
//
//******************************************************************************
void ShowCursor
(
    CP_iteminfo *item_i,
    CP_itemtype *items,
    int x,
    int *y,
    int which,
    int basey
)

{
    int time = GetTicCount();
    int delay;
    int posx;
    int posy;

    if ( MenuNum )
    {
        EraseMenuBufRegion( x, *y, cursorwidth, cursorheight );
        *y = basey + which * yinc;
    }
    else
    {
        *y = CUSTOM_y[ which ];
    }

    if ( MenuNum != 5 )
    {
        DrawMenuBufItem( x, *y, W_GetNumForName( CursorLump ) +
                         CursorFrame[ CursorNum ] );
    }

    if ( items[ which ].active != CP_SemiActive )
    {
        if ( MenuNum && ( MenuNum != 4 ) && ( MenuNum != 6 ) )
        {
            posx = item_i->x + item_i->indent;
            posy = item_i->y + which * yinc;

            if ( item_i->names == NULL )
            {
                DrawIMenuBufItem( posx, posy,
                                  W_GetNumForName( items[ which ].texture ), ACTIVECOLOR);
            }
            else
            {
                IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
                                                      PU_CACHE, Cvt_cfont_t, 1 );
                if ( item_i->fontsize == mn_tinyfont )
                {
                    DrawMenuBufIString( posx + 1, posy, item_i->names[ which ], 0 );
                }
                DrawMenuBufIString( posx, posy - 1, item_i->names[ which ],
                                    ACTIVECOLOR );
            }
        }

        items[ which ].active = CP_CursorLocation;
    }

    delay = DELAYAMT - tics;
    while( ( time + delay ) > GetTicCount() )
    {
        RefreshMenuBuf( 0 );
    }
}

//******************************************************************************
//
// DrawOrderInfo()
//
//******************************************************************************

void DrawOrderInfo
(
    int which
)

{
    int start;
    char *lumpname;

    start = W_GetNumForName( "ORDRSTRT" ) + 1;

    lumpname = W_GetNameForNum( start + which );

    // Screen shots are grabbed as pics
    if ( lumpname[ 0 ] == 'S' )
    {
        VWB_DrawPic( 0, 0, ( pic_t * )W_CacheLumpNum( start + which, PU_CACHE, Cvt_pic_t, 1 ) );
    }
    else
    {
        VL_DrawPostPic( W_GetNumForName( "trilogo" ) );
        DrawNormalSprite( 0, 0, start );
        DrawNormalSprite( 0, 0, start + which );
    }

    VW_UpdateScreen();
}


//******************************************************************************
//
// CP_OrderInfo()
//
//******************************************************************************

void CP_OrderInfo
(
    void
)

{
    int maxpage;
    int page;
    int key;
    boolean newpage;



    maxpage = W_GetNumForName( "ORDRSTOP" ) - W_GetNumForName( "ORDRSTRT" ) - 2;
    newpage = false;
    page = 1;

    do
    {
        EnableScreenStretch();//bna++
        DrawOrderInfo( page );
        DisableScreenStretch();//bna++ turn off or screen will be strected every time it passes VW_UpdateScreen
        if ( newpage )
        {
            while( Keyboard[ key ] )
            {
                VW_UpdateScreen();
                IN_UpdateKeyboard ();
            }
        }

        LastScan=0;
        while( LastScan == 0 )
        {
            VW_UpdateScreen();
            IN_UpdateKeyboard ();
        }

        key = LastScan;
        switch( key )
        {
        case sc_Home :
            if ( page != 1 )
            {
                page = 1;
                newpage = true;
                MN_PlayMenuSnd( SD_MOVECURSORSND );
            }
            break;

        case sc_End :
            if ( page != maxpage )
            {
                page = maxpage;
                newpage = true;
                MN_PlayMenuSnd( SD_MOVECURSORSND );
            }
            break;

        case sc_PgUp :
        case sc_UpArrow :
        case sc_LeftArrow :
            if ( page > 1 )
            {
                page--;
                newpage = true;
                MN_PlayMenuSnd( SD_MOVECURSORSND );
            }
            break;

        case sc_PgDn :
        case sc_DownArrow :
        case sc_RightArrow :
            if ( page < maxpage )
            {
                page++;
                newpage = true;
                MN_PlayMenuSnd( SD_MOVECURSORSND );
            }
            break;
        }
    }
    while( key != sc_Escape );

    Keyboard[ key ] = 0;
    LastScan = 0;
    EnableScreenStretch();//bna++
    MN_PlayMenuSnd( SD_ESCPRESSEDSND );
}


//******************************************************************************
//
// CP_ViewScores ()
//
//******************************************************************************

void CP_ViewScores (void)
{
    CheckHighScore (0, 0, true);
}


//******************************************************************************
//
// CP_Quit () - QUIT THIS INFERNAL GAME!
//
//******************************************************************************
void CP_Quit ( int which )
{
    int num = 100;
    static int oldnum;

    while ((num >= 7) || (oldnum == num))
        num = (RandomNumber ("CP_QUIT", 0) & 7);

    oldnum = num;

    if (CP_DisplayMsg (endStrings[num], num))
    {
        int handle;

        MU_FadeOut(310);
        handle=SD_Play(SD_QUIT1SND+num);
        VL_FadeOut (0, 255, 0, 0, 0, 10);
        CleanUpControlPanel();
        SD_WaitSound (handle);
        QuitGame ();
    }

    if ( which != -1 )
    {
        ClearMenuBuf();
        DrawMainMenu();
        DrawMenuBufItem (MainItems.x,  ((MainItems.curpos*14)+(MainItems.y-2)),
                         W_GetNumForName ( LargeCursor ) + CursorFrame[ CursorNum ] );
        RefreshMenuBuf (0);
    }
}

//******************************************************************************
//
// CP_DisplayMsg ()
//
//******************************************************************************

boolean CP_DisplayMsg
(
    char *s,
    int number
)

{
#define Q_W    184
#define Q_H    72
#define Q_X    ((320-Q_W)/2)-18
#define Q_Y    ((200-Q_H)/2)-33

#define Q_b1X  (Q_X+85)
#define Q_b2X  (Q_X+135)
#define Q_bY   (Q_Y+45)
#define Q_bW   33
#define Q_bH   10

#define W_X    72
#define W_Y    11
#define W_W    102

#define YES    "q_yes\0"
#define NO     "q_no\0"

    ControlInfo ci;
    boolean retval;
    boolean done;
    boolean YESON;
    boolean redraw;
    boolean blowout;
    char   *temp;
    char   *active;
    char   *inactive;
    int     activex;
    int     inactivex;
    int     W_H = 0;
    int     L_Y = 0;
    int     tri;
    int     QUITPIC;
    int     t;

    W_H = 1;
    retval  = false;
    done    = false;
    YESON   = true;
    redraw  = false;
    blowout = false;

    IN_ClearKeysDown();
    IN_IgnoreMouseButtons();


    QUITPIC = W_GetNumForName( "quitpic" );

    if ( number < 11 )
    {
        tri = W_GetNumForName( "QUIT01" ) + number;
        MN_PlayMenuSnd( SD_WARNINGBOXSND );
    }
    else
    {
        if ( number == 11 )
        {
            tri = W_GetNumForName( "tri1pic" );
            MN_PlayMenuSnd( SD_INFOBOXSND );
        }
        else
        {
            if ( number == 12 )
            {
                tri = W_GetNumForName( "tri2pic" );
                MN_PlayMenuSnd( SD_QUESTIONBOXSND );
            }
            if ( number == 13 )
            {
                tri = W_GetNumForName( "tri1pic" );
                MN_PlayMenuSnd( SD_WARNINGBOXSND );
            }
        }
    }

    DrawMenuBufPic( Q_X, Q_Y, QUITPIC );
    DrawMenuBufPic( Q_X + 12, Q_Y + 11, tri );

    temp = s;
    while( *temp )
    {
        if ( *temp == '\n' )
        {
            W_H++;
        }
        temp++;
    }

    CurrentFont = tinyfont;
    W_H = ( W_H * CurrentFont->height ) + 3;

    WindowX = Q_X + W_X;
    WindowY = L_Y + 2;
    L_Y     = Q_Y + W_Y;
    PrintX  = WindowX;
    PrintY  = WindowY;

    WindowW = W_W;
    WindowH = W_H;

    redraw = true;

    IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_smallfont ],
                                          PU_CACHE, Cvt_cfont_t, 1 );
    /*
       DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
       MenuBufCPrint( s );

       DrawSTMenuBuf( Q_b1X, Q_bY, Q_bW, Q_bH, false );
       DrawMenuBufIString( Q_b1X + 3, Q_Y + 46, "YES", NORMALCOLOR );
    //   DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (YES), NORMALCOLOR);

       DrawSTMenuBuf( Q_b2X, Q_bY, Q_bW, Q_bH, true );
       DrawMenuBufIString( Q_b2X + 2, Q_Y + 45, "NO", ACTIVECOLOR );
    //   DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (NO), ACTIVECOLOR);
    */
    if (number != 13)
    {
        while ( !done )
        {
            RefreshMenuBuf( 0 );

            ReadAnyControl( &ci );

            if ( ( ci.dir == dir_West ) && ( !YESON ) )
            {
                MN_PlayMenuSnd( SD_MOVECURSORSND );
                YESON = 1;
                redraw = true;
            }
            else if ( ( ci.dir == dir_East ) && ( YESON ) )
            {
                MN_PlayMenuSnd( SD_MOVECURSORSND );
                YESON = 0;
                redraw = true;
            }

            if ( Keyboard[ sc_Y ] )
            {
                YESON  = 1;
                redraw = true;
                Keyboard[ sc_Enter ] = true;
                blowout = true;
            }
            else if ( Keyboard[ sc_N ] )
            {
                YESON  = 0;
                redraw = true;
                Keyboard[ sc_Enter ] = true;
                blowout = true;
            }

            if ( redraw )
            {
                redraw = false;

                DrawMenuBufPic( Q_X, Q_Y, QUITPIC );
                DrawMenuBufPic( Q_X + 12, Q_Y + 11, tri );

                PrintX = Q_X + W_X;
                PrintY = Q_Y + W_Y + 2;
                DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
                CurrentFont = tinyfont;
                MenuBufCPrint( s );

                if ( YESON )
                {
                    active    = "YES";
                    inactive  = "NO";
                    activex   = Q_b1X;
                    inactivex = Q_b2X;
                }
                else
                {
                    active    = "NO";
                    inactive  = "YES";
                    activex   = Q_b2X;
                    inactivex = Q_b1X;
                }

                DrawSTMenuBuf( activex, Q_bY, Q_bW, Q_bH, false );
                DrawMenuBufIString( activex + 3, Q_Y + 46, active, ACTIVECOLOR );
//         DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (YES), NORMALCOLOR);

                DrawSTMenuBuf( inactivex, Q_bY, Q_bW, Q_bH, true );
                DrawMenuBufIString( inactivex + 2, Q_Y + 45, inactive, NORMALCOLOR );
//         DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (NO), ACTIVECOLOR);

                for( t = 0; t < 5; t++ )
                {
                    RefreshMenuBuf( 0 );
                }
            }

            if ( ( Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] ||
                    ci.button0 ) && YESON )
            {
                done   = true;
                retval = true;
                MN_PlayMenuSnd( SD_SELECTSND );
                CP_Acknowledge = CP_YES;
            }
            else if ( Keyboard[ sc_Escape ] || ci.button1 )
            {
                done   = true;
                retval = false;
                CP_Acknowledge = CP_ESC;
                MN_PlayMenuSnd( SD_ESCPRESSEDSND );
            }
            else if ( ( Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] ||
                        ci.button0 ) && !YESON )
            {
                done   = true;
                retval = false;
                CP_Acknowledge = CP_NO;

                if ( Keyboard[ sc_N ] )
                {
                    MN_PlayMenuSnd( SD_SELECTSND );
                }
                else
                {
                    MN_PlayMenuSnd( SD_ESCPRESSEDSND );
                }
            }
        }

        while( ( Keyboard[ sc_Enter ] || Keyboard[ sc_Space ] ||
                 Keyboard[ sc_Escape ] ) && !blowout )
        {
            IN_UpdateKeyboard();
            RefreshMenuBuf( 0 );
        }
    }
    else
    {
        PrintX = Q_X + W_X;
        PrintY = Q_Y + W_Y + 2;
        DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
        CurrentFont = tinyfont;
        MenuBufCPrint( s );
        LastScan=0;
        while (LastScan == 0)
        {
            IN_UpdateKeyboard();
            RefreshMenuBuf( 0 );
        }
        LastScan = 0;
    }
    IN_ClearKeysDown();
    return( retval );
}


//******************************************************************************
//
// EndGameStuff ()
//
//******************************************************************************

void EndGameStuff (void)
{
    Z_FreeTags( PU_LEVELSTRUCT, PU_LEVELEND );

    pickquick = false;
    CheckHighScore (gamestate.score, gamestate.mapon+1, true);
    locplayerstate->lives = 0;
    playstate = ex_died;
    damagecount = 0;
    SetBorderColor (0);

    AdjustMenuStruct ();
    ingame = false;

    GamePaused  = false;
}


//******************************************************************************
//
// START A NEW GAME
//
//******************************************************************************

#define CURGAME   "You are currently in\n"\
      "a game. Continuing will\n"\
      "erase old game. Ok?\0"

int ToughMenuNum;

void CP_NewGame
(
    void
)

{
    int which;

#if ( SHAREWARE == 1 )
    ToughMenuNum = 0;
#else
    int temp;

    temp = ToughMenuNum;

    while( ToughMenuNum == temp )
    {
        temp = ( ( RandomNumber( "TOUGH MENU", 0 ) ) & 3 );
        if ( temp == 3 )
        {
            temp = 1;
        }
    }

    ToughMenuNum = temp;
#endif

    //
    // ALREADY IN A GAME?
    //
    if ( ingame )
    {
        if ( !CP_DisplayMsg( CURGAME, 12 ) )
        {
            return;
        }
        else
        {
            EndGameStuff();
        }
    }
    else
    {
        handlewhich = 100;
    }

    if ( CP_PlayerSelection() == 0 )
    {
        return;
    }

    TufMenu[ ToughMenuNum ][ 0 ].active = CP_Active;
    TufMenu[ ToughMenuNum ][ 2 ].active = CP_Active;
    TufMenu[ ToughMenuNum ][ 4 ].active = CP_Active;
    TufMenu[ ToughMenuNum ][ 6 ].active = CP_Active;

    switch( DefaultDifficulty )
    {
    case gd_baby :
        TufItems.curpos = 0;
        break;

    case gd_easy :
        TufItems.curpos = 2;
        break;

    case gd_medium :
        TufItems.curpos = 4;
        break;

    case gd_hard :
        TufItems.curpos = 6;
        break;

    default :
        TufItems.curpos = 0;
        break;
    }

    TufMenu[ ToughMenuNum ][ TufItems.curpos ].active = CP_CursorLocation;

    DrawNewGame();

    which = HandleMenu( &TufItems, &TufMenu[ ToughMenuNum ][ 0 ],
                        DrawNewGameDiff );

    if ( which < 0 )
    {
        handlewhich = 1;
        return;
    }

    handlewhich = 0;

    switch( which )
    {
    case 0 :
        DefaultDifficulty = gd_baby;
        break;

    case 2 :
        DefaultDifficulty = gd_easy;
        break;

    case 4 :
        DefaultDifficulty = gd_medium;
        break;

    case 6 :
        DefaultDifficulty = gd_hard;
        break;
    }

    MainMenu[ savegame ].active = CP_Active;

    gamestate.battlemode = battle_StandAloneGame;
    StartGame = true;
    DisableScreenStretch();
    playstate = ex_resetgame;


}

//******************************************************************************
//
// CP_EndGame ()
//
//******************************************************************************

#define ENDGAMESTR   "Are you sure you want\n"\
               "to end the game you\n"\
               "are playing? (Y or N):"

void CP_EndGame
(
    void
)

{
    boolean action;

    SetMenuTitle( "End Game" );
    action = CP_DisplayMsg( ENDGAMESTR, 12 );

    StartGame = false;
    EnableScreenStretch();
    if ( action )
    {
        EndGameStuff ();
        pickquick = false;
    }
}

//******************************************************************************
//
// AdjustMenuStruct ()
//
//******************************************************************************
void AdjustMenuStruct
(
    void
)

{
    MainMenu[ savegame ].active         = CP_Inactive;
    MainMenu[ viewscores ].routine      = ( void * )CP_ViewScores;
    MainMenu[ viewscores ].texture[ 6 ] = '7';
    MainMenu[ viewscores ].texture[ 7 ] = '\0';
    MainMenu[ viewscores ].letter       = 'V';
    strcpy (MainMenuNames[ viewscores ], "VIEW SCORES");
}

//******************************************************************************
//
// CP_DrawSelectedGame
//
//******************************************************************************

void CP_DrawSelectedGame (int w)
{
    gamestorage_t game;

    if (SaveGamesAvail[w])
    {
        GetSavedHeader(w,&game);

        DrawStoredGame(&game.picture[0],game.episode,game.area);
    }
    else
        EraseMenuBufRegion(SaveGamePicX,SaveGamePicY,160,124);
}

//******************************************************************************
//
// DrawStoredGame
//
//******************************************************************************

void DrawStoredGame ( byte * pic, int episode, int area )
{
    char str[3];
    int level;
    byte *shape;

    shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
    newfont1 = (font_t *)shape;
    CurrentFont = newfont1;
    EraseMenuBufRegion (74, 128, 85, 14);

    DrawMenuBufPropString (74, 128, "E");

    itoa (episode, str, 10);
    DrawMenuBufPropString (87, 128, str);

    DrawMenuBufPropString (103, 128, "A");

    if (episode > 1)
        level = (area+1) - ((episode-1) << 3);
    else
        level = area+1;

    ltoa (level, str, 10);
    DrawMenuBufPropString (117, 128, str);
    CurrentFont = tinyfont;

    DrawMenuBufPicture(SaveGamePicX,SaveGamePicY,pic,160,100);
}



//******************************************************************************
//
// DoLoad ()
//
//******************************************************************************

int DoLoad (int which)
{
    gamestorage_t game;
    int exit = 0;

    if ((which >= 0) && SaveGamesAvail[which])
    {
        loadedgame = true;

        if (loadsavesound)
            MN_PlayMenuSnd (SD_SELECTSND);

        if (LoadTheGame (which, &game) == true)
        {
            MenuFixup ();
            DisableScreenStretch();
            StartGame = true;
            exit      = 1;
        }
        else
        {
            if (CP_DisplayMsg ("Saved Game is\n old or incompatible\nDelete it?", 12)==true)
            {
                char loadname[45] = "rottgam0.rot";
                char filename[128];

                // Create the proper file name
                itoa (which, &loadname[7], 16);
                loadname[8]='.';

                GetPathFromEnvironment( filename, ApogeePath, loadname );

                // Delete the file

                unlink (filename);

                memset (&SaveGameNames[which][0], 0, 32);
                SaveGamesAvail[which] = 0;
            }

            loadedgame = false;
            DrawLoadSaveScreenAlt (0);
        }
    }

    return (exit);
}


//******************************************************************************
//
// LOAD SAVED GAMES
//
//******************************************************************************

int CP_LoadGame (int quick, int dieload)
{
    int which,
        exit = 0;


    MenuNum = 6;

    SaveTime = GetTicCount();

    //
    // QUICKLOAD?
    //
    if (quick)
    {
        which = LSItems.curpos;

        if (SaveGamesAvail[which])
        {
            if (dieload)
            {
                DrawLoadSaveScreenAlt (0);
                CP_DrawSelectedGame (which);
                RefreshMenuBuf (0);
                DoLoad (which);

                return (1);
            }
            else
            {
                DrawLoadSaveScreen (0);
                if (CP_DisplayMsg ("Quick load saved game?\nAre you sure?", 12) == true)
                {
                    DrawLoadSaveScreen (0);
                    CP_DrawSelectedGame (which);
                    RefreshMenuBuf (0);
                    DoLoad (which);

                    return (1);
                }
                else
                {
                    return (0);
                }
            }
        }
    }

    DrawLoadSaveScreen (0);
    do
    {
        which = HandleMenu (&LSItems, &LSMenu[0], CP_DrawSelectedGame);

        if ((exit = DoLoad (which)))
            break;

    } while (which >= 0);

    handlewhich = OUTOFRANGE;

    if (MainMenu[loadgame].active == CP_Inactive)    // If all the saved games have been
    {
        MainItems.curpos = 0;               //  deleted dehighlight LOADGAME
        MainMenu[newgame].active = CP_CursorLocation;
    }

    return exit;
}

//******************************************************************************
//
// QuickSaveGame ()
//
//******************************************************************************

void QuickSaveGame (void)
{
    int i;
    int j;
    byte * b;
    byte * s;
    int which;
    gamestorage_t game;
    byte * buf;
    int length;

    char   loadname[45]="rottgam0.rot";
    char   filename[128];

    // Create the proper file name

    itoa(quicksaveslot,&loadname[7],16);
    loadname[8]='.';

    GetPathFromEnvironment( filename, ApogeePath, loadname );
    length=LoadFile(filename,(void **)&buf);
    GetPathFromEnvironment( filename, ApogeePath, QUICKSAVEBACKUP );
    SaveFile(filename,buf,length);
    SafeFree(buf);

    s=&game.picture[0];
    for (i=0; i<320; i+=2)
    {
        b=(byte *)bufferofs+i;
        for (j=0; j<100; j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1))
            *s=*b;
    }

    ScanForSavedGames ();
    which = quicksaveslot;

    if (SaveGamesAvail[which])
    {
        game.episode = gamestate.episode;
        game.area    = gamestate.mapon;
        game.version = ROTTVERSION;
        strcpy (game.message, &SaveGameNames[which][0]);

        if (SaveTheGame (which, &game) == true)
        {
            char str[50];

            strcpy (str, "Game Saved: ");
            strcat (str, &SaveGameNames[which][0]);
            AddMessage(str,MSG_SYSTEM);
        }
        else
        {
            AddMessage("Game Not Saved.",MSG_SYSTEM);
        }
    }
    else
    {
        AddMessage("No Quick Save Slot.",MSG_SYSTEM);
    }

}

//******************************************************************************
//
// UndoQuickSaveGame ()
//
//******************************************************************************

void UndoQuickSaveGame (void)
{
    byte * buf;
    char   loadname[45]="rottgam0.rot";
    char   filename[128];
    int length;

    if (quicksaveslot!=-1)
    {
        // Create the proper file name

        itoa(quicksaveslot,&loadname[7],16);
        loadname[8]='.';
        GetPathFromEnvironment( filename, ApogeePath, QUICKSAVEBACKUP );
        length=LoadFile(filename,(void **)&buf);
        GetPathFromEnvironment( filename, ApogeePath, loadname );
        SaveFile(filename,buf,length);
        SafeFree(buf);
        AddMessage("Previous Quicksave Game Restored.",MSG_SYSTEM);
    }
    else
    {
        AddMessage("No Quick Save Slot Selected.",MSG_SYSTEM);
    }
}


//******************************************************************************
//
// SAVE CURRENT GAME
//
//******************************************************************************
int CP_SaveGame ( void )
{
    int  which,
         exit=0;

    char input[32];
    gamestorage_t game;


    MenuNum = 4;


    DrawLoadSaveScreen (1);

    do
    {
        which = HandleMenu (&LSItems, &LSMenu[0], CP_DrawSelectedGame);
        if (which >= 0)
        {
            //
            // OVERWRITE EXISTING SAVEGAME?
            //
            if (SaveGamesAvail[which]) {
                if (!CP_DisplayMsg (GAMESVD, 12))
                {
                    DrawLoadSaveScreenAlt (1);
                    continue;
                }
                else
                {
                    DrawLoadSaveScreenAlt (1);
                    EraseMenuBufRegion (LSM_X+LSItems.indent, LSM_Y+1+which*9, 80, 8);
                    PrintLSEntry (which);
                }
            }
            quicksaveslot=which;

            DrawStoredGame (savedscreen, gamestate.episode, gamestate.mapon);

            strcpy (input, &SaveGameNames[which][0]);

            if (!SaveGamesAvail[which])
                EraseMenuBufRegion (LSM_X+LSItems.indent+1, LSM_Y+which*9+2,
                                    77, 6);

            if (US_LineInput (LSM_X+LSItems.indent+2, LSM_Y+which*9+2,
                              input, input, true, 22, 75, 0))
            {
                SaveGamesAvail[which] = 1;
                memcpy(&game.picture[0],savedscreen,16000);
                game.episode=gamestate.episode;
                game.area=gamestate.mapon;
                game.version=ROTTVERSION;
                strcpy (game.message, input);
                strcpy (&SaveGameNames[which][0], input);

                if (SaveTheGame(which,&game)==true)
                {
                    MainMenu[loadgame].active=CP_Active;

//               MN_PlayMenuSnd (SD_SELECTSND);
                    exit = 1;
                }
                WaitKeyUp ();
            }
            else
            {
                EraseMenuBufRegion (LSM_X+LSItems.indent+1, LSM_Y+which*9+2,
                                    77, 6);

                PrintX = LSM_X+LSItems.indent+2;
                PrintY = LSM_Y+which*9+2;

                if (SaveGamesAvail[which])
                    DrawMenuBufPropString (PrintX, PrintY, SaveGameNames[which]);
                else
                    DrawMenuBufPropString (PrintX, PrintY, "     - � -");

//            MN_PlayMenuSnd (SD_ESCPRESSEDSND);
                continue;
            }
            break;
        }

    } while (which >= 0);

    handlewhich = OUTOFRANGE;

    return (exit);
}



//******************************************************************************
//
// DEFINE CONTROLS
//
//******************************************************************************

void CP_Control (void)
{
#define CTL_SPC   70

    int which;

    DrawCtlScreen ();
    WaitKeyUp ();

    do
    {
        which = HandleMenu (&CtlItems, &CtlMenu[0], NULL);

        switch (CSTactive)
        {
        case MOUSEENABLE:
            if (MousePresent)
            {
                mouseenabled^=1;
                if (mouseenabled)
                    SDL_SetRelativeMouseMode(SDL_TRUE);
                else
                    SDL_SetRelativeMouseMode(SDL_FALSE);
                
                DrawCtlButtons ();
                CusItems.curpos=-1;
            }
            else
            {
                mouseenabled = 0;
                SDL_SetRelativeMouseMode(SDL_FALSE);
            }
            break;

        case JOYENABLE:
            joystickenabled^=1;
            if ( joystickenabled )
            {
                if ( !CalibrateJoystick() )
                {
                    joystickenabled = 0;
                    joypadenabled = 0;
                }
            }
            else
            {
                joypadenabled = 0;
            }
            DrawCtlScreen();
            break;

        case USEPORT2:
            joystickport^=1;
            if ( joystickport )
            {
                joypadenabled = 0;
            }

            joystickenabled = 1;
            if ( !CalibrateJoystick() )
            {
                joystickenabled = 0;
                joystickport = 0;
            }

            if ( joystickport )
            {
                CtlMenu[ 3 ].active = CP_Inactive;
                joypadenabled = 0;
            }
            else
            {
                CtlMenu[ 3 ].active = CP_Active;
            }

            DrawCtlScreen();
            break;

        case PADENABLE:
            joypadenabled^=1;
            if ( ( joypadenabled ) && ( !joystickenabled ) )
            {
                joystickenabled=1;
                if ( !CalibrateJoystick() )
                {
                    joystickenabled = 0;
                    joypadenabled = 0;
                }

                DrawCtlScreen();
            }
            else
            {
                DrawCtlButtons ();
            }
            break;

        case THRESSENS:
        case MOUSESENS:
        case CUSTOMIZE:
            DrawCtlScreen ();
            break;
        }

    } while (which >= 0);

    DrawControlMenu ();

    if (which < 0)
    {
        handlewhich = 1;
        return;
    }
}


//****************************************************************************
//
// CP_Custom ()
//
//****************************************************************************

void CP_Custom (void)
{
    int which;

    DrawCustomMenu();

    do
    {
        which = HandleMenu (&CustomItems, &CustomMenu[0], NULL);
    } while (which >= 0);

    DrawCtlScreen ();
}


//******************************************************************************
//
// CUSTOMIZE CONTROLS
//
//******************************************************************************

//****************************************************************************
//
// CP_Keyboard ()
//
//****************************************************************************
void CP_Keyboard
(
    void
)

{
    int which;

    MenuNum = 1;

    DrawCustomKeyboard ();

    do
    {
        which = HandleMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ], NULL );
    }
    while( which >= 0 );

    DrawCustomMenu();
}


//******************************************************************************
//
// DEFINE THE KEYBOARD BUTTONS
//
//******************************************************************************

void DefineKey
(
    void
)

{
    boolean tick;
    boolean picked;
    int     timer;
    int     x;
    int     y;

    tick   = false;
    picked = false;
    timer  = GetTicCount();

    x = NORMALKEY_X + 97;
    y = NORMALKEY_Y + ( handlewhich * FontSize[ NormalKeyItems.fontsize ] );

    strcpy( &NormalKeyNames[ handlewhich ][ KEYNAMEINDEX ],
            "     " );

//   SetMenuTitle ( "Select which key to use" );
    ClearMenuBuf();
    DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
    DisplayInfo( 0 );

    DrawMenuBufIString( x + 3, y, "?", 0 );
    DrawMenuBufIString( x + 2, y - 1, "?", HIGHLIGHTCOLOR );

    RefreshMenuBuf( 0 );

    do
    {

        IN_PumpEvents();

        //
        // FLASH CURSOR
        //
        if ( ( GetTicCount() - timer ) > 10 )
        {
            int color;

            if ( tick )
            {
                color = HIGHLIGHTCOLOR;
            }
            else
            {
                color = DIMMEDCOLOR;
            }

            DrawMenuBufIString( x + 3, y, "?", 0 );
            DrawMenuBufIString( x + 2, y - 1, "?", color );

            tick  = !tick;
            timer = GetTicCount();
        }

        RefreshMenuBuf( 0 );


        if ( LastScan )
        {
            int key;

            key = LastScan;
            LastScan = 0;

            buttonscan[ (unsigned int)order[ handlewhich ] ] = key;

            strcpy( &NormalKeyNames[ handlewhich ][ KEYNAMEINDEX ],
                    (char *)IN_GetScanName( key ) );

            picked = true;

            WaitKeyUp();
            Keyboard[ key ] = 0;

            IN_ClearKeysDown();
        }
    }
    while( !picked );

    ClearMenuBuf();
    SetMenuTitle( "Customize Keyboard" );

    DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
    DisplayInfo( 0 );
    RefreshMenuBuf (0);
}

//****************************************************************************
//
// DrawControlSelect ()
//
//****************************************************************************

void DrawControlSelect
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Select Button Function");

    MN_GetCursorLocation( &ControlSelectItems, &ControlSelectMenu[ 0 ] );
    DrawMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ] );

    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// DefineMouseBtn()
//
//****************************************************************************

void DefineMouseBtn
(
    void
)

{
    int button;
    int which;

    button = handlewhich;

    MN_GetActive( &ControlSelectItems, &ControlSelectMenu[ 0 ],
                  buttonmouse[ button ], controlorder );

    DrawControlSelect();

    which = HandleMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ], NULL );
    if ( which != -1 )
    {
        buttonmouse[ button ] = controlorder[ which ];
    }

    handlewhich = OUTOFRANGE;
}

//****************************************************************************
//
// CP_Mouse ()
//
//****************************************************************************
void CP_Mouse
(
    void
)

{
    int which;

    MenuNum = 1;

    do
    {
        DrawCustomMouse();
        which = HandleMenu( &MouseBtnItems, &MouseBtnMenu[ 0 ], NULL );
    }
    while( which >= 0 );

    handlewhich = OUTOFRANGE;

    DrawCustomMenu();
}


//****************************************************************************
//
// DrawCustomMouse ()
//
//****************************************************************************

void DrawCustomMouse
(
    void
)

{
    int i;
    int j;
    int num;
    int button;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Customize Mouse");

    for( i = 0; i < 6; i++ )
    {
        num = 0;
        button = buttonmouse[ i ];
        buttonmouse[ i ] = bt_nobutton;
        MouseBtnNames[ i ][ MOUSEBTNINDEX ] = 0;

        for( j = 0; j < NUMCONTROLNAMES; j++ )
        {
            if ( button == controlorder[ j ] )
            {
                buttonmouse[ i ] = button;
                num = j;
                break;
            }
        }

        strcpy( &MouseBtnNames[ i ][ MOUSEBTNINDEX ],
                ControlNames[ num ] );
    }

    MN_GetCursorLocation( &MouseBtnItems, &MouseBtnMenu[ 0 ] );
    DrawMenu( &MouseBtnItems, &MouseBtnMenu[ 0 ] );

    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// DefineJoyBtn()
//
//****************************************************************************

void DefineJoyBtn
(
    void
)

{
    int button;
    int which;

    button = handlewhich;

    MN_GetActive( &ControlSelectItems, &ControlSelectMenu[ 0 ],
                  buttonjoy[ button ], controlorder );

    DrawControlSelect();

    which = HandleMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ], NULL );
    if ( which != -1 )
    {
        buttonjoy[ button ] = controlorder[ which ];
    }

    handlewhich = OUTOFRANGE;
}


//****************************************************************************
//
// DrawCustomJoystick ()
//
//****************************************************************************

void DrawCustomJoystick
(
    void
)

{
    int i;
    int j;
    int num;
    int button;
    int active;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Customize Joystick");

    for( i = 0; i < 8; i++ )
    {
        num = 0;
        button = buttonjoy[ i ];
        buttonjoy[ i ] = bt_nobutton;
        JoyBtnNames[ i ][ JOYBTNINDEX ] = 0;

        for( j = 0; j < NUMCONTROLNAMES; j++ )
        {
            if ( button == controlorder[ j ] )
            {
                buttonjoy[ i ] = button;
                num = j;
                break;
            }
        }

        strcpy( &JoyBtnNames[ i ][ JOYBTNINDEX ], ControlNames[ num ] );
    }

    JoyBtnMenu[ 0 ].active = CP_Active;
    JoyBtnMenu[ 1 ].active = CP_Active;
    JoyBtnMenu[ 4 ].active = CP_Active;
    JoyBtnMenu[ 5 ].active = CP_Active;

    if ( joypadenabled )
    {
        active = CP_Active;
    }
    else
    {
        active = CP_Inactive;
    }

    JoyBtnMenu[ 2 ].active = active;
    JoyBtnMenu[ 3 ].active = active;
    JoyBtnMenu[ 6 ].active = active;
    JoyBtnMenu[ 7 ].active = active;

    if ( JoyBtnMenu[ JoyBtnItems.curpos ].active == CP_Inactive )
    {
        MN_GetCursorLocation( &JoyBtnItems, &JoyBtnMenu[ 0 ] );
    }
    else
    {
        JoyBtnMenu[ JoyBtnItems.curpos ].active = CP_CursorLocation;
    }

    DrawMenu( &JoyBtnItems, &JoyBtnMenu[ 0 ] );

    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_Joystick ()
//
//****************************************************************************

void CP_Joystick
(
    void
)

{
    int which;

    MenuNum = 1;

    do
    {
        DrawCustomJoystick();
        which = HandleMenu( &JoyBtnItems, &JoyBtnMenu[ 0 ], NULL );
    }
    while( which >= 0 );

    handlewhich = OUTOFRANGE;

    DrawCustomMenu();
}


//******************************************************************************
//
// PRINT A MESSAGE IN A WINDOW
//
//******************************************************************************

void Message (char *string)
{
    int   h = 0,
          w = 0,
          mw = 0,
          i;
    byte *shape;

    shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
    newfont1 = (font_t *)shape;
    CurrentFont = newfont1;
    h = CurrentFont->height;

    for (i = 0; i < (int)strlen (string); i++)
        if (string[i] == '\n')
        {
            if (w > mw)
                mw = w;
            w = 0;
            h += CurrentFont->height;
        }
        else
            w += CurrentFont->width[string[i]-31];

    if ((w + 10) > mw)
        mw = w+10;

    PrintY = 78 - (h / 2);
    PrintX = WindowX = 143 - (mw / 2);
    WindowW = mw;

    EraseMenuBufRegion (WindowX-5, PrintY-5, (mw+14)&0xFFFC, h+10);
    DrawSTMenuBuf (WindowX-5, PrintY-5, (mw+14)&0xFFFC, h+10, true);

    MenuBufCPrint (string);
    RefreshMenuBuf (0);
}



//******************************************************************************
//
// DRAW NEW GAME MENU
//
//******************************************************************************

void DrawNewGame (void)
{
    MenuNum = 5;

    SetAlternateMenuBuf ();
    ClearMenuBuf ();
    SetMenuTitle ("Choose Difficulty");
    DrawMenu (&TufItems, &TufMenu[ToughMenuNum][0]);
    DrawNewGameDiff (TufItems.curpos);
    DisplayInfo (0);
    FlipMenuBuf();

}

//******************************************************************************
//
// DRAW NEW GAME GRAPHIC
//
//******************************************************************************

int newgameY[7] = {19, 0, 42, 0, 74, 0, 93};
char *DifficultyStrings[ 4 ] =
{
    "Easy", "Medium", "Hard", "Crezzy Man"
};

void DrawNewGameDiff
(
    int w
)

{
    int x;

    switch ( w )
    {
    case 0:
        x = 0;
        break;

    case 2:
        x = 1;
        break;

    case 4:
        x = 2;
        break;

    case 6:
        x = 3;
        break;
    }

    EraseMenuBufRegion( 25, 18, 52, 125 );
    DrawMenuBufPic( 25, newgameY[ w ], W_GetNumForName( "NEWG1" ) +
                    ( ToughMenuNum * 4 ) + x );
    EraseMenuBufRegion( 25, 149, 64, 8 );
//   DrawMenuBufPic (25, 149, W_GetNumForName( "O_EASY" ) + x );

    CurrentFont = tinyfont;
    DrawMenuBufPropString( 25, 149, DifficultyStrings[ x ] );
}


//******************************************************************************
//
// DRAW THE LOAD/SAVE SCREEN
//
//******************************************************************************

void DrawLoadSaveScreen (int loadsave)
{
    int i;
    byte *shape;

    shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
    newfont1 = (font_t *)shape;
    CurrentFont = newfont1;

    if (numdone || (!ingame) || (!inmenu))
        SetAlternateMenuBuf();

    ClearMenuBuf();
    if (loadsave)
    {
        SetMenuTitle ("Save Game");
    }
    else
    {
        SetMenuTitle ("Load Game");
    }

    for (i = 0; i < NUMSAVEGAMES; i++)
        PrintLSEntry (i);
    DrawMenuBufItem (LSItems.x, ((LSItems.curpos*9)+(LSItems.y)),
                     W_GetNumForName( SmallCursor ) + CursorFrame[ CursorNum ] );
    DisplayInfo (7);
    if ((!numdone) && ingame && inmenu)
        RefreshMenuBuf (0);
    else
        FlipMenuBuf();

    WaitKeyUp ();

    numdone++;
}

//******************************************************************************
//
// DRAW THE LOAD/SAVE SCREEN - no flip
//
//******************************************************************************

void DrawLoadSaveScreenAlt (int loadsave)
{
    int i;
    byte *shape;

    shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
    newfont1 = (font_t *)shape;
    CurrentFont = newfont1;

    ClearMenuBuf();
    if (loadsave)
    {
        SetMenuTitle ("Save Game");
    }
    else
    {
        SetMenuTitle ("Load Game");
    }

    for (i = 0; i < NUMSAVEGAMES; i++)
        PrintLSEntry (i);
    DrawMenuBufItem (LSItems.x, ((LSItems.curpos*9)+(LSItems.y)),
                     W_GetNumForName( SmallCursor ) + CursorFrame[ CursorNum ] );
    DisplayInfo (7);
    RefreshMenuBuf (0);

    WaitKeyUp ();

    numdone++;
}


//******************************************************************************
//
// PRINT LOAD/SAVE GAME ENTRY W/BOX OUTLINE
//
//******************************************************************************

void PrintLSEntry (int w)
{

    DrawSTMenuBuf (LSM_X+LSItems.indent, LSM_Y+1+w*9, 80, 7, false);

    PrintX = LSM_X+LSItems.indent+2;
    PrintY = LSM_Y+(w*9)+2;

    CurrentFont = tinyfont;

    if (SaveGamesAvail[w])
        DrawMenuBufPropString (PrintX, PrintY, SaveGameNames[w]);
    else
        DrawMenuBufPropString (PrintX, PrintY, "     - � -");
}



//******************************************************************************
//
// CALIBRATE JOYSTICK
//
//******************************************************************************
int CalibrateJoystick
(
    void
)

{
#define CALX   45
#define CALY   22

    word xmax, ymax, xmin, ymin, jb;
    int  checkbits;
    int  status;
    boolean done;

    if ( joypadenabled )
    {
        // Gravis GamePad : Check all buttons
        checkbits = ( 1 << 0 ) + ( 1 << 1 ) + ( 1 << 2 ) + ( 1 << 3 );
    }
    else if ( joystickport )
    {
        // Joystick port 2 : check only buttons 2 and 3
        checkbits = ( 1 << 2 ) + ( 1 << 3 );
    }
    else
    {
        // Joystick port 1 : check only buttons 0 and 1
        checkbits = ( 1 << 0 ) + ( 1 << 1 );
    }

    status = 0;
    done = false;
    while( !done )
    {
        SetAlternateMenuBuf();
        ClearMenuBuf();
        SetMenuTitle ("Calibrate Joystick");
        //DrawMenuBufItem( CALX, CALY, W_GetNumForName( "joystk2" ) );
        WindowW = 288;
        WindowH = 158;
        PrintX = WindowX = 0;
        PrintY = WindowY = 50;

        newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
        CurrentFont = newfont1;
        MenuBufCPrint( "MOVE JOYSTICK TO\nUPPER LEFT AND\nPRESS A BUTTON." );

        DisplayInfo( 2 );
        FlipMenuBuf();

        do
        {
            RefreshMenuBuf( 0 );
            jb = IN_JoyButtons();
            IN_UpdateKeyboard();

            if ( Keyboard[ sc_Escape ] )
            {
                return( 0 );
            }
        }
        while( !( jb & checkbits ) );

        IN_GetJoyAbs( joystickport, &xmin, &ymin );
        MN_PlayMenuSnd( SD_SELECTSND );

        while( IN_JoyButtons() & checkbits )
        {
            IN_UpdateKeyboard();

            if ( Keyboard[ sc_Escape ] )
            {
                return( 0 );
            }
        }

        ClearMenuBuf();
//      DrawMenuBufItem( CALX, CALY, W_GetNumForName( "joystk1" ) );
        WindowW = 288;
        WindowH = 158;
        PrintX = WindowX = 0;
        PrintY = WindowY = 50;

        newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
        CurrentFont = newfont1;
        MenuBufCPrint( "MOVE JOYSTICK TO\nLOWER RIGHT AND\nPRESS A BUTTON." );

        DisplayInfo( 2 );

        do
        {
            RefreshMenuBuf( 0 );
            jb = IN_JoyButtons();
            IN_UpdateKeyboard();

            if ( Keyboard[ sc_Escape ] )
            {
                return( 0 );
            }
        }
        while( !( jb & checkbits ) );

        IN_GetJoyAbs( joystickport, &xmax, &ymax );
        MN_PlayMenuSnd( SD_SELECTSND );

        while( IN_JoyButtons() & checkbits )
        {
            IN_UpdateKeyboard();

            if ( Keyboard[ sc_Escape ] )
            {
                return( 0 );
            }
        }

        //
        // ASSIGN ACTUAL VALUES HERE
        //
        if ( ( xmin < xmax ) && ( ymin < ymax ) )
        {
            IN_SetupJoy( joystickport, xmin, xmax, ymin, ymax );
            joyxmin = xmin;
            joyxmax = xmax;
            joyymin = ymin;
            joyymax = ymax;

            status = 1;
            done = true;
        }
        else
        {
            CP_ErrorMsg( "Joystick Error",
                         "Calibration failed.  The joystick must be moved "
                         "to the upper-left first and then the lower-right.",
                         mn_smallfont );
        }
    }

    return( status );
}


//******************************************************************************
//
// ADJUST MOUSE SENSITIVITY
//
//******************************************************************************

void MouseSensitivity
(
    void
)

{
    SliderMenu( &mouseadjustment, 480, 1, 21, 81, 240, 1, "block1", NULL,
                "Mouse Sensitivity", "Slow", "Ludicrous" );
}

//******************************************************************************
//
// ADJUST MOUSE AND JOYSTICK THRESHOLD
//
//******************************************************************************

void DoThreshold
(
    void
)

{
    SliderMenu (&threshold, 15, 1, 44, 81, 194, 1, "block2", NULL,
                "Adjust Threshold", "Small", "Large" );
}

//******************************************************************************
//
// DRAW CONTROL MENU SCREEN
//
//******************************************************************************

void DrawCtlScreen (void)
{
    MenuNum = 3;

    if (numdone || (!ingame) || (!inmenu))
        SetAlternateMenuBuf();

    ClearMenuBuf();
    SetMenuTitle ("Options");


    DrawCtlButtons ();

    DisplayInfo (0);
    DrawMenu (&CtlItems, &CtlMenu[0]);
    DrawMenuBufItem (CtlItems.x, ((CtlItems.curpos*14)+(CtlItems.y-2)),
                     W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );

    if (ingame && inmenu && (!numdone))
        RefreshMenuBuf (0);
    else
        FlipMenuBuf();

    numdone++;
}


//******************************************************************************
//
// DrawCtlButtons ()
//
//******************************************************************************

void DrawCtlButtons (void)
{
    int i,
        x,
        y;
    static boolean first = true;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName ("snd_on");
    button_off = W_GetNumForName ("snd_off");

    WindowX = 0;
    WindowW = 320;

    if (first)
    {
        if (JoysPresent[0] || JoysPresent[1])
        {
            CtlMenu[JOYENABLE].active = CP_Active;
            CtlMenu[USEPORT2].active  = CP_Active;
            CtlMenu[PADENABLE].active = CP_Active;
            CtlMenu[THRESSENS].active = CP_Active;
        }
        else
        {
            joystickenabled = 0;
            joypadenabled   = 0;
            joystickport    = 0;
        }

        if (MousePresent)
        {
            CtlMenu[THRESSENS].active = CP_Active;
            CtlMenu[MOUSESENS].active = CP_Active;
            CtlMenu[MOUSEENABLE].active = CP_Active;
        }
        else
        {
            CtlMenu[0].active = CP_Inactive;
            mouseenabled = 0;
        }

        for (x = 0; x < CtlItems.amount; x++)
        {
            if (CtlMenu[x].active)
            {
                CtlMenu[x].active = CP_CursorLocation;
                break;
            }
        }
        first = false;
    }

    x = CTL_X+CtlItems.indent-18;
    y = MENU_Y-1;

    if (mouseenabled)
        DrawMenuBufItem (x, y, button_on);
    else
    {
        EraseMenuBufRegion (x, y, 16, 16);
        DrawMenuBufItem  (x, y, button_off);
    }

    y += 14;
    if (joystickenabled)
        DrawMenuBufItem (x, y, button_on);
    else
    {
        EraseMenuBufRegion (x, y, 16, 16);
        DrawMenuBufItem (x, y, button_off);
    }

    y += 14;
    if (joystickport)
        DrawMenuBufItem (x, y, button_on);
    else
    {
        EraseMenuBufRegion (x, y, 16, 16);
        DrawMenuBufItem (x, y, button_off);
    }

    y += 14;
    if (joypadenabled)
        DrawMenuBufItem (x, y, button_on);
    else
    {
        EraseMenuBufRegion (x, y, 16, 16);
        DrawMenuBufItem (x, y, button_off);
    }

    if ((CtlItems.curpos < 0) || (!CtlMenu[CtlItems.curpos].active))
        for (i = 0; i < CtlItems.amount; i++)
            if (CtlMenu[i].active)
            {
                CtlItems.curpos = i;
                break;
            }

}

//******************************************************************************
//
// WAIT FOR CTRLKEY-UP OR BUTTON-UP
//
//******************************************************************************

void WaitKeyUp (void)
{
    ControlInfo ci;

    IN_IgnoreMouseButtons();
    ReadAnyControl (&ci);

    while (ci.button0 || ci.button1 || ci.button2 || ci.button3 ||
            Keyboard[sc_Space] || Keyboard[sc_Enter] || Keyboard[sc_Escape])
    {
        ReadAnyControl (&ci);
        RefreshMenuBuf (0);
        if (Keystate[sc_CapsLock] && Keystate[sc_Q])
            Error("Stuck in WaitKeyUp\n");
    }
}

#define PMOUSE    3
#define SMOUSE    4

//******************************************************************************
//
// READ KEYBOARD, JOYSTICK AND MOUSE FOR INPUT
//
//******************************************************************************

void ReadAnyControl (ControlInfo *ci)
{

    int mouseactive = 0;
    word buttons = 0;
//   struct Spw_IntPacket packet;


    IN_UpdateKeyboard ();  /* implies IN_PumpEvents() ... */
    IN_ReadControl (0, ci);

    if (MousePresent && mouseenabled)
    {
        int mousey,
            mousex;

#if USE_SDL
        INL_GetMouseDelta(&mousex, &mousey);
        if (mousex >= SENSITIVE)
        {
            ci->dir = dir_East;
            mouseactive = 1;
        }
        else if (mousex <= -SENSITIVE)
        {
            ci->dir = dir_West;
            mouseactive = 1;
        }

        if (mousey >= SENSITIVE)
        {
            ci->dir = dir_South;
            mouseactive = 1;
        }
        else if (mousey <= -SENSITIVE)
        {
            ci->dir = dir_North;
            mouseactive = 1;
        }
#endif

        buttons = IN_GetMouseButtons();
        if ( buttons )
        {
            ci->button0 = buttons & 1;
            ci->button1 = buttons & 2;
            ci->button2 = buttons & 4;
            ci->button3 = false;
            mouseactive = 1;
        }
    }

    if (joystickenabled && !mouseactive)
    {
        int jx,jy,jb;


        INL_GetJoyDelta (joystickport, &jx, &jy);

        if (jy<-SENSITIVE)
            ci->dir=dir_North;
        else if (jy>SENSITIVE)
            ci->dir=dir_South;

        if (jx<-SENSITIVE)
            ci->dir=dir_West;
        else if (jx>SENSITIVE)
            ci->dir=dir_East;

        jb = IN_JoyButtons();
        if (jb)
        {
            ci->button0=jb&1;
            ci->button1=jb&2;
            if (joypadenabled)
            {
                ci->button2=jb&4;
                ci->button3=jb&8;
            }
            else
                ci->button2=ci->button3=false;
        }
    }
}


//******************************************************************************
//
// IN_GetScanName () - Returns a string containing the name of the
//                     specified scan code
//
//******************************************************************************

byte * IN_GetScanName (ScanCode scan)
{
    byte     **p;
    ScanCode *s;

    for (s = ExtScanCodes, p = (byte**)ExtScanNames; *s; p++, s++)
        if (*s == scan)
            return (*p);

    return((byte*)ScanNames[scan]);
}


//******************************************************************************
//
// DisplayInfo ()
//
//******************************************************************************

void DisplayInfo (int which)
{
    patch_t *p;
    int x;
    int num;

    num = W_GetNumForName ( "info1" ) + which;
    p = (patch_t *) W_CacheLumpNum (num, PU_CACHE, Cvt_patch_t, 1);

    x = (288 - p->width) >> 1;

    DrawMenuBufItem (x, 149, num);
}


//******************************************************************************
//
// DrawSTMenuBuf()
//
//******************************************************************************

void DrawSTMenuBuf (int x, int y, int w, int h, boolean up)
{
    if (!up)
    {
        DrawTMenuBufHLine (x,   y,   w+1, false);
        DrawTMenuBufVLine (x,   y+1, h-1, false);
        DrawTMenuBufHLine (x,   y+h, w+1, true);
        DrawTMenuBufVLine (x+w, y+1, h-1, true);
    }
    else
    {
        DrawTMenuBufHLine (x,   y,   w+1, true);
        DrawTMenuBufVLine (x,   y+1, h-1, true);
        DrawTMenuBufHLine (x,   y+h, w+1, false);
        DrawTMenuBufVLine (x+w, y+1, h-1, false);
    }
}


//****************************************************************************
//
// DoMainMenu ()
//
//****************************************************************************

void DoMainMenu (void)
{
    EnableScreenStretch();//bna++ shut on streech mode
    SetAlternateMenuBuf();
    ClearMenuBuf();
    DrawMainMenu();
    DrawMenuBufItem (MainItems.x,  ((MainItems.curpos*14)+(MainItems.y-2)),
                     W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
    FlipMenuBuf();
}


//****************************************************************************
//
// DrawCustomMenu ()
//
//****************************************************************************

void DrawCustomMenu (void)
{
    MenuNum = 3;
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Customize Menu");
    MN_GetCursorLocation( &CustomItems, &CustomMenu[ 0 ] );
    DrawMenu (&CustomItems, &CustomMenu[0]);
    DrawMenuBufItem (CustomItems.x, ((CustomItems.curpos*14)+(CustomItems.y-2)),
                     W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
    DisplayInfo (0);
    FlipMenuBuf();
}



//****************************************************************************
//
// DrawCustomKeyboard ()
//
//****************************************************************************
void DrawCustomKeyboard (void)
{
    int i;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Customize Keyboard");

    for( i = 0; i < NormalKeyItems.amount; i++ )
    {
        strcpy( &NormalKeyNames[ i ][ KEYNAMEINDEX ],
                (char*)IN_GetScanName( buttonscan[ (unsigned int)order[ i ] ] ) );
    }

    MN_GetCursorLocation( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
    DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );

    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// MusicVolume ()
//
//****************************************************************************

void MusicVolume (void)
{

    SliderMenu( &MUvolume, 254, 0, 33, 81, 225, 8, "block3", MUSIC_SetVolume,
                "Music Volume", "Low", "High" );

    DrawControlMenu();
}


//****************************************************************************
//
// FXVolume ()
//
//****************************************************************************

void FXVolume
(
    void
)

{
    SliderMenu( &FXvolume, 254, 0, 33, 81, 225, 8, "block3", FX_SetVolume,
                "Sound Volume", "Low", "High" );

    DrawControlMenu();
}



//****************************************************************************
//
// DrawPlayerMenu ()
//
//****************************************************************************

void DrawPlayerMenu (void)
{
    MenuNum = 5;


    MN_MakeActive( &PlayerItems, &PlayerMenu[0], DefaultPlayerCharacter );

#if ( SHAREWARE == 1 )
    PlayerMenu[ 1 ].active = CP_SemiActive; // Thi Barrett
    PlayerMenu[ 2 ].active = CP_SemiActive; // Doug Wendt
    PlayerMenu[ 3 ].active = CP_SemiActive; // Lorelei Ni
    PlayerMenu[ 4 ].active = CP_SemiActive; // Ian Paul Freeley
#endif

    if (numdone || (!ingame) || (!inmenu))
        SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Choose Player");

    DrawMenu (&PlayerItems, &PlayerMenu[0]);
    DrawNewPlayerDiff (PlayerItems.curpos);

    DisplayInfo (0);


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    if (ingame && inmenu && (!numdone))
        RefreshMenuBuf (0);
    else
        FlipMenuBuf();
}

//******************************************************************************
//
// DRAW NEW PLAYER GRAPHIC
//
//******************************************************************************

int newplayerY[5] = {28, 42, 56, 70, 84};

void DrawNewPlayerDiff (int w)
{
    EraseMenuBufRegion (25, 18, 52, 125);
    DrawMenuBufPic (25, newplayerY[w], W_GetNumForName( "PLAYER1" ) + w );
}


//******************************************************************************
//
// MenuFixup ()
//
//******************************************************************************
void MenuFixup
(
    void
)

{
    MainMenu[ viewscores ].texture[ 6 ] = '1';
    MainMenu[ viewscores ].texture[ 7 ] = '0';
    MainMenu[ viewscores ].texture[ 8 ] = '\0';
    MainMenu[ viewscores ].routine      = ( void * )CP_EndGame;
    MainMenu[ viewscores ].letter       = 'E';
    strcpy (MainMenuNames[ viewscores ], "END GAME");
    MainMenu[ savegame ].active         = CP_Active;
    ingame = true;
}

//******************************************************************************
//
// GetEpisode ()
//
//******************************************************************************

void GetEpisode (int level)
{
    if (level < 8)
        gamestate.episode = 1;
    else if (level < 16)
        gamestate.episode = 2;
    else if (level < 24)
        gamestate.episode = 3;
    else
        gamestate.episode = 4;
}


//****************************************************************************
//
// DrawControlMenu ()
//
//****************************************************************************

void DrawControlMenu (void)
{
    MenuNum = 1;

    if (numdone || (!ingame) || (!inmenu))
        SetAlternateMenuBuf();

    ClearMenuBuf();
    SetMenuTitle ("Options");

    MN_GetCursorLocation( &ControlMItems, &ControlMMenu[ 0 ] );
    DrawMenu (&ControlMItems, &ControlMMenu[0]);
    DisplayInfo (0);

    if (ingame && inmenu && (!numdone))
        RefreshMenuBuf (0);
    else
        FlipMenuBuf();

    numdone ++;
}

//****************************************************************************
//
//  CP_ControlMenu ()
//
//****************************************************************************

void CP_ControlMenu (void)
{
    int which;

    DrawControlMenu();

    do
    {
        which = HandleMenu (&ControlMItems, &ControlMMenu[0], NULL);

    } while (which >= 0);

    handlewhich = OUTOFRANGE;
}




//****************************************************************************
//
// DrawOptionsMenu ()
//
//****************************************************************************

void DrawOptionsMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("User Options");

    MN_GetCursorLocation( &OptionsItems, &OptionsMenu[ 0 ] );
    DrawMenu (&OptionsItems, &OptionsMenu[0]);
    DrawOptionsButtons ();
    DisplayInfo (0);
    FlipMenuBuf();
}

void DrawVisualsMenu (void)
{
    MenuNum = 1;
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Visuals Menu");
    
    MN_GetCursorLocation( &VisualOptionsItems, &VisualsOptionsMenu[ 0 ] );
    DrawMenu (&VisualOptionsItems, &VisualsOptionsMenu[0]);
    DrawMenuBufItem (VisualOptionsItems.x, ((VisualOptionsItems.curpos*14)+(VisualOptionsItems.y-2)),
                     W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
    DisplayInfo (0);
    FlipMenuBuf();
    
}

void CP_VisualsMenu(void)
{
    int which;
    DrawVisualsMenu();

    do
    {
        which = HandleMenu (&VisualOptionsItems, &VisualsOptionsMenu[0], NULL);
    } while (which >= 0);

    DrawControlMenu();
}


extern int FocalWidthOffset;

void DoAdjustFocalWidth (void)
{
    SliderMenu (&FocalWidthOffset, 200, 0, 44, 81, 194, 1, "block2", NULL,
                "Adjust Focal Width", "Default", "You Crazy" );
    DrawVisualsMenu ();
}


extern int hudRescaleFactor;
void DoAdjustHudScale (void)
{   
    SliderMenu (&hudRescaleFactor, 10, 0, 44, 81, 194, 1, "block2", NULL,
                "Adjust Hud Scaling", "Small", "Large" );
    DrawVisualsMenu ();
}

void DrawScreenResolutionMenu(void)
{
    int position;
    int i;

    MenuNum = 1;
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Screen Resolution");

    // First time create the menu from our list of resolutions
    if (ScreenResolutions == NULL)
    {
        int nbrResolutions = sizeof(AvailableResolutions) / sizeof(AvailableResolutions[0]);

        ScreenResolutions = malloc(nbrResolutions * sizeof(CP_MenuNames));
        ScreenResolutionMenu = malloc(nbrResolutions * sizeof(CP_itemtype));

        for (i = 0; i < nbrResolutions; i++)
        {
            // Create menu resolution labels. They are already 64 byte chars
            if(AvailableResolutions[i].extraMenuText)
                snprintf(ScreenResolutions[i] , 64, "%dx%d (%s)", AvailableResolutions[i].width, AvailableResolutions[i].height, AvailableResolutions[i].extraMenuText);
            else
                snprintf(ScreenResolutions[i] , 64, "%dx%d", AvailableResolutions[i].width, AvailableResolutions[i].height);

            // Populate items
            ScreenResolutionMenu[i].active = CP_Active;
            ScreenResolutionMenu[i].texture[0] = 0;
            ScreenResolutionMenu[i].letter = ' ';
            ScreenResolutionMenu[i].routine = NULL;
        }

        // Set item info
        ScreenResolutionItems =  (CP_iteminfo){NORMALKEY_X, 17, nbrResolutions, 0, 16, ScreenResolutions, mn_tinyfont};
    }

	// Find the current resolution and select the resolution
    position = 0; // Default select first if current resolution isn't in the list
    for (i = 0; i < ScreenResolutionItems.amount; i++ )
    {
        ScreenResolutionMenu[ i ].active = CP_Active;

        if ( AvailableResolutions[i].width == iGLOBAL_SCREENWIDTH && AvailableResolutions[i].height == iGLOBAL_SCREENHEIGHT)
        {
            position = i;
        }
    }

    ScreenResolutionItems.curpos = position;
	ScreenResolutionMenu[ position ].active = CP_CursorLocation;

    DrawMenu (&ScreenResolutionItems, &ScreenResolutionMenu[0]);

    DisplayInfo (0);
    FlipMenuBuf();
}

void CP_RestartProgramMessage
(
    void
)

{
    CP_ErrorMsg( "Note:",
                 "Changes will not be applied until the application is restarted. "
                 "Hit any key to continue.",
                 mn_smallfont );
}

extern int ScreenWidthToWriteToCfg;
extern int ScreenHeightToWriteToCfg;
extern int HudScaleToWriteToCfg;
extern boolean writeNewResIntoCfg;

void CP_ScreenResolution(void)
{
    int which;

    DrawScreenResolutionMenu();

    which = HandleMenu (&ScreenResolutionItems, &ScreenResolutionMenu[0], NULL);

    if (which >= 0)
    {
        ScreenWidthToWriteToCfg = AvailableResolutions[which].width;
        ScreenHeightToWriteToCfg = AvailableResolutions[which].height;
        HudScaleToWriteToCfg = AvailableResolutions[which].hudScale;
        writeNewResIntoCfg = true;
    }

    if (writeNewResIntoCfg)
        CP_RestartProgramMessage();

    DrawVisualsMenu();
}
extern boolean sdl_fullscreen;
extern boolean borderWindow;
extern boolean borderlessWindow;

void DrawDisplayOptionsButtons (void)
{
    int i,
        on;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName ("snd_on");
    button_off = W_GetNumForName ("snd_off");

    for (i = 0; i < DisplayOptionsMenu.amount; i++)
        if (DisplayOptionsItems[i].active != CP_Active3)
        {
            //
            // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
            //

            on = 0;

            switch (i)
            {
            case 0:
                if (sdl_fullscreen  == 1) on = 1;
                break;
            case 1:
                if (borderWindow == 1)on = 1;
                break;
            case 2:
                if (borderlessWindow == 1) on = 1;
                break;
            default:
                break;
            }

            if (on)
                DrawMenuBufItem (20+22, DisplayOptionsMenu.y+i*14-1, button_on);
            else
                DrawMenuBufItem (20+22, DisplayOptionsMenu.y+i*14-1, button_off);
        }
}

/*
CP_MenuNames DisplayOptionsNames[] = {
    "Fullscreen",
    "Bordered Window",
    "Borderless Window",
};
*/

void DrawDisplayOptionsMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Display Options");

    MN_GetCursorLocation( &DisplayOptionsMenu, &DisplayOptionsItems[ 0 ] );
    DrawMenu (&DisplayOptionsMenu, &DisplayOptionsItems[0]);
    DrawDisplayOptionsButtons();
    
    DisplayInfo (0);

    FlipMenuBuf();
}


void CP_DisplayOptions(void)
{
    DrawDisplayOptionsMenu();

    int which;
    
    do
    {
        which = HandleMenu (&DisplayOptionsMenu, &DisplayOptionsItems[0], NULL);
        switch(which)
        {
            case 0:
                if (!sdl_fullscreen){
                    SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
                    sdl_fullscreen ^= 1;
                    borderWindow = 0;
                    borderlessWindow = 0;
                }
                DrawDisplayOptionsButtons ();
                break;
            case 1:
                if (!borderWindow){
                    if (sdl_fullscreen)
                    {
                        SDL_SetWindowFullscreen(window, 0);
                    }
                    SDL_SetWindowBordered(window, SDL_TRUE);
                    sdl_fullscreen = 0;
                    borderWindow ^=1;
                    borderlessWindow = 0;
                }
                DrawDisplayOptionsButtons ();
                break;
            case 2:
                if (!borderlessWindow){
                    if (sdl_fullscreen)
                    {
                        SDL_SetWindowFullscreen(window, 0);
                    }
                    SDL_SetWindowBordered(window, SDL_FALSE);
                    sdl_fullscreen = 0;
                    borderWindow = 0;
                    borderlessWindow^=1;
                }
                DrawDisplayOptionsButtons();
                break;
            default:
                break;
        }
        
    } while (which >= 0);
    
    DrawVisualsMenu();

}


//****************************************************************************
//
// DrawExtOptionsMenu ()  () bna added
//
//****************************************************************************

void DrawExtOptionsMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Extended User Options");

    MN_GetCursorLocation( &ExtOptionsItems, &ExtOptionsMenu[ 0 ] );
    DrawMenu (&ExtOptionsItems, &ExtOptionsMenu[0]);
    DrawExtOptionsButtons ();
    
    DisplayInfo (0);

    FlipMenuBuf();
}

static char * ExtOptionsDesc[7] = {
    "Allow mouse look.",
    "Invert the mouse.",
    "Move forward and backward using mouse.",
    "Enable Crosshairs.",
    "Allow Jumping (may completely break levels)",
    "Missile weapons are auto aimed after 1st shot.",
    "Allow auto aim."
};

void DrawExtOptionDescription (int w)
{

    int     width;
    int     height;
    char   *string;
    font_t *temp;

    EraseMenuBufRegion (25, 4, 287 - 25, 10 );

    temp = CurrentFont;
    CurrentFont = tinyfont;

    string = ExtOptionsDesc[ w ];

    VW_MeasurePropString ( string, &width, &height );
    DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );

    CurrentFont = temp;


}

extern int inverse_mouse;
extern boolean usemouselook;
extern boolean iG_aimCross;
extern boolean usejump;
extern boolean autoAimMissileWeps;
extern boolean autoAim;
extern boolean allowMovementWithMouseYAxis;



void CP_ExtOptionsMenu (void)
{
    int which;

    DrawExtOptionsMenu();

    do
    {
        which = HandleMenu (&ExtOptionsItems, &ExtOptionsMenu[0], DrawExtOptionDescription);

        switch (which)
        {
        case 0:
            usemouselook  ^= 1;
            DrawExtOptionsButtons ();
            break;
        case 1:
            if (inverse_mouse == 1) {
                inverse_mouse = -1;
            } else {
                inverse_mouse = 1;
            }
            DrawExtOptionsButtons ();
            break;
        case 2:
            allowMovementWithMouseYAxis   ^= 1;
            DrawExtOptionsButtons ();
            break;
        case 3:
            iG_aimCross   ^= 1;
            DrawExtOptionsButtons ();
            break;
        case 4:
            usejump       ^= 1;
            DrawExtOptionsButtons ();
            break;
        case 5:
            autoAimMissileWeps ^= 1;
            DrawExtOptionsButtons();
            break;
        case 6:
            autoAim ^= 1;
            DrawExtOptionsButtons();
            break;
        }

    } while (which >= 0);

    DrawControlMenu();
}

void DrawExtOptionsButtons (void)
{
    int i,
        on;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName ("snd_on");
    button_off = W_GetNumForName ("snd_off");

    for (i = 0; i < ExtOptionsItems.amount; i++)
        if (ExtOptionsMenu[i].active != CP_Active3)
        {
            //
            // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
            //

            on = 0;

            switch (i)
            {
            case 0:
                if (usemouselook  == 1) on = 1;
                break;
            case 1:
                if (inverse_mouse == -1)on = 1;
                break;
            case 2:
                if (allowMovementWithMouseYAxis   == 1) on = 1;
                break;
            case 3:
                if (iG_aimCross   == 1) on = 1;
                break;
            case 4:
                if (usejump       == 1) on = 1;
                break;
            case 5:
                if (autoAimMissileWeps == 1) on = 1;
                break;
            case 6:
                if (autoAim == 1) on = 1;
                break;
            }

            if (on)
                DrawMenuBufItem (20+22, ExtOptionsItems.y+i*14-1, button_on);
            else
                DrawMenuBufItem (20+22, ExtOptionsItems.y+i*14-1, button_off);
        }
}
extern boolean allowBlitzMoreMissileWeps;
extern boolean enableAmmoPickups;
extern boolean enableZomROTT;
extern boolean enableExtraPistolDrops;
static char *ExtGameOptionsDesc[ sizeof(ExtGameOptionsItems)] =
{
    "Allow Blitzguards to be randomly given any missile weapon.",
    "Take ammo from dropped missile weapons upon touching them.",
    "Guards with pistols drop their pistol when killed.",
    "If enabled, guards will respawn UNLESS if GIBBED."
};

void DrawExtGameOptionsButtons (void)
{
    int i,
        on;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName ("snd_on");
    button_off = W_GetNumForName ("snd_off");

    for (i = 0; i < ExtGameOptionsItems.amount; i++)
        if (ExtGameMenu[i].active != CP_Active3)
        {
            //
            // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
            //

            on = 0;

            switch (i)
            {
            case 0:
                if (allowBlitzMoreMissileWeps  == 1){
                    on = 1;
                }
                break;
            case 1:
                if (enableAmmoPickups == 1) {
/*
                    EraseMenuBufRegion (25, 4, 287 - 25, 10 );
                    DrawOptionDescription( ExtGameOptionsDesc, 1);
*/
                    on = 1;
                }
                break;
            case 2:
                if (enableExtraPistolDrops == 1){
/*
                    EraseMenuBufRegion (25, 4, 287 - 25, 10 );
                    DrawOptionDescription( ExtGameOptionsDesc, 2 );
*/
                    on = 1;
                }
                break;
            case 3:
                if (enableZomROTT == 1) {
/*
                    EraseMenuBufRegion (25, 4, 287 - 25, 10 );
                    DrawOptionDescription( ExtGameOptionsDesc, 3 );
*/
                    on = 1;
                }
                break;
            }


            if (on)
                DrawMenuBufItem (20+22, ExtGameOptionsItems.y+i*14-1, button_on);
            else
                DrawMenuBufItem (20+22, ExtGameOptionsItems.y+i*14-1, button_off);
        }

}

void DrawExtGameMenu (void)
{
    MenuNum = 1;
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Extended Game Options");

    MN_GetCursorLocation( &ExtGameOptionsItems, &ExtGameMenu[0]);

    DrawMenu(&ExtGameOptionsItems, &ExtGameMenu[0]);

    DrawExtGameOptionsButtons();

    DisplayInfo(0);

    FlipMenuBuf();

}

void DrawExtGameOptionDescription (int w)
{

    int     width;
    int     height;
    char   *string;
    font_t *temp;

    EraseMenuBufRegion (25, 4, 287 - 25, 10 );

    temp = CurrentFont;
    CurrentFont = tinyfont;

    string = ExtGameOptionsDesc[ w ];

    VW_MeasurePropString ( string, &width, &height );
    DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );

    CurrentFont = temp;


}


//****************************************************************************
//
// DrawExtGameOptionsMenu ()  () LT added
//
//****************************************************************************

void CP_ExtGameOptionsMenu (void)
{
    int which;

    DrawExtGameMenu();

    do
    {
        //EraseMenuBufRegion (25, 4, 287 - 25, 10 );
        //DrawOptionDescription( ExtGameOptionsDesc, w );
        which = HandleMenu (&ExtGameOptionsItems, &ExtGameMenu[0], DrawExtGameOptionDescription);

        //EraseMenuBufRegion (25, 4, 287 - 25, 10 );
        //DrawOptionDescription( ExtGameOptionsDesc, which);
        
        switch (which)
        {
        case 0:
            allowBlitzMoreMissileWeps  ^= 1;
            DrawExtGameOptionsButtons ();
            break;
        case 1:
            enableAmmoPickups ^= 1;
            DrawExtGameOptionsButtons();
            break;
        case 2:
            enableExtraPistolDrops ^= 1;
            DrawExtGameOptionsButtons();
            break;
        case 3:
            enableZomROTT ^= 1;
            DrawExtGameOptionsButtons();
            break;
        }
    } while (which >= 0);

    DrawControlMenu();
}


//****************************************************************************
//
// CP_OptionsMenu ()
//
//****************************************************************************

void CP_OptionsMenu (void)
{
    int which;

    DrawOptionsMenu();

    do
    {
        which = HandleMenu (&OptionsItems, &OptionsMenu[0], NULL);

        switch (which)
        {
        case 0:
            AutoDetailOn  ^= 1;
            DrawOptionsButtons ();
            break;
        case 1:
            fulllight     ^= 1;
            DrawOptionsButtons ();
            break;
        case 2:
            BobbinOn      ^= 1;
            DrawOptionsButtons ();
            break;
        case 3:
            fandc         ^= 1;
            DrawOptionsButtons ();
            break;
        }

    } while (which >= 0);

    DrawControlMenu();
}

//****************************************************************************
//
// DrawOptionsButtons
//
//****************************************************************************

void DrawOptionsButtons (void)
{
    int i,
        on;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName ("snd_on");
    button_off = W_GetNumForName ("snd_off");

    for (i = 0; i < OptionsItems.amount-5; i++)
        if (OptionsMenu[i].active != CP_Active3)
        {
            //
            // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
            //

            on = 0;

            switch (i)
            {
            case 0:
                if (AutoDetailOn  == 1) on = 1;
                break;
            case 1:
                if (fulllight     == 0) on = 1;
                break;
            case 2:
                if (BobbinOn      == 1) on = 1;
                break;
            case 3:
                if (fandc         == 1) on = 1;
                break;
            }

            if (on)
                DrawMenuBufItem (20+22, OptionsItems.y+i*14-1, button_on);
            else
                DrawMenuBufItem (20+22, OptionsItems.y+i*14-1, button_off);
        }
}


//****************************************************************************
//
// CP_DoubleClickSpeed()
//
//****************************************************************************

void CP_DoubleClickSpeed
(
    void
)

{
    int temp;

    temp = 50 - ( DoubleClickSpeed - 5 );
    SliderMenu( &temp, 50, 5, 31, 81, 225, 3, "block1", NULL,
                "Double-Click Speed", "Slow", "Fast" );
    DoubleClickSpeed = 50 - ( temp - 5 );

    handlewhich = 100;
    DrawOptionsMenu();
}

//****************************************************************************
//
// MenuFlipSpeed ()
//
//****************************************************************************

void MenuFlipSpeed
(
    void
)

{
    int temp;

    temp = 50 - ( Menuflipspeed - 5 );

    SliderMenu( &temp, 50, 5, 31, 81, 225, 3, "block1", NULL,
                "Menu Flip Speed", "Slow", "Fast" );

    Menuflipspeed = 50 - ( temp - 5 );

    DrawOptionsMenu ();
    handlewhich = 10;
}


//****************************************************************************
//
// DrawDetailMenu ()
//
//****************************************************************************

void DrawDetailMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Detail Menu");

    MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
    MN_GetCursorLocation( &DetailItems, &DetailMenu[ 0 ] );
    DrawMenu (&DetailItems, &DetailMenu[0]);
    DisplayInfo (0);
    FlipMenuBuf();
}

//****************************************************************************
//
// CP_DetailMenu ()
//
//****************************************************************************

void CP_DetailMenu (void)
{
    int which;

    DrawDetailMenu();

    do
    {
        which = HandleMenu (&DetailItems, &DetailMenu[0], NULL);

        switch (which)
        {
        case 0:
            DetailLevel = 0;
            MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
            break;

        case 1:
            DetailLevel = 1;
            MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
            break;

        case 2:
            DetailLevel = 2;
            MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
            break;
        }

    } while (which >= 0);

    handlewhich = 10;
    DrawOptionsMenu();
}


//****************************************************************************
//
// DrawBattleMenu ()
//
//****************************************************************************

void DrawBattleMenu (void)
{
    MenuNum = 1;

    if (numdone || (!ingame) || (!inmenu))
        SetAlternateMenuBuf();

    ClearMenuBuf();
    SetMenuTitle ("Battle Menu");

    DrawBattleModeName( gamestate.battlemode );

    MN_GetCursorLocation( &BattleItems, &BattleMenu[ 0 ] );
    DrawMenu (&BattleItems, &BattleMenu[0]);
    DisplayInfo (0);

    BATTLE_SetOptions( &BATTLE_Options[ gamestate.battlemode ] );
    ShowBattleOptions( true, MENU_X, MENU_Y + 49 );

    if (ingame && inmenu && (!numdone))
        RefreshMenuBuf (0);
    else
        FlipMenuBuf();
}


//****************************************************************************
//
// BattleGamePlayerSetup()
//
//****************************************************************************

void BattleGamePlayerSetup( void )
{
    int status;
    int pos;

    pos = 1;
    if ( consoleplayer == 0 )
    {
        pos = 0;
    }

    while( 1 )
    {
        switch( pos )
        {
        case 0 :
            // Select level to play on
            status = CP_LevelSelectionMenu ();
            if ( status >= 0  )
            {
                gamestate.mapon=status;
                pos = 1;
            }
            else
            {
                DrawBattleMenu();
                return;
            }
            break;

        case 1 :
            // Select CodeName
            status = CP_EnterCodeNameMenu();
            pos = 2;
            if ( !status )
            {
                if ( consoleplayer == 0 )
                {
                    pos = 0;
                }
                else
                {
                    return;
                }
            }
            break;

        case 2 :
            // Select character
            status = CP_PlayerSelection ();
            pos = 1;
            if ( status )
            {
                pos = 3;
            }
            break;

        case 3 :
            // Select color/team
            status = CP_ColorSelection();
            pos = 2;
            if ( status )
            {
                StartGame   = true;
                DisableScreenStretch();
                handlewhich = -2;
                playstate   = ex_resetgame;
                BATTLEMODE  = true;
                // Show please wait
                CP_ModemGameMessage( consoleplayer );
                return;
            }
            break;
        }
    }
}


//****************************************************************************
//
// BattleNoTeams()
//
//****************************************************************************

void BattleNoTeams( void )
{
    BattleGamePlayerSetup();
    if ( StartGame )
    {
        gamestate.teamplay = false;
    }
}


//****************************************************************************
//
// BattleTeams()
//
//****************************************************************************

void BattleTeams( void )
{
    BattleGamePlayerSetup();
    if ( StartGame )
    {
        gamestate.teamplay = true;
    }
}


//****************************************************************************
//
// CP_BattleMenu ()
//
//****************************************************************************

void CP_BattleMenu (void)
{
    int which;

    gamestate.battlemode = handlewhich + battle_Normal;

    BattleMenu[0].active = CP_Active;
    BattleMenu[1].active = CP_Active;


    // Tag can't be played in team mode
    // Also, can't play teams if only 1 person is playing
    if ( ( gamestate.battlemode == battle_Tag ) ||
            ( numplayers < 2 ) )
    {
        BattleMenu[1].active = CP_Inactive;
        if ( BattleItems.curpos == 1 )
        {
            BattleItems.curpos = 0;
        }
    }

    // Capture the Triad can only be played in team mode
    if ( gamestate.battlemode == battle_CaptureTheTriad )
    {
        BattleMenu[0].active = CP_Inactive;
        if ( BattleItems.curpos == 0 )
        {
            BattleItems.curpos = 1;
        }
    }

    BattleMenu[ BattleItems.curpos ].active = CP_CursorLocation;
    DrawBattleMenu();

    do
    {
        which = HandleMenu (&BattleItems, &BattleMenu[0], NULL);
    }
    while (which >= 0);

    if ( which == -1 )
    {
        DrawBattleModes ();
        handlewhich = OUTOFRANGE;
    }
}


//****************************************************************************
//
// MN_PlayMenuSnd ()
//
//****************************************************************************

extern boolean dopefish;
void MN_PlayMenuSnd (int which)
{
    if (INFXSETUP || (SD_Started == false))
        return;
#if (SHAREWARE==0)
    if (dopefish==true)
    {
        switch (which)
        {
        case SD_ESCPRESSEDSND:
            which = SD_SOUNDESCSND;
            break;
        case SD_MOVECURSORSND:
            which = SD_SILLYMOVESND;
            break;
        case SD_SELECTSND:
            which = SD_SOUNDSELECTSND;
            break;
        }
    }
#endif
    SD_Play (which);
}


//******************************************************************************
//
// SliderMenu ()
//
//******************************************************************************

boolean SliderMenu
(
    int *number,
    int upperbound,
    int lowerbound,
    int erasex,
    int erasey,
    int erasew,
    int numadjust,
    char *blockname,
    void ( *routine )( int w ),
    char *title,
    char *left,
    char *right
)

{
    ControlInfo ci;
    Direction   lastdir;
    patch_t    *shape;
    boolean     returnval;
    boolean     moved;
    unsigned long scale;
    int         exit;
    int         range;
    int         timer;
    int         width;
    int         height;
    int         blkx;
    int         eraseh;
    int         block;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle( title );

    newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1);
    CurrentFont = newfont1;
    PrintX = 25;
    PrintY = 62;
    DrawMenuBufPropString( PrintX, PrintY, left );

    VW_MeasurePropString( right, &width, &height );
    DrawMenuBufPropString( 263 - width, PrintY, right );

    block = W_GetNumForName( blockname );
    shape = ( patch_t * )W_CacheLumpNum( block, PU_CACHE, Cvt_patch_t, 1 );
    blkx  = erasex - shape->leftoffset;
    eraseh =  shape->height;
    scale = ( erasew + shape->leftoffset - shape->width ) << 16;
    range = upperbound - lowerbound;

    DrawSTMenuBuf( erasex - 1, erasey - 1, erasew + 1, eraseh + 1, false );

    DrawMenuBufItem( blkx + ( ( ( ( *number - lowerbound ) *
                                  scale ) / range ) >> 16 ), erasey, block );

    DisplayInfo( 1 );
    FlipMenuBuf();

    exit  = 0;
    moved = false;
    timer = GetTicCount();
    lastdir = dir_None;

    do
    {
        RefreshMenuBuf( 0 );

        ReadAnyControl( &ci );
        if ( ( ( GetTicCount() - timer ) > 5 ) || ( ci.dir != lastdir ) )
        {
            timer = GetTicCount();

            switch( ci.dir )
            {
            case dir_North:
            case dir_West:
                if ( *number > lowerbound )
                {
                    *number = *number - numadjust;

                    if ( *number < lowerbound )
                    {
                        *number = lowerbound;
                    }

                    moved = true;
                }
                break;

            case dir_South:
            case dir_East:
                if ( *number < upperbound )
                {
                    *number = *number + numadjust;

                    if ( *number > upperbound )
                    {
                        *number = upperbound;
                    }

                    moved = true;
                }
                break;
            default:
                ;
            }

            lastdir = ci.dir;
        }

        if ( moved )
        {
            moved = false;

            EraseMenuBufRegion( erasex, erasey, erasew, eraseh );

            DrawMenuBufItem( blkx + ( ( ( ( *number - lowerbound ) *
                                          scale ) / range ) >> 16 ), erasey, block );

            if ( routine )
            {
                routine( *number );
            }

            MN_PlayMenuSnd( SD_MOVECURSORSND );
        }

        if ( ci.button0 || Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] )
        {
            exit = 1;
        }
        else if ( ci.button1 || Keyboard[ sc_Escape ] )
        {
            exit = 2;
        }
    }
    while( !exit );

    if ( exit == 2 )
    {
        MN_PlayMenuSnd( SD_ESCPRESSEDSND );
        returnval = false;
    }
    else
    {
        MN_PlayMenuSnd( SD_SELECTSND );
        returnval = true;
    }

    WaitKeyUp ();
    return( returnval );
}


//******************************************************************************
//
// DrawF1Help ()
//
//******************************************************************************

void DrawF1Help (void)
{

    VL_DrawPostPic (W_GetNumForName("trilogo"));

    DrawNormalSprite (0, 0, W_GetNumForName("help"));

    VW_UpdateScreen ();
}

//******************************************************************************
//
// CP_F1Help ()
//
//******************************************************************************

void CP_F1Help (void)
{
    LastScan=0;

    DrawF1Help ();

    while (LastScan == 0)
    {
        IN_UpdateKeyboard ();
    }

    LastScan=0;
#if (SHAREWARE==1)
    {
        DrawOrderInfo( 2 );
        while (LastScan == 0)
        {
            IN_UpdateKeyboard ();
        }

        LastScan=0;
    }
#endif
}


//****************************************************************************
//
// CP_ScreenSize()
//
//****************************************************************************

void CP_ScreenSize
(
    void
)

{
    SliderMenu( &viewsize, MAXVIEWSIZES - 1, 0, 33, 81, 225, 1, "block1",
                NULL, "Screen Size", "Small", "Large" );

    handlewhich = 100;
    DrawOptionsMenu();
}


//****************************************************************************
//
// DrawViolenceMenu ()
//
//****************************************************************************

void DrawViolenceMenu (void)
{
    MenuNum = 1;
    if ( POK )
    {
        memcpy( &VMenu[ 1 ].texture, "mcpass\0", 7 );
        VMenu[ 1 ].letter = 'C';
        strcpy (VMenuNames[ 1 ], "CHANGE PASSWORD");
    }
    else
    {
        memcpy( &VMenu[ 1 ].texture, "mepass\0", 7 );
        VMenu[ 1 ].letter = 'E';
        strcpy (VMenuNames[ 1 ], "ENTER PASSWORD");
    }

    if (VMenu[0].active != CP_CursorLocation)
        VMenu[0].active = CP_Active;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Violence Level");

    MN_GetCursorLocation( &VItems, &VMenu[ 0 ] );
    DrawMenu (&VItems, &VMenu[0]);
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_ViolenceMenu ()
//
//****************************************************************************

void CP_ViolenceMenu (void)
{
    int which;

    CurrentFont = smallfont;
    DrawViolenceMenu ();

    do
    {
        which = HandleMenu (&VItems, &VMenu[0], NULL);

    } while (which >= 0);

    handlewhich = 100;
    DrawOptionsMenu();
}


//****************************************************************************
//
// DrawViolenceLevel ()
//
//****************************************************************************

void DrawViolenceLevel (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Change Violence Level");

    MN_DrawButtons (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);
    MN_GetActive (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);

//   DrawMenuBufItem (58, 24, W_GetNumForName ("blood"));
    IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
                                          PU_CACHE, Cvt_cfont_t, 1 );
    DrawMenuBufIString( 58, 24, "HOW MUCH ", NORMALCOLOR );
    DrawMenuBufIString( PrintX, PrintY, "BLOOD", 51 );
    DrawMenuBufIString( 71, 37, "DO YOU WANT?", NORMALCOLOR );

    DrawMenu (&ViolenceItems, &ViolenceMenu[0]);
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_ViolenceLevel ()
//
//****************************************************************************

void CP_ViolenceLevel (void)
{
    int which;
    char p1[13];
    boolean passok=false;

    if (ingame)
    {
        CP_ErrorMsg( "Change Violence Level",
                     "The current game must be ended to change the Violence Level.",
                     mn_largefont );
    }
    else if ( POK )
    {
        memset (p1, 0, 13);

        CurrentFont = smallfont;
        DrawViolenceLevelPWord ();

        if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, 110, 0))
        {
            //compare user entered to password
            if (StringsNotEqual (p1, pword, StringLength (p1)) == false)
                passok=true;
            else
            {
                CP_ErrorMsg( "Violence Password", "Incorrect Password.",
                             mn_largefont );
            }
        }
    }
    else
        passok=true;
    if (passok==true)
    {
        DrawViolenceLevel ();
        do
        {
            which = HandleMenu (&ViolenceItems, &ViolenceMenu[0], NULL);

            if (which >= 0)
                gamestate.violence = which;

            MN_DrawButtons (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);

        } while (which >= 0);

        WriteMenuInfo ();
    }

    handlewhich = 100;
    DrawViolenceMenu();
}



//****************************************************************************
//
// DrawViolenceLevelPWord ();
//
//****************************************************************************

void DrawViolenceLevelPWord
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle( "Violence Password" );

//   CurrentFont = newfont1;
//   DrawMenuBufPropString( PWORDX, PWORDY, "ENTER PASSWORD" );

    IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
                                          PU_CACHE, Cvt_cfont_t, 1 );
    DrawMenuBufIString( PWORDX, PWORDY, "ENTER PASSWORD", NORMALCOLOR );

    DrawSTMenuBuf( PBOXX, PBOXY, PBOXW, PBOXH, false );
    FlipMenuBuf();
}



//****************************************************************************
//
// DrawPWMenu ()
//
//****************************************************************************

void DrawPWMenu
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle( "Violence Password" );

//   CurrentFont = newfont1;
    IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
                                          PU_CACHE, Cvt_cfont_t, 1 );

    if ( POK )
    {
//      DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER OLD PASSWORD" );
        DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER OLD PASSWORD", NORMALCOLOR );
    }
    else
    {
//      DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER PASSWORD" );
        DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER PASSWORD", NORMALCOLOR );
    }

    DrawSTMenuBuf( PBOXX, PBOXY, PBOXW, PBOXH, false );
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_PWMenu ()
//
//****************************************************************************

void CP_PWMenu (void)
{
    char p1[13];
    char p2[13];
    boolean EnterNewPassword;
    boolean AskForNew;
    boolean RetypePassword;

    memset (p1, 0, 13);
    memset (p2, 0, 13);

    CurrentFont = smallfont;

    EnterNewPassword = true;
    if ( POK )
    {
        DrawPWMenu ();

        // get old password
        //
        EnterNewPassword = false;
        if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, PSTRW, 0))
        {
            //compare user entered to old
            //
            if (StringsNotEqual (p1, pword, StringLength (p1))==false)
            {

                // Password was correct so they may change it.
                EnterNewPassword = true;
            }
            else
            {
                CP_ErrorMsg( "Violence Password", "Incorrect Password.",
                             mn_largefont );
            }
        }
    }

    if ( EnterNewPassword )
    {
        MenuNum = 1;

        // get new password
        //
        AskForNew = true;
        RetypePassword = false;
        while( AskForNew )
        {
            CurrentFont = smallfont;

            SetAlternateMenuBuf ();
            ClearMenuBuf();
            SetMenuTitle ("Violence Password");

            IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
                                                  PU_CACHE, Cvt_cfont_t, 1 );
            DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER NEW PASSWORD", NORMALCOLOR );

//         CurrentFont = newfont1;
//         DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER NEW PASSWORD" );
//         DrawMenuBufItem (PWORDX-24, PWORDY, W_GetNumForName ("mnewpass"));

            DrawSTMenuBuf (PBOXX, PBOXY, PBOXW, PBOXH, false);
            FlipMenuBuf();

            memset (p1, 0, 13);

            AskForNew = false;
            if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, PSTRW, 0))
            {
                // Check for blank password
                if ( p1[ 0 ] == 0 )
                {
                    if ( CP_DisplayMsg ( "Clear Password?\nAre you sure?", 12 ) )
                    {
                        AskForNew = false;
                        memset (pword, 0, 13);
                        WriteMenuInfo ();
                        POK = false;
                    }
                    else
                    {
                        AskForNew = true;
                    }
                }
                else
                {
                    RetypePassword = true;
                }
            }
        }

        if ( RetypePassword )
        {
            SetAlternateMenuBuf();
            ClearMenuBuf();
            SetMenuTitle ("Violence Password");

//         CurrentFont = newfont1;
//         DrawMenuBufPropString( PWORDX, PWORDY, "RETYPE PASSWORD" );

            IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
                                                  PU_CACHE, Cvt_cfont_t, 1 );
            DrawMenuBufIString( PWORDX, PWORDY, "RETYPE PASSWORD", NORMALCOLOR );

            DrawSTMenuBuf (PBOXX, PBOXY, PBOXW, PBOXH, false);

            FlipMenuBuf();

            // reenter password
            //
            if ( US_lineinput (PBOXX+2, PBOXY+1, p2, NULL, true, 12, PSTRW, 0) )
            {
                // compare password and retyped password
                //
                if (stricmp (p1, p2) == 0)
                {
                    memset (pword, 0, 13);
                    strcpy (pword, p1);
                    WriteMenuInfo ();

                    // If we have a null password, then we don't need to
                    // ask for one.
                    POK = true;
                    if ( pword[ 0 ] == 0 )
                    {
                        POK = false;
                    }
                }
                else
                {
                    CP_ErrorMsg( "Violence Password", "Passwords did not match.",
                                 mn_largefont );
                }
            }
        }
    }

    DrawViolenceMenu ();
}

//****************************************************************************
//
// DrawOptionDescription()
//
//****************************************************************************

void DrawOptionDescription( char ** options, int w )
{
    int     width;
    int     height;
    char   *string;
    font_t *temp;

    EraseMenuBufRegion (25, 4, 287 - 25, 10 );

    temp = CurrentFont;
    CurrentFont = tinyfont;

    string = options[ w ];

    VW_MeasurePropString ( string, &width, &height );
    DrawMenuBufPropString ( ( 288 - width) / 2, 4, string );

    CurrentFont = temp;
}

//****************************************************************************
//
// DrawBattleOptionDescription()
//
//****************************************************************************

void DrawBattleOptionDescription( int w )
{
    DrawOptionDescription( BattleOptionDescriptions, w );
}
//****************************************************************************
//
// DrawGravityOptionDescription()
//
//****************************************************************************

void DrawGravityOptionDescription( int w )
{
    DrawOptionDescription( GravityOptionDescriptions, w );
}
//****************************************************************************
//
// DrawSpeedOptionDescription()
//
//****************************************************************************

void DrawSpeedOptionDescription( int w )
{
    DrawOptionDescription( SpeedOptionDescriptions, w );
}
//****************************************************************************
//
// DrawAmmoOptionDescription()
//
//****************************************************************************

void DrawAmmoOptionDescription( int w )
{
    DrawOptionDescription( AmmoOptionDescriptions, w );
}
//****************************************************************************
//
// DrawHitPointsOptionDescription()
//
//****************************************************************************

void DrawHitPointsOptionDescription( int w )
{
    DrawOptionDescription( HitPointsOptionDescriptions, w );
}
//****************************************************************************
//
// DrawRadicalOptionDescription()
//
//****************************************************************************

void DrawRadicalOptionDescription( int w )
{
    DrawOptionDescription( RadicalOptionDescriptions, w );
}
//****************************************************************************
//
// DrawLightLevelOptionDescription()
//
//****************************************************************************

void DrawLightLevelOptionDescription( int w )
{
    DrawOptionDescription( LightLevelOptionDescriptions, w );
}
//****************************************************************************
//
// DrawPointGoalOptionDescription()
//
//****************************************************************************

void DrawPointGoalOptionDescription( int w )
{
    DrawOptionDescription( PointGoalOptionDescriptions, w );
}
//****************************************************************************
//
// DrawDangerDamageOptionDescription()
//
//****************************************************************************

void DrawDangerDamageOptionDescription( int w )
{
    DrawOptionDescription( DangerDamageOptionDescriptions, w );
}

//****************************************************************************
//
// DrawTimeLimitOptionDescription()
//
//****************************************************************************

void DrawTimeLimitOptionDescription( int w )
{
    DrawOptionDescription( TimeLimitOptionDescriptions, w );
}



#define TURN_OFF_BATTLE_MODE( x ) \
   ModeMenu[ ( x ) - 1 ].active  = CP_SemiActive; \
   ModeMenu[ ( x ) - 1 ].routine = NULL;


//****************************************************************************
//
// DrawBattleModes ()
//
//****************************************************************************
void DrawBattleModes
(
    void
)

{
    int i;

    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Battle Modes");


    MN_GetActive( &ModeItems, &ModeMenu[ 0 ], gamestate.battlemode -
                  battle_Normal, OptionNums );

#if ( SHAREWARE == 1 )
    TURN_OFF_BATTLE_MODE( battle_ScoreMore );
    TURN_OFF_BATTLE_MODE( battle_Scavenger );
    TURN_OFF_BATTLE_MODE( battle_Tag );
    TURN_OFF_BATTLE_MODE( battle_Eluder );
    TURN_OFF_BATTLE_MODE( battle_Deluder );
    TURN_OFF_BATTLE_MODE( battle_CaptureTheTriad );
#endif

    // Capture the Triad, Tag, ScoreMore, and Hunter can only be
    // played with 2 or more players
    if ( numplayers < 2 )
    {
        TURN_OFF_BATTLE_MODE( battle_ScoreMore );
        TURN_OFF_BATTLE_MODE( battle_Tag );
        TURN_OFF_BATTLE_MODE( battle_Hunter );
        TURN_OFF_BATTLE_MODE( battle_CaptureTheTriad );
    }

    if ( ModeMenu[ ModeItems.curpos ].active != CP_CursorLocation )
    {
        for( i = 0; i < ModeItems.amount; i++ )
        {
            if ( ModeMenu[ i ].active == CP_Active )
            {
                ModeItems.curpos = i;
                ModeMenu[ i ].active = CP_CursorLocation;
                break;
            }
        }
    }

    DrawMenu( &ModeItems, &ModeMenu[ 0 ] );
    DisplayInfo( 0 );
    DrawBattleModeDescription( ModeItems.curpos );

    FlipMenuBuf();
}



//****************************************************************************
//
// DrawBattleModeName()
//
//****************************************************************************

void DrawBattleModeName( int which )
{
    int     width;
    int     height;
    char   *string;
    font_t *temp;


    if ( ( which < battle_Normal ) || ( which > battle_CaptureTheTriad ) )
    {
        return;
    }

    string = BattleModeNames[ which - battle_Normal ];

    temp = CurrentFont;
    CurrentFont = tinyfont;

    VW_MeasurePropString ( string, &width, &height );
    DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );
//   DrawMenuBufPropString ( 270-width, 4, string );

    CurrentFont = temp;
}


//****************************************************************************
//
// DrawBattleModeDescription()
//
//****************************************************************************

void DrawBattleModeDescription( int w )
{
    int     width;
    int     height;
    char   *string;
    font_t *temp;

    EraseMenuBufRegion (25, 4, 287 - 25, 10 );

    temp = CurrentFont;
    CurrentFont = tinyfont;

    string = BattleModeDescriptions[ w ];

    // Capture the Triad, Tag, ScoreMore, and Hunter can only be
    // played with 2 or more players
    if ( numplayers < 2 )
    {
        switch( w + 1 )
        {
        case battle_ScoreMore :
        case battle_Tag :
        case battle_Hunter :
        case battle_CaptureTheTriad :
            string = "This mode can only be played with 2 or more players.";
            break;
        }
    }

#if ( SHAREWARE == 1 )
    switch( w + 1 )
    {
    case battle_ScoreMore :
    case battle_Scavenger :
    case battle_Tag :
    case battle_Eluder :
    case battle_Deluder :
    case battle_CaptureTheTriad :
        string = "See Ordering Info to find out how to get this game.";
        break;
    }
#endif

    VW_MeasurePropString ( string, &width, &height );
    DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );

    CurrentFont = temp;
}


//****************************************************************************
//
// CP_BattleModes ()
//
//****************************************************************************

void CP_BattleModes ( void )
{
    int which;
    static char Warning = 0;

    //
    // ALREADY IN A GAME?
    //
    if ( ingame )
    {
        if ( !CP_DisplayMsg( CURGAME, 12 ) )
        {
            return;
        }
        else
        {
            EndGameStuff();
        }
    }

    if ( ( numplayers==1 ) && ( Warning == 0 ) )
    {
        Warning = 1;
        CP_OnePlayerWarningMessage();
    }

    DrawBattleModes ();

    damagecount = 0;
    BATTLEMODE  = true;

    do
    {
        which = HandleMenu( &ModeItems, &ModeMenu[ 0 ],
                            DrawBattleModeDescription );
    }
    while ( which >= 0 );

    handlewhich = 100;

    if ( !StartGame )
    {
        BATTLEMODE = false;
        gamestate.battlemode = battle_StandAloneGame;
    }
}

//****************************************************************************
//
// DrawBattleOptions ()
//
//****************************************************************************

void DrawBattleOptions (void)
{
    int i;

    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Battle Mode Options");

    MN_MakeActive ( &BOptItems, &BOptMenu[0], BOptItems.curpos );

    switch( gamestate.battlemode )
    {
    case battle_Collector :
        BOptMenu[2].active = CP_Inactive; // Ammo
        BOptMenu[6].active = CP_Inactive; // Point Goal
        break;

    case battle_Scavenger :
        BOptMenu[6].active = CP_Inactive; // Point Goal
        break;

    case battle_Tag :
        BOptMenu[2].active = CP_Inactive; // Ammo
        break;

    case battle_Eluder :
        BOptMenu[2].active = CP_Inactive; // Ammo
        BOptMenu[3].active = CP_Inactive; // Hit points
        BOptMenu[7].active = CP_Inactive; // Danger damage
        break;
    }

    if ( BOptMenu[ BOptItems.curpos ].active == CP_Inactive )
    {
        // Find an available cursor position
        for( i = 0; i < BOptItems.amount; i++ )
        {
            if ( BOptMenu[ i ].active == CP_Active )
            {
                BOptMenu[ i ].active = CP_CursorLocation;
                BOptItems.curpos = i;
                break;
            }
        }
    }

    DrawBattleModeName( gamestate.battlemode );
    DrawBattleOptionDescription( BOptItems.curpos );
    DrawMenu (&BOptItems, &BOptMenu[0]);
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_BattleOptions ()
//
//****************************************************************************

void CP_BattleOptions (void)
{
    int which;

    DrawBattleOptions ();

    do
    {
        which = HandleMenu (&BOptItems, &BOptMenu[0], DrawBattleOptionDescription);

    } while (which >= 0);

    handlewhich = 100;
//   WriteBattleConfig();
    CalcTics();

    DrawBattleMenu ();
}



//****************************************************************************
//
// DrawColorMenu ()
//
//****************************************************************************


void DrawColorMenu( void )
{
    int   width;
    int   height;
    char *text;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Uniform Color");

    CurrentFont = smallfont;

    text = colorname[ locplayerstate->uniformcolor ];
    VW_MeasurePropString ( text, &width, &height );
    DrawMenuBufPropString ( ( 320 - width ) / 2 - 16, MENU_Y + 5, text );
    DisplayInfo( 8 );
    EraseMenuBufRegion( COLORX, COLORY, COLORW, COLORH );
    DrawTMenuBufBox( COLORX, COLORY, COLORW, COLORH );
    DrawColoredMenuBufItem( COLORX - 36, COLORY - 33,
                            W_GetNumForName( playerwadname[ locplayerstate->player ] ),
                            locplayerstate->uniformcolor);


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    FlipMenuBuf();
}


//****************************************************************************
//
// CP_ColorSelection ()
//
//****************************************************************************

int CP_ColorSelection (void)
{
    int status;

    locplayerstate->uniformcolor = DefaultPlayerColor;

    DrawColorMenu ();
    status = ColorMenu();
    return( status );
}

int ColorMenu
(
    void
)

{
    ControlInfo ci;
    int colorindex;
    char *text;
    int width;
    int height;
    int timer;
    int baseshape;
    int status;
    boolean update;
    boolean done;

    colorindex = DefaultPlayerColor;
    timer      = GetTicCount();
    baseshape  = W_GetNumForName( playerwadname[ locplayerstate->player ] );

    update = false;
    done   = false;
    while( !done )
    {
        ReadAnyControl( &ci );
        if ( ( ci.dir == dir_East ) && ( ( GetTicCount() - timer ) > 5 ) )
        {
            update = true;
            timer = GetTicCount();

            colorindex++;
            if ( colorindex >= MAXPLAYERCOLORS )
            {
                colorindex = 0;
            }

            MN_PlayMenuSnd( SD_MOVECURSORSND );
        }

        if ( ( ci.dir == dir_West ) && ( ( GetTicCount() - timer ) > 5 ) )
        {
            update = true;
            timer = GetTicCount();

            colorindex--;
            if ( colorindex < 0 )
            {
                colorindex = MAXPLAYERCOLORS - 1;
            }
            MN_PlayMenuSnd( SD_MOVECURSORSND );
        }

        if ( update )
        {
            update = false;
            DefaultPlayerColor = colorindex;
            locplayerstate->uniformcolor = colorindex;
            text = colorname[ locplayerstate->uniformcolor ];

            EraseMenuBufRegion( 0, MENU_Y + 5, 200, 10 );
            EraseMenuBufRegion( COLORX, COLORY, COLORW, COLORH );
            VW_MeasurePropString( text, &width, &height );
            DrawMenuBufPropString( ( 320 - width ) / 2 - 16, MENU_Y + 5, text );
            DrawTMenuBufBox( COLORX, COLORY, COLORW, COLORH );
            DrawColoredMenuBufItem( COLORX - 36, COLORY - 33,
                                    baseshape, locplayerstate->uniformcolor );
        }

        if ( ci.button0 || Keyboard[ sc_Space ] || Keyboard[sc_Enter ] )
        {
            Keyboard[ sc_Space ] = 0;
            Keyboard[ sc_Enter ] = 0;
            MN_PlayMenuSnd( SD_SELECTSND );
            status = 1;
            done = true;
        }
        else if ( ci.button1 || Keyboard[ sc_Escape ] )
        {
            MN_PlayMenuSnd( SD_ESCPRESSEDSND );
            status = 0;
            done = true;
        }

        RefreshMenuBuf( 0 );
    }

    IN_ClearKeysDown();
    return( status );
}


//****************************************************************************
//
// CP_PlayerSelection ()
//
//****************************************************************************
int CP_PlayerSelection
(
    void
)

{
    int which;

    // Do Pick-A-Player menu
    DrawPlayerMenu();

    do
    {
        which = HandleMenu( &PlayerItems, &PlayerMenu[ 0 ], DrawNewPlayerDiff );
        if ( which < 0 )
        {
            handlewhich = 1;
            return( 0 );
        }

#if ( SHAREWARE == 1 )
        if ( PlayerMenu[ which ].active == CP_SemiActive )
        {
            CP_ErrorMsg( "Choose Player",
                         "Read the Ordering Info section from the Main Menu to "
                         "find out how to get the other characters.",
                         mn_smallfont );

            DrawPlayerMenu();
        }
#endif
    }
    while( PlayerMenu[ which ].active == CP_SemiActive );


#if ( SHAREWARE == 1 )
    DefaultPlayerCharacter = 0;
    locplayerstate->player = 0;
#else
    DefaultPlayerCharacter = which;
    locplayerstate->player = which;
#endif

    return (1);
}

//****************************************************************************
//
// CP_OnePlayerWarningMessage ()
//
//****************************************************************************

void CP_OnePlayerWarningMessage
(
    void
)

{
    CP_ErrorMsg( "Comm-bat Warning",
                 "Comm-bat is designed for modem and network play.  "
                 "One player mode is provided for exploration.  The "
                 "Collector battle mode is still fun on your own.",
                 mn_smallfont );
}


//****************************************************************************
//
// CP_CaptureTheTriadError()
//
//****************************************************************************

void CP_CaptureTheTriadError
(
    void
)

{
    SetupMenuBuf();
    SetUpControlPanel();

    CP_ErrorMsg( "Comm-bat Warning",
                 "Capture the Traid can only be played with 2 teams."
                 "  All players must return to the menu to choose their "
                 "team colors.", mn_largefont );

    CleanUpControlPanel();
    ShutdownMenuBuf();
}


//****************************************************************************
//
// CP_TeamPlayErrorMessage()
//
//****************************************************************************

void CP_TeamPlayErrorMessage
(
    void
)

{
    SetupMenuBuf();
    SetUpControlPanel();

    CP_ErrorMsg( "Comm-bat Warning",
                 "Team play can only be played with 2 or more teams."
                 "  All players must return to the menu to choose their "
                 "team colors.", mn_largefont );

    CleanUpControlPanel();
    ShutdownMenuBuf();
}


//****************************************************************************
//
// CP_ModemGameMessage ()
//
//****************************************************************************

#define SITELINES 8

char *sitemessage[] =
{
    "HEY! ARE YOU PLAYING ON AN ILLEGAL COPY?",
    "Network players: it's easy to play legally!",
    "Just get a site license.  For a little over",
    "the price of two games, you get 10 more battle",
    "levels, 11 command cards, and a signed Site",
    "License.  We don't charge you for 11 copies--",
    "just for two!  Call 1-800-APOGEE1 to order.",
    "For more on site licenses, see ORDERING INFO."
};

void CP_ModemGameMessage (int player  )

{
    int i;
    EnableScreenStretch();
    // SetTextMode (  );

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Game Message");

    newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1);
    CurrentFont = newfont1;
    if ( modemgame == false )
    {
        WindowW = 288;
        WindowH = 158;
        PrintX = WindowX = 0;
        PrintY = WindowY = 60;
        MenuBufCPrint ("Please wait.\nLoading game.");
    }
    else
    {
        WindowW = 288;
        WindowH = 158;
        PrintX = WindowX = 0;
        PrintY = WindowY = 50;

        if (networkgame==true)
        {
            PrintY = WindowY = 28;
        }

        if ( player == 0 )
        {
            MenuBufCPrint ("Please wait for\nplayers to choose\ntheir characters.");
        }
        else
        {
            MenuBufCPrint ("Please wait while\nMaster selects\nCOMM-BAT options.");
        }

        if (gamestate.Product != ROTT_SITELICENSE)
        {
            if (networkgame==true)
            {
                for( i = 0; i < SITELINES; i++ )
                {
                    PrintBattleOption( true, 68, 77 + i * 8,
                                       sitemessage[ i ] );
                }
            }
        }
    }

    FlipMenuBuf();
    RefreshMenuBuf (0);

    DisableScreenStretch();
}


//****************************************************************************
//
// DrawGravityMenu ()
//
//****************************************************************************

void DrawGravityMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Gravity");


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons (&GravityItems, &GravityMenu[0],
                    BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);
    MN_GetActive (&GravityItems, &GravityMenu[0],
                  BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);

    DrawMenu (&GravityItems, &GravityMenu[0]);
    DrawGravityOptionDescription( GravityItems.curpos );
    PrintBattleOption( true, 32, 79,
                       "WARNING: High gravity has an unfortunate side effect in" );
    PrintBattleOption( true, 32, 87,
                       "some levels.  It is possible to jump into an area that is" );
    PrintBattleOption( true, 32, 95,
                       "impossible, or at least extremely difficult to get out" );
    PrintBattleOption( true, 32, 103,
                       "of.  In these situations, the only thing you can do is" );
    PrintBattleOption( true, 32, 111,
                       "kill your character, or find some kindly soul to do it" );
    PrintBattleOption( true, 32, 119,
                       "for you.  If this fails, you'll just have to end your game." );

    DisplayInfo( 0 );

    FlipMenuBuf();
}


//****************************************************************************
//
// CP_GravityOptions ()
//
//****************************************************************************

void CP_GravityOptions (void)
{
    int which;

    DrawGravityMenu ();

    do
    {
        which = HandleMenu (&GravityItems, &GravityMenu[0], DrawGravityOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].Gravity = GravityNums[ which ];

        MN_DrawButtons (&GravityItems, &GravityMenu[0],
                        BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);

    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}


//****************************************************************************
//
// DrawSpeedMenu ()
//
//****************************************************************************

void DrawSpeedMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Speed");


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons (&SpeedItems, &SpeedMenu[0],
                    BATTLE_Options[gamestate.battlemode].Speed, OptionNums );
    MN_GetActive (&SpeedItems, &SpeedMenu[0],
                  BATTLE_Options[gamestate.battlemode].Speed, OptionNums );

    DrawMenu (&SpeedItems, &SpeedMenu[0]);
    DrawSpeedOptionDescription( SpeedItems.curpos );
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_SpeedOptions ()
//
//****************************************************************************

void CP_SpeedOptions (void)
{
    int which;

    DrawSpeedMenu ();

    do
    {
        which = HandleMenu (&SpeedItems, &SpeedMenu[0], DrawSpeedOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].Speed = which;

        MN_DrawButtons (&SpeedItems, &SpeedMenu[0],
                        BATTLE_Options[gamestate.battlemode].Speed, OptionNums );
    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}


//****************************************************************************
//
// DrawAmmoPerWeaponMenu ()
//
//****************************************************************************
void DrawAmmoPerWeaponMenu
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Ammo Per Weapon");

    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
                    BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );

    MN_GetActive( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
                  BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );

    DrawMenu( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ] );

    PrintBattleOption( true, 32, 79,
                       "WARNING: Infinite ammo can seriously alter the balance of" );
    PrintBattleOption( true, 32, 87,
                       "the game.  We recommend that you only use it occasionally." );
    PrintBattleOption( true, 32, 95,
                       "It tends to only work well on small levels with lots of" );
    PrintBattleOption( true, 32, 103,
                       "weapons, where the action is far more intense.  On large" );
    PrintBattleOption( true, 32, 111,
                       "levels, you may find it causes people to wait in easily" );
    PrintBattleOption( true, 32, 119,
                       "guardable areas and pick off anyone that comes in the room" );
    PrintBattleOption( true, 32, 127,
                       "(creating an unfair advantage)." );

    if ( AmmoPerWeaponItems.curpos == 2 )
    {
        PrintBattleOption( true, 102, 136, "You have been warned." );
    }

    DrawAmmoOptionDescription( AmmoPerWeaponItems.curpos );
    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_AmmoPerWeaponOptions ()
//
//****************************************************************************
void CP_AmmoPerWeaponOptions
(
    void
)

{
    int which;

    DrawAmmoPerWeaponMenu();

    do
    {
        which = HandleMenu( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ], DrawAmmoOptionDescription);

        if (which >= 0)
        {
            if ( AmmoPerWeaponItems.curpos == 2 )
            {
                MN_PlayMenuSnd( SD_LIGHTNINGSND );
                PrintBattleOption( true, 102, 136, "You have been warned." );
                VL_FillPalette(255,255,255);
                VL_FadeIn(0,255,origpal,10);
            }
            else if ( BATTLE_Options[ gamestate.battlemode ].Ammo == 2 )
            {
                EraseMenuBufRegion( 102, 136, 84, 8 );
                MN_PlayMenuSnd( SD_PLAYERTCSND );
            }

            BATTLE_Options[ gamestate.battlemode ].Ammo = which;
        }

        MN_DrawButtons( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
                        BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );
    }
    while( which >= 0 );

    handlewhich = 100;
    DrawBattleOptions();
}


//****************************************************************************
//
// DrawHitPointsMenu ()
//
//****************************************************************************
void DrawHitPointsMenu
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Player Hitpoints");

    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons( &HitPointItems, &HitPointMenu[ 0 ],
                    BATTLE_Options[ gamestate.battlemode ].HitPoints, HitPointNums );

    MN_GetActive( &HitPointItems, &HitPointMenu[ 0 ],
                  BATTLE_Options[ gamestate.battlemode ].HitPoints, HitPointNums );

    DrawMenu( &HitPointItems, &HitPointMenu[ 0 ] );
    DrawHitPointsOptionDescription( HitPointItems.curpos );
    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_HitPointsOptions ()
//
//****************************************************************************

void CP_HitPointsOptions (void)
{
    int which;

    DrawHitPointsMenu ();

    do
    {
        which = HandleMenu (&HitPointItems, &HitPointMenu[0], DrawHitPointsOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].HitPoints = HitPointNums[ which ];

        MN_DrawButtons (&HitPointItems, &HitPointMenu[0],
                        BATTLE_Options[gamestate.battlemode].HitPoints, HitPointNums);

    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}



//****************************************************************************
//
// DrawSpawnControlMenu ()
//
//****************************************************************************
void DrawSpawnControlMenu
(
    void
)

{
    int i;

    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Radical Options");

    MN_MakeActive( &SpawnItems, &SpawnMenu[ 0 ], SpawnItems.curpos );

#if ( SHAREWARE == 1 )
    BATTLE_Options[ gamestate.battlemode ].SpawnMines = false;
    SpawnMenu[ 3 ].active = CP_Inactive; // Mines
#endif

    switch( gamestate.battlemode )
    {
    case battle_Normal :
        break;

    case battle_ScoreMore :
        break;

    case battle_Collector :
        SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
        SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
        SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
        SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
        break;

    case battle_Scavenger :
        SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
        break;

    case battle_Hunter :
        break;

    case battle_Tag :
        SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
        SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
        SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
        break;

    case battle_Eluder :
        SpawnMenu[ 1 ].active = CP_Inactive; // Health
        SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
        SpawnMenu[ 4 ].active = CP_Inactive; // Respawn
        SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
        SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
        SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
        break;

    case battle_Deluder :
        SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
        break;

    case battle_CaptureTheTriad :
        SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
        break;
    }

    if ( SpawnMenu[ SpawnItems.curpos ].active == CP_Inactive )
    {
        // Find an available cursor position
        for( i = 0; i < SpawnItems.amount; i++ )
        {
            if ( SpawnMenu[ i ].active == CP_Active )
            {
                SpawnMenu[ i ].active = CP_CursorLocation;
                SpawnItems.curpos = i;
                break;
            }
        }
    }

    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    DrawSpawnControlButtons();

    MN_GetCursorLocation( &SpawnItems, &SpawnMenu[ 0 ] );

    DrawMenu( &SpawnItems, &SpawnMenu[ 0 ] );
    DrawRadicalOptionDescription( SpawnItems.curpos );
    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// DrawSpawnControlButtons ()
//
//****************************************************************************
void DrawSpawnControlButtons
(
    void
)

{
    int x;
    int y;
    int button_on;
    int button_off;

    button_on  = W_GetNumForName( "snd_on" );
    button_off = W_GetNumForName( "snd_off" );

    x = SpawnItems.x + 18;
    y = SpawnItems.y - 1;

    if ( BATTLE_Options[ gamestate.battlemode ].SpawnDangers )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].SpawnHealth )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].SpawnWeapons )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].SpawnMines )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].RespawnItems )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].WeaponPersistence )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].RandomWeapons )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }

    y += 14;
    if ( BATTLE_Options[ gamestate.battlemode ].FriendlyFire )
    {
        DrawMenuBufItem( x, y, button_on );
    }
    else
    {
        EraseMenuBufRegion( x, y, 16, 16 );
        DrawMenuBufItem( x, y, button_off );
    }
}


//****************************************************************************
//
// CP_SpawnControlOptions ()
//
//****************************************************************************
void CP_SpawnControlOptions
(
    void
)

{
    int which;

    DrawSpawnControlMenu();

    do
    {
        which = HandleMenu( &SpawnItems, &SpawnMenu[ 0 ], DrawRadicalOptionDescription );
        switch( which )
        {
        case 0 :
            BATTLE_Options[ gamestate.battlemode ].SpawnDangers =
                !BATTLE_Options[ gamestate.battlemode ].SpawnDangers;
            break;

        case 1 :
            BATTLE_Options[ gamestate.battlemode ].SpawnHealth =
                !BATTLE_Options[ gamestate.battlemode ].SpawnHealth;
            break;

        case 2 :
            BATTLE_Options[ gamestate.battlemode ].SpawnWeapons =
                !BATTLE_Options[ gamestate.battlemode ].SpawnWeapons;
            break;

        case 3 :
            BATTLE_Options[ gamestate.battlemode ].SpawnMines =
                !BATTLE_Options[ gamestate.battlemode ].SpawnMines;
            break;

        case 4 :
            BATTLE_Options[ gamestate.battlemode ].RespawnItems =
                !BATTLE_Options[ gamestate.battlemode ].RespawnItems;
            break;

        case 5 :
            BATTLE_Options[ gamestate.battlemode ].WeaponPersistence =
                !BATTLE_Options[ gamestate.battlemode ].WeaponPersistence;
            break;

        case 6 :
            BATTLE_Options[ gamestate.battlemode ].RandomWeapons =
                !BATTLE_Options[ gamestate.battlemode ].RandomWeapons;
            break;

        case 7 :
            BATTLE_Options[ gamestate.battlemode ].FriendlyFire =
                !BATTLE_Options[ gamestate.battlemode ].FriendlyFire;
            break;
        }

        DrawSpawnControlButtons();
    }
    while( which >= 0 );

    handlewhich = 100;
    DrawBattleOptions();
}



//****************************************************************************
//
// DrawLightLevelMenu ()
//
//****************************************************************************

void DrawLightLevelMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Light Levels");


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons (&LightLevelItems, &LightLevelMenu[0],
                    BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );
    MN_GetActive (&LightLevelItems, &LightLevelMenu[0],
                  BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );

    DrawMenu (&LightLevelItems, &LightLevelMenu[0]);
    DrawLightLevelOptionDescription( LightLevelItems.curpos );
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_LightLevelOptions ()
//
//****************************************************************************

void CP_LightLevelOptions (void)
{
    int which;

    DrawLightLevelMenu ();

    do
    {
        which = HandleMenu (&LightLevelItems, &LightLevelMenu[0], DrawLightLevelOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].LightLevel = which;

        MN_DrawButtons (&LightLevelItems, &LightLevelMenu[0],
                        BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );

    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}



//****************************************************************************
//
// DrawPointGoalMenu()
//
//****************************************************************************

void DrawPointGoalMenu
(
    void
)

{
    MenuNum = 1;

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Point Goal");

    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    MN_DrawButtons( &PointGoalItems, &PointGoalMenu[ 0 ],
                    BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );

    MN_GetActive( &PointGoalItems, &PointGoalMenu[ 0 ],
                  BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );

    DrawMenu( &PointGoalItems, &PointGoalMenu[ 0 ] );
    DrawPointGoalOptionDescription( PointGoalItems.curpos );
    DisplayInfo( 0 );
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_PointGoalOptions()
//
//****************************************************************************

void CP_PointGoalOptions
(
    void
)

{
    int which;

    DrawPointGoalMenu();

    do
    {
        which = HandleMenu( &PointGoalItems, &PointGoalMenu[ 0 ], DrawPointGoalOptionDescription );

        if ( which >= 0 )
        {
            BATTLE_Options[ gamestate.battlemode ].Kills = KillNums[ which ];

            MN_DrawButtons( &PointGoalItems, &PointGoalMenu[ 0 ],
                            BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );
        }
    }
    while( which >= 0 );

    handlewhich = 100;
    DrawBattleOptions();
}


//****************************************************************************
//
// DrawDangerMenu ()
//
//****************************************************************************

void DrawDangerMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Danger Damage");


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }
    MN_DrawButtons (&DangerItems, &DangerMenu[0],
                    BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);
    MN_GetActive (&DangerItems, &DangerMenu[0],
                  BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);

    DrawMenu (&DangerItems, &DangerMenu[0]);
    DrawDangerDamageOptionDescription( DangerItems.curpos );
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_DangerOptions ()
//
//****************************************************************************

void CP_DangerOptions (void)
{
    int which;

    DrawDangerMenu ();

    do
    {
        which = HandleMenu (&DangerItems, &DangerMenu[0], DrawDangerDamageOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].DangerDamage = DangerNums[which];

        MN_DrawButtons (&DangerItems, &DangerMenu[0],
                        BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);

    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}


//****************************************************************************
//
// DrawTimeLimitMenu ()
//
//****************************************************************************

void DrawTimeLimitMenu (void)
{
    MenuNum = 1;

    SetAlternateMenuBuf ();
    ClearMenuBuf();
    SetMenuTitle ("Time Limit");


    if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
            ( consoleplayer == 0 ) )
    {
        DrawBattleModeName( gamestate.battlemode );
    }
    MN_DrawButtons (&TimeLimitItems, &TimeLimitMenu[0],
                    BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);
    MN_GetActive (&TimeLimitItems, &TimeLimitMenu[0],
                  BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);

    if ( gamestate.battlemode == battle_Hunter )
    {
        TimeLimitMenu[7].active = CP_Inactive; // No time limit
        if ( TimeLimitItems.curpos == 7 )
        {
            TimeLimitMenu[0].active = CP_CursorLocation;
            TimeLimitItems.curpos = 0;
        }
    }

    DrawMenu (&TimeLimitItems, &TimeLimitMenu[0]);
    DrawTimeLimitOptionDescription( TimeLimitItems.curpos );
    DisplayInfo (0);
    FlipMenuBuf();
}


//****************************************************************************
//
// CP_TimeLimitOptions ()
//
//****************************************************************************

void CP_TimeLimitOptions (void)
{
    int which;

    DrawTimeLimitMenu ();

    do
    {
        which = HandleMenu (&TimeLimitItems, &TimeLimitMenu[0], DrawTimeLimitOptionDescription);

        if (which >= 0)
            BATTLE_Options[gamestate.battlemode].TimeLimit = TimeLimitNums[which];

        MN_DrawButtons (&TimeLimitItems, &TimeLimitMenu[0],
                        BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);

    } while (which >= 0);

    handlewhich = 100;
    DrawBattleOptions ();
}

void PrintBattleOption
(
    boolean inmenu,
    int x,
    int y,
    char *text
)

{
    if ( inmenu )
    {
        IFont = ( cfont_t * )W_CacheLumpName( "itnyfont", PU_CACHE, Cvt_cfont_t, 1 );
        DrawMenuBufIString( x + 1, y + 1, text, 0 );
        DrawMenuBufIString( x, y, text, ACTIVECOLOR );
    }
    else
    {
        PrintX = x;
        PrintY = y;
        US_BufPrint( text );
    }
}

void ShowBattleOption
(
    boolean inmenu,
    int PosX,
    int PosY,
    int column,
    int Line,
    char *text1,
    char *text2
)

{
    char text[ 80 ];
    int x;
    int y;

    y = PosY + ( Line * 7 );
    x = PosX + column * 120;

    PrintBattleOption( inmenu, x, y, text1 );

    strcpy( text, ": " );
    strcat( text, text2 );

    PrintBattleOption( inmenu, x + 60, y, text );
}

void ShowBattleOptions
(
    boolean inmenu,
    int PosX,
    int PosY
)

{
    battle_type *options;
    battle_type BatOps;
    char *string;
    char text[ 80 ];
    int  width;
    int  height;
    int  temp;

    CurrentFont = tinyfont;

    strcpy( text, "CURRENT OPTIONS FOR " );
    strcat( text, BattleModeNames[ gamestate.battlemode - battle_Normal ] );
    VW_MeasurePropString ( text, &width, &height );
    if ( inmenu )
    {
        temp = 288;
    }
    else
    {
        temp = 320;
    }
    PrintBattleOption( inmenu, (temp - width)/2, PosY, text );

    PosY++;

    BATTLE_GetOptions( &BatOps );
    options = &BatOps;

    ShowBattleOption( inmenu, PosX, PosY, 0, 1, "Friendly Fire",
                      ( options->FriendlyFire ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 2, "Weapon Persist",
                      ( options->WeaponPersistence ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 3, "Random Weapons",
                      ( options->RandomWeapons ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 4, "Respawn Items",
                      ( options->RespawnItems ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 5, "Spawn Health",
                      ( options->SpawnHealth ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 6, "Spawn Weapons",
                      ( options->SpawnWeapons ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 7, "Spawn Mines",
                      ( options->SpawnMines ) ? "On" : "Off" );

    ShowBattleOption( inmenu, PosX, PosY, 0, 8, "Spawn Dangers",
                      ( options->SpawnDangers ) ? "On" : "Off" );

    switch( options->DangerDamage )
    {
    case bo_danger_low :
        string = "Low";
        break;

    case bo_danger_normal :
        string = "Normal";
        break;

    case bo_danger_kill :
        string = "Kill";
        break;

    default :
        itoa( options->DangerDamage, text, 10 );
        string = text;
    }
    ShowBattleOption( inmenu, PosX, PosY, 0, 9, "Danger Damage", string );

    GetMapFileName ( text );
    ShowBattleOption( inmenu, PosX, PosY, 0, 10, "Filename", text );

    itoa( numplayers, text, 10 );
    ShowBattleOption( inmenu, PosX, PosY, 1, 1, "Players", text );

    if ( options->TimeLimit == bo_time_infinite )
    {
        string = "None";
    }
    else
    {
        itoa( options->TimeLimit, text, 10 );
        string = text;
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 2, "Time Limit", string );

    if ( ( gamestate.battlemode == battle_Collector ) ||
            ( gamestate.battlemode == battle_Scavenger ) )
    {
        string = "?";
    }
    else
    {
        switch( options->Kills )
        {
        case bo_kills_random :
            string = "Random";
            break;

        case bo_kills_blind :
            string = "Blind";
            break;

        case bo_kills_infinite :
            string = "Infinite";
            break;

        default :
            itoa( options->Kills, text, 10 );
            string = text;
        }
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 3, "Point Goal", string );

    switch( options->Ammo )
    {
    case bo_one_shot :
        string = "One shot";
        break;

    case bo_normal_shots :
        string = "Normal";
        break;

    case bo_infinite_shots :
        string = "Gunfinity";
        break;
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 4, "Ammo", string );

    if ( options->HitPoints == bo_character_hitpoints )
    {
        string = "Character";
    }
    else
    {
        itoa( options->HitPoints, text, 10 );
        string = text;
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 5, "Hit Points", string );

    itoa( options->RespawnTime, text, 10 );
    ShowBattleOption( inmenu, PosX, PosY, 1, 6, "Respawn Time", text );

    switch( options->Speed )
    {
    case bo_normal_speed :
        string = "Normal";
        break;

    case bo_fast_speed :
        string = "Fast";
        break;
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 7, "Speed", string );

    switch( options->LightLevel )
    {
    case bo_light_dark :
        string = "Dark";
        break;

    case bo_light_normal :
        string = "Normal";
        break;

    case bo_light_bright :
        string = "Bright";
        break;

    case bo_light_fog :
        string = "Fog";
        break;

    case bo_light_periodic :
        string = "Periodic";
        break;

    case bo_light_lightning :
        string = "Lightning";
        break;
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 8, "Light", string );

    if ( options->Gravity == NORMAL_GRAVITY )
    {
        string = "Normal";
        temp = NORMAL_GRAVITY;
    }
    else if ( options->Gravity < NORMAL_GRAVITY )
    {
        string = "Low";
        temp = LOW_GRAVITY;
    }
    else
    {
        string = "High";
        temp = HIGH_GRAVITY;
    }

    strcpy( text, string );
    if ( options->Gravity < (unsigned int)temp )
    {
        strcat( text, "-" );
    }

    if ( options->Gravity > (unsigned int)temp )
    {
        strcat( text, "+" );
    }
    ShowBattleOption( inmenu, PosX, PosY, 1, 9, "Gravity", text );
}


//****************************************************************************
//
// SetMenuHeader()
//
//****************************************************************************

void SetMenuHeader
(
    char *header
)

{
    int width;
    int height;

    EraseMenuBufRegion( 16, 0, 256, 16 );

    CurrentFont = tinyfont;
    VW_MeasurePropString ( header, &width, &height );
    DrawMenuBufPropString ( ( 288 - width ) / 2, 4, header );

    RefreshMenuBuf( 0 );
}


//****************************************************************************
//
// DrawMultiPageCustomMenu()
//
//****************************************************************************

void DrawMultiPageCustomMenu
(
    char *title,
    void ( *redrawfunc )( void )
)

{
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle( title );

    DrawMenu( &MultiPageCustomItems, &MultiPageCustomMenu[ 0 ] );

    DisplayInfo( 0 );

    if ( redrawfunc != NULL )
    {
        redrawfunc();
    }

    CalcTics();
    FlipMenuBuf();
    RefreshMenuBuf( 0 );
}


//****************************************************************************
//
// HandleMultiPageCustomMenu()
//
//****************************************************************************

int HandleMultiPageCustomMenu
(
    char **names,
    int   amount,
    int   curpos,
    char *title,
    void  ( *routine )( int w ),
    void ( *redrawfunc )( void ),
    boolean exitonselect
)

{
    boolean redraw;
    int  page;
    int  cursorpos;
    int  maxpos;
    int  numpos;
    int  which;
    int  selection;
    int  i;
    char letter;

    MenuNum = 11;

    cursorpos = curpos % MAXCUSTOM;
    page      = curpos - cursorpos;
    MultiPageCustomItems.curpos = cursorpos + 2;

    redraw = true;

    do
    {
        if ( redraw )
        {
            redraw = false;
            MultiPageCustomMenu[ 0 ].active = CP_Active;
            MultiPageCustomMenu[ 1 ].active = CP_Active;
            if ( page == 0 )
            {
                MultiPageCustomMenu[ 1 ].active = CP_Inactive;
            }

            maxpos = page + MAXCUSTOM;
            if ( maxpos >= amount )
            {
                MultiPageCustomMenu[ 0 ].active = CP_Inactive;
                maxpos = amount;
            }

            numpos = maxpos - page + 2;
            MultiPageCustomItems.amount = numpos;

            for( i = 2; i < numpos; i++ )
            {
                MultiPageCustomMenu[ i ].active = CP_Active;

                // Set the name of the level
                strcpy (MultiPageCustomNames[ i ], names[ page + i - 2 ]);

                // Set the quick key
                letter = *names[ page + i - 2 ];

                // Force it to upper case
                if ( ( letter >= 'a' ) && ( letter <= 'z' ) )
                {
                    letter = letter - 'a' + 'A';
                }

                // Only use letters
                if ( ( letter < 'A' ) || ( letter > 'Z' ) )
                {
                    letter = 'a';
                }
                MultiPageCustomMenu[ i ].letter = letter;
            }

            // If the cursor is at an invalid position, find a valid one
            cursorpos = MultiPageCustomItems.curpos;
            if ( cursorpos >= numpos )
            {
                cursorpos = numpos - 1;
            }
            else
            {
                while( MultiPageCustomMenu[ cursorpos ].active == CP_Inactive )
                {
                    cursorpos++;
                }
            }
            MultiPageCustomItems.curpos = cursorpos;
            MultiPageCustomMenu[ cursorpos ].active = CP_CursorLocation;

            DrawMultiPageCustomMenu( title, redrawfunc );
        }

        which = HandleMenu( &MultiPageCustomItems, &MultiPageCustomMenu[ 0 ],
                            NULL );

        switch( which )
        {
        case ESCPRESSED :
            selection = -1;
            break;

        case PAGEDOWN :
        case 0 :
            page += MAXCUSTOM;
            which = 0;
            redraw = true;
            break;

        case PAGEUP :
        case 1 :
            page -= MAXCUSTOM;
            which = 0;
            redraw = true;
            break;

        default :
            selection = page + which - 2;
            if ( routine )
            {
                routine( selection );
            }

            if ( exitonselect )
            {
                which = -1;
            }
            break;
        }
    }
    while( which >= 0 );

    return( selection );
}


//****************************************************************************
//
// CP_LevelSelectionRedraw()
//
//****************************************************************************

void CP_LevelSelectionRedraw
(
    void
)

{
    if ( gamestate.battlemode >= battle_Normal )
    {
        SetMenuHeader( BattleModeNames[ gamestate.battlemode - battle_Normal ] );
    }
}


//****************************************************************************
//
// CP_LevelSelectionMenu ()
//
//****************************************************************************
int CP_LevelSelectionMenu
(
    void
)

{
    static char levelcursorpos[ 2 ] = { 0 };

    char *LevelNames[ 100 ];
    int   whichlevels;
    int   numlevels;
    int   level;
    int   i;

    whichlevels = 0;
    if ( BATTLEMODE )
    {
        whichlevels = 1;
    }

    mapinfo = ( mapfileinfo_t * )SafeMalloc( sizeof( mapfileinfo_t ) );
    GetMapInfo( mapinfo );

    numlevels = mapinfo->nummaps;
    if ( numlevels <= 0 )
    {
        Error( "CP_LevelSelectionMenu : No maps found in RTL/RTC file." );
    }

    for( i = 0; i < numlevels; i++ )
    {
        LevelNames[ i ] = mapinfo->maps[ i ].mapname;
    }

    level = HandleMultiPageCustomMenu( LevelNames, numlevels,
                                       levelcursorpos[ whichlevels ], "Level Selection", NULL,
                                       CP_LevelSelectionRedraw, true );

    SafeFree( mapinfo );

    if ( level >= 0 )
    {
        levelcursorpos[ whichlevels ] = level;
    }

    return( level );
}


//****************************************************************************
//
// DrawEnterCodeNameMenu ()
//
//****************************************************************************
void DrawEnterCodeNameMenu
(
    void
)

{
    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle ("Enter CodeName");

    if ( consoleplayer == 0 )
    {
        DrawBattleModeName( gamestate.battlemode );
    }

    WindowW = 288;
    WindowH = 158;
    WindowX = 0;
    WindowY = 50;
    PrintX  = 0;
    PrintY  = 50;

    CurrentFont = smallfont;

    MenuBufCPrint( "Enter CodeName\n" );
    MenuBufCPrint( "maximum 8 letters\n" );

    DrawSTMenuBuf( ( 288 - 92 ) / 2 - 2, 80 - 2, 92 + 4, 10 + 4, false );

    DrawMenuBufPropString( ( 288 - 92 ) / 2, 80, CodeName );

    WindowX = 144 - ( 9 * 4 );
    PrintX  = WindowX;

    FlipMenuBuf();
    RefreshMenuBuf( 0 );
}

//****************************************************************************
//
// CP_EnterCodeNameMenu ()
//
//****************************************************************************
int CP_EnterCodeNameMenu
(
    void
)

{
    char input[10];

    DrawEnterCodeNameMenu();

    memset(input,0,sizeof(input));
    strcpy(input,CodeName);


    if (US_LineInput ((288-92)/2, 80, input, input, true, 8, 92, 0))
    {
        strcpy (&locplayerstate->codename[0], input);
        strcpy (CodeName, input);
        WaitKeyUp();
        return 1;
    }
    else
    {
        WaitKeyUp();
        return 0;
    }
}

//******************************************************************************
//
// GetNextWord()
//
//******************************************************************************
char *GetNextWord
(
    char *dest,
    char *source,
    int  length
)

{
    while( ( *source != 0 ) && ( isspace( *source ) ) && ( length > 0 ) )
    {
        *dest = *source;
        length--;
        dest++;
        source++;
    }

    while( ( *source != 0 ) && ( !isspace( *source ) ) && ( length > 0 ) )
    {
        *dest = *source;
        length--;
        dest++;
        source++;
    }

    *dest = 0;
    return( source );
}

//******************************************************************************
//
// CP_ErrorMsg()
//
//******************************************************************************

void CP_ErrorMsg
(
    char *title,
    char *error,
    int font
)

{
    char wordtext[ 80 ];
    char text[ 10 ][ 80 ];
    int  pos;
    int  length;
    int  line;
    int  w;
    int  h;
    int  y;
    extern void VWL_MeasureIntensityString (char *s, int *width, int *height, cfont_t *font);

    SetAlternateMenuBuf();
    ClearMenuBuf();
    SetMenuTitle( title );

    WindowW = 288;
    WindowH = 158;
    WindowX = 0;
    WindowY = 40;

    IFont = ( cfont_t * )W_CacheLumpName( FontNames[ font ], PU_CACHE, Cvt_cfont_t, 1 );

    pos = 0;
    line = 0;

    text[ 0 ][ 0 ] = 0;

    while( *error != 0 )
    {
        error = GetNextWord( wordtext, error, 79 );

        pos = 0;
        while( ( wordtext[ pos ] != 0 ) && ( isspace( wordtext[ pos ] ) ) )
        {
            pos++;
        }

        length = strlen( text[ line ] );
        if ( length == 0 )
        {
            strcat( text[ line ], &wordtext[ pos ] );
        }
        else
        {
            strcat( text[ line ], wordtext );
        }

        VWL_MeasureIntensityString( text[ line ], &w, &h, IFont );

        if ( w > WindowW - 32 )
        {
            text[ line ][ length ] = 0;
            if ( line >= 10 )
            {
                break;
            }
            line++;
            strcpy( text[ line ], &wordtext[ pos ] );
        }
    }

    if ( strlen( text[ line ] ) == 0 )
    {
        line--;
    }

    VWL_MeasureIntensityString( text[ 0 ], &w, &h, IFont );

    y = ( WindowH - ( line + 1 ) * h ) / 2;

    for( pos = 0; pos <= line; pos++ )
    {
        VWL_MeasureIntensityString( text[ pos ], &w, &h, IFont );
        DrawMenuBufIString( ( 288 - w ) / 2, y, text[ pos ], ACTIVECOLOR );
        y += h;
    }

    DisplayInfo( 5 );
    FlipMenuBuf();
    RefreshMenuBuf( 0 );

    IN_Ack();
    WaitKeyUp();

    MN_PlayMenuSnd( SD_ESCPRESSEDSND );
}