]> icculus.org git repositories - btb/d2x.git/blob - main/netlist.c
allow specifying file to extract
[btb/d2x.git] / main / netlist.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/main/netlist.c,v $
3  * $Revision: 1.3 $
4  * $Author: bradleyb $
5  * $Date: 2002-02-14 10:18:24 $
6  *
7  * Descent II-a-like network game join menu
8  * Arne de Bruijn, 1998
9  *
10  * $Log: not supported by cvs2svn $
11  * Revision 1.2  2002/02/14 09:24:19  bradleyb
12  * d1x->d2x
13  *
14  * Revision 1.1  2002/02/14 09:05:33  bradleyb
15  * Lotsa networking stuff from d1x
16  *
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "pstypes.h"
29 #include "timer.h"
30 #include "gr.h"
31 #include "palette.h"
32 #include "inferno.h"
33 #include "mono.h"
34 #include "key.h"
35 #include "error.h"
36 #include "netmisc.h"
37 #include "network.h"
38 #include "ipx.h"
39 #include "game.h"
40 #include "multi.h"
41 #include "text.h"
42 //added 4/18/99 Matt Mueller - show radar in game info
43 #include "multipow.h"
44 //end addition -MM
45
46 #include "gamefont.h"
47 #include "u_mem.h"
48
49 #include "string.h"
50
51 //added on 1/5/99 by Victor Rachels for missiondir
52 #include "cfile.h"
53 //end this section addition
54
55 #define LINE_ITEMS 8
56 #define MAX_TEXT_LEN 25
57 // from network.c
58 extern int Network_games_changed;
59 extern netgame_info Active_games[MAX_ACTIVE_NETGAMES];
60 extern AllNetPlayers_info ActiveNetPlayers[MAX_ACTIVE_NETGAMES];
61 extern int num_active_games;
62 extern int Network_socket;
63 void network_listen();
64 void network_send_game_list_request();
65 // bitblt.c
66 void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest);
67
68 typedef struct bkg {
69   grs_canvas * menu_canvas;
70   grs_bitmap * saved;                   // The background under the menu.
71   grs_bitmap * background;
72   int background_is_sub;
73 } bkg;
74
75 extern grs_bitmap nm_background;
76
77 struct line_item {
78         int x, y;
79         int width;
80         char *value;
81 };
82
83 void network_draw_game(const netgame_info *game) {
84 }
85
86 char *network_mode_text(const netgame_info *game) {
87         //edit 4/18/99 Matt Mueller - GTEAM?  heh.  Should be "TEAM" I think.
88         static char *names[4]={"ANRCHY", "TEAM", "ROBO", "COOP"};
89         //end edit -MM
90 #ifndef SHAREWARE
91         if (game->gamemode >= 4 ||
92             (game->protocol_version != MULTI_PROTO_VERSION &&
93              (game->protocol_version != MULTI_PROTO_D2X_VER ||
94               game->required_subprotocol > MULTI_PROTO_D2X_MINOR)))
95             return "UNSUP";
96 #endif
97         return names[game->gamemode];
98 }
99
100 char *network_status_text(const netgame_info *game, int activeplayers) {
101         switch (game->game_status) {
102                 case NETSTAT_STARTING:
103                         return "Forming";
104                 case NETSTAT_PLAYING:
105                         if (game->game_flags & NETGAME_FLAG_CLOSED)
106                                 return "Closed";
107                         else if (activeplayers == game->max_numplayers)
108                                 return "Full";
109                         else
110                                 return "Open";
111                 default:
112                         return "Between";
113         }
114 }
115
116 static void network_update_item(const netgame_info *game, const AllNetPlayers_info *players, struct line_item li[]) {
117         int i, activeplayers = 0;
118         // get number of active players
119         for (i = 0; i < game->numplayers; i++)
120                 if (players->players[i].connected)
121                         activeplayers++;
122         strcpy(li[1].value, game->protocol_version == MULTI_PROTO_D2X_VER ? "+" : "");
123         strcpy(li[2].value, game->game_name);
124         strcpy(li[3].value, network_mode_text(game));
125
126         sprintf(li[4].value, "%d/%d", activeplayers, game->max_numplayers);
127 #ifndef SHAREWARE
128         strcpy(li[5].value, game->mission_title);
129 #else
130         strcpy(li[5].value, "Descent: First Strike");
131 #endif
132         if (game->levelnum < 0)
133                 sprintf(li[6].value, "S%d", -game->levelnum);
134         else    
135                 sprintf(li[6].value, "%d", game->levelnum);
136         strcpy(li[7].value, network_status_text(game, activeplayers));
137 }
138
139 static void update_items(struct line_item lis[MAX_ACTIVE_NETGAMES][LINE_ITEMS]) {
140         int i, j;
141
142         for (i = 0; i < MAX_ACTIVE_NETGAMES; i++) {
143                 if (i >= num_active_games) {
144                         for (j = 1; j < LINE_ITEMS; j++)
145                                 lis[i][j].value[0] = 0;
146                 } else
147                         network_update_item(&Active_games[i], &ActiveNetPlayers[i], lis[i]);
148         }
149 }
150
151 int network_menu_hskip=4;
152 int network_menu_width[LINE_ITEMS] = { 10, 6, 72, 37, 38, 66, 25, 40 };
153 int ref_network_menu_width[LINE_ITEMS] = { 10, 6, 72, 37, 38, 66, 25, 40 };
154 char *network_menu_title[LINE_ITEMS] = { "", "", "Game", "Mode", "#Plrs", "Mission", "Lev", "Status" };
155
156 static int selected_game;
157
158 static void draw_back(bkg *b, int x, int y, int w, int h) {
159        gr_bm_bitblt(b->background->bm_w-15, h, 5, y, 5, y, b->background, &(grd_curcanv->cv_bitmap) );
160 }
161
162 static void draw_item(bkg *b, struct line_item *li, int is_current) {
163         int i, w, h, aw, max_w, pad_w, y;
164         char str[MAX_TEXT_LEN], *p;
165
166         y = li[0].y;
167         if (is_current)
168                 gr_set_fontcolor(BM_XRGB(31, 27, 6), -1);
169         else
170                 gr_set_fontcolor(BM_XRGB(17, 17, 26), -1);
171         gr_get_string_size(" ...", &pad_w, &h, &aw);
172         draw_back(b, li[0].x, y, 
173          li[LINE_ITEMS-1].x + li[LINE_ITEMS-1].width - li[0].x, h);
174         for (i = 0; i < LINE_ITEMS; i++) {
175                 strcpy(str, li[i].value);
176                 gr_get_string_size(str, &w, &h, &aw);
177                 if (w > li[i].width) {
178                         max_w = li[i].width - pad_w;
179                         p = str + strlen(str);
180                         while (p > str && w > max_w) {
181                                 *(--p) = 0;
182                                 gr_get_string_size(str, &w, &h, &aw);
183                         }
184                         strcpy(p, " ...");
185                 }
186                 gr_ustring(li[i].x, y, str);
187         }
188 }
189
190 static void draw_list(bkg *bg,
191  struct line_item lis[MAX_ACTIVE_NETGAMES][LINE_ITEMS]) {
192         int i;
193         update_items(lis);
194         for (i = 0; i < MAX_ACTIVE_NETGAMES; i++) {
195                 draw_item(bg, lis[i], i == selected_game);
196         }
197 }
198 static void init_background(bkg *bg, int x, int y, int w, int h) {
199         bg->menu_canvas = gr_create_sub_canvas( &grd_curscreen->sc_canvas, x, y, w, h );
200         gr_set_current_canvas( bg->menu_canvas );
201
202         // Save the background under the menu...
203         bg->saved = gr_create_bitmap( w, h );
204         Assert( bg->saved != NULL );
205         gr_bm_bitblt(w, h, 0, 0, 0, 0, &grd_curcanv->cv_bitmap, bg->saved );
206         gr_set_current_canvas( NULL );
207         nm_draw_background(x,y,x+w-1,y+h-1);
208         if (w > nm_background.bm_w || h > nm_background.bm_h){
209                 bg->background=gr_create_bitmap(w,h);
210                 gr_bitmap_scale_to(&nm_background,bg->background);
211                 bg->background_is_sub=0;
212         }else{
213                 bg->background = gr_create_sub_bitmap(&nm_background,0,0,w,h);
214                 bg->background_is_sub=1;
215         }
216         gr_set_current_canvas( bg->menu_canvas );
217 }
218
219 static void done_background(bkg *bg) {
220         gr_set_current_canvas(bg->menu_canvas);
221         gr_bitmap(0, 0, bg->saved);     
222         gr_free_bitmap(bg->saved);
223         if (bg->background_is_sub)
224                 gr_free_sub_bitmap( bg->background );
225         else
226                 gr_free_bitmap( bg->background );
227         gr_free_sub_canvas( bg->menu_canvas );
228 }
229
230
231 //added on 9/16-18/98 by Victor Rachels to add info boxes to netgameslist
232 void show_game_players(netgame_info game, AllNetPlayers_info players)
233 {
234  char pilots[(CALLSIGN_LEN+2)*MAX_PLAYERS];
235  int i;
236
237   memset(pilots,0,sizeof(char)*(CALLSIGN_LEN+2)*MAX_PLAYERS);
238
239    for(i=0;i<game.numplayers;i++)
240     if(players.players[i].connected)
241      {
242       strcat(pilots,players.players[i].callsign);
243       strcat(pilots,"\n");
244      }
245
246   nm_messagebox("Players", 1, TXT_OK, pilots);
247 }
248
249 void show_game_score(netgame_info game, AllNetPlayers_info players);
250
251 int show_game_stats(netgame_info game, AllNetPlayers_info players, int awesomeflag)
252 {
253  //edited 4/18/99 Matt Mueller - show radar flag and banned stuff too
254  //switched to the info/rinfo mode to 1)allow sprintf easily 2) save some
255  //cpu cycles not seeking to the end of the string each time.
256  char rinfo[512],*info=rinfo;
257
258   memset(info,0,sizeof(char)*256);
259
260 #ifndef SHAREWARE
261    if(!game.mission_name)
262 #endif
263     info+=sprintf(info,"Level: Descent: First Strike");
264 #ifndef SHAREWARE
265    else
266     info+=sprintf(info,game.mission_name);
267 #endif
268
269    switch(game.gamemode)
270     {
271      case 0 : info+=sprintf(info,"\nMode:  Anarchy"); break;
272      case 1 : info+=sprintf(info,"\nMode:  Team"); break;
273      case 2 : info+=sprintf(info,"\nMode:  Robo"); break;
274      case 3 : info+=sprintf(info,"\nMode:  Coop"); break;
275      default: info+=sprintf(info,"\nMode:  Unknown"); break;
276     }
277
278    switch(game.difficulty)
279     {
280      case 0 : info+=sprintf(info,"\nDiff:  Trainee"); break;
281      case 1 : info+=sprintf(info,"\nDiff:  Rookie"); break;
282      case 2 : info+=sprintf(info,"\nDiff:  Hotshot"); break;
283      case 3 : info+=sprintf(info,"\nDiff:  Ace"); break;
284      case 4 : info+=sprintf(info,"\nDiff:  Insane"); break;
285      default: info+=sprintf(info,"\nDiff:  Unknown"); break;
286     }
287
288    switch(game.protocol_version)
289     {
290      case 1 : info+=sprintf(info,"\nPrtcl: Shareware"); break;
291      case 2 : info+=sprintf(info,"\nPrtcl: Normal"); break;
292      case 3 : info+=sprintf(info,"\nPrtcl: D2X only"); break;
293      case 0 : info+=sprintf(info,"\nPrtcl: D2X hybrid"); break;
294      default: info+=sprintf(info,"\nPrtcl: Unknown"); break;
295     }
296
297    if(game.game_flags & NETGAME_FLAG_SHOW_MAP)
298            info+=sprintf(info,"\n Players on Map");
299    //edited 04/19/99 Matt Mueller - check protocol_ver too.
300    if (game.protocol_version==MULTI_PROTO_D2X_VER 
301 #ifndef SHAREWARE
302 && game.subprotocol>=1
303 #endif
304 ){
305 #ifndef SHAREWARE
306            int i=0,b=0;
307            char sep0=':';
308            if(game.flags & NETFLAG_ENABLE_RADAR)
309                    info+=sprintf(info,"\n Radar");
310            if(game.flags & NETFLAG_ENABLE_ALT_VULCAN)
311                    info+=sprintf(info,"\n Alt Vulcan");
312            info+=sprintf(info,"\n Banned");
313 #define NETFLAG_SHOW_BANNED(D,V) if (!(game.flags&NETFLAG_DO ## D)) {if (i>3) i=0; else i++; info+=sprintf(info,"%c %s",i?sep0:'\n',#V);b++;sep0=',';}
314            NETFLAG_SHOW_BANNED(LASER,laser);
315            NETFLAG_SHOW_BANNED(QUAD,quad);
316            NETFLAG_SHOW_BANNED(VULCAN,vulcan);
317            NETFLAG_SHOW_BANNED(SPREAD,spread);
318            NETFLAG_SHOW_BANNED(PLASMA,plasma);
319            NETFLAG_SHOW_BANNED(FUSION,fusion);
320            NETFLAG_SHOW_BANNED(HOMING,homing);
321            NETFLAG_SHOW_BANNED(SMART,smart);
322            NETFLAG_SHOW_BANNED(MEGA,mega);
323            NETFLAG_SHOW_BANNED(PROXIM,proxim);
324            NETFLAG_SHOW_BANNED(CLOAK,cloak);
325            NETFLAG_SHOW_BANNED(INVUL,invuln);
326            if (b==0) info+=sprintf(info,": none");
327 #endif /* ! SHAREWARE */
328    }
329    //end edit -MM
330  //end edit -MM
331         if (awesomeflag){
332                 int c;
333                 while (1){
334                         c=nm_messagebox("Stats", 3, "Players","Scores","Join Game", rinfo);
335                         if (c==0)
336                                 show_game_players(game, players);
337                         else if (c==1)
338                                 show_game_score(game, players);
339                         else if (c==2)
340                                 return 1;
341                         else
342                                 return 0;
343                 }
344         }else{
345            nm_messagebox("Stats", 1, TXT_OK, rinfo);
346            return 0;
347         }
348 }
349 //end this section addition - Victor Rachels
350
351 //added on 11/12/98 by Victor Rachels to maybe fix some bugs
352 void alphanumize(char *string, int length);
353
354 void alphanumize(char *string, int length)
355 {
356  int i=0;
357   while(i<length && string[i])
358    {
359      if(!((string[i]<=122&&string[i]>=97) ||
360           (string[i]<=90 &&string[i]>=65) ||
361           (string[i]<=57 &&string[i]>=48) ||
362           (string[i]=='\n') ||
363           (string[i]==' ')  ||
364           (string[i]=='-')
365           ) )
366       string[i] = '_';
367     i++;
368    }
369 }
370
371 //added on 10/12/98 by Victor Rachels to show netgamelist scores
372 void show_game_score(netgame_info game, AllNetPlayers_info players)
373 {
374  char scores[2176]="",info[2048]="",deaths[128]="",tmp[10];
375  int i,j,k;
376
377   strcat(scores,"Pilots ");
378   strcat(deaths,"    ");
379
380    for(i=0;i<game.numplayers;i++)
381     if(players.players[i].connected)
382      {
383        strcat(scores,"     ");
384        sprintf(tmp,"%c",players.players[i].callsign[0]);
385        strcat(scores,tmp);
386        strcat(info,players.players[i].callsign);
387         for(k=strlen(players.players[i].callsign);k<9;k++)
388          strcat(info," ");
389         for(j=0;j<game.numplayers;j++)
390          if(players.players[j].connected)
391           {
392            if(i==j&&game.kills[i][j]>0)
393             {
394              strcat(info,"  ");
395              sprintf(tmp,"-%i",game.kills[i][j]);
396             }
397            else
398             {
399              strcat(info,"   ");
400              sprintf(tmp,"%i",game.kills[i][j]);
401             }
402            strcat(info,tmp);
403             for(k=strlen(tmp);k<3;k++)
404              strcat(info," ");
405           }
406        sprintf(tmp,"     %i",game.player_kills[i]);
407        strcat(info,tmp);
408        strcat(info,"\n\n");
409        sprintf(tmp,"     %i",game.killed[i]);
410        strcat(deaths,tmp);
411      }
412   strcat(scores,"   Total\n\n");
413   strcat(scores,info);
414   strcat(deaths,"   \n\n");
415   strcat(scores,deaths);
416   alphanumize(scores,sizeof(scores));
417   nm_messagebox_fixedfont("Score\n", 1, TXT_OK, scores);
418 }
419 //end this section addition - Victor Rachels
420
421 //added on 2000/01/29 by Matt Mueller for direct ip join.
422 #include "netpkt.h"
423 int network_do_join_game(netgame_info *jgame);
424 int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address){
425         sequence_packet me;
426         fix nextsend;
427         int numsent;
428         fix curtime;
429
430         if (setjmp(LeaveGame))
431                 return 0;
432     num_active_games = 0;
433         Network_games_changed = 0;
434         Network_status = NETSTAT_BROWSING;
435     memset(Active_games, 0, sizeof(netgame_info)*MAX_ACTIVE_NETGAMES);
436
437         nextsend=0;numsent=0;
438
439         while (1){
440                 curtime=timer_get_fixed_seconds();
441                 if (nextsend<curtime){
442                         if (numsent>=5)
443                                 return 0;//timeout
444                         nextsend=curtime+F1_0*3;
445                         numsent++;
446                         mprintf((0, "Sending game_list request.\n"));
447                         memcpy( me.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1 );
448                         memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
449                         memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
450                         me.type = PID_D2X_GAME_INFO_REQ;//get full info.
451
452                         send_sequence_packet( me, server,node,net_address);
453                 }
454
455                 network_listen();
456
457                 if (Network_games_changed){
458                         if (num_active_games<1){
459                                 Network_games_changed=0;
460                                 continue;
461                         }
462                         if (show_game_stats(Active_games[0], ActiveNetPlayers[0], 1))
463                                 return (network_do_join_game(&Active_games[0]));
464                         else
465                                 return 0;
466                 }
467                 if (key_inkey()==KEY_ESC)
468                         return 0;
469
470         }
471         return 0;
472 }
473 //end addition -MM
474
475 //added on 1/5/99 by Victor Rachels for missiondir
476 void change_missiondir()
477 {
478  newmenu_item m[1];
479  int i=1;
480  char thogdir[64];
481
482   sprintf(thogdir,AltHogDir);
483
484   m[0].type = NM_TYPE_INPUT; m[0].text = thogdir; m[0].text_len = 64;
485
486   i=newmenu_do1(NULL, "Mission Directory", 1, m, NULL, 0);
487
488    if(i==0)
489     {
490      cfile_use_alternate_hogdir(thogdir);
491      sprintf(thogdir,AltHogDir);
492      m[0].text=thogdir;
493     }
494 }
495 //end this section addition - VR
496
497 //added/changed on 9/17/98 by Victor Rachels for netgame info screen redraw
498 //this was mostly a bunch of random moves and copies from the main function
499 //if you can figure this out more elegantly, go for it.
500 void netlist_redraw(bkg bg,
501                     char menu_text[MAX_ACTIVE_NETGAMES][LINE_ITEMS][MAX_TEXT_LEN],
502                     struct line_item lis[MAX_ACTIVE_NETGAMES][LINE_ITEMS])
503 {
504  int i,j,k,yp;
505
506         gr_set_current_canvas( NULL );
507
508         init_background(&bg, 0, 7, grd_curcanv->cv_bitmap.bm_w,
509          grd_curcanv->cv_bitmap.bm_h - 14);
510
511         yp=22;
512         gr_set_curfont(Gamefonts[GFONT_BIG_1]);
513         gr_string(0x8000, yp, "Netgames");//yp was 22
514         yp+=grd_curcanv->cv_font->ft_h+network_menu_hskip*3+Gamefonts[GFONT_SMALL]->ft_h;//need to account for size of current socket, drawn elsewhere
515         // draw titles
516         gr_set_curfont(Gamefonts[GFONT_SMALL]);
517         gr_set_fontcolor(BM_XRGB(27, 27, 27), -1);
518         k = 15;
519         for (j = 0; j < LINE_ITEMS; j++) {
520                 gr_ustring(k, yp, network_menu_title[j]);//yp was 61
521                 k += network_menu_width[j];
522         }
523         
524
525         for (i = 0; i < MAX_ACTIVE_NETGAMES; i++) {
526                 struct line_item *li = lis[i];
527                 k=15;
528
529                 yp+=grd_curcanv->cv_font->ft_h+network_menu_hskip;
530                 for (j = 0; j < LINE_ITEMS; j++) {
531                         li[j].x = k;
532                         li[j].y = yp;
533                         //                      li[j].y = 70 + i * 9;
534                         li[j].width = network_menu_width[j] - (j > 1 ? 4 : 0); // HACK!
535                         k += network_menu_width[j];
536                         li[j].value = menu_text[i][j];
537                 }
538                 sprintf(li[0].value, "%d.", i + 1); 
539         }
540
541 }
542 //end this section addition - Victor Rachels
543
544 int network_join_game_menu() {
545         char menu_text[MAX_ACTIVE_NETGAMES][LINE_ITEMS][MAX_TEXT_LEN];
546         struct line_item lis[MAX_ACTIVE_NETGAMES][LINE_ITEMS];
547         int k;
548         int old_select, old_socket, done, last_num_games;
549         grs_canvas * save_canvas;
550         grs_font * save_font;
551         bkg bg;
552         fix t, req_timer = 0;
553         
554         selected_game = 0;
555         gr_palette_fade_in( gr_palette, 32, 0 );
556         save_canvas = grd_curcanv;
557         gr_set_current_canvas( NULL );
558         save_font = grd_curcanv->cv_font;
559         
560         for (k=0;k<LINE_ITEMS;k++)//scale columns to fit screen res.
561                 network_menu_width[k]=ref_network_menu_width[k]*grd_curcanv->cv_bitmap.bm_w/320;
562         network_menu_hskip=(grd_curcanv->cv_bitmap.bm_h-Gamefonts[GFONT_BIG_1]->ft_h-22-Gamefonts[GFONT_SMALL]->ft_h*17)/17;
563
564         init_background(&bg, 0, 7, grd_curcanv->cv_bitmap.bm_w,
565          grd_curcanv->cv_bitmap.bm_h - 14);
566
567         game_flush_inputs();
568
569 //added/changed on 9/17/98 by Victor Rachels for netgame info screen redraw
570         netlist_redraw(bg,menu_text,lis);
571 //end this section addition - Victor Rachels
572
573         Network_games_changed = 1;
574         old_socket = -32768;
575         old_select = -1;
576         last_num_games = 0;
577         if ( gr_palette_faded_out ) {
578             gr_palette_fade_in( gr_palette, 32, 0 );
579         }
580
581         done = 0;
582
583         while (!done) {
584                 if (Network_socket != old_socket) {
585                         gr_set_fontcolor(BM_XRGB(27, 27, 27), -1);
586                         draw_back(&bg, 30, 22+Gamefonts[GFONT_BIG_1]->ft_h+network_menu_hskip*2, 250, Gamefonts[GFONT_SMALL]->ft_h+4);//was 52,250,9
587                         gr_printf(30, 22+Gamefonts[GFONT_BIG_1]->ft_h+network_menu_hskip*2, "Current IPX socket is %+d "
588                                         "(PgUp/PgDn to change)", Network_socket);
589                         if (old_socket != -32768) { /* changed by user? */
590                                 network_listen();
591                                 ipx_change_default_socket( IPX_DEFAULT_SOCKET + Network_socket );
592                                 num_active_games = 0;
593                         }
594                         req_timer -= F1_0 * 5; /* force send request */
595                         Network_games_changed = 1;
596                 }
597                 if (Network_games_changed) {
598                         if (num_active_games > last_num_games) /* new game? */
599                                 digi_play_sample(SOUND_HUD_MESSAGE, F1_0);
600                         last_num_games = num_active_games;
601                         Network_games_changed = 0;
602                         draw_list(&bg, lis);
603                         //added on 9/13/98 by adb to make update-needing arch's work
604                         gr_update();
605                         //end addition - adb
606
607                 } else if (selected_game != old_select) {
608                         draw_item(&bg, lis[old_select], 0);
609                         draw_item(&bg, lis[selected_game], 1);
610                         //added on 9/13/98 by adb to make update-needing arch's work
611                         gr_update();
612                         //end addition - adb
613                 }
614                 old_socket = Network_socket;
615                 old_select = selected_game;
616
617                 t = timer_get_approx_seconds();
618                 if (t < req_timer || t > req_timer + F1_0 * 5) {
619                         req_timer = timer_get_approx_seconds();
620                         network_send_game_list_request();
621                 }                               
622                 network_listen();
623
624                 k = key_inkey();
625                 switch (k) {
626 //added 9/16-17/98 by Victor Rachels for netgamelist info
627         //edit 4/18/99 Matt Mueller - use KEY_? defines so it actually works on non-dos
628                         case KEY_U: //U = 0x16
629                                 if(selected_game<num_active_games)
630                                  {
631                                    show_game_players(Active_games[selected_game], ActiveNetPlayers[selected_game]);
632                                    netlist_redraw(bg,menu_text,lis);
633                                    old_socket = -32768;
634                                    old_select = -1;
635                                  }
636                                 break;
637                         case KEY_I: //I = 0x17
638                                 if(selected_game<num_active_games)
639                                  {
640                                    show_game_stats(Active_games[selected_game], ActiveNetPlayers[selected_game], 0);
641                                    netlist_redraw(bg,menu_text,lis);
642                                    old_socket = -32768;
643                                    old_select = -1;
644                                  }
645                                 break;
646 //end this section addition - Victor
647 //added 10/12/98 by Victor Rachels for netgamelist scores
648                         case  KEY_S: //S = 0x1f
649                                 if(selected_game<num_active_games)
650                                  {
651                                   show_game_score(Active_games[selected_game], ActiveNetPlayers[selected_game]);
652                                   netlist_redraw(bg,menu_text,lis);
653                                   old_socket = -32768;
654                                   old_select = -1;
655                                  }
656                                 break;
657 //end this section addition - Victor
658                         case KEY_M: //M = 0x32
659         //end edit -MM
660                                  {
661                                   change_missiondir();
662                                   netlist_redraw(bg,menu_text,lis);
663                                   old_socket = -32768;
664                                   old_select = -1;
665                                  }
666                         case KEY_PAGEUP:
667                         case KEY_PAD9:
668                                 if (Network_socket < 99) Network_socket++;
669                                 break;
670                         case KEY_PAGEDOWN:
671                         case KEY_PAD3:
672                                 if (Network_socket > -99) Network_socket--;
673                                 break;
674                         case KEY_PAD5:
675                                 Network_socket = 0;
676                                 break;
677                         case KEY_TAB + KEY_SHIFTED:
678                         case KEY_UP:
679                         case KEY_PAD8:
680                                 if (selected_game-- == 0)
681                                         selected_game = MAX_ACTIVE_NETGAMES - 1;
682                                 break;
683                         case KEY_TAB:
684                         case KEY_DOWN:
685                         case KEY_PAD2:
686                                 if (++selected_game == MAX_ACTIVE_NETGAMES)
687                                         selected_game = 0;
688                                 break;
689                         case KEY_ENTER:
690                         case KEY_PADENTER:
691                                 done = 1;
692                                 break;
693 #if 0
694                         //added on 11/20/99 by Victor Rachels to add observer mode
695                         case KEY_O:
696                                 I_am_observer=1;
697                                 done = 1;
698                                 break;
699                         //end this section addition - VR
700 #endif
701                         case KEY_ESC:
702                                 selected_game = -1;
703                                 done = 1;
704                                 break;
705                         case KEY_CTRLED+KEY_SHIFTED+KEY_PADENTER:
706                         case KEY_ALTED+KEY_CTRLED+KEY_PADENTER:
707                         case KEY_ALTED+KEY_SHIFTED+KEY_PADENTER:
708                                 gr_toggle_fullscreen_menu();
709                                 break;
710                 }
711         }
712     done_background(&bg);
713         //edited 05/18/99 Matt Mueller - restore the font *after* the canvas, or else we are writing into the free'd memory
714         gr_set_current_canvas( save_canvas );
715         grd_curcanv->cv_font = save_font;
716         //end edit -MM
717         return selected_game;
718 }