Annotation of quake1/menu.c, revision 1.1.1.1

1.1       root        1: #include "quakedef.h"
                      2: 
                      3: enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;
                      4: 
                      5: void M_Menu_Main_f (void);
                      6:        void M_Menu_SinglePlayer_f (void);
                      7:                void M_Menu_Load_f (void);
                      8:                void M_Menu_Save_f (void);
                      9:        void M_Menu_MultiPlayer_f (void);
                     10:                void M_Menu_Setup_f (void);
                     11:                void M_Menu_Net_f (void);
                     12:        void M_Menu_Options_f (void);
                     13:                void M_Menu_Keys_f (void);
                     14:                void M_Menu_Video_f (void);
                     15:        void M_Menu_Help_f (void);
                     16:        void M_Menu_Quit_f (void);
                     17: void M_Menu_SerialConfig_f (void);
                     18:        void M_Menu_ModemConfig_f (void);
                     19: void M_Menu_LanConfig_f (void);
                     20: void M_Menu_GameOptions_f (void);
                     21: void M_Menu_Search_f (void);
                     22: void M_Menu_ServerList_f (void);
                     23: 
                     24: void M_Main_Draw (void);
                     25:        void M_SinglePlayer_Draw (void);
                     26:                void M_Load_Draw (void);
                     27:                void M_Save_Draw (void);
                     28:        void M_MultiPlayer_Draw (void);
                     29:                void M_Setup_Draw (void);
                     30:                void M_Net_Draw (void);
                     31:        void M_Options_Draw (void);
                     32:                void M_Keys_Draw (void);
                     33:                void M_Video_Draw (void);
                     34:        void M_Help_Draw (void);
                     35:        void M_Quit_Draw (void);
                     36: void M_SerialConfig_Draw (void);
                     37:        void M_ModemConfig_Draw (void);
                     38: void M_LanConfig_Draw (void);
                     39: void M_GameOptions_Draw (void);
                     40: void M_Search_Draw (void);
                     41: void M_ServerList_Draw (void);
                     42: 
                     43: void M_Main_Key (int key);
                     44:        void M_SinglePlayer_Key (int key);
                     45:                void M_Load_Key (int key);
                     46:                void M_Save_Key (int key);
                     47:        void M_MultiPlayer_Key (int key);
                     48:                void M_Setup_Key (int key);
                     49:                void M_Net_Key (int key);
                     50:        void M_Options_Key (int key);
                     51:                void M_Keys_Key (int key);
                     52:                void M_Video_Key (int key);
                     53:        void M_Help_Key (int key);
                     54:        void M_Quit_Key (int key);
                     55: void M_SerialConfig_Key (int key);
                     56:        void M_ModemConfig_Key (int key);
                     57: void M_LanConfig_Key (int key);
                     58: void M_GameOptions_Key (int key);
                     59: void M_Search_Key (int key);
                     60: void M_ServerList_Key (int key);
                     61: 
                     62: qboolean       m_entersound;           // play after drawing a frame, so caching
                     63:                                                                // won't disrupt the sound
                     64: qboolean       m_recursiveDraw;
                     65: 
                     66: int                    m_return_state;
                     67: qboolean       m_return_onerror;
                     68: char           m_return_reason [32];
                     69: 
                     70: #define StartingGame   (m_multiplayer_cursor == 1)
                     71: #define JoiningGame            (m_multiplayer_cursor == 0)
                     72: #define SerialConfig   (m_net_cursor == 0)
                     73: #define DirectConfig   (m_net_cursor == 1)
                     74: #define        IPXConfig               (m_net_cursor == 2)
                     75: #define        TCPIPConfig             (m_net_cursor == 3)
                     76: 
                     77: void M_ConfigureNetSubsystem(void);
                     78: 
                     79: //=============================================================================
                     80: /* Support Routines */
                     81: 
                     82: typedef struct cachepic_s
                     83: {
                     84:        char            name[MAX_QPATH];
                     85:        cache_user_t    cache;
                     86: } cachepic_t;
                     87: 
                     88: #define        MAX_CACHED_PICS         128
                     89: cachepic_t     menu_cachepics[MAX_CACHED_PICS];
                     90: int                    menu_numcachepics;
                     91: 
                     92: 
                     93: /*
                     94: ================
                     95: M_CachePic
                     96: ================
                     97: */
                     98: qpic_t *M_CachePic (char *path)
                     99: {
                    100:        cachepic_t      *pic;
                    101:        int                     i;
                    102:        qpic_t          *dat;
                    103:        
                    104:        for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
                    105:                if (!strcmp (path, pic->name))
                    106:                        break;
                    107: 
                    108:        if (i == menu_numcachepics)
                    109:        {
                    110:                if (menu_numcachepics == MAX_CACHED_PICS)
                    111:                        Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
                    112:                menu_numcachepics++;
                    113:                strcpy (pic->name, path);
                    114:        }
                    115: 
                    116:        dat = Cache_Check (&pic->cache);
                    117:        if (dat)
                    118:                return dat;
                    119: 
                    120: //
                    121: // load the pic from disk
                    122: //
                    123:        COM_LoadCacheFile (path, &pic->cache);
                    124:        
                    125:        dat = (qpic_t *)pic->cache.data;
                    126:        if (!dat)
                    127:                Sys_Error ("M_CachePic: failed to load %s", path);
                    128: 
                    129:        SwapPic (dat);
                    130: 
                    131:        return dat;
                    132: }
                    133: 
                    134: /*
                    135: ================
                    136: M_DrawCharacter
                    137: 
                    138: Draws one solid graphics character
                    139: ================
                    140: */
                    141: void M_DrawCharacter (int cx, int line, int num)
                    142: {
                    143:        Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
                    144: }
                    145: 
                    146: void M_Print (int cx, int cy, char *str)
                    147: {
                    148:        while (*str)
                    149:        {
                    150:                M_DrawCharacter (cx, cy, (*str)+128);
                    151:                str++;
                    152:                cx += 8;
                    153:        }
                    154: }
                    155: 
                    156: void M_PrintWhite (int cx, int cy, char *str)
                    157: {
                    158:        while (*str)
                    159:        {
                    160:                M_DrawCharacter (cx, cy, *str);
                    161:                str++;
                    162:                cx += 8;
                    163:        }
                    164: }
                    165: 
                    166: void M_DrawTransPic (int x, int y, qpic_t *pic)
                    167: {
                    168:        Draw_TransPic (x + ((vid.width - 320)>>1), y, pic);
                    169: }
                    170: 
                    171: void M_DrawPic (int x, int y, qpic_t *pic)
                    172: {
                    173:        Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
                    174: }
                    175: 
                    176: byte identityTable[256];
                    177: byte translationTable[256];
                    178: 
                    179: void M_BuildTranslationTable(int top, int bottom)
                    180: {
                    181:        int             j;
                    182:        byte    *dest, *source;
                    183: 
                    184:        for (j = 0; j < 256; j++)
                    185:                identityTable[j] = j;
                    186:        dest = translationTable;
                    187:        source = identityTable;
                    188:        memcpy (dest, source, 256);
                    189: 
                    190:        if (top < 128)  // the artists made some backwards ranges.  sigh.
                    191:                memcpy (dest + TOP_RANGE, source + top, 16);
                    192:        else
                    193:                for (j=0 ; j<16 ; j++)
                    194:                        dest[TOP_RANGE+j] = source[top+15-j];
                    195: 
                    196:        if (bottom < 128)
                    197:                memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
                    198:        else
                    199:                for (j=0 ; j<16 ; j++)
                    200:                        dest[BOTTOM_RANGE+j] = source[bottom+15-j];             
                    201: }
                    202: 
                    203: 
                    204: void M_DrawTransPicTranslate (int x, int y, qpic_t *pic)
                    205: {
                    206:        Draw_TransPicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
                    207: }
                    208: 
                    209: 
                    210: void M_DrawTextBox (int x, int y, int width, int lines)
                    211: {
                    212:        qpic_t  *p;
                    213:        int             cx, cy;
                    214:        int             n;
                    215: 
                    216:        // draw left side
                    217:        cx = x;
                    218:        cy = y;
                    219:        p = M_CachePic ("gfx/box_tl.lmp");
                    220:        M_DrawTransPic (cx, cy, p);
                    221:        p = M_CachePic ("gfx/box_ml.lmp");
                    222:        for (n = 0; n < lines; n++)
                    223:        {
                    224:                cy += 8;
                    225:                M_DrawTransPic (cx, cy, p);
                    226:        }
                    227:        p = M_CachePic ("gfx/box_bl.lmp");
                    228:        M_DrawTransPic (cx, cy+8, p);
                    229: 
                    230:        // draw middle
                    231:        cx += 8;
                    232:        while (width > 0)
                    233:        {
                    234:                cy = y;
                    235:                p = M_CachePic ("gfx/box_tm.lmp");
                    236:                M_DrawTransPic (cx, cy, p);
                    237:                p = M_CachePic ("gfx/box_mm.lmp");
                    238:                for (n = 0; n < lines; n++)
                    239:                {
                    240:                        cy += 8;
                    241:                        if (n == 1)
                    242:                                p = M_CachePic ("gfx/box_mm2.lmp");
                    243:                        M_DrawTransPic (cx, cy, p);
                    244:                }
                    245:                p = M_CachePic ("gfx/box_bm.lmp");
                    246:                M_DrawTransPic (cx, cy+8, p);
                    247:                width -= 2;
                    248:                cx += 16;
                    249:        }
                    250: 
                    251:        // draw right side
                    252:        cy = y;
                    253:        p = M_CachePic ("gfx/box_tr.lmp");
                    254:        M_DrawTransPic (cx, cy, p);
                    255:        p = M_CachePic ("gfx/box_mr.lmp");
                    256:        for (n = 0; n < lines; n++)
                    257:        {
                    258:                cy += 8;
                    259:                M_DrawTransPic (cx, cy, p);
                    260:        }
                    261:        p = M_CachePic ("gfx/box_br.lmp");
                    262:        M_DrawTransPic (cx, cy+8, p);
                    263: }
                    264: 
                    265: //=============================================================================
                    266: 
                    267: int m_save_demonum;
                    268:                
                    269: /*
                    270: ================
                    271: M_ToggleMenu_f
                    272: ================
                    273: */
                    274: void M_ToggleMenu_f (void)
                    275: {
                    276:        m_entersound = true;
                    277: 
                    278:        if (key_dest == key_menu)
                    279:        {
                    280:                if (m_state != m_main)
                    281:                {
                    282:                        M_Menu_Main_f ();
                    283:                        return;
                    284:                }
                    285:                key_dest = key_game;
                    286:                m_state = m_none;
                    287:                return;
                    288:        }
                    289:        if (key_dest == key_console)
                    290:        {
                    291:                Con_ToggleConsole_f ();
                    292:        }
                    293:        else
                    294:        {
                    295:                M_Menu_Main_f ();
                    296:        }
                    297: }
                    298: 
                    299:                
                    300: //=============================================================================
                    301: /* MAIN MENU */
                    302: 
                    303: int    m_main_cursor;
                    304: #define        MAIN_ITEMS      5
                    305: 
                    306: 
                    307: void M_Menu_Main_f (void)
                    308: {
                    309:        if (key_dest != key_menu)
                    310:        {
                    311:                m_save_demonum = cls.demonum;
                    312:                cls.demonum = -1;
                    313:        }
                    314:        key_dest = key_menu;
                    315:        m_state = m_main;
                    316:        m_entersound = true;
                    317: }
                    318:                                
                    319: 
                    320: void M_Main_Draw (void)
                    321: {
                    322:        int             f;
                    323:        qpic_t  *p;
                    324: 
                    325:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                    326:        p = M_CachePic ("gfx/ttl_main.lmp");
                    327:        M_DrawPic ( (320-p->width)/2, 4, p);
                    328:        M_DrawTransPic (72, 32, M_CachePic ("gfx/mainmenu.lmp") );
                    329: 
                    330:        f = (int)(host_time * 10)%6;
                    331:        
                    332:        M_DrawTransPic (54, 32 + m_main_cursor * 20,M_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
                    333: }
                    334: 
                    335: 
                    336: void M_Main_Key (int key)
                    337: {
                    338:        switch (key)
                    339:        {
                    340:        case K_ESCAPE:
                    341:                key_dest = key_game;
                    342:                m_state = m_none;
                    343:                cls.demonum = m_save_demonum;
                    344:                if (cls.demonum != -1 && !cls.demoplayback && cls.state != ca_connected)
                    345:                        CL_NextDemo ();
                    346:                break;
                    347:                
                    348:        case K_DOWNARROW:
                    349:                S_LocalSound ("misc/menu1.wav");
                    350:                if (++m_main_cursor >= MAIN_ITEMS)
                    351:                        m_main_cursor = 0;
                    352:                break;
                    353: 
                    354:        case K_UPARROW:
                    355:                S_LocalSound ("misc/menu1.wav");
                    356:                if (--m_main_cursor < 0)
                    357:                        m_main_cursor = MAIN_ITEMS - 1;
                    358:                break;
                    359: 
                    360:        case K_ENTER:
                    361:                m_entersound = true;
                    362: 
                    363:                switch (m_main_cursor)
                    364:                {
                    365:                case 0:
                    366:                        M_Menu_SinglePlayer_f ();
                    367:                        break;
                    368: 
                    369:                case 1:
                    370:                        M_Menu_MultiPlayer_f ();
                    371:                        break;
                    372: 
                    373:                case 2:
                    374:                        M_Menu_Options_f ();
                    375:                        break;
                    376: 
                    377:                case 3:
                    378:                        M_Menu_Help_f ();
                    379:                        break;
                    380: 
                    381:                case 4:
                    382:                        M_Menu_Quit_f ();
                    383:                        break;
                    384:                }
                    385:        }
                    386: }
                    387: 
                    388: //=============================================================================
                    389: /* SINGLE PLAYER MENU */
                    390: 
                    391: int    m_singleplayer_cursor;
                    392: #define        SINGLEPLAYER_ITEMS      3
                    393: 
                    394: 
                    395: void M_Menu_SinglePlayer_f (void)
                    396: {
                    397:        key_dest = key_menu;
                    398:        m_state = m_singleplayer;
                    399:        m_entersound = true;
                    400: }
                    401:                                
                    402: 
                    403: void M_SinglePlayer_Draw (void)
                    404: {
                    405:        int             f;
                    406:        qpic_t  *p;
                    407: 
                    408:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                    409:        p = M_CachePic ("gfx/ttl_sgl.lmp");
                    410:        M_DrawPic ( (320-p->width)/2, 4, p);
                    411:        M_DrawTransPic (72, 32, M_CachePic ("gfx/sp_menu.lmp") );
                    412: 
                    413:        f = (int)(host_time * 10)%6;
                    414:        
                    415:        M_DrawTransPic (54, 32 + m_singleplayer_cursor * 20,M_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
                    416: }
                    417: 
                    418: 
                    419: void M_SinglePlayer_Key (int key)
                    420: {
                    421:        switch (key)
                    422:        {
                    423:        case K_ESCAPE:
                    424:                M_Menu_Main_f ();
                    425:                break;
                    426:                
                    427:        case K_DOWNARROW:
                    428:                S_LocalSound ("misc/menu1.wav");
                    429:                if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS)
                    430:                        m_singleplayer_cursor = 0;
                    431:                break;
                    432: 
                    433:        case K_UPARROW:
                    434:                S_LocalSound ("misc/menu1.wav");
                    435:                if (--m_singleplayer_cursor < 0)
                    436:                        m_singleplayer_cursor = SINGLEPLAYER_ITEMS - 1;
                    437:                break;
                    438: 
                    439:        case K_ENTER:
                    440:                m_entersound = true;
                    441: 
                    442:                switch (m_singleplayer_cursor)
                    443:                {
                    444:                case 0:
                    445:                        if (sv.active)
                    446:                                if (!SCR_ModalMessage("Are you sure you want to\nstart a new game?\n"))
                    447:                                        break;
                    448:                        key_dest = key_game;
                    449:                        if (sv.active)
                    450:                                Cbuf_AddText ("disconnect\n");
                    451:                        Cbuf_AddText ("maxplayers 1\n");
                    452:                        Cbuf_AddText ("map start\n");
                    453:                        break;
                    454: 
                    455:                case 1:
                    456:                        M_Menu_Load_f ();
                    457:                        break;
                    458: 
                    459:                case 2:
                    460:                        M_Menu_Save_f ();
                    461:                        break;
                    462:                }
                    463:        }
                    464: }
                    465: 
                    466: //=============================================================================
                    467: /* LOAD/SAVE MENU */
                    468: 
                    469: int            load_cursor;            // 0 < load_cursor < MAX_SAVEGAMES
                    470: 
                    471: #define        MAX_SAVEGAMES           12
                    472: char   m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
                    473: int            loadable[MAX_SAVEGAMES];
                    474: 
                    475: void M_ScanSaves (void)
                    476: {
                    477:        int             i, j;
                    478:        char    name[MAX_OSPATH];
                    479:        FILE    *f;
                    480:        int             version;
                    481: 
                    482:        for (i=0 ; i<MAX_SAVEGAMES ; i++)
                    483:        {
                    484:                strcpy (m_filenames[i], "--- UNUSED SLOT ---");
                    485:                loadable[i] = false;
                    486:                sprintf (name, "%s/s%i.sav", com_gamedir, i);
                    487:                f = fopen (name, "r");
                    488:                if (!f)
                    489:                        continue;
                    490:                fscanf (f, "%i\n", &version);
                    491:                fscanf (f, "%79s\n", name);
                    492:                strncpy (m_filenames[i], name, sizeof(m_filenames[i])-1);
                    493: 
                    494:        // change _ back to space
                    495:                for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
                    496:                        if (m_filenames[i][j] == '_')
                    497:                                m_filenames[i][j] = ' ';
                    498:                loadable[i] = true;
                    499:                fclose (f);                     
                    500:        }
                    501: }
                    502: 
                    503: void M_Menu_Load_f (void)
                    504: {
                    505:        m_entersound = true;
                    506:        m_state = m_load;
                    507:        key_dest = key_menu;
                    508:        M_ScanSaves ();
                    509: }
                    510:                                
                    511: 
                    512: void M_Menu_Save_f (void)
                    513: {
                    514:        if (!sv.active)
                    515:                return;
                    516:        if (cl.intermission)
                    517:                return;
                    518:        if (svs.maxclients != 1)
                    519:                return;
                    520:        m_entersound = true;
                    521:        m_state = m_save;
                    522:        key_dest = key_menu;
                    523:        M_ScanSaves ();
                    524: }
                    525: 
                    526: 
                    527: void M_Load_Draw (void)
                    528: {
                    529:        int             i;
                    530:        qpic_t  *p;
                    531:        
                    532:        p = M_CachePic ("gfx/p_load.lmp");
                    533:        M_DrawPic ( (320-p->width)/2, 4, p);
                    534:        
                    535:        for (i=0 ; i< MAX_SAVEGAMES; i++)
                    536:                M_Print (16, 32 + 8*i, m_filenames[i]);
                    537: 
                    538: // line cursor
                    539:        M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
                    540: }
                    541: 
                    542: 
                    543: void M_Save_Draw (void)
                    544: {
                    545:        int             i;
                    546:        qpic_t  *p;
                    547:        
                    548:        p = M_CachePic ("gfx/p_save.lmp");
                    549:        M_DrawPic ( (320-p->width)/2, 4, p);
                    550: 
                    551:        for (i=0 ; i<MAX_SAVEGAMES ; i++)
                    552:                M_Print (16, 32 + 8*i, m_filenames[i]);
                    553: 
                    554: // line cursor
                    555:        M_DrawCharacter (8, 32 + load_cursor*8, 12+((int)(realtime*4)&1));
                    556: }
                    557: 
                    558: 
                    559: void M_Load_Key (int k)
                    560: {      
                    561:        switch (k)
                    562:        {
                    563:        case K_ESCAPE:
                    564:                M_Menu_SinglePlayer_f ();
                    565:                break;
                    566: 
                    567:        case K_ENTER:
                    568:                S_LocalSound ("misc/menu2.wav");
                    569:                if (!loadable[load_cursor])
                    570:                        return;
                    571:                m_state = m_none;
                    572:                key_dest = key_game;
                    573: 
                    574:        // Host_Loadgame_f can't bring up the loading plaque because too much
                    575:        // stack space has been used, so do it now
                    576:                SCR_BeginLoadingPlaque ();
                    577: 
                    578:        // issue the load command
                    579:                Cbuf_AddText (va ("load s%i\n", load_cursor) );
                    580:                return;
                    581:        
                    582:        case K_UPARROW:
                    583:        case K_LEFTARROW:
                    584:                S_LocalSound ("misc/menu1.wav");
                    585:                load_cursor--;
                    586:                if (load_cursor < 0)
                    587:                        load_cursor = MAX_SAVEGAMES-1;
                    588:                break;
                    589: 
                    590:        case K_DOWNARROW:
                    591:        case K_RIGHTARROW:
                    592:                S_LocalSound ("misc/menu1.wav");
                    593:                load_cursor++;
                    594:                if (load_cursor >= MAX_SAVEGAMES)
                    595:                        load_cursor = 0;
                    596:                break;
                    597:        }
                    598: }
                    599: 
                    600: 
                    601: void M_Save_Key (int k)
                    602: {
                    603:        switch (k)
                    604:        {
                    605:        case K_ESCAPE:
                    606:                M_Menu_SinglePlayer_f ();
                    607:                break;
                    608: 
                    609:        case K_ENTER:
                    610:                m_state = m_none;
                    611:                key_dest = key_game;
                    612:                Cbuf_AddText (va("save s%i\n", load_cursor));
                    613:                return;
                    614:        
                    615:        case K_UPARROW:
                    616:        case K_LEFTARROW:
                    617:                S_LocalSound ("misc/menu1.wav");
                    618:                load_cursor--;
                    619:                if (load_cursor < 0)
                    620:                        load_cursor = MAX_SAVEGAMES-1;
                    621:                break;
                    622: 
                    623:        case K_DOWNARROW:
                    624:        case K_RIGHTARROW:
                    625:                S_LocalSound ("misc/menu1.wav");
                    626:                load_cursor++;
                    627:                if (load_cursor >= MAX_SAVEGAMES)
                    628:                        load_cursor = 0;
                    629:                break;  
                    630:        }
                    631: }
                    632: 
                    633: //=============================================================================
                    634: /* MULTIPLAYER MENU */
                    635: 
                    636: int    m_multiplayer_cursor;
                    637: #define        MULTIPLAYER_ITEMS       3
                    638: 
                    639: 
                    640: void M_Menu_MultiPlayer_f (void)
                    641: {
                    642:        key_dest = key_menu;
                    643:        m_state = m_multiplayer;
                    644:        m_entersound = true;
                    645: }
                    646:                                
                    647: 
                    648: void M_MultiPlayer_Draw (void)
                    649: {
                    650:        int             f;
                    651:        qpic_t  *p;
                    652: 
                    653:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                    654:        p = M_CachePic ("gfx/p_multi.lmp");
                    655:        M_DrawPic ( (320-p->width)/2, 4, p);
                    656:        M_DrawTransPic (72, 32, M_CachePic ("gfx/mp_menu.lmp") );
                    657: 
                    658:        f = (int)(host_time * 10)%6;
                    659:        
                    660:        M_DrawTransPic (54, 32 + m_multiplayer_cursor * 20,M_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
                    661: 
                    662:        if (serialAvailable || ipxAvailable || tcpipAvailable)
                    663:                return;
                    664:        M_PrintWhite ((320/2) - ((27*8)/2), 148, "No Communications Available");
                    665: }
                    666: 
                    667: 
                    668: void M_MultiPlayer_Key (int key)
                    669: {
                    670:        switch (key)
                    671:        {
                    672:        case K_ESCAPE:
                    673:                M_Menu_Main_f ();
                    674:                break;
                    675:                
                    676:        case K_DOWNARROW:
                    677:                S_LocalSound ("misc/menu1.wav");
                    678:                if (++m_multiplayer_cursor >= MULTIPLAYER_ITEMS)
                    679:                        m_multiplayer_cursor = 0;
                    680:                break;
                    681: 
                    682:        case K_UPARROW:
                    683:                S_LocalSound ("misc/menu1.wav");
                    684:                if (--m_multiplayer_cursor < 0)
                    685:                        m_multiplayer_cursor = MULTIPLAYER_ITEMS - 1;
                    686:                break;
                    687: 
                    688:        case K_ENTER:
                    689:                m_entersound = true;
                    690:                switch (m_multiplayer_cursor)
                    691:                {
                    692:                case 0:
                    693:                        if (serialAvailable || ipxAvailable || tcpipAvailable)
                    694:                                M_Menu_Net_f ();
                    695:                        break;
                    696: 
                    697:                case 1:
                    698:                        if (serialAvailable || ipxAvailable || tcpipAvailable)
                    699:                                M_Menu_Net_f ();
                    700:                        break;
                    701: 
                    702:                case 2:
                    703:                        M_Menu_Setup_f ();
                    704:                        break;
                    705:                }
                    706:        }
                    707: }
                    708: 
                    709: //=============================================================================
                    710: /* SETUP MENU */
                    711: 
                    712: int            setup_cursor = 4;
                    713: int            setup_cursor_table[] = {40, 56, 80, 104, 140};
                    714: 
                    715: char   setup_hostname[16];
                    716: char   setup_myname[16];
                    717: int            setup_oldtop;
                    718: int            setup_oldbottom;
                    719: int            setup_top;
                    720: int            setup_bottom;
                    721: 
                    722: #define        NUM_SETUP_CMDS  5
                    723: 
                    724: void M_Menu_Setup_f (void)
                    725: {
                    726:        key_dest = key_menu;
                    727:        m_state = m_setup;
                    728:        m_entersound = true;
                    729:        Q_strcpy(setup_myname, cl_name.string);
                    730:        Q_strcpy(setup_hostname, hostname.string);
                    731:        setup_top = setup_oldtop = ((int)cl_color.value) >> 4;
                    732:        setup_bottom = setup_oldbottom = ((int)cl_color.value) & 15;
                    733: }
                    734:                                
                    735: 
                    736: void M_Setup_Draw (void)
                    737: {
                    738:        qpic_t  *p;
                    739: 
                    740:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                    741:        p = M_CachePic ("gfx/p_multi.lmp");
                    742:        M_DrawPic ( (320-p->width)/2, 4, p);
                    743:        
                    744:        M_Print (64, 40, "Hostname");
                    745:        M_DrawTextBox (160, 32, 16, 1);
                    746:        M_Print (168, 40, setup_hostname);
                    747: 
                    748:        M_Print (64, 56, "Your name");
                    749:        M_DrawTextBox (160, 48, 16, 1);
                    750:        M_Print (168, 56, setup_myname);
                    751: 
                    752:        M_Print (64, 80, "Shirt color");
                    753:        M_Print (64, 104, "Pants color");
                    754:        
                    755:        M_DrawTextBox (64, 140-8, 14, 1);
                    756:        M_Print (72, 140, "Accept Changes");
                    757: 
                    758:        p = M_CachePic ("gfx/bigbox.lmp");
                    759:        M_DrawTransPic (160, 64, p);
                    760:        p = M_CachePic ("gfx/menuplyr.lmp");
                    761:        M_BuildTranslationTable(setup_top*16, setup_bottom*16);
                    762:        M_DrawTransPicTranslate (172, 72, p);
                    763: 
                    764:        M_DrawCharacter (56, setup_cursor_table [setup_cursor], 12+((int)(realtime*4)&1));
                    765: 
                    766:        if (setup_cursor == 0)
                    767:                M_DrawCharacter (168 + 8*strlen(setup_hostname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
                    768: 
                    769:        if (setup_cursor == 1)
                    770:                M_DrawCharacter (168 + 8*strlen(setup_myname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1));
                    771: }
                    772: 
                    773: 
                    774: void M_Setup_Key (int k)
                    775: {
                    776:        int                     l;
                    777: 
                    778:        switch (k)
                    779:        {
                    780:        case K_ESCAPE:
                    781:                M_Menu_MultiPlayer_f ();
                    782:                break;
                    783: 
                    784:        case K_UPARROW:
                    785:                S_LocalSound ("misc/menu1.wav");
                    786:                setup_cursor--;
                    787:                if (setup_cursor < 0)
                    788:                        setup_cursor = NUM_SETUP_CMDS-1;
                    789:                break;
                    790: 
                    791:        case K_DOWNARROW:
                    792:                S_LocalSound ("misc/menu1.wav");
                    793:                setup_cursor++;
                    794:                if (setup_cursor >= NUM_SETUP_CMDS)
                    795:                        setup_cursor = 0;
                    796:                break;
                    797: 
                    798:        case K_LEFTARROW:
                    799:                if (setup_cursor < 2)
                    800:                        return;
                    801:                S_LocalSound ("misc/menu3.wav");
                    802:                if (setup_cursor == 2)
                    803:                        setup_top = setup_top - 1;
                    804:                if (setup_cursor == 3)
                    805:                        setup_bottom = setup_bottom - 1;
                    806:                break;
                    807:        case K_RIGHTARROW:
                    808:                if (setup_cursor < 2)
                    809:                        return;
                    810: forward:
                    811:                S_LocalSound ("misc/menu3.wav");
                    812:                if (setup_cursor == 2)
                    813:                        setup_top = setup_top + 1;
                    814:                if (setup_cursor == 3)
                    815:                        setup_bottom = setup_bottom + 1;
                    816:                break;
                    817: 
                    818:        case K_ENTER:
                    819:                if (setup_cursor == 0 || setup_cursor == 1)
                    820:                        return;
                    821: 
                    822:                if (setup_cursor == 2 || setup_cursor == 3)
                    823:                        goto forward;
                    824: 
                    825:                // setup_cursor == 4 (OK)
                    826:                if (Q_strcmp(cl_name.string, setup_myname) != 0)
                    827:                        Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) );
                    828:                if (Q_strcmp(hostname.string, setup_hostname) != 0)
                    829:                        Cvar_Set("hostname", setup_hostname);
                    830:                if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom)
                    831:                        Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) );
                    832:                m_entersound = true;
                    833:                M_Menu_MultiPlayer_f ();
                    834:                break;
                    835:        
                    836:        case K_BACKSPACE:
                    837:                if (setup_cursor == 0)
                    838:                {
                    839:                        if (strlen(setup_hostname))
                    840:                                setup_hostname[strlen(setup_hostname)-1] = 0;
                    841:                }
                    842: 
                    843:                if (setup_cursor == 1)
                    844:                {
                    845:                        if (strlen(setup_myname))
                    846:                                setup_myname[strlen(setup_myname)-1] = 0;
                    847:                }
                    848:                break;
                    849:                
                    850:        default:
                    851:                if (k < 32 || k > 127)
                    852:                        break;
                    853:                if (setup_cursor == 0)
                    854:                {
                    855:                        l = strlen(setup_hostname);
                    856:                        if (l < 15)
                    857:                        {
                    858:                                setup_hostname[l+1] = 0;
                    859:                                setup_hostname[l] = k;
                    860:                        }
                    861:                }
                    862:                if (setup_cursor == 1)
                    863:                {
                    864:                        l = strlen(setup_myname);
                    865:                        if (l < 15)
                    866:                        {
                    867:                                setup_myname[l+1] = 0;
                    868:                                setup_myname[l] = k;
                    869:                        }
                    870:                }
                    871:        }
                    872: 
                    873:        if (setup_top > 13)
                    874:                setup_top = 0;
                    875:        if (setup_top < 0)
                    876:                setup_top = 13;
                    877:        if (setup_bottom > 13)
                    878:                setup_bottom = 0;
                    879:        if (setup_bottom < 0)
                    880:                setup_bottom = 13;
                    881: }
                    882: 
                    883: //=============================================================================
                    884: /* NET MENU */
                    885: 
                    886: int    m_net_cursor;
                    887: int m_net_items;
                    888: int m_net_saveHeight;
                    889: 
                    890: char *net_helpMessage [] = 
                    891: {
                    892: /* .........1.........2.... */
                    893:   "                        ",
                    894:   " Two computers connected",
                    895:   "   through two modems.  ",
                    896:   "                        ",
                    897:  
                    898:   "                        ",
                    899:   " Two computers connected",
                    900:   " by a null-modem cable. ",
                    901:   "                        ",
                    902: 
                    903:   " Novell network LANs    ",
                    904:   " or Windows 95 DOS-box. ",
                    905:   "                        ",
                    906:   "(LAN=Local Area Network)",
                    907: 
                    908:   " Commonly used to play  ",
                    909:   " over the Internet, but ",
                    910:   " also used on a Local   ",
                    911:   " Area Network.          "
                    912: };
                    913: 
                    914: void M_Menu_Net_f (void)
                    915: {
                    916:        key_dest = key_menu;
                    917:        m_state = m_net;
                    918:        m_entersound = true;
                    919:        m_net_items = 4;
                    920: 
                    921:        if (m_net_cursor >= m_net_items)
                    922:                m_net_cursor = 0;
                    923:        m_net_cursor--;
                    924:        M_Net_Key (K_DOWNARROW);
                    925: }
                    926: 
                    927: 
                    928: void M_Net_Draw (void)
                    929: {
                    930:        int             f;
                    931:        qpic_t  *p;
                    932: 
                    933:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                    934:        p = M_CachePic ("gfx/p_multi.lmp");
                    935:        M_DrawPic ( (320-p->width)/2, 4, p);
                    936: 
                    937:        f = 32;
                    938:        if (serialAvailable)
                    939:                p = M_CachePic ("gfx/netmen1.lmp");
                    940:        else
                    941:                p = M_CachePic ("gfx/dim_modm.lmp");
                    942:        M_DrawTransPic (72, f, p);
                    943: 
                    944:        f += 19;
                    945:        if (serialAvailable)
                    946:                p = M_CachePic ("gfx/netmen2.lmp");
                    947:        else
                    948:                p = M_CachePic ("gfx/dim_drct.lmp");
                    949:        M_DrawTransPic (72, f, p);
                    950: 
                    951:        f += 19;
                    952:        if (ipxAvailable)
                    953:                p = M_CachePic ("gfx/netmen3.lmp");
                    954:        else
                    955:                p = M_CachePic ("gfx/dim_ipx.lmp");
                    956:        M_DrawTransPic (72, f, p);
                    957: 
                    958:        f += 19;
                    959:        if (tcpipAvailable)
                    960:                p = M_CachePic ("gfx/netmen4.lmp");
                    961:        else
                    962:                p = M_CachePic ("gfx/dim_tcp.lmp");
                    963:        M_DrawTransPic (72, f, p);
                    964: 
                    965:        if (m_net_items == 5)   // JDC, could just be removed
                    966:        {
                    967:                f += 19;
                    968:                p = M_CachePic ("gfx/netmen5.lmp");
                    969:                M_DrawTransPic (72, f, p);
                    970:        }
                    971: 
                    972:        f = (320-26*8)/2;
                    973:        M_DrawTextBox (f, 134, 24, 4);
                    974:        f += 8;
                    975:        M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]);
                    976:        M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]);
                    977:        M_Print (f, 158, net_helpMessage[m_net_cursor*4+2]);
                    978:        M_Print (f, 166, net_helpMessage[m_net_cursor*4+3]);
                    979: 
                    980:        f = (int)(host_time * 10)%6;
                    981:        M_DrawTransPic (54, 32 + m_net_cursor * 20,M_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) );
                    982: }
                    983: 
                    984: 
                    985: void M_Net_Key (int k)
                    986: {
                    987: again:
                    988:        switch (k)
                    989:        {
                    990:        case K_ESCAPE:
                    991:                M_Menu_MultiPlayer_f ();
                    992:                break;
                    993:                
                    994:        case K_DOWNARROW:
                    995:                S_LocalSound ("misc/menu1.wav");
                    996:                if (++m_net_cursor >= m_net_items)
                    997:                        m_net_cursor = 0;
                    998:                break;
                    999: 
                   1000:        case K_UPARROW:
                   1001:                S_LocalSound ("misc/menu1.wav");
                   1002:                if (--m_net_cursor < 0)
                   1003:                        m_net_cursor = m_net_items - 1;
                   1004:                break;
                   1005: 
                   1006:        case K_ENTER:
                   1007:                m_entersound = true;
                   1008: 
                   1009:                switch (m_net_cursor)
                   1010:                {
                   1011:                case 0:
                   1012:                        M_Menu_SerialConfig_f ();
                   1013:                        break;
                   1014: 
                   1015:                case 1:
                   1016:                        M_Menu_SerialConfig_f ();
                   1017:                        break;
                   1018: 
                   1019:                case 2:
                   1020:                        M_Menu_LanConfig_f ();
                   1021:                        break;
                   1022: 
                   1023:                case 3:
                   1024:                        M_Menu_LanConfig_f ();
                   1025:                        break;
                   1026: 
                   1027:                case 4:
                   1028: // multiprotocol
                   1029:                        break;
                   1030:                }
                   1031:        }
                   1032: 
                   1033:        if (m_net_cursor == 0 && !serialAvailable)
                   1034:                goto again;
                   1035:        if (m_net_cursor == 1 && !serialAvailable)
                   1036:                goto again;
                   1037:        if (m_net_cursor == 2 && !ipxAvailable)
                   1038:                goto again;
                   1039:        if (m_net_cursor == 3 && !tcpipAvailable)
                   1040:                goto again;
                   1041: }
                   1042: 
                   1043: //=============================================================================
                   1044: /* OPTIONS MENU */
                   1045: 
                   1046: #define        OPTIONS_ITEMS   13
                   1047: #define        SLIDER_RANGE    10
                   1048: 
                   1049: int            options_cursor;
                   1050: 
                   1051: void M_Menu_Options_f (void)
                   1052: {
                   1053:        key_dest = key_menu;
                   1054:        m_state = m_options;
                   1055:        m_entersound = true;
                   1056: }
                   1057: 
                   1058: 
                   1059: void M_AdjustSliders (int dir)
                   1060: {
                   1061:        S_LocalSound ("misc/menu3.wav");
                   1062: 
                   1063:        switch (options_cursor)
                   1064:        {
                   1065:        case 3: // screen size
                   1066:                scr_viewsize.value += dir * 10;
                   1067:                if (scr_viewsize.value < 30)
                   1068:                        scr_viewsize.value = 30;
                   1069:                if (scr_viewsize.value > 120)
                   1070:                        scr_viewsize.value = 120;
                   1071:                Cvar_SetValue ("viewsize", scr_viewsize.value);
                   1072:                break;
                   1073:        case 4: // gamma
                   1074:                v_gamma.value -= dir * 0.05;
                   1075:                if (v_gamma.value < 0.5)
                   1076:                        v_gamma.value = 0.5;
                   1077:                if (v_gamma.value > 1)
                   1078:                        v_gamma.value = 1;
                   1079:                Cvar_SetValue ("gamma", v_gamma.value);
                   1080:                break;
                   1081:        case 5: // mouse speed
                   1082:                sensitivity.value += dir * 0.5;
                   1083:                if (sensitivity.value < 1)
                   1084:                        sensitivity.value = 1;
                   1085:                if (sensitivity.value > 6)
                   1086:                        sensitivity.value = 6;
                   1087:                Cvar_SetValue ("sensitivity", sensitivity.value);
                   1088:                break;
                   1089:        case 6: // music volume
                   1090:                bgmvolume.value += dir * 0.1;
                   1091:                if (bgmvolume.value < 0)
                   1092:                        bgmvolume.value = 0;
                   1093:                if (bgmvolume.value > 1)
                   1094:                        bgmvolume.value = 1;
                   1095:                Cvar_SetValue ("bgmvolume", bgmvolume.value);
                   1096:                break;
                   1097:        case 7: // sfx volume
                   1098:                volume.value += dir * 0.1;
                   1099:                if (volume.value < 0)
                   1100:                        volume.value = 0;
                   1101:                if (volume.value > 1)
                   1102:                        volume.value = 1;
                   1103:                Cvar_SetValue ("volume", volume.value);
                   1104:                break;
                   1105:                
                   1106:        case 8: // allways run
                   1107:                if (cl_forwardspeed.value > 200)
                   1108:                {
                   1109:                        Cvar_SetValue ("cl_forwardspeed", 200);
                   1110:                        Cvar_SetValue ("cl_backspeed", 200);
                   1111:                }
                   1112:                else
                   1113:                {
                   1114:                        Cvar_SetValue ("cl_forwardspeed", 400);
                   1115:                        Cvar_SetValue ("cl_backspeed", 400);
                   1116:                }
                   1117:                break;
                   1118:        
                   1119:        case 9: // invert mouse
                   1120:                Cvar_SetValue ("m_pitch", -m_pitch.value);
                   1121:                break;
                   1122:        
                   1123:        case 10:        // lookspring
                   1124:                Cvar_SetValue ("lookspring", !lookspring.value);
                   1125:                break;
                   1126:        
                   1127:        case 11:        // lookstrafe
                   1128:                Cvar_SetValue ("lookstrafe", !lookstrafe.value);
                   1129:                break;
                   1130:        }
                   1131: }
                   1132: 
                   1133: 
                   1134: void M_DrawSlider (int x, int y, float range)
                   1135: {
                   1136:        int     i;
                   1137: 
                   1138:        if (range < 0)
                   1139:                range = 0;
                   1140:        if (range > 1)
                   1141:                range = 1;
                   1142:        M_DrawCharacter (x-8, y, 128);
                   1143:        for (i=0 ; i<SLIDER_RANGE ; i++)
                   1144:                M_DrawCharacter (x + i*8, y, 129);
                   1145:        M_DrawCharacter (x+i*8, y, 130);
                   1146:        M_DrawCharacter (x + (SLIDER_RANGE-1)*8 * range, y, 131);
                   1147: }
                   1148: 
                   1149: void M_DrawCheckbox (int x, int y, int on)
                   1150: {
                   1151: #if 0
                   1152:        if (on)
                   1153:                M_DrawCharacter (x, y, 131);
                   1154:        else
                   1155:                M_DrawCharacter (x, y, 129);
                   1156: #endif
                   1157:        if (on)
                   1158:                M_Print (x, y, "on");
                   1159:        else
                   1160:                M_Print (x, y, "off");
                   1161: }
                   1162: 
                   1163: void M_Options_Draw (void)
                   1164: {
                   1165:        float           r;
                   1166:        qpic_t  *p;
                   1167:        
                   1168:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                   1169:        p = M_CachePic ("gfx/p_option.lmp");
                   1170:        M_DrawPic ( (320-p->width)/2, 4, p);
                   1171:        
                   1172:        M_Print (16, 32, "    Customize controls");
                   1173:        M_Print (16, 40, "         Go to console");
                   1174:        M_Print (16, 48, "     Reset to defaults");
                   1175: 
                   1176:        M_Print (16, 56, "           Screen size");
                   1177:        r = (scr_viewsize.value - 30) / (120 - 30);
                   1178:        M_DrawSlider (220, 56, r);
                   1179: 
                   1180:        M_Print (16, 64, "            Brightness");
                   1181:        r = (1.0 - v_gamma.value) / 0.5;
                   1182:        M_DrawSlider (220, 64, r);
                   1183: 
                   1184:        M_Print (16, 72, "           Mouse Speed");
                   1185:        r = (sensitivity.value - 1)/5;
                   1186:        M_DrawSlider (220, 72, r);
                   1187: 
                   1188:        M_Print (16, 80, "       CD Music Volume");
                   1189:        r = bgmvolume.value;
                   1190:        M_DrawSlider (220, 80, r);
                   1191: 
                   1192:        M_Print (16, 88, "          Sound Volume");
                   1193:        r = volume.value;
                   1194:        M_DrawSlider (220, 88, r);
                   1195: 
                   1196:        M_Print (16, 96,  "            Always Run");
                   1197:        M_DrawCheckbox (220, 96, cl_forwardspeed.value > 200);
                   1198: 
                   1199:        M_Print (16, 104, "          Invert Mouse");
                   1200:        M_DrawCheckbox (220, 104, m_pitch.value < 0);
                   1201: 
                   1202:        M_Print (16, 112, "            Lookspring");
                   1203:        M_DrawCheckbox (220, 112, lookspring.value);
                   1204: 
                   1205:        M_Print (16, 120, "            Lookstrafe");
                   1206:        M_DrawCheckbox (220, 120, lookstrafe.value);
                   1207: 
                   1208:        if (vid_menudrawfn)
                   1209:                M_Print (16, 128, "         Video Options");
                   1210: 
                   1211: // cursor
                   1212:        M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(realtime*4)&1));
                   1213: }
                   1214: 
                   1215: 
                   1216: void M_Options_Key (int k)
                   1217: {
                   1218:        switch (k)
                   1219:        {
                   1220:        case K_ESCAPE:
                   1221:                M_Menu_Main_f ();
                   1222:                break;
                   1223:                
                   1224:        case K_ENTER:
                   1225:                m_entersound = true;
                   1226:                switch (options_cursor)
                   1227:                {
                   1228:                case 0:
                   1229:                        M_Menu_Keys_f ();
                   1230:                        break;
                   1231:                case 1:
                   1232:                        m_state = m_none;
                   1233:                        Con_ToggleConsole_f ();
                   1234:                        break;
                   1235:                case 2:
                   1236:                        Cbuf_AddText ("exec default.cfg\n");
                   1237:                        break;
                   1238:                case 12:
                   1239:                        M_Menu_Video_f ();
                   1240:                        break;
                   1241:                default:
                   1242:                        M_AdjustSliders (1);
                   1243:                        break;
                   1244:                }
                   1245:                return;
                   1246:        
                   1247:        case K_UPARROW:
                   1248:                S_LocalSound ("misc/menu1.wav");
                   1249:                options_cursor--;
                   1250:                if (options_cursor < 0)
                   1251:                        options_cursor = OPTIONS_ITEMS-1;
                   1252:                break;
                   1253: 
                   1254:        case K_DOWNARROW:
                   1255:                S_LocalSound ("misc/menu1.wav");
                   1256:                options_cursor++;
                   1257:                if (options_cursor >= OPTIONS_ITEMS)
                   1258:                        options_cursor = 0;
                   1259:                break;  
                   1260: 
                   1261:        case K_LEFTARROW:
                   1262:                M_AdjustSliders (-1);
                   1263:                break;
                   1264: 
                   1265:        case K_RIGHTARROW:
                   1266:                M_AdjustSliders (1);
                   1267:                break;
                   1268:        }
                   1269: 
                   1270:        if (options_cursor == 12 && vid_menudrawfn == NULL)
                   1271:                if (k == K_UPARROW)
                   1272:                        options_cursor = 11;
                   1273:                else
                   1274:                        options_cursor = 0;
                   1275: }
                   1276: 
                   1277: //=============================================================================
                   1278: /* KEYS MENU */
                   1279: 
                   1280: char *bindnames[][2] =
                   1281: {
                   1282: {"+attack",            "attack"},
                   1283: {"impulse 10",                 "change weapon"},
                   1284: {"+jump",                      "jump / swim up"},
                   1285: {"+forward",           "walk forward"},
                   1286: {"+back",                      "backpedal"},
                   1287: {"+left",                      "turn left"},
                   1288: {"+right",                     "turn right"},
                   1289: {"+speed",                     "run"},
                   1290: {"+moveleft",          "step left"},
                   1291: {"+moveright",                 "step right"},
                   1292: {"+strafe",            "sidestep"},
                   1293: {"+lookup",            "look up"},
                   1294: {"+lookdown",          "look down"},
                   1295: {"centerview",                 "center view"},
                   1296: {"+mlook",                     "mouse look"},
                   1297: {"+klook",                     "keyboard look"},
                   1298: {"+moveup",                    "swim up"},
                   1299: {"+movedown",          "swim down"}
                   1300: };
                   1301: 
                   1302: #define        NUMCOMMANDS     (sizeof(bindnames)/sizeof(bindnames[0]))
                   1303: 
                   1304: int            keys_cursor;
                   1305: int            bind_grab;
                   1306: 
                   1307: void M_Menu_Keys_f (void)
                   1308: {
                   1309:        key_dest = key_menu;
                   1310:        m_state = m_keys;
                   1311:        m_entersound = true;
                   1312: }
                   1313: 
                   1314: 
                   1315: void M_FindKeysForCommand (char *command, int *twokeys)
                   1316: {
                   1317:        int             count;
                   1318:        int             j;
                   1319:        int             l;
                   1320:        char    *b;
                   1321: 
                   1322:        twokeys[0] = twokeys[1] = -1;
                   1323:        l = strlen(command);
                   1324:        count = 0;
                   1325: 
                   1326:        for (j=0 ; j<256 ; j++)
                   1327:        {
                   1328:                b = keybindings[j];
                   1329:                if (!b)
                   1330:                        continue;
                   1331:                if (!strncmp (b, command, l) )
                   1332:                {
                   1333:                        twokeys[count] = j;
                   1334:                        count++;
                   1335:                        if (count == 2)
                   1336:                                break;
                   1337:                }
                   1338:        }
                   1339: }
                   1340: 
                   1341: void M_UnbindCommand (char *command)
                   1342: {
                   1343:        int             j;
                   1344:        int             l;
                   1345:        char    *b;
                   1346: 
                   1347:        l = strlen(command);
                   1348: 
                   1349:        for (j=0 ; j<256 ; j++)
                   1350:        {
                   1351:                b = keybindings[j];
                   1352:                if (!b)
                   1353:                        continue;
                   1354:                if (!strncmp (b, command, l) )
                   1355:                        Key_SetBinding (j, "");
                   1356:        }
                   1357: }
                   1358: 
                   1359: 
                   1360: void M_Keys_Draw (void)
                   1361: {
                   1362:        int             i, l;
                   1363:        int             keys[2];
                   1364:        char    *name;
                   1365:        int             x, y;
                   1366:        qpic_t  *p;
                   1367: 
                   1368:        p = M_CachePic ("gfx/ttl_cstm.lmp");
                   1369:        M_DrawPic ( (320-p->width)/2, 4, p);
                   1370: 
                   1371:        if (bind_grab)
                   1372:                M_Print (12, 32, "Press a key or button for this action");
                   1373:        else
                   1374:                M_Print (18, 32, "Enter to change, backspace to clear");
                   1375:                
                   1376: // search for known bindings
                   1377:        for (i=0 ; i<NUMCOMMANDS ; i++)
                   1378:        {
                   1379:                y = 48 + 8*i;
                   1380: 
                   1381:                M_Print (16, y, bindnames[i][1]);
                   1382: 
                   1383:                l = strlen (bindnames[i][0]);
                   1384:                
                   1385:                M_FindKeysForCommand (bindnames[i][0], keys);
                   1386:                
                   1387:                if (keys[0] == -1)
                   1388:                {
                   1389:                        M_Print (140, y, "???");
                   1390:                }
                   1391:                else
                   1392:                {
                   1393:                        name = Key_KeynumToString (keys[0]);
                   1394:                        M_Print (140, y, name);
                   1395:                        x = strlen(name) * 8;
                   1396:                        if (keys[1] != -1)
                   1397:                        {
                   1398:                                M_Print (140 + x + 8, y, "or");
                   1399:                                M_Print (140 + x + 32, y, Key_KeynumToString (keys[1]));
                   1400:                        }
                   1401:                }
                   1402:        }
                   1403:        
                   1404:        if (bind_grab)
                   1405:                M_DrawCharacter (130, 48 + keys_cursor*8, '=');
                   1406:        else
                   1407:                M_DrawCharacter (130, 48 + keys_cursor*8, 12+((int)(realtime*4)&1));
                   1408: }
                   1409: 
                   1410: 
                   1411: void M_Keys_Key (int k)
                   1412: {
                   1413:        char    cmd[80];
                   1414:        int             keys[2];
                   1415:        
                   1416:        if (bind_grab)
                   1417:        {       // defining a key
                   1418:                S_LocalSound ("misc/menu1.wav");
                   1419:                if (k == K_ESCAPE)
                   1420:                {
                   1421:                        bind_grab = false;
                   1422:                }
                   1423:                else if (k != '`')
                   1424:                {
                   1425:                        sprintf (cmd, "bind \"%s\" \"%s\"\n", Key_KeynumToString (k), bindnames[keys_cursor][0]);                       
                   1426:                        Cbuf_InsertText (cmd);
                   1427:                }
                   1428:                
                   1429:                bind_grab = false;
                   1430:                return;
                   1431:        }
                   1432:        
                   1433:        switch (k)
                   1434:        {
                   1435:        case K_ESCAPE:
                   1436:                M_Menu_Options_f ();
                   1437:                break;
                   1438: 
                   1439:        case K_LEFTARROW:
                   1440:        case K_UPARROW:
                   1441:                S_LocalSound ("misc/menu1.wav");
                   1442:                keys_cursor--;
                   1443:                if (keys_cursor < 0)
                   1444:                        keys_cursor = NUMCOMMANDS-1;
                   1445:                break;
                   1446: 
                   1447:        case K_DOWNARROW:
                   1448:        case K_RIGHTARROW:
                   1449:                S_LocalSound ("misc/menu1.wav");
                   1450:                keys_cursor++;
                   1451:                if (keys_cursor >= NUMCOMMANDS)
                   1452:                        keys_cursor = 0;
                   1453:                break;
                   1454: 
                   1455:        case K_ENTER:           // go into bind mode
                   1456:                M_FindKeysForCommand (bindnames[keys_cursor][0], keys);
                   1457:                S_LocalSound ("misc/menu2.wav");
                   1458:                if (keys[1] != -1)
                   1459:                        M_UnbindCommand (bindnames[keys_cursor][0]);
                   1460:                bind_grab = true;
                   1461:                break;
                   1462: 
                   1463:        case K_BACKSPACE:               // delete bindings
                   1464:        case K_DEL:                             // delete bindings
                   1465:                S_LocalSound ("misc/menu2.wav");
                   1466:                M_UnbindCommand (bindnames[keys_cursor][0]);
                   1467:                break;
                   1468:        }
                   1469: }
                   1470: 
                   1471: //=============================================================================
                   1472: /* VIDEO MENU */
                   1473: 
                   1474: void M_Menu_Video_f (void)
                   1475: {
                   1476:        key_dest = key_menu;
                   1477:        m_state = m_video;
                   1478:        m_entersound = true;
                   1479: }
                   1480: 
                   1481: 
                   1482: void M_Video_Draw (void)
                   1483: {
                   1484:        (*vid_menudrawfn) ();
                   1485: }
                   1486: 
                   1487: 
                   1488: void M_Video_Key (int key)
                   1489: {
                   1490:        (*vid_menukeyfn) (key);
                   1491: }
                   1492: 
                   1493: //=============================================================================
                   1494: /* HELP MENU */
                   1495: 
                   1496: int            help_page;
                   1497: #define        NUM_HELP_PAGES  6
                   1498: 
                   1499: 
                   1500: void M_Menu_Help_f (void)
                   1501: {
                   1502:        key_dest = key_menu;
                   1503:        m_state = m_help;
                   1504:        m_entersound = true;
                   1505:        help_page = 0;
                   1506: }
                   1507: 
                   1508: 
                   1509: 
                   1510: void M_Help_Draw (void)
                   1511: {
                   1512:        M_DrawPic (0, 0, M_CachePic ( va("gfx/help%i.lmp", help_page)) );
                   1513: }
                   1514: 
                   1515: 
                   1516: void M_Help_Key (int key)
                   1517: {
                   1518:        switch (key)
                   1519:        {
                   1520:        case K_ESCAPE:
                   1521:                M_Menu_Main_f ();
                   1522:                break;
                   1523:                
                   1524:        case K_UPARROW:
                   1525:        case K_RIGHTARROW:
                   1526:                m_entersound = true;
                   1527:                if (++help_page >= NUM_HELP_PAGES)
                   1528:                        help_page = 0;
                   1529:                break;
                   1530: 
                   1531:        case K_DOWNARROW:
                   1532:        case K_LEFTARROW:
                   1533:                m_entersound = true;
                   1534:                if (--help_page < 0)
                   1535:                        help_page = NUM_HELP_PAGES-1;
                   1536:                break;
                   1537:        }
                   1538: 
                   1539: }
                   1540: 
                   1541: //=============================================================================
                   1542: /* QUIT MENU */
                   1543: 
                   1544: int            msgNumber;
                   1545: int            m_quit_prevstate;
                   1546: qboolean       wasInMenus;
                   1547: 
                   1548: char *quitMessage [] = 
                   1549: {
                   1550: /* .........1.........2.... */
                   1551:   "  Are you gonna quit    ",
                   1552:   "  this game just like   ",
                   1553:   "   everything else?     ",
                   1554:   "                        ",
                   1555:  
                   1556:   " Milord, methinks that  ",
                   1557:   "   thou art a lowly     ",
                   1558:   " quitter. Is this true? ",
                   1559:   "                        ",
                   1560: 
                   1561:   " Do I need to bust your ",
                   1562:   "  face open for trying  ",
                   1563:   "        to quit?        ",
                   1564:   "                        ",
                   1565: 
                   1566:   " Man, I oughta smack you",
                   1567:   "   for trying to quit!  ",
                   1568:   "     Press Y to get     ",
                   1569:   "      smacked out.      ",
                   1570:  
                   1571:   " Press Y to quit like a ",
                   1572:   "   big loser in life.   ",
                   1573:   "  Press N to stay proud ",
                   1574:   "    and successful!     ",
                   1575:  
                   1576:   "   If you press Y to    ",
                   1577:   "  quit, I will summon   ",
                   1578:   "  Satan all over your   ",
                   1579:   "      hard drive!       ",
                   1580:  
                   1581:   "  Um, Asmodeus dislikes ",
                   1582:   " his children trying to ",
                   1583:   " quit. Press Y to return",
                   1584:   "   to your Tinkertoys.  ",
                   1585:  
                   1586:   "  If you quit now, I'll ",
                   1587:   "  throw a blanket-party ",
                   1588:   "   for you next time!   ",
                   1589:   "                        "
                   1590: };
                   1591: 
                   1592: void M_Menu_Quit_f (void)
                   1593: {
                   1594:        if (m_state == m_quit)
                   1595:                return;
                   1596:        wasInMenus = (key_dest == key_menu);
                   1597:        key_dest = key_menu;
                   1598:        m_quit_prevstate = m_state;
                   1599:        m_state = m_quit;
                   1600:        m_entersound = true;
                   1601:        msgNumber = rand()&7;
                   1602: }
                   1603: 
                   1604: 
                   1605: void M_Quit_Key (int key)
                   1606: {
                   1607:        switch (key)
                   1608:        {
                   1609:        case K_ESCAPE:
                   1610:        case 'n':
                   1611:        case 'N':
                   1612:                if (wasInMenus)
                   1613:                {
                   1614:                        m_state = m_quit_prevstate;
                   1615:                        m_entersound = true;
                   1616:                }
                   1617:                else
                   1618:                {
                   1619:                        key_dest = key_game;
                   1620:                        m_state = m_none;
                   1621:                }
                   1622:                break;
                   1623: 
                   1624:        case 'Y':
                   1625:        case 'y':
                   1626:                key_dest = key_console;
                   1627:                Host_Quit_f ();
                   1628:                break;
                   1629: 
                   1630:        default:
                   1631:                break;
                   1632:        }
                   1633: 
                   1634: }
                   1635: 
                   1636: 
                   1637: void M_Quit_Draw (void)
                   1638: {
                   1639:        if (wasInMenus)
                   1640:        {
                   1641:                m_state = m_quit_prevstate;
                   1642:                m_recursiveDraw = true;
                   1643:                M_Draw ();
                   1644:                m_state = m_quit;
                   1645:        }
                   1646:        M_DrawTextBox (56, 76, 24, 4);
                   1647:        M_Print (64, 84,  quitMessage[msgNumber*4+0]);
                   1648:        M_Print (64, 92,  quitMessage[msgNumber*4+1]);
                   1649:        M_Print (64, 100, quitMessage[msgNumber*4+2]);
                   1650:        M_Print (64, 108, quitMessage[msgNumber*4+3]);
                   1651: }
                   1652: 
                   1653: //=============================================================================
                   1654: 
                   1655: /* SERIAL CONFIG MENU */
                   1656: 
                   1657: int            serialConfig_cursor;
                   1658: int            serialConfig_cursor_table[] = {48, 64, 80, 96, 112, 132};
                   1659: #define        NUM_SERIALCONFIG_CMDS   6
                   1660: 
                   1661: static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
                   1662: static int ISA_IRQs[]  = {4,3,4,3};
                   1663: int serialConfig_baudrate[] = {9600,14400,19200,28800,38400,57600};
                   1664: 
                   1665: int            serialConfig_comport;
                   1666: int            serialConfig_irq ;
                   1667: int            serialConfig_baud;
                   1668: char   serialConfig_phone[16];
                   1669: 
                   1670: void M_Menu_SerialConfig_f (void)
                   1671: {
                   1672:        int             n;
                   1673:        int             port;
                   1674:        int             baudrate;
                   1675:        qboolean        useModem;
                   1676: 
                   1677:        key_dest = key_menu;
                   1678:        m_state = m_serialconfig;
                   1679:        m_entersound = true;
                   1680:        if (JoiningGame && SerialConfig)
                   1681:                serialConfig_cursor = 4;
                   1682:        else
                   1683:                serialConfig_cursor = 5;
                   1684: 
                   1685:        (*GetComPortConfig) (0, &port, &serialConfig_irq, &baudrate, &useModem);
                   1686: 
                   1687:        // map uart's port to COMx
                   1688:        for (n = 0; n < 4; n++)
                   1689:                if (ISA_uarts[n] == port)
                   1690:                        break;
                   1691:        if (n == 4)
                   1692:        {
                   1693:                n = 0;
                   1694:                serialConfig_irq = 4;
                   1695:        }
                   1696:        serialConfig_comport = n + 1;
                   1697: 
                   1698:        // map baudrate to index
                   1699:        for (n = 0; n < 6; n++)
                   1700:                if (serialConfig_baudrate[n] == baudrate)
                   1701:                        break;
                   1702:        if (n == 6)
                   1703:                n = 5;
                   1704:        serialConfig_baud = n;
                   1705: 
                   1706:        m_return_onerror = false;
                   1707:        m_return_reason[0] = 0;
                   1708: }
                   1709:                                
                   1710: 
                   1711: void M_SerialConfig_Draw (void)
                   1712: {
                   1713:        qpic_t  *p;
                   1714:        int             basex;
                   1715:        char    *startJoin;
                   1716:        char    *directModem;
                   1717: 
                   1718:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                   1719:        p = M_CachePic ("gfx/p_multi.lmp");
                   1720:        basex = (320-p->width)/2;
                   1721:        M_DrawPic (basex, 4, p);
                   1722: 
                   1723:        if (StartingGame)
                   1724:                startJoin = "New Game";
                   1725:        else
                   1726:                startJoin = "Join Game";
                   1727:        if (SerialConfig)
                   1728:                directModem = "Modem";
                   1729:        else
                   1730:                directModem = "Direct Connect";
                   1731:        M_Print (basex, 32, va ("%s - %s", startJoin, directModem));
                   1732:        basex += 8;
                   1733: 
                   1734:        M_Print (basex, serialConfig_cursor_table[0], "Port");
                   1735:        M_DrawTextBox (160, 40, 4, 1);
                   1736:        M_Print (168, serialConfig_cursor_table[0], va("COM%u", serialConfig_comport));
                   1737: 
                   1738:        M_Print (basex, serialConfig_cursor_table[1], "IRQ");
                   1739:        M_DrawTextBox (160, serialConfig_cursor_table[1]-8, 1, 1);
                   1740:        M_Print (168, serialConfig_cursor_table[1], va("%u", serialConfig_irq));
                   1741: 
                   1742:        M_Print (basex, serialConfig_cursor_table[2], "Baud");
                   1743:        M_DrawTextBox (160, serialConfig_cursor_table[2]-8, 5, 1);
                   1744:        M_Print (168, serialConfig_cursor_table[2], va("%u", serialConfig_baudrate[serialConfig_baud]));
                   1745: 
                   1746:        if (SerialConfig)
                   1747:        {
                   1748:                M_Print (basex, serialConfig_cursor_table[3], "Modem Setup...");
                   1749:                if (JoiningGame)
                   1750:                {
                   1751:                        M_Print (basex, serialConfig_cursor_table[4], "Phone number");
                   1752:                        M_DrawTextBox (160, serialConfig_cursor_table[4]-8, 16, 1);
                   1753:                        M_Print (168, serialConfig_cursor_table[4], serialConfig_phone);
                   1754:                }
                   1755:        }
                   1756: 
                   1757:        if (JoiningGame)
                   1758:        {
                   1759:                M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 7, 1);
                   1760:                M_Print (basex+8, serialConfig_cursor_table[5], "Connect");
                   1761:        }
                   1762:        else
                   1763:        {
                   1764:                M_DrawTextBox (basex, serialConfig_cursor_table[5]-8, 2, 1);
                   1765:                M_Print (basex+8, serialConfig_cursor_table[5], "OK");
                   1766:        }
                   1767: 
                   1768:        M_DrawCharacter (basex-8, serialConfig_cursor_table [serialConfig_cursor], 12+((int)(realtime*4)&1));
                   1769: 
                   1770:        if (serialConfig_cursor == 4)
                   1771:                M_DrawCharacter (168 + 8*strlen(serialConfig_phone), serialConfig_cursor_table [serialConfig_cursor], 10+((int)(realtime*4)&1));
                   1772: 
                   1773:        if (*m_return_reason)
                   1774:                M_PrintWhite (basex, 148, m_return_reason);
                   1775: }
                   1776: 
                   1777: 
                   1778: void M_SerialConfig_Key (int key)
                   1779: {
                   1780:        int             l;
                   1781: 
                   1782:        switch (key)
                   1783:        {
                   1784:        case K_ESCAPE:
                   1785:                M_Menu_Net_f ();
                   1786:                break;
                   1787: 
                   1788:        case K_UPARROW:
                   1789:                S_LocalSound ("misc/menu1.wav");
                   1790:                serialConfig_cursor--;
                   1791:                if (serialConfig_cursor < 0)
                   1792:                        serialConfig_cursor = NUM_SERIALCONFIG_CMDS-1;
                   1793:                break;
                   1794: 
                   1795:        case K_DOWNARROW:
                   1796:                S_LocalSound ("misc/menu1.wav");
                   1797:                serialConfig_cursor++;
                   1798:                if (serialConfig_cursor >= NUM_SERIALCONFIG_CMDS)
                   1799:                        serialConfig_cursor = 0;
                   1800:                break;
                   1801: 
                   1802:        case K_LEFTARROW:
                   1803:                if (serialConfig_cursor > 2)
                   1804:                        break;
                   1805:                S_LocalSound ("misc/menu3.wav");
                   1806: 
                   1807:                if (serialConfig_cursor == 0)
                   1808:                {
                   1809:                        serialConfig_comport--;
                   1810:                        if (serialConfig_comport == 0)
                   1811:                                serialConfig_comport = 4;
                   1812:                        serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
                   1813:                }
                   1814: 
                   1815:                if (serialConfig_cursor == 1)
                   1816:                {
                   1817:                        serialConfig_irq--;
                   1818:                        if (serialConfig_irq == 6)
                   1819:                                serialConfig_irq = 5;
                   1820:                        if (serialConfig_irq == 1)
                   1821:                                serialConfig_irq = 7;
                   1822:                }
                   1823: 
                   1824:                if (serialConfig_cursor == 2)
                   1825:                {
                   1826:                        serialConfig_baud--;
                   1827:                        if (serialConfig_baud < 0)
                   1828:                                serialConfig_baud = 5;
                   1829:                }
                   1830: 
                   1831:                break;
                   1832: 
                   1833:        case K_RIGHTARROW:
                   1834:                if (serialConfig_cursor > 2)
                   1835:                        break;
                   1836: forward:
                   1837:                S_LocalSound ("misc/menu3.wav");
                   1838: 
                   1839:                if (serialConfig_cursor == 0)
                   1840:                {
                   1841:                        serialConfig_comport++;
                   1842:                        if (serialConfig_comport > 4)
                   1843:                                serialConfig_comport = 1;
                   1844:                        serialConfig_irq = ISA_IRQs[serialConfig_comport-1];
                   1845:                }
                   1846: 
                   1847:                if (serialConfig_cursor == 1)
                   1848:                {
                   1849:                        serialConfig_irq++;
                   1850:                        if (serialConfig_irq == 6)
                   1851:                                serialConfig_irq = 7;
                   1852:                        if (serialConfig_irq == 8)
                   1853:                                serialConfig_irq = 2;
                   1854:                }
                   1855: 
                   1856:                if (serialConfig_cursor == 2)
                   1857:                {
                   1858:                        serialConfig_baud++;
                   1859:                        if (serialConfig_baud > 5)
                   1860:                                serialConfig_baud = 0;
                   1861:                }
                   1862: 
                   1863:                break;
                   1864: 
                   1865:        case K_ENTER:
                   1866:                if (serialConfig_cursor < 3)
                   1867:                        goto forward;
                   1868: 
                   1869:                m_entersound = true;
                   1870: 
                   1871:                if (serialConfig_cursor == 3)
                   1872:                {
                   1873:                        (*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
                   1874: 
                   1875:                        M_Menu_ModemConfig_f ();
                   1876:                        break;
                   1877:                }
                   1878: 
                   1879:                if (serialConfig_cursor == 4)
                   1880:                {
                   1881:                        serialConfig_cursor = 5;
                   1882:                        break;
                   1883:                }
                   1884: 
                   1885:                // serialConfig_cursor == 5 (OK/CONNECT)
                   1886:                (*SetComPortConfig) (0, ISA_uarts[serialConfig_comport-1], serialConfig_irq, serialConfig_baudrate[serialConfig_baud], SerialConfig);
                   1887: 
                   1888:                M_ConfigureNetSubsystem ();
                   1889: 
                   1890:                if (StartingGame)
                   1891:                {
                   1892:                        M_Menu_GameOptions_f ();
                   1893:                        break;
                   1894:                }
                   1895: 
                   1896:                m_return_state = m_state;
                   1897:                m_return_onerror = true;
                   1898:                key_dest = key_game;
                   1899:                m_state = m_none;
                   1900: 
                   1901:                if (SerialConfig)
                   1902:                        Cbuf_AddText (va ("connect \"%s\"\n", serialConfig_phone));
                   1903:                else
                   1904:                        Cbuf_AddText ("connect\n");
                   1905:                break;
                   1906:        
                   1907:        case K_BACKSPACE:
                   1908:                if (serialConfig_cursor == 4)
                   1909:                {
                   1910:                        if (strlen(serialConfig_phone))
                   1911:                                serialConfig_phone[strlen(serialConfig_phone)-1] = 0;
                   1912:                }
                   1913:                break;
                   1914:                
                   1915:        default:
                   1916:                if (key < 32 || key > 127)
                   1917:                        break;
                   1918:                if (serialConfig_cursor == 4)
                   1919:                {
                   1920:                        l = strlen(serialConfig_phone);
                   1921:                        if (l < 15)
                   1922:                        {
                   1923:                                serialConfig_phone[l+1] = 0;
                   1924:                                serialConfig_phone[l] = key;
                   1925:                        }
                   1926:                }
                   1927:        }
                   1928: 
                   1929:        if (DirectConfig && (serialConfig_cursor == 3 || serialConfig_cursor == 4))
                   1930:                if (key == K_UPARROW)
                   1931:                        serialConfig_cursor = 2;
                   1932:                else
                   1933:                        serialConfig_cursor = 5;
                   1934: 
                   1935:        if (SerialConfig && StartingGame && serialConfig_cursor == 4)
                   1936:                if (key == K_UPARROW)
                   1937:                        serialConfig_cursor = 3;
                   1938:                else
                   1939:                        serialConfig_cursor = 5;
                   1940: }
                   1941: 
                   1942: //=============================================================================
                   1943: /* MODEM CONFIG MENU */
                   1944: 
                   1945: int            modemConfig_cursor;
                   1946: int            modemConfig_cursor_table [] = {40, 56, 88, 120, 156};
                   1947: #define NUM_MODEMCONFIG_CMDS   5
                   1948: 
                   1949: char   modemConfig_dialing;
                   1950: char   modemConfig_clear [16];
                   1951: char   modemConfig_init [32];
                   1952: char   modemConfig_hangup [16];
                   1953: 
                   1954: void M_Menu_ModemConfig_f (void)
                   1955: {
                   1956:        key_dest = key_menu;
                   1957:        m_state = m_modemconfig;
                   1958:        m_entersound = true;
                   1959:        (*GetModemConfig) (0, &modemConfig_dialing, modemConfig_clear, modemConfig_init, modemConfig_hangup);
                   1960: }
                   1961:                                
                   1962: 
                   1963: void M_ModemConfig_Draw (void)
                   1964: {
                   1965:        qpic_t  *p;
                   1966:        int             basex;
                   1967: 
                   1968:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                   1969:        p = M_CachePic ("gfx/p_multi.lmp");
                   1970:        basex = (320-p->width)/2;
                   1971:        M_DrawPic (basex, 4, p);
                   1972:        basex += 8;
                   1973: 
                   1974:        if (modemConfig_dialing == 'P')
                   1975:                M_Print (basex, modemConfig_cursor_table[0], "Pulse Dialing");
                   1976:        else
                   1977:                M_Print (basex, modemConfig_cursor_table[0], "Touch Tone Dialing");
                   1978: 
                   1979:        M_Print (basex, modemConfig_cursor_table[1], "Clear");
                   1980:        M_DrawTextBox (basex, modemConfig_cursor_table[1]+4, 16, 1);
                   1981:        M_Print (basex+8, modemConfig_cursor_table[1]+12, modemConfig_clear);
                   1982:        if (modemConfig_cursor == 1)
                   1983:                M_DrawCharacter (basex+8 + 8*strlen(modemConfig_clear), modemConfig_cursor_table[1]+12, 10+((int)(realtime*4)&1));
                   1984: 
                   1985:        M_Print (basex, modemConfig_cursor_table[2], "Init");
                   1986:        M_DrawTextBox (basex, modemConfig_cursor_table[2]+4, 30, 1);
                   1987:        M_Print (basex+8, modemConfig_cursor_table[2]+12, modemConfig_init);
                   1988:        if (modemConfig_cursor == 2)
                   1989:                M_DrawCharacter (basex+8 + 8*strlen(modemConfig_init), modemConfig_cursor_table[2]+12, 10+((int)(realtime*4)&1));
                   1990: 
                   1991:        M_Print (basex, modemConfig_cursor_table[3], "Hangup");
                   1992:        M_DrawTextBox (basex, modemConfig_cursor_table[3]+4, 16, 1);
                   1993:        M_Print (basex+8, modemConfig_cursor_table[3]+12, modemConfig_hangup);
                   1994:        if (modemConfig_cursor == 3)
                   1995:                M_DrawCharacter (basex+8 + 8*strlen(modemConfig_hangup), modemConfig_cursor_table[3]+12, 10+((int)(realtime*4)&1));
                   1996: 
                   1997:        M_DrawTextBox (basex, modemConfig_cursor_table[4]-8, 2, 1);
                   1998:        M_Print (basex+8, modemConfig_cursor_table[4], "OK");
                   1999: 
                   2000:        M_DrawCharacter (basex-8, modemConfig_cursor_table [modemConfig_cursor], 12+((int)(realtime*4)&1));
                   2001: }
                   2002: 
                   2003: 
                   2004: void M_ModemConfig_Key (int key)
                   2005: {
                   2006:        int             l;
                   2007: 
                   2008:        switch (key)
                   2009:        {
                   2010:        case K_ESCAPE:
                   2011:                M_Menu_SerialConfig_f ();
                   2012:                break;
                   2013: 
                   2014:        case K_UPARROW:
                   2015:                S_LocalSound ("misc/menu1.wav");
                   2016:                modemConfig_cursor--;
                   2017:                if (modemConfig_cursor < 0)
                   2018:                        modemConfig_cursor = NUM_MODEMCONFIG_CMDS-1;
                   2019:                break;
                   2020: 
                   2021:        case K_DOWNARROW:
                   2022:                S_LocalSound ("misc/menu1.wav");
                   2023:                modemConfig_cursor++;
                   2024:                if (modemConfig_cursor >= NUM_MODEMCONFIG_CMDS)
                   2025:                        modemConfig_cursor = 0;
                   2026:                break;
                   2027: 
                   2028:        case K_LEFTARROW:
                   2029:        case K_RIGHTARROW:
                   2030:                if (modemConfig_cursor == 0)
                   2031:                {
                   2032:                        if (modemConfig_dialing == 'P')
                   2033:                                modemConfig_dialing = 'T';
                   2034:                        else
                   2035:                                modemConfig_dialing = 'P';
                   2036:                        S_LocalSound ("misc/menu1.wav");
                   2037:                }
                   2038:                break;
                   2039: 
                   2040:        case K_ENTER:
                   2041:                if (modemConfig_cursor == 0)
                   2042:                {
                   2043:                        if (modemConfig_dialing == 'P')
                   2044:                                modemConfig_dialing = 'T';
                   2045:                        else
                   2046:                                modemConfig_dialing = 'P';
                   2047:                        m_entersound = true;
                   2048:                }
                   2049: 
                   2050:                if (modemConfig_cursor == 4)
                   2051:                {
                   2052:                        (*SetModemConfig) (0, va ("%c", modemConfig_dialing), modemConfig_clear, modemConfig_init, modemConfig_hangup);
                   2053:                        m_entersound = true;
                   2054:                        M_Menu_SerialConfig_f ();
                   2055:                }
                   2056:                break;
                   2057:        
                   2058:        case K_BACKSPACE:
                   2059:                if (modemConfig_cursor == 1)
                   2060:                {
                   2061:                        if (strlen(modemConfig_clear))
                   2062:                                modemConfig_clear[strlen(modemConfig_clear)-1] = 0;
                   2063:                }
                   2064: 
                   2065:                if (modemConfig_cursor == 2)
                   2066:                {
                   2067:                        if (strlen(modemConfig_init))
                   2068:                                modemConfig_init[strlen(modemConfig_init)-1] = 0;
                   2069:                }
                   2070: 
                   2071:                if (modemConfig_cursor == 3)
                   2072:                {
                   2073:                        if (strlen(modemConfig_hangup))
                   2074:                                modemConfig_hangup[strlen(modemConfig_hangup)-1] = 0;
                   2075:                }
                   2076:                break;
                   2077:                
                   2078:        default:
                   2079:                if (key < 32 || key > 127)
                   2080:                        break;
                   2081: 
                   2082:                if (modemConfig_cursor == 1)
                   2083:                {
                   2084:                        l = strlen(modemConfig_clear);
                   2085:                        if (l < 15)
                   2086:                        {
                   2087:                                modemConfig_clear[l+1] = 0;
                   2088:                                modemConfig_clear[l] = key;
                   2089:                        }
                   2090:                }
                   2091: 
                   2092:                if (modemConfig_cursor == 2)
                   2093:                {
                   2094:                        l = strlen(modemConfig_init);
                   2095:                        if (l < 29)
                   2096:                        {
                   2097:                                modemConfig_init[l+1] = 0;
                   2098:                                modemConfig_init[l] = key;
                   2099:                        }
                   2100:                }
                   2101: 
                   2102:                if (modemConfig_cursor == 3)
                   2103:                {
                   2104:                        l = strlen(modemConfig_hangup);
                   2105:                        if (l < 15)
                   2106:                        {
                   2107:                                modemConfig_hangup[l+1] = 0;
                   2108:                                modemConfig_hangup[l] = key;
                   2109:                        }
                   2110:                }
                   2111:        }
                   2112: }
                   2113: 
                   2114: //=============================================================================
                   2115: /* LAN CONFIG MENU */
                   2116: 
                   2117: int            lanConfig_cursor = -1;
                   2118: int            lanConfig_cursor_table [] = {72, 92, 124};
                   2119: #define NUM_LANCONFIG_CMDS     3
                   2120: 
                   2121: int    lanConfig_port;
                   2122: char   lanConfig_portname[6];
                   2123: char   lanConfig_joinname[22];
                   2124: 
                   2125: void M_Menu_LanConfig_f (void)
                   2126: {
                   2127:        key_dest = key_menu;
                   2128:        m_state = m_lanconfig;
                   2129:        m_entersound = true;
                   2130:        if (lanConfig_cursor == -1)
                   2131:        {
                   2132:                if (JoiningGame && TCPIPConfig)
                   2133:                        lanConfig_cursor = 2;
                   2134:                else
                   2135:                        lanConfig_cursor = 1;
                   2136:        }
                   2137:        if (StartingGame && lanConfig_cursor == 2)
                   2138:                lanConfig_cursor = 1;
                   2139:        lanConfig_port = DEFAULTnet_hostport;
                   2140:        sprintf(lanConfig_portname, "%u", lanConfig_port);
                   2141: 
                   2142:        m_return_onerror = false;
                   2143:        m_return_reason[0] = 0;
                   2144: }
                   2145:                                
                   2146: 
                   2147: void M_LanConfig_Draw (void)
                   2148: {
                   2149:        qpic_t  *p;
                   2150:        int             basex;
                   2151:        char    *startJoin;
                   2152:        char    *protocol;
                   2153: 
                   2154:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                   2155:        p = M_CachePic ("gfx/p_multi.lmp");
                   2156:        basex = (320-p->width)/2;
                   2157:        M_DrawPic (basex, 4, p);
                   2158: 
                   2159:        if (StartingGame)
                   2160:                startJoin = "New Game";
                   2161:        else
                   2162:                startJoin = "Join Game";
                   2163:        if (IPXConfig)
                   2164:                protocol = "IPX";
                   2165:        else
                   2166:                protocol = "TCP/IP";
                   2167:        M_Print (basex, 32, va ("%s - %s", startJoin, protocol));
                   2168:        basex += 8;
                   2169: 
                   2170:        M_Print (basex, 52, "Address:");
                   2171:        if (IPXConfig)
                   2172:                M_Print (basex+9*8, 52, my_ipx_address);
                   2173:        else
                   2174:                M_Print (basex+9*8, 52, my_tcpip_address);
                   2175: 
                   2176:        M_Print (basex, lanConfig_cursor_table[0], "Port");
                   2177:        M_DrawTextBox (basex+8*8, lanConfig_cursor_table[0]-8, 6, 1);
                   2178:        M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname);
                   2179: 
                   2180:        if (JoiningGame)
                   2181:        {
                   2182:                M_Print (basex, lanConfig_cursor_table[1], "Search for local games...");
                   2183:                M_Print (basex, 108, "Join game at:");
                   2184:                M_DrawTextBox (basex+8, lanConfig_cursor_table[2]-8, 22, 1);
                   2185:                M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname);
                   2186:        }
                   2187:        else
                   2188:        {
                   2189:                M_DrawTextBox (basex, lanConfig_cursor_table[1]-8, 2, 1);
                   2190:                M_Print (basex+8, lanConfig_cursor_table[1], "OK");
                   2191:        }
                   2192: 
                   2193:        M_DrawCharacter (basex-8, lanConfig_cursor_table [lanConfig_cursor], 12+((int)(realtime*4)&1));
                   2194: 
                   2195:        if (lanConfig_cursor == 0)
                   2196:                M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1));
                   2197: 
                   2198:        if (lanConfig_cursor == 2)
                   2199:                M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1));
                   2200: 
                   2201:        if (*m_return_reason)
                   2202:                M_PrintWhite (basex, 148, m_return_reason);
                   2203: }
                   2204: 
                   2205: 
                   2206: void M_LanConfig_Key (int key)
                   2207: {
                   2208:        int             l;
                   2209: 
                   2210:        switch (key)
                   2211:        {
                   2212:        case K_ESCAPE:
                   2213:                M_Menu_Net_f ();
                   2214:                break;
                   2215: 
                   2216:        case K_UPARROW:
                   2217:                S_LocalSound ("misc/menu1.wav");
                   2218:                lanConfig_cursor--;
                   2219:                if (lanConfig_cursor < 0)
                   2220:                        lanConfig_cursor = NUM_LANCONFIG_CMDS-1;
                   2221:                break;
                   2222: 
                   2223:        case K_DOWNARROW:
                   2224:                S_LocalSound ("misc/menu1.wav");
                   2225:                lanConfig_cursor++;
                   2226:                if (lanConfig_cursor >= NUM_LANCONFIG_CMDS)
                   2227:                        lanConfig_cursor = 0;
                   2228:                break;
                   2229: 
                   2230:        case K_ENTER:
                   2231:                if (lanConfig_cursor == 0)
                   2232:                        break;
                   2233: 
                   2234:                m_entersound = true;
                   2235: 
                   2236:                M_ConfigureNetSubsystem ();
                   2237: 
                   2238:                if (lanConfig_cursor == 1)
                   2239:                {
                   2240:                        if (StartingGame)
                   2241:                        {
                   2242:                                M_Menu_GameOptions_f ();
                   2243:                                break;
                   2244:                        }
                   2245:                        M_Menu_Search_f();
                   2246:                        break;
                   2247:                }
                   2248: 
                   2249:                if (lanConfig_cursor == 2)
                   2250:                {
                   2251:                        m_return_state = m_state;
                   2252:                        m_return_onerror = true;
                   2253:                        key_dest = key_game;
                   2254:                        m_state = m_none;
                   2255:                        Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) );
                   2256:                        break;
                   2257:                }
                   2258: 
                   2259:                break;
                   2260:        
                   2261:        case K_BACKSPACE:
                   2262:                if (lanConfig_cursor == 0)
                   2263:                {
                   2264:                        if (strlen(lanConfig_portname))
                   2265:                                lanConfig_portname[strlen(lanConfig_portname)-1] = 0;
                   2266:                }
                   2267: 
                   2268:                if (lanConfig_cursor == 2)
                   2269:                {
                   2270:                        if (strlen(lanConfig_joinname))
                   2271:                                lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0;
                   2272:                }
                   2273:                break;
                   2274:                
                   2275:        default:
                   2276:                if (key < 32 || key > 127)
                   2277:                        break;
                   2278: 
                   2279:                if (lanConfig_cursor == 2)
                   2280:                {
                   2281:                        l = strlen(lanConfig_joinname);
                   2282:                        if (l < 21)
                   2283:                        {
                   2284:                                lanConfig_joinname[l+1] = 0;
                   2285:                                lanConfig_joinname[l] = key;
                   2286:                        }
                   2287:                }
                   2288: 
                   2289:                if (key < '0' || key > '9')
                   2290:                        break;
                   2291:                if (lanConfig_cursor == 0)
                   2292:                {
                   2293:                        l = strlen(lanConfig_portname);
                   2294:                        if (l < 5)
                   2295:                        {
                   2296:                                lanConfig_portname[l+1] = 0;
                   2297:                                lanConfig_portname[l] = key;
                   2298:                        }
                   2299:                }
                   2300:        }
                   2301: 
                   2302:        if (StartingGame && lanConfig_cursor == 2)
                   2303:                if (key == K_UPARROW)
                   2304:                        lanConfig_cursor = 1;
                   2305:                else
                   2306:                        lanConfig_cursor = 0;
                   2307: 
                   2308:        l =  Q_atoi(lanConfig_portname);
                   2309:        if (l > 65535)
                   2310:                l = lanConfig_port;
                   2311:        else
                   2312:                lanConfig_port = l;
                   2313:        sprintf(lanConfig_portname, "%u", lanConfig_port);
                   2314: }
                   2315: 
                   2316: //=============================================================================
                   2317: /* GAME OPTIONS MENU */
                   2318: 
                   2319: typedef struct
                   2320: {
                   2321:        char    *name;
                   2322:        char    *description;
                   2323: } level_t;
                   2324: 
                   2325: level_t                levels[] =
                   2326: {
                   2327:        {"start", "Entrance"},  // 0
                   2328: 
                   2329:        {"e1m1", "Slipgate Complex"},                           // 1
                   2330:        {"e1m2", "Castle of the Damned"},
                   2331:        {"e1m3", "The Necropolis"},
                   2332:        {"e1m4", "The Grisly Grotto"},
                   2333:        {"e1m5", "Gloom Keep"},
                   2334:        {"e1m6", "The Door To Chthon"},
                   2335:        {"e1m7", "The House of Chthon"},
                   2336:        {"e1m8", "Ziggurat Vertigo"},
                   2337: 
                   2338:        {"e2m1", "The Installation"},                           // 9
                   2339:        {"e2m2", "Ogre Citadel"},
                   2340:        {"e2m3", "Crypt of Decay"},
                   2341:        {"e2m4", "The Ebon Fortress"},
                   2342:        {"e2m5", "The Wizard's Manse"},
                   2343:        {"e2m6", "The Dismal Oubliette"},
                   2344:        {"e2m7", "Underearth"},
                   2345: 
                   2346:        {"e3m1", "Termination Central"},                        // 16
                   2347:        {"e3m2", "The Vaults of Zin"},
                   2348:        {"e3m3", "The Tomb of Terror"},
                   2349:        {"e3m4", "Satan's Dark Delight"},
                   2350:        {"e3m5", "Wind Tunnels"},
                   2351:        {"e3m6", "Chambers of Torment"},
                   2352:        {"e3m7", "The Haunted Halls"},
                   2353: 
                   2354:        {"e4m1", "The Sewage System"},                          // 23
                   2355:        {"e4m2", "The Tower of Despair"},
                   2356:        {"e4m3", "The Elder God Shrine"},
                   2357:        {"e4m4", "The Palace of Hate"},
                   2358:        {"e4m5", "Hell's Atrium"},
                   2359:        {"e4m6", "The  Pain Maze"},
                   2360:        {"e4m7", "Azure Agony"},
                   2361:        {"e4m8", "The Nameless City"},
                   2362: 
                   2363:        {"end", "Shub-Niggurath's Pit"},                        // 31
                   2364: 
                   2365:        {"dm1", "Place of Two Deaths"},                         // 32
                   2366:        {"dm2", "Claustrophobopolis"},
                   2367:        {"dm3", "The Abandoned Base"},
                   2368:        {"dm4", "The Bad Place"},
                   2369:        {"dm5", "The Cistern"},
                   2370:        {"dm6", "The Dark Zone"}
                   2371: };
                   2372: 
                   2373: typedef struct
                   2374: {
                   2375:        char    *description;
                   2376:        int             firstLevel;
                   2377:        int             levels;
                   2378: } episode_t;
                   2379: 
                   2380: episode_t      episodes[] =
                   2381: {
                   2382:        {"Welcome to Quake", 0, 1},
                   2383:        {"Doomed Dimension", 1, 8},
                   2384:        {"Realm of Black Magic", 9, 7},
                   2385:        {"Netherworld", 16, 7},
                   2386:        {"The Elder World", 23, 8},
                   2387:        {"Final Level", 31, 1},
                   2388:        {"Deathmatch Arena", 32, 6}
                   2389: };
                   2390: 
                   2391: int    startepisode;
                   2392: int    startlevel;
                   2393: int maxplayers;
                   2394: qboolean m_serverInfoMessage = false;
                   2395: double m_serverInfoMessageTime;
                   2396: 
                   2397: void M_Menu_GameOptions_f (void)
                   2398: {
                   2399:        key_dest = key_menu;
                   2400:        m_state = m_gameoptions;
                   2401:        m_entersound = true;
                   2402:        if (maxplayers == 0)
                   2403:                maxplayers = svs.maxclients;
                   2404:        if (maxplayers < 2)
                   2405:                maxplayers = svs.maxclientslimit;
                   2406: }
                   2407: 
                   2408:                                
                   2409: int gameoptions_cursor_table[] = {40, 56, 64, 72, 80, 88, 96, 112, 120};
                   2410: #define        NUM_GAMEOPTIONS 9
                   2411: int            gameoptions_cursor;
                   2412: 
                   2413: void M_GameOptions_Draw (void)
                   2414: {
                   2415:        qpic_t  *p;
                   2416:        int             x;
                   2417: 
                   2418:        M_DrawTransPic (16, 4, M_CachePic ("gfx/qplaque.lmp") );
                   2419:        p = M_CachePic ("gfx/p_multi.lmp");
                   2420:        M_DrawPic ( (320-p->width)/2, 4, p);
                   2421: 
                   2422:        M_DrawTextBox (152, 32, 10, 1);
                   2423:        M_Print (160, 40, "begin game");
                   2424:        
                   2425:        M_Print (0, 56, "      Max players");
                   2426:        M_Print (160, 56, va("%i", maxplayers) );
                   2427: 
                   2428:        M_Print (0, 64, "        Game Type");
                   2429:        if (coop.value)
                   2430:                M_Print (160, 64, "Cooperative");
                   2431:        else
                   2432:                M_Print (160, 64, "Deathmatch");
                   2433: 
                   2434:        M_Print (0, 72, "        Teamplay");
                   2435:        if (teamplay.value)
                   2436:                M_Print (160, 72, "on");
                   2437:        else
                   2438:                M_Print (160, 72, "off");
                   2439: 
                   2440:        M_Print (0, 80, "            Skill");
                   2441:        if (skill.value == 0)
                   2442:                M_Print (160, 80, "Easy difficulty");
                   2443:        else if (skill.value == 1)
                   2444:                M_Print (160, 80, "Normal difficulty");
                   2445:        else if (skill.value == 2)
                   2446:                M_Print (160, 80, "Hard difficulty");
                   2447:        else
                   2448:                M_Print (160, 80, "Nightmare difficulty");
                   2449: 
                   2450:        M_Print (0, 88, "       Frag Limit");
                   2451:        if (fraglimit.value == 0)
                   2452:                M_Print (160, 88, "none");
                   2453:        else
                   2454:                M_Print (160, 88, va("%i frags", (int)fraglimit.value));
                   2455: 
                   2456:        M_Print (0, 96, "       Time Limit");
                   2457:        if (timelimit.value == 0)
                   2458:                M_Print (160, 96, "none");
                   2459:        else
                   2460:                M_Print (160, 96, va("%i minutes", (int)timelimit.value));
                   2461: 
                   2462:        M_Print (0, 112, "         Episode");
                   2463:        M_Print (160, 112, episodes[startepisode].description);
                   2464: 
                   2465:        M_Print (0, 120, "           Level");
                   2466:        M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
                   2467:        M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
                   2468: 
                   2469: // line cursor
                   2470:        M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
                   2471: 
                   2472:        if (m_serverInfoMessage)
                   2473:        {
                   2474:                if ((realtime - m_serverInfoMessageTime) < 5.0)
                   2475:                {
                   2476:                        x = (320-26*8)/2;
                   2477:                        M_DrawTextBox (x, 138, 24, 4);
                   2478:                        x += 8;
                   2479:                        M_Print (x, 146, "  More than 4 players   ");
                   2480:                        M_Print (x, 154, " requires using command ");
                   2481:                        M_Print (x, 162, "line parameters; please ");
                   2482:                        M_Print (x, 170, "   see techinfo.txt.    ");
                   2483:                }
                   2484:                else
                   2485:                {
                   2486:                        m_serverInfoMessage = false;
                   2487:                }
                   2488:        }
                   2489: }
                   2490: 
                   2491: 
                   2492: void M_NetStart_Change (int dir)
                   2493: {
                   2494:        int count;
                   2495: 
                   2496:        switch (gameoptions_cursor)
                   2497:        {
                   2498:        case 1:
                   2499:                maxplayers += dir;
                   2500:                if (maxplayers > svs.maxclientslimit)
                   2501:                {
                   2502:                        maxplayers = svs.maxclientslimit;
                   2503:                        m_serverInfoMessage = true;
                   2504:                        m_serverInfoMessageTime = realtime;
                   2505:                }
                   2506:                if (maxplayers < 2)
                   2507:                        maxplayers = 2;
                   2508:                break;
                   2509: 
                   2510:        case 2:
                   2511:                Cvar_SetValue ("coop", coop.value ? 0 : 1);
                   2512:                break;
                   2513: 
                   2514:        case 3:
                   2515:                Cvar_SetValue ("teamplay", teamplay.value ? 0 : 1);
                   2516:                break;
                   2517: 
                   2518:        case 4:
                   2519:                Cvar_SetValue ("skill", skill.value + dir);
                   2520:                if (skill.value > 3)
                   2521:                        Cvar_SetValue ("skill", 0);
                   2522:                if (skill.value < 0)
                   2523:                        Cvar_SetValue ("skill", 3);
                   2524:                break;
                   2525: 
                   2526:        case 5:
                   2527:                Cvar_SetValue ("fraglimit", fraglimit.value + dir*10);
                   2528:                if (fraglimit.value > 100)
                   2529:                        Cvar_SetValue ("fraglimit", 0);
                   2530:                if (fraglimit.value < 0)
                   2531:                        Cvar_SetValue ("fraglimit", 100);
                   2532:                break;
                   2533: 
                   2534:        case 6:
                   2535:                Cvar_SetValue ("timelimit", timelimit.value + dir*5);
                   2536:                if (timelimit.value > 60)
                   2537:                        Cvar_SetValue ("timelimit", 0);
                   2538:                if (timelimit.value < 0)
                   2539:                        Cvar_SetValue ("timelimit", 60);
                   2540:                break;
                   2541: 
                   2542:        case 7:
                   2543:                startepisode += dir;
                   2544:                if (registered.value)
                   2545:                        count = 7;
                   2546:                else
                   2547:                        count = 2;
                   2548:                if (startepisode < 0)
                   2549:                        startepisode = count - 1;
                   2550:                if (startepisode >= count)
                   2551:                        startepisode = 0;
                   2552:                startlevel = 0;
                   2553:                break;
                   2554: 
                   2555:        case 8:
                   2556:                startlevel += dir;
                   2557:                count = episodes[startepisode].levels;
                   2558:                if (startlevel < 0)
                   2559:                        startlevel = count - 1;
                   2560:                if (startlevel >= count)
                   2561:                        startlevel = 0;
                   2562:                break;
                   2563:        }
                   2564: }
                   2565: 
                   2566: void M_GameOptions_Key (int key)
                   2567: {
                   2568:        switch (key)
                   2569:        {
                   2570:        case K_ESCAPE:
                   2571:                M_Menu_Net_f ();
                   2572:                break;
                   2573: 
                   2574:        case K_UPARROW:
                   2575:                S_LocalSound ("misc/menu1.wav");
                   2576:                gameoptions_cursor--;
                   2577:                if (gameoptions_cursor < 0)
                   2578:                        gameoptions_cursor = NUM_GAMEOPTIONS-1;
                   2579:                break;
                   2580: 
                   2581:        case K_DOWNARROW:
                   2582:                S_LocalSound ("misc/menu1.wav");
                   2583:                gameoptions_cursor++;
                   2584:                if (gameoptions_cursor >= NUM_GAMEOPTIONS)
                   2585:                        gameoptions_cursor = 0;
                   2586:                break;
                   2587: 
                   2588:        case K_LEFTARROW:
                   2589:                if (gameoptions_cursor == 0)
                   2590:                        break;
                   2591:                S_LocalSound ("misc/menu3.wav");
                   2592:                M_NetStart_Change (-1);
                   2593:                break;
                   2594: 
                   2595:        case K_RIGHTARROW:
                   2596:                if (gameoptions_cursor == 0)
                   2597:                        break;
                   2598:                S_LocalSound ("misc/menu3.wav");
                   2599:                M_NetStart_Change (1);
                   2600:                break;
                   2601: 
                   2602:        case K_ENTER:
                   2603:                S_LocalSound ("misc/menu2.wav");
                   2604:                if (gameoptions_cursor == 0)
                   2605:                {
                   2606:                        if (sv.active)
                   2607:                                Cbuf_AddText ("disconnect\n");
                   2608:                        Cbuf_AddText ("listen 0\n");    // so host_netport will be re-examined
                   2609:                        Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
                   2610:                        SCR_BeginLoadingPlaque ();
                   2611:                        Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
                   2612:                        return;
                   2613:                }
                   2614:                
                   2615:                M_NetStart_Change (1);
                   2616:                break;  
                   2617:        }
                   2618: }
                   2619: 
                   2620: //=============================================================================
                   2621: /* SEARCH MENU */
                   2622: 
                   2623: qboolean       searchComplete = false;
                   2624: double         searchCompleteTime;
                   2625: 
                   2626: void M_Menu_Search_f (void)
                   2627: {
                   2628:        key_dest = key_menu;
                   2629:        m_state = m_search;
                   2630:        m_entersound = false;
                   2631:        slistSilent = true;
                   2632:        slistLocal = false;
                   2633:        searchComplete = false;
                   2634:        NET_Slist_f();
                   2635: 
                   2636: }
                   2637: 
                   2638: 
                   2639: void M_Search_Draw (void)
                   2640: {
                   2641:        qpic_t  *p;
                   2642:        int x;
                   2643: 
                   2644:        p = M_CachePic ("gfx/p_multi.lmp");
                   2645:        M_DrawPic ( (320-p->width)/2, 4, p);
                   2646:        x = (320/2) - ((12*8)/2) + 4;
                   2647:        M_DrawTextBox (x-8, 32, 12, 1);
                   2648:        M_Print (x, 40, "Searching...");
                   2649: 
                   2650:        if(slistInProgress)
                   2651:        {
                   2652:                NET_Poll();
                   2653:                return;
                   2654:        }
                   2655: 
                   2656:        if (! searchComplete)
                   2657:        {
                   2658:                searchComplete = true;
                   2659:                searchCompleteTime = realtime;
                   2660:        }
                   2661: 
                   2662:        if (hostCacheCount)
                   2663:        {
                   2664:                M_Menu_ServerList_f ();
                   2665:                return;
                   2666:        }
                   2667: 
                   2668:        M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found");
                   2669:        if ((realtime - searchCompleteTime) < 3.0)
                   2670:                return;
                   2671: 
                   2672:        M_Menu_LanConfig_f ();
                   2673: }
                   2674: 
                   2675: 
                   2676: void M_Search_Key (int key)
                   2677: {
                   2678: }
                   2679: 
                   2680: //=============================================================================
                   2681: /* SLIST MENU */
                   2682: 
                   2683: int            slist_cursor;
                   2684: qboolean slist_sorted;
                   2685: 
                   2686: void M_Menu_ServerList_f (void)
                   2687: {
                   2688:        key_dest = key_menu;
                   2689:        m_state = m_slist;
                   2690:        m_entersound = true;
                   2691:        slist_cursor = 0;
                   2692:        m_return_onerror = false;
                   2693:        m_return_reason[0] = 0;
                   2694:        slist_sorted = false;
                   2695: }
                   2696: 
                   2697: 
                   2698: void M_ServerList_Draw (void)
                   2699: {
                   2700:        int             n;
                   2701:        char    string [64];
                   2702:        qpic_t  *p;
                   2703: 
                   2704:        if (!slist_sorted)
                   2705:        {
                   2706:                if (hostCacheCount > 1)
                   2707:                {
                   2708:                        int     i,j;
                   2709:                        hostcache_t temp;
                   2710:                        for (i = 0; i < hostCacheCount; i++)
                   2711:                                for (j = i+1; j < hostCacheCount; j++)
                   2712:                                        if (strcmp(hostcache[j].name, hostcache[i].name) < 0)
                   2713:                                        {
                   2714:                                                Q_memcpy(&temp, &hostcache[j], sizeof(hostcache_t));
                   2715:                                                Q_memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t));
                   2716:                                                Q_memcpy(&hostcache[i], &temp, sizeof(hostcache_t));
                   2717:                                        }
                   2718:                }
                   2719:                slist_sorted = true;
                   2720:        }
                   2721: 
                   2722:        p = M_CachePic ("gfx/p_multi.lmp");
                   2723:        M_DrawPic ( (320-p->width)/2, 4, p);
                   2724:        for (n = 0; n < hostCacheCount; n++)
                   2725:        {
                   2726:                if (hostcache[n].maxusers)
                   2727:                        sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
                   2728:                else
                   2729:                        sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
                   2730:                M_Print (16, 32 + 8*n, string);
                   2731:        }
                   2732:        M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1));
                   2733: 
                   2734:        if (*m_return_reason)
                   2735:                M_PrintWhite (16, 148, m_return_reason);
                   2736: }
                   2737: 
                   2738: 
                   2739: void M_ServerList_Key (int k)
                   2740: {
                   2741:        switch (k)
                   2742:        {
                   2743:        case K_ESCAPE:
                   2744:                M_Menu_LanConfig_f ();
                   2745:                break;
                   2746: 
                   2747:        case K_SPACE:
                   2748:                M_Menu_Search_f ();
                   2749:                break;
                   2750: 
                   2751:        case K_UPARROW:
                   2752:        case K_LEFTARROW:
                   2753:                S_LocalSound ("misc/menu1.wav");
                   2754:                slist_cursor--;
                   2755:                if (slist_cursor < 0)
                   2756:                        slist_cursor = hostCacheCount - 1;
                   2757:                break;
                   2758: 
                   2759:        case K_DOWNARROW:
                   2760:        case K_RIGHTARROW:
                   2761:                S_LocalSound ("misc/menu1.wav");
                   2762:                slist_cursor++;
                   2763:                if (slist_cursor >= hostCacheCount)
                   2764:                        slist_cursor = 0;
                   2765:                break;
                   2766: 
                   2767:        case K_ENTER:
                   2768:                S_LocalSound ("misc/menu2.wav");
                   2769:                m_return_state = m_state;
                   2770:                m_return_onerror = true;
                   2771:                slist_sorted = false;
                   2772:                key_dest = key_game;
                   2773:                m_state = m_none;
                   2774:                Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) );
                   2775:                break;
                   2776: 
                   2777:        default:
                   2778:                break;
                   2779:        }
                   2780: 
                   2781: }
                   2782: 
                   2783: //=============================================================================
                   2784: /* Menu Subsystem */
                   2785: 
                   2786: 
                   2787: void M_Init (void)
                   2788: {
                   2789:        Cmd_AddCommand ("togglemenu", M_ToggleMenu_f);
                   2790: 
                   2791:        Cmd_AddCommand ("menu_main", M_Menu_Main_f);
                   2792:        Cmd_AddCommand ("menu_singleplayer", M_Menu_SinglePlayer_f);
                   2793:        Cmd_AddCommand ("menu_load", M_Menu_Load_f);
                   2794:        Cmd_AddCommand ("menu_save", M_Menu_Save_f);
                   2795:        Cmd_AddCommand ("menu_multiplayer", M_Menu_MultiPlayer_f);
                   2796:        Cmd_AddCommand ("menu_setup", M_Menu_Setup_f);
                   2797:        Cmd_AddCommand ("menu_options", M_Menu_Options_f);
                   2798:        Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
                   2799:        Cmd_AddCommand ("menu_video", M_Menu_Video_f);
                   2800:        Cmd_AddCommand ("help", M_Menu_Help_f);
                   2801:        Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
                   2802: }
                   2803: 
                   2804: 
                   2805: void M_Draw (void)
                   2806: {
                   2807:        if (m_state == m_none || key_dest != key_menu)
                   2808:                return;
                   2809: 
                   2810:        if (!m_recursiveDraw)
                   2811:        {
                   2812:                scr_copyeverything = 1;
                   2813: 
                   2814:                if (scr_con_current)
                   2815:                {
                   2816:                        Draw_ConsoleBackground (vid.height);
                   2817:                        VID_UnlockBuffer ();
                   2818:                        S_ExtraUpdate ();
                   2819:                        VID_LockBuffer ();
                   2820:                }
                   2821:                else
                   2822:                        Draw_FadeScreen ();
                   2823: 
                   2824:                scr_fullupdate = 0;
                   2825:        }
                   2826:        else
                   2827:        {
                   2828:                m_recursiveDraw = false;
                   2829:        }
                   2830: 
                   2831:        switch (m_state)
                   2832:        {
                   2833:        case m_none:
                   2834:                break;
                   2835: 
                   2836:        case m_main:
                   2837:                M_Main_Draw ();
                   2838:                break;
                   2839: 
                   2840:        case m_singleplayer:
                   2841:                M_SinglePlayer_Draw ();
                   2842:                break;
                   2843: 
                   2844:        case m_load:
                   2845:                M_Load_Draw ();
                   2846:                break;
                   2847: 
                   2848:        case m_save:
                   2849:                M_Save_Draw ();
                   2850:                break;
                   2851: 
                   2852:        case m_multiplayer:
                   2853:                M_MultiPlayer_Draw ();
                   2854:                break;
                   2855: 
                   2856:        case m_setup:
                   2857:                M_Setup_Draw ();
                   2858:                break;
                   2859: 
                   2860:        case m_net:
                   2861:                M_Net_Draw ();
                   2862:                break;
                   2863: 
                   2864:        case m_options:
                   2865:                M_Options_Draw ();
                   2866:                break;
                   2867: 
                   2868:        case m_keys:
                   2869:                M_Keys_Draw ();
                   2870:                break;
                   2871: 
                   2872:        case m_video:
                   2873:                M_Video_Draw ();
                   2874:                break;
                   2875: 
                   2876:        case m_help:
                   2877:                M_Help_Draw ();
                   2878:                break;
                   2879: 
                   2880:        case m_quit:
                   2881:                M_Quit_Draw ();
                   2882:                break;
                   2883: 
                   2884:        case m_serialconfig:
                   2885:                M_SerialConfig_Draw ();
                   2886:                break;
                   2887: 
                   2888:        case m_modemconfig:
                   2889:                M_ModemConfig_Draw ();
                   2890:                break;
                   2891: 
                   2892:        case m_lanconfig:
                   2893:                M_LanConfig_Draw ();
                   2894:                break;
                   2895: 
                   2896:        case m_gameoptions:
                   2897:                M_GameOptions_Draw ();
                   2898:                break;
                   2899: 
                   2900:        case m_search:
                   2901:                M_Search_Draw ();
                   2902:                break;
                   2903: 
                   2904:        case m_slist:
                   2905:                M_ServerList_Draw ();
                   2906:                break;
                   2907:        }
                   2908: 
                   2909:        if (m_entersound)
                   2910:        {
                   2911:                S_LocalSound ("misc/menu2.wav");
                   2912:                m_entersound = false;
                   2913:        }
                   2914: 
                   2915:        VID_UnlockBuffer ();
                   2916:        S_ExtraUpdate ();
                   2917:        VID_LockBuffer ();
                   2918: }
                   2919: 
                   2920: 
                   2921: void M_Keydown (int key)
                   2922: {
                   2923:        switch (m_state)
                   2924:        {
                   2925:        case m_none:
                   2926:                return;
                   2927: 
                   2928:        case m_main:
                   2929:                M_Main_Key (key);
                   2930:                return;
                   2931: 
                   2932:        case m_singleplayer:
                   2933:                M_SinglePlayer_Key (key);
                   2934:                return;
                   2935: 
                   2936:        case m_load:
                   2937:                M_Load_Key (key);
                   2938:                return;
                   2939: 
                   2940:        case m_save:
                   2941:                M_Save_Key (key);
                   2942:                return;
                   2943: 
                   2944:        case m_multiplayer:
                   2945:                M_MultiPlayer_Key (key);
                   2946:                return;
                   2947: 
                   2948:        case m_setup:
                   2949:                M_Setup_Key (key);
                   2950:                return;
                   2951: 
                   2952:        case m_net:
                   2953:                M_Net_Key (key);
                   2954:                return;
                   2955: 
                   2956:        case m_options:
                   2957:                M_Options_Key (key);
                   2958:                return;
                   2959: 
                   2960:        case m_keys:
                   2961:                M_Keys_Key (key);
                   2962:                return;
                   2963: 
                   2964:        case m_video:
                   2965:                M_Video_Key (key);
                   2966:                return;
                   2967: 
                   2968:        case m_help:
                   2969:                M_Help_Key (key);
                   2970:                return;
                   2971: 
                   2972:        case m_quit:
                   2973:                M_Quit_Key (key);
                   2974:                return;
                   2975: 
                   2976:        case m_serialconfig:
                   2977:                M_SerialConfig_Key (key);
                   2978:                return;
                   2979: 
                   2980:        case m_modemconfig:
                   2981:                M_ModemConfig_Key (key);
                   2982:                return;
                   2983: 
                   2984:        case m_lanconfig:
                   2985:                M_LanConfig_Key (key);
                   2986:                return;
                   2987: 
                   2988:        case m_gameoptions:
                   2989:                M_GameOptions_Key (key);
                   2990:                return;
                   2991: 
                   2992:        case m_search:
                   2993:                M_Search_Key (key);
                   2994:                break;
                   2995: 
                   2996:        case m_slist:
                   2997:                M_ServerList_Key (key);
                   2998:                return;
                   2999:        }
                   3000: }
                   3001: 
                   3002: 
                   3003: void M_ConfigureNetSubsystem(void)
                   3004: {
                   3005: // enable/disable net systems to match desired config
                   3006: 
                   3007:        Cbuf_AddText ("stopdemo\n");
                   3008:        if (SerialConfig || DirectConfig)
                   3009:        {
                   3010:                Cbuf_AddText ("com1 enable\n");
                   3011:        }
                   3012: 
                   3013:        if (IPXConfig || TCPIPConfig)
                   3014:                net_hostport = lanConfig_port;
                   3015: }
                   3016: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.