source: abuse/tags/pd/abuse/src/game.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 12 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 60.9 KB
Line 
1#include "game.hpp"
2#include "dev.hpp"
3#include "id.hpp"
4#include "joy.hpp"
5#include "timing.hpp"
6#include "automap.hpp"
7#include "help.hpp"
8#include "ability.hpp"
9#include "cache.hpp"
10#include "loader.hpp"
11#include "lisp.hpp"
12#include "monoprnt.hpp"
13#include "jrand.hpp"
14#include "config.hpp"
15#include "light.hpp"
16#include "scroller.hpp"
17#include "dprint.hpp"
18#include "nfserver.hpp"
19#include "video.hpp"
20#include "transp.hpp"
21#include "clisp.hpp"
22#include "guistat.hpp"
23#include "menu.hpp"
24#include "gamma.hpp"
25#include "lisp_gc.hpp"
26#include "demo.hpp"
27#include "sbar.hpp"
28#include "profile.hpp"
29#include "compiled.hpp"
30#include "lisp_gc.hpp"
31#include "pmenu.hpp"
32#include "timing.hpp"
33#include "chat.hpp"
34#include "demo.hpp"
35#include "netcfg.hpp"
36
37#ifdef __POWERPC__
38#include <profiler.h>  //prof
39#endif
40
41#include <ctype.h>
42#include <setjmp.h>
43
44#define SHIFT_RIGHT_DEFAULT 0
45#define SHIFT_DOWN_DEFAULT 30
46
47class game;
48extern crc_manager *net_crcs;
49extern void show_verinfo(int argc, char **argv);
50game *the_game;
51window_manager *eh=NULL;
52int dev,shift_down=SHIFT_DOWN_DEFAULT,shift_right=SHIFT_RIGHT_DEFAULT;
53double sum_diffs=1,total_diffs=12;
54int total_active=0;
55long map_xoff=0,map_yoff=0;
56long current_vxadd,current_vyadd;
57int frame_panic=0,massive_frame_panic=0;
58int demo_start=0,idle_ticks=0;
59int req_end=0;
60
61extern palette *old_pal;
62char **start_argv;
63int start_argc;
64int has_joystick=0;
65char req_name[100];
66
67int registered=0;
68extern uchar chatting_enabled;
69
70extern int confirm_quit();
71
72#ifdef __POWERPC__
73extern char *macify_name(char *s);
74
75#include "tcpip.hpp"
76
77tcpip_protocol tcpip;
78
79#endif
80
81FILE *open_FILE(char *filename, char *mode)
82{
83/*  char *prefix=get_filename_prefix() ? get_filename_prefix() : "",*c;
84 
85  if (get_save_filename_prefix)
86  {
87    for (c=mode;*c;c++)
88      if (c=='w' || c=='W')
89      {
90      }
91  } */
92     
93 
94  char tmp_name[200];
95  if (get_filename_prefix() && filename[0] != '/')
96    sprintf(tmp_name,"%s%s",get_filename_prefix(),filename);
97  else strcpy(tmp_name,filename);
98#ifdef __POWERPC__
99  macify_name(tmp_name);
100#endif
101  return fopen(tmp_name,mode);
102}
103
104
105void handle_no_space()
106{
107  char *no_space_msg= "\nYou are out of disk space or the game\n"
108                      "was unable to write to disk for some reason\n"
109                      "The game cannot continue, please check this out\n"
110                      "and try again.\n";
111  if (eh)
112  {
113    jwindow *no_space=eh->new_window(0,0,-1,-1,
114                                     new button(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_QUIT_OK,"Quit",
115                                                new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP+eh->font()->height()*2,ID_NULL,
116                                                              no_space_msg,NULL)),"ERROR");
117    event ev;
118    do
119    {
120      eh->flush_screen();
121      eh->get_event(ev);
122    } while (ev.type!=EV_MESSAGE || ev.message.id!=ID_QUIT_OK);
123    eh->close_window(no_space);
124
125    close_graphics();
126    exit(1);
127  } else
128  {
129    fprintf(stderr,"%s\n",no_space_msg);
130    exit(0);
131  }
132}
133
134void game::play_sound(int id, int vol, long x, long y)
135{
136  if (sound_avail&SFX_INITIALIZED)
137  {
138    if (vol<15) return ;
139    if (!player_list) return ;
140
141    ulong mdist=0xffffffff;
142    view *cd=NULL;
143    for (view *f=player_list;f;f=f->next)
144    {
145      if (f->local_player())
146      {
147        long cx=abs(f->x_center()-x),cy=abs(f->y_center()-y),d;
148        if (cx<cy)
149        d=cx+cy-(cx>>1);
150        else d=cx+cy-(cy>>1);
151
152        if (d<mdist)
153        {
154          cd=f;
155          mdist=d;
156        }
157      }
158    } 
159    if (mdist>500 || !cd) return ;
160    if (mdist<100) mdist=0;
161    else mdist-=100;
162
163    int v=(400-mdist)*sfx_volume/400-(127-vol);
164    if (v>0 && (sound_avail&SFX_INITIALIZED))
165      cash.sfx(id)->play(v);
166  }
167}
168
169int get_option(char *name)
170{
171  int i;
172  for (i=1;i<start_argc;i++)
173    if (!strcmp(start_argv[i],name))
174      return i;
175  return 0;
176}
177
178
179void make_screen_size(int w, int h)
180{
181  for (view *f=player_list;f;f=f->next)
182  {
183    if (f->local_player())
184    {
185      if (w>=xres-1) w=xres-2;
186      if (h>=yres-1) h=yres-2;
187      f->suggest.cx1=(xres+1)/2-w/2;
188      f->suggest.cx2=(xres+1)/2+w/2;
189      f->suggest.cy1=(yres-31)/2+5-h/2;
190      f->suggest.cy2=(yres-51)/2+5+h/2;
191      f->suggest.shift_down=f->shift_down;
192      f->suggest.shift_right=f->shift_right;
193      f->suggest.pan_x=f->pan_x;
194      f->suggest.pan_y=f->pan_y;
195
196      f->suggest.send_view=1;
197    }
198  }
199}
200
201void game::grow_views(int amount)
202{
203  int undo=0;
204  view *f=first_view;
205  for (;f;f=f->next)
206  {
207    if (f->local_player())
208    {
209      f->suggest.cx1=(f->cx1-amount);
210      f->suggest.cy1=f->cy1-amount/2;
211      f->suggest.cx2=(f->cx2+amount);
212      f->suggest.cy2=f->cy2+amount/2;
213      f->suggest.shift_down=f->shift_down;
214      f->suggest.shift_right=f->shift_right;
215      f->suggest.pan_x=f->pan_x;
216      f->suggest.pan_y=f->pan_y;
217
218      f->suggest.send_view=1;
219    }
220  }
221
222
223  for (f=first_view;f;f=f->next) 
224  {
225    if (f->local_player())
226    {
227      if (f->suggest.cx2-f->suggest.cx1<20 || f->suggest.cy2-f->suggest.cy1<15 ||
228        f->suggest.cx1<0 || f->suggest.cy1<0) f->suggest.send_view=0;
229      if (f->next && f->next->local_player() && f->suggest.cy2>=f->next->cy1) f->suggest.send_view=0;
230    }
231  }
232}
233
234void game::pan(int xv, int yv)
235{
236  first_view->pan_x+=xv;
237  first_view->pan_y+=yv;
238}
239
240view *game::view_in(int mousex, int mousey)
241{
242  for (view *f=first_view;f;f=f->next)
243    if (f->drawable() && mousex>=f->cx1 && mousey>=f->cy1 && mousex<=f->cx2 && mousey<=f->cy2)
244      return f;
245  return NULL;
246}
247
248int playing_state(int state)
249{
250  if (state==RUN_STATE || state==PAUSE_STATE) return 1;
251  else return 0;
252}
253
254void game::ftile_on(int screenx, int screeny, long &x, long &y)
255{
256  mouse_to_game(screenx,screeny,x,y);
257  x/=ftile_width();
258  y/=ftile_height();
259/*  view *f=view_in(screenx,screeny);
260  if (f)
261  {
262    x=((long)(screenx)-(long)f->cx1+f->xoff())/(long)f_wid;
263    y=((long)(screeny)-(long)f->cy1+f->yoff())/(long)f_hi;
264  }
265  else
266  {
267    x=-1;
268    y=-1;
269  }*/
270}
271
272void game::btile_on(int screenx, int screeny, long &x, long &y)
273{
274  view *f=view_in(screenx,screeny);
275  if (f)
276  {
277    x=((long)(screenx)-(long)f->cx1+f->xoff()*bg_xmul/bg_xdiv)/(long)b_wid;
278    y=((long)(screeny)-(long)f->cy1+f->yoff()*bg_ymul/bg_ydiv)/(long)b_hi;
279  }
280  else
281  {
282    x=-1;
283    y=-1;
284  }
285}
286
287
288void game::mouse_to_game(long x, long y, long &gamex, long &gamey, view *f)
289{
290  if (!f)
291  {
292    f=view_in(x,y);
293    if (!f) f=player_list;  // if not in a view use the first on
294  }
295
296  if (f)
297  {
298
299      if (dev&MAP_MODE)
300      {
301        gamex=((x-(long)f->cx1)*ftile_width()/AUTOTILE_WIDTH+map_xoff*ftile_width());
302        gamey=((y-(long)f->cy1)*ftile_height()/AUTOTILE_HEIGHT+map_yoff*ftile_height());
303      } else
304      {
305        gamex=(x-(long)f->cx1+f->xoff());
306        gamey=(y-(long)f->cy1+f->yoff());
307      }
308
309  }
310
311}
312
313void game::game_to_mouse(long gamex, long gamey, view *which, long &x, long &y)
314{
315  if (dev&MAP_MODE)
316  {
317    long x1,y1;
318    if (dev&EDIT_MODE)
319    {
320      x1=map_xoff;
321      y1=map_yoff;
322    } else
323    {
324      if (which->focus)
325      {
326        x1=which->focus->x/ftile_width()-(which->cx2-which->cx1)/AUTOTILE_WIDTH/2;
327        y1=which->focus->y/ftile_height()-(which->cy2-which->cy1)/AUTOTILE_HEIGHT/2;
328      } else x1=y1=0;
329    }
330    if (x1<0) x1=0;
331    if (y1<0) y1=0;
332
333    x=gamex*AUTOTILE_WIDTH/ftile_width()-x1*AUTOTILE_WIDTH+which->cx1;
334    if (x1>0)
335      x-=((which->focus->x*AUTOTILE_WIDTH/ftile_width()) %AUTOTILE_WIDTH);
336
337    y=gamey*AUTOTILE_HEIGHT/ftile_height()-y1*AUTOTILE_HEIGHT+which->cy1;
338    if (y1>0)
339      y-=((which->focus->y*AUTOTILE_HEIGHT/ftile_height()) %AUTOTILE_HEIGHT);
340  }
341  else
342  {
343    x=gamex-which->xoff()+which->cx1;
344    y=gamey-which->yoff()+which->cy1;
345  }
346}
347
348int window_state(int state)
349{
350  switch (state)
351  {
352    case RUN_STATE :
353    case PAUSE_STATE :
354    case JOY_CALB_STATE :
355    { return 1; } break;
356
357    case INTRO_START_STATE :
358    case HELP_STATE :
359    case INTRO_MORPH_STATE :
360    case MENU_STATE :
361    case SCENE_STATE :
362    { return 0; } break;
363  }
364  return 1;
365}
366
367
368
369void game::set_state(int new_state)
370{
371  int d=0;
372  reset_keymap();                             // we think all the keys are up right now
373  if (playing_state(new_state) && !playing_state(state))
374  {
375    if (first_view && first_view!=player_list)
376    {
377      while (first_view)
378      {
379        view *tmp=first_view;
380        first_view=first_view->next;
381        delete tmp;
382      }
383      first_view=old_view;
384      old_view=NULL;
385    }
386    first_view=player_list;
387    d=1;
388  } else if (!playing_state(new_state) && (playing_state(state) || state==START_STATE))
389  {
390    if (player_list)   
391    {
392      first_view=new view(player_list->focus,NULL,-1);
393      first_view->pan_x=player_list->xoff();
394      first_view->pan_y=player_list->yoff();
395    }
396    else   
397      first_view=new view(NULL,NULL,0);
398    first_view->cx1=(xres+1)/2-155;
399    first_view->cy1=(yres+1)/2-95;
400    first_view->cx2=(xres+1)/2+155;
401    if (total_weapons)
402      first_view->cy2=(yres+1)/2+68;
403    else
404      first_view->cy2=(yres+1)/2+95;
405    d=1;
406  }
407 
408
409
410  // switching to/from scene mode cause the screen size to change and the border to change
411  // so we need to redraw.
412  if (window_state(new_state) && !window_state(state))
413    eh->show_windows();
414  else if (!window_state(new_state) && window_state(state))
415    eh->hide_windows();
416
417  int old_state=state;
418  state=new_state;
419
420  pal->load();    // restore old palette
421
422  if (playing_state(state) &&  !(dev&EDIT_MODE))
423    eh->set_mouse_shape(cash.img(c_target)->copy(),8,8);
424  else
425    eh->set_mouse_shape(cash.img(c_normal)->copy(),1,1);
426
427  if (old_state==SCENE_STATE && new_state!=SCENE_STATE)
428  {
429    d=1;
430    scene_director.set_abort(0);   // don't skip any more scene stuff
431  }
432  else if (new_state==SCENE_STATE && old_state!=SCENE_STATE)
433    d=1;
434 
435  if (d)
436    draw(state==SCENE_STATE);
437
438  dev_cont->set_state(new_state);
439}
440
441void game::joy_calb(event &ev)
442{
443  if (joy_win)   // make sure the joy stick calibration window is open
444  {
445   
446    if (ev.type==EV_SPURIOUS)   // spurious means we should update your status
447    {
448      int b1,b2,b3=0,x,y;
449      joy_status(b1,b2,b2,x,y);
450      int but=b1|b2|b3;
451      if (x>0) x=1; else if (x<0) x=-1;
452      if (y>0) y=1; else if (y<0) y=-1;
453      if (but) but=1;
454      int dx=WINDOW_FRAME_LEFT+20,dy=WINDOW_FRAME_TOP+5;
455      image *jim=cash.img(joy_picts[but*9+(y+1)*3+x+1]);
456      joy_win->screen->bar(dx,dy,dx+jim->width()+6,dy+jim->height()+6,eh->black());
457      jim->put_image(joy_win->screen,dx+3,dy+3);
458
459      if (but)
460        joy_calibrate();
461    } else if (ev.type==EV_MESSAGE && ev.message.id==JOY_OK)
462    {
463      eh->close_window(joy_win);
464      joy_win=NULL;
465      set_state(MENU_STATE);
466    }       
467  }
468}
469
470void game::menu_select(event &ev)
471{
472  state=DEV_MOUSE_RELEASE;
473  if (top_menu)
474  {
475/*    eh->push_event(new event(men_mess[((pick_list *)ev.message.data)->get_selection()],NULL));
476    eh->close_window(top_menu);
477    top_menu=NULL;*/
478  }
479}
480
481
482void game::show_help(char *st)
483{
484  strcpy(help_text,st);
485  help_text_frames=0; 
486  refresh=1;
487}
488
489void game::draw_value(image *screen, int x, int y, int w, int h, int val, int max)
490{
491  screen->bar(x,y,x+w-1,y+h,eh->dark_color());
492  screen->bar(x,y+1,x+w*val/max,y+h-1,eh->bright_color()); 
493}
494
495
496void game::set_level(level *nl)
497{
498  if (current_level)
499    delete current_level; 
500  current_level=nl;
501}
502
503void game::load_level(char *name)
504{
505  if (current_level)
506    delete current_level;
507
508  bFILE *fp=open_file(name,"rb");
509
510  if (fp->open_failure())
511  {
512    delete fp;
513    current_level=new level(100,100,name);
514    char msg[100];
515    sprintf(msg,symbol_str("no_file"),name);
516    show_help(msg);
517  }
518  else
519  {                           
520    spec_directory sd(fp); 
521
522    spec_entry *e=sd.find("Copyright 1995 Crack dot Com, All Rights reserved");
523    if (!e)
524    {
525      the_game->show_help(symbol_str("missing_c"));
526      current_level=new level(100,100,"untitled");
527      the_game->need_refresh();
528    }
529    else
530      current_level=new level(&sd,fp,name);
531    delete fp;
532  }
533 
534  base->current_tick=(current_level->tick_counter()&0xff);
535
536  current_level->level_loaded_notify();
537  the_game->help_text_frames=0; 
538
539}
540
541int game::done()
542{
543  return finished || (main_net_cfg && main_net_cfg->restart_state());
544
545}
546
547void game::end_session()
548{
549  finished=1;
550  if (main_net_cfg)
551  {
552    delete main_net_cfg;
553    main_net_cfg=NULL;
554  }
555}
556
557void game::put_block_fg(int x, int y, trans_image *im)
558{
559  for (view *f=first_view;f;f=f->next)
560  {
561    if (f->drawable())
562    {
563      int xoff=f->xoff(),yoff=f->yoff(),viewx1=f->cx1,viewy1=f->cy1,viewx2=f->cx2,viewy2=f->cy2;
564      if (xoff/ftile_width()>x || xoff/ftile_width()+(viewx2-viewx1)/ftile_width()+1<x ||
565          yoff/ftile_height()>y || yoff/ftile_height()+(viewy2-viewy1)/ftile_height()+1<y) return;
566      short cx1,cy1,cx2,cy2;
567      screen->get_clip(cx1,cy1,cx2,cy2);
568      screen->set_clip(viewx1,viewy1,viewx2,viewy2);
569      im->put_image(screen,(x-xoff/ftile_width())*ftile_width()+viewx1-xoff%ftile_width(),
570                    (y-yoff/ftile_height())*ftile_height()+viewy1-yoff%ftile_height());
571      screen->set_clip(cx1,cy1,cx2,cy2);
572    }
573  }
574}
575
576void game::put_block_bg(int x, int y, image *im)
577{
578  for (view *f=first_view;f;f=f->next)
579  {
580    if (f->drawable())
581    {
582      int xoff=f->xoff(),yoff=f->yoff(),viewx1=f->cx1,viewy1=f->cy1,viewx2=f->cx2,viewy2=f->cy2;
583      int xo=xoff*bg_xmul/bg_xdiv;
584      int yo=yoff*bg_ymul/bg_ydiv;
585     
586      if (xo/btile_width()>x || xo/btile_width()+(viewx2-viewx1)/btile_width()+1<x ||
587          yo/btile_height()>y || yo/btile_height()+(viewy2-viewy1)/btile_height()+1<y) return;
588      short cx1,cy1,cx2,cy2;
589      screen->get_clip(cx1,cy1,cx2,cy2);
590      screen->set_clip(viewx1,viewy1,viewx2,viewy2);
591      im->put_image(screen,(x-xo/btile_width())*btile_width()+viewx1-xo%btile_width(),
592                    (y-yo/btile_height())*btile_height()+viewy1-yo%btile_height(),0);
593      screen->set_clip(cx1,cy1,cx2,cy2);
594    }
595  }
596}
597
598int need_delay=1;
599
600void game::dev_scroll()
601{
602  need_delay=0;
603  if (dev)
604  {
605    int xmargin,ymargin;
606    if (xres>400)
607    {
608      xmargin=20;
609      ymargin=10;
610    }
611    else
612    {
613      xmargin=10;
614      ymargin=5;
615    }
616
617    int xs,ys;
618    if (mousex<xmargin &&  dev_cont->ok_to_scroll()) xs=-18;
619    else if (mousex>(screen->width()-xmargin) &&  dev_cont->ok_to_scroll()) xs=18;
620    else if (eh->key_pressed(JK_LEFT) && !last_input && !dev_cont->need_arrows())
621      xs=-18;
622    else if (eh->key_pressed(JK_RIGHT) && !last_input && !dev_cont->need_arrows())
623      xs=18;
624    else xs=0;
625             
626
627    if (mousey<ymargin && dev_cont->ok_to_scroll()) ys=-18;
628    else if (mousey>(screen->height()-ymargin) &&  dev_cont->ok_to_scroll()) ys=18;
629    else if (eh->key_pressed(JK_UP) && !last_input)
630      ys=-18;
631    else if (eh->key_pressed(JK_DOWN) && !last_input)
632      ys=18;
633    else ys=0;
634
635   
636    if (xs || ys)
637    {
638      need_delay=1;
639      if (dev&MAP_MODE)
640      {
641        map_xoff+=xs/2;
642        map_yoff+=ys/2;
643        if (map_xoff<0) map_xoff=0;
644        if (map_yoff<0) map_yoff=0;
645      }
646      else
647      {
648        for (view *v=first_view;v;v=v->next)
649        {
650          if (xs>=0 || v->xoff()>0)
651            v->pan_x+=xs;
652          if (ys>=0 || v->yoff()>0)
653            v->pan_y+=ys;
654        }
655      }
656      refresh=1;
657    }
658  }
659}
660
661void remap_area(image *screen, int x1, int y1, int x2, int y2, uchar *remap)
662{
663  uchar *sl=(uchar *)screen->scan_line(y1)+x1;
664  int x,y,a=screen->width()-(x2-x1+1);
665  uchar c;
666  for (y=y1;y<=y2;y++)
667  {
668    for (x=x1;x<=x2;x++)
669    {
670      c=*sl;
671      *(sl++)=remap[c];
672    }
673    sl+=a;
674  }
675}
676
677void post_render()
678{
679  if (DEFINEDP(symbol_function(l_post_render)))
680  {
681    screen->dirt_off();
682    clear_tmp();
683    eval_function((lisp_symbol *)l_post_render,NULL);
684    clear_tmp();
685    screen->dirt_on();
686  }
687}
688 
689void game::draw_map(view *v, int interpolate)
690{
691  foretile *ft;
692  backtile *bt;
693  int x1,y1,x2,y2,x,y,xo,yo,nxoff,nyoff;
694  short cx1,cy1,cx2,cy2;
695  screen->get_clip(cx1,cy1,cx2,cy2);
696
697  if (!current_level || state==MENU_STATE)
698  {
699    if (title_screen>=0)
700    {
701      if (state==SCENE_STATE)
702        screen->set_clip(v->cx1,v->cy1,v->cx2,v->cy2);       
703      image *tit=cash.img(title_screen);
704      tit->put_image(screen,screen->width()/2-tit->width()/2,
705                            screen->height()/2-tit->height()/2);
706      if (state==SCENE_STATE)
707        screen->set_clip(cx1,cy1,cx2,cy2);
708      eh->flush_screen();
709    }   
710    return ;
711  }
712
713  refresh=0; 
714
715
716  // save the dirty rect routines some work by markinging evrything in the
717  // view area dirty alreadt
718
719  if (small_render)
720    screen->add_dirty(v->cx1,v->cy1,(v->cx2-v->cx1+1)*2+v->cx1,v->cy1+(v->cy2-v->cy1+1)*2);   
721  else
722    screen->add_dirty(v->cx1,v->cy1,v->cx2,v->cy2);   
723
724  if (v->draw_solid!=-1)      // fill the screen and exit..
725  {
726    int c=v->draw_solid;
727    for (int y=v->cy1;y<=v->cy2;y++)
728      memset(screen->scan_line(y)+v->cx1,c,v->cx2-v->cx1+1);
729    v->draw_solid=-1;
730    return ;
731  }
732
733  long old_cx1,old_cy1,old_cx2,old_cy2;   // if we do a small render, we need to restore these
734  image *old_screen=NULL;
735  if (small_render && (dev&DRAW_LIGHTS))  // cannot do this if we skip lighting
736  {
737    old_cx1=v->cx1;
738    old_cy1=v->cy1;
739    old_cx2=v->cx2;
740    old_cy2=v->cy2;
741
742    v->cx1=0;
743    v->cy1=0;
744    v->cx2=small_render->width()-1;
745    v->cy2=small_render->height()-1;
746
747    old_screen=screen;
748    screen=small_render;
749  } else
750    screen->dirt_off();
751
752
753
754//  long max_xoff=(current_level->foreground_width()-1)*ftile_width()-(v->cx2-v->cx1+1);
755//  long max_yoff=(current_level->foreground_height()-1)*ftile_height()-(v->cy2-v->cy1+1);
756
757  long xoff,yoff;
758  if (interpolate)
759  {
760    xoff=v->interpolated_xoff();
761    yoff=v->interpolated_yoff();
762  } else
763  {
764    xoff=v->xoff();
765    yoff=v->yoff();
766  }
767
768//  if (xoff>max_xoff) xoff=max_xoff;
769//  if (yoff>max_yoff) yoff=max_yoff; 
770
771  current_vxadd=xoff-v->cx1;
772  current_vyadd=yoff-v->cy1;
773
774  screen->set_clip(v->cx1,v->cy1,v->cx2,v->cy2);
775
776  nxoff=xoff*bg_xmul/bg_xdiv;
777  nyoff=yoff*bg_ymul/bg_ydiv;
778
779//  long max_bg_xoff=(current_level->background_width())*btile_width()-(v->cx2-v->cx1+1);
780//  long max_bg_yoff=(current_level->background_height())*btile_height()-(v->cy2-v->cy1+1);
781//  if (nxoff>max_bg_xoff) nxoff=max_xoff;
782//  if (nyoff>max_bg_yoff) nyoff=max_yoff; 
783 
784 
785  x1=nxoff/btile_width(); y1=nyoff/btile_height();
786  x2=x1+(v->cx2-v->cx1+btile_width())/btile_width();
787  y2=y1+(v->cy2-v->cy1+btile_height())/btile_height();
788
789
790  xo=v->cx1-nxoff%btile_width();
791  yo=v->cy1-nyoff%btile_height();
792 
793  int xinc,yinc,draw_x,draw_y;
794
795
796  if (!(dev & MAP_MODE) && (dev & DRAW_BG_LAYER))
797  {
798    xinc=btile_width(); 
799    yinc=btile_height(); 
800   
801    int bh=current_level->background_height(),bw=current_level->background_width();
802    ushort *bl;
803    for (draw_y=yo,y=y1;y<=y2;y++,draw_y+=yinc)
804    {
805      if (y>=bh)
806        bl=NULL;
807      else
808        bl=current_level->get_bgline(y)+x1;
809
810      for (x=x1,draw_x=xo;x<=x2;x++,draw_x+=xinc)
811      {
812        if (x<bw && y<bh)
813        {
814          bt=get_bg(*bl);
815          bl++;
816        }
817        else bt=get_bg(0);
818
819        bt->im->put_image(screen,draw_x,draw_y);
820//        if (!(dev & EDIT_MODE) && bt->next)
821//        current_level->put_bg(x,y,bt->next);
822      }
823    }
824  }
825
826//  if (!(dev&EDIT_MODE))
827//    server_check();
828
829  uchar rescan=0; 
830
831    int fw,fh;
832
833    if (dev&MAP_MODE)
834    {
835      fw=AUTOTILE_WIDTH;
836      fh=AUTOTILE_HEIGHT;
837      if (dev&EDIT_MODE)
838      {
839        x1=map_xoff;
840        y1=map_yoff;
841      } else
842      {
843        if (v->focus)
844        {
845          x1=v->focus->x/ftile_width()-(v->cx2-v->cx1)/fw/2;
846          y1=v->focus->y/ftile_height()-(v->cy2-v->cy1)/fh/2;
847        } else x1=y1=0;
848      }
849      if (x1>0)
850        xo=v->cx1-((v->focus->x*fw/ftile_width()) %fw);
851      else xo=v->cx1;
852      if (y1>0)
853        yo=v->cy1-((v->focus->y*fh/ftile_height()) %fh);
854      else yo=v->cy1;
855    } else
856    {
857      fw=ftile_width();
858      fh=ftile_height();
859      x1=(xoff)/fw; y1=(yoff)/fh;
860      xo=v->cx1-xoff%fw;
861      yo=v->cy1-yoff%fh;
862
863    }
864    if (x1<0) x1=0;
865    if (y1<0) y1=0;
866   
867    x2=x1+(v->cx2-v->cx1+fw)/fw;
868    y2=y1+(v->cy2-v->cy1+fh)/fh;
869    if (x2>=current_level->foreground_width())
870      x2=current_level->foreground_width()-1;
871    if (y2>=current_level->foreground_height())
872      y2=current_level->foreground_height()-1;
873
874
875    xinc=fw;
876    yinc=fh;
877
878  if (dev & DRAW_FG_LAYER)
879  {
880    short ncx1,ncy1,ncx2,ncy2;
881    screen->get_clip(ncx1,ncy1,ncx2,ncy2);
882
883    int scr_w=screen->width();
884    if (dev&MAP_MODE)
885    {
886      if (dev&EDIT_MODE)
887        screen->clear(eh->bright_color());
888      else
889        screen->clear(eh->black());
890      for (y=y1,draw_y=yo;y<=y2;y++,draw_y+=yinc)
891      {
892        if (!(draw_y<ncy1 ||draw_y+yinc>=ncy2))
893        {
894          ushort *cl=current_level->get_fgline(y)+x1;
895          uchar *sl1=screen->scan_line(draw_y)+xo;
896          for (x=x1,draw_x=xo;x<=x2;x++,cl++,sl1+=xinc,draw_x+=xinc)
897          {
898            if (!(draw_x<ncx1 || draw_x+xinc>=ncx2))
899            {
900              int fort_num;
901//            if (*cl&0x8000 || (dev&EDIT_MODE))
902                fort_num=fgvalue(*cl);
903//            else fort_num=0;
904
905              uchar *sl2=get_fg(fort_num)->micro_image->scan_line(0);
906              uchar *sl3=sl1;
907              memcpy(sl3,sl2,AUTOTILE_WIDTH); sl2+=AUTOTILE_WIDTH; sl3+=scr_w;
908              memcpy(sl3,sl2,AUTOTILE_WIDTH); sl2+=AUTOTILE_WIDTH; sl3+=scr_w;
909              memcpy(sl3,sl2,AUTOTILE_WIDTH);
910            }
911          }
912        }
913      }
914
915      if (dev&EDIT_MODE)
916        current_level->draw_areas(v);
917    } else
918    {
919
920      int fg_h=current_level->foreground_height(),fg_w=current_level->foreground_width();
921     
922      for (y=y1,draw_y=yo;y<=y2;y++,draw_y+=yinc)
923      {
924       
925        ushort *cl;
926        if (y<fg_h)
927          cl=current_level->get_fgline(y)+x1;
928        else cl=NULL;
929        uchar *sl1=draw_y<ncy1 ? 0 : screen->scan_line(draw_y)+xo;
930
931        for (x=x1,draw_x=xo;x<=x2;x++,draw_x+=xinc,cl++,sl1+=xinc)
932        {
933          if (x<fg_w && y<fg_h)
934          {
935            if (above_tile(*cl))
936            rescan=1;
937            else
938            {
939              int fort_num=fgvalue(*cl);         
940              if (fort_num!=BLACK)
941              {
942                if (draw_y<ncy1 || draw_y+yinc>=ncy2 || draw_x<ncx1 || draw_x+xinc>=ncx2)
943                get_fg(fort_num)->im->put_image(screen,draw_x,draw_y);
944                else
945                get_fg(fort_num)->im->put_image_offseted(screen,sl1);
946
947                if (!(dev & EDIT_MODE))
948                *cl|=0x8000;      // mark as has-been-seen
949              }
950            }
951          }
952        }
953      } 
954    }
955/*        if (dev==0)
956          current_level->put_fg(x,y,ft->next);  */       
957  }
958
959//  if (!(dev&EDIT_MODE))
960//    server_check();
961
962  long ro=rand_on;
963  if (dev & DRAW_PEOPLE_LAYER)
964  {
965    if (interpolate)
966      current_level->interpolate_draw_objects(v);
967    else
968      current_level->draw_objects(v);
969  }
970
971//  if (!(dev&EDIT_MODE))
972//    server_check();
973
974  if (!(dev&MAP_MODE))
975  {
976
977    draw_panims(v);
978
979    int fg_h=current_level->foreground_height(),fg_w=current_level->foreground_width();
980
981    if (dev & DRAW_FG_LAYER && rescan)
982    {
983      for (y=y1,draw_y=yo;y<=y2;y++,draw_y+=yinc)
984      {
985        ushort *cl=current_level->get_fgline(y)+x1;
986        for (x=x1,draw_x=xo;x<=x2;x++,draw_x+=xinc,cl++)
987        {
988          if (above_tile(*cl))
989          {
990            int fort_num=fgvalue(*cl);   
991            if (fort_num!=BLACK)
992            {
993              if (dev & DRAW_BG_LAYER)
994              get_fg(fort_num)->im->put_image(screen,draw_x,draw_y);
995              else
996              get_fg(fort_num)->im->put_image_filled(screen,draw_x,draw_y,0);
997
998              if (!(dev & EDIT_MODE))
999              current_level->mark_seen(x,y);
1000              else
1001              {
1002                screen->line(draw_x,draw_y,draw_x+xinc,draw_y+yinc,eh->bright_color());
1003                screen->line(draw_x+xinc,draw_y,draw_x,draw_y+yinc,eh->bright_color());
1004              }
1005            }   
1006          }
1007        }
1008      }   
1009    }
1010
1011   
1012    if (dev & DRAW_FG_BOUND_LAYER)
1013    {
1014      int b=eh->bright_color();
1015      int fg_h=current_level->foreground_height(),fg_w=current_level->foreground_width();
1016
1017      for (y=y1,draw_y=yo;y<=y2;y++,draw_y+=yinc)
1018      {
1019        ushort *cl;
1020        if (y<fg_h)
1021          cl=current_level->get_fgline(y)+x1;
1022        else cl=NULL;
1023        for (x=x1,draw_x=xo;x<=x2;x++,draw_x+=xinc,cl++)
1024        {
1025          if (x<fg_w && y<fg_h)
1026          {
1027            int fort_num=fgvalue(*cl);   
1028            if (fort_num!=BLACK)
1029            {
1030              point_list *p=get_fg(fort_num)->points;
1031              uchar *d=p->data;
1032              if (p->tot)
1033              {
1034                for (int i=1;i<p->tot;i++)
1035                {
1036                  d+=2;
1037                  screen->line(draw_x+*(d-2),draw_y+*(d-1),draw_x+*d,draw_y+*(d+1),b);
1038                }
1039                screen->line(draw_x+*d,draw_y+*(d-1),draw_x+p->data[0],draw_y+p->data[1],b);
1040              }
1041            }
1042          }
1043        }
1044      }
1045    }
1046
1047//    if (!(dev&EDIT_MODE))
1048//      server_check();
1049
1050    if (dev & DRAW_HELP_LAYER)
1051    {
1052      if (help_text_frames>=0)
1053      {
1054        int color;
1055       
1056        if (help_text_frames<10)
1057        color=2;
1058        else
1059        color=2+(help_text_frames-10);
1060       
1061        int x1=v->cx1,y1=v->cy1,x2=v->cx2,y2=v->cy1+eh->font()->height()+10;
1062
1063        remap_area(screen,x1,y1,x2,y2,white_light+40*256);
1064        screen->bar(x1,y1,x2,y1,color);
1065        screen->bar(x1,y2,x2,y2,color);
1066
1067        eh->font()->put_string(screen,x1+5,y1+5,
1068                               help_text,color);
1069        if (color>30)
1070        help_text_frames=-1;     
1071        else help_text_frames++;
1072       
1073      }   
1074    }
1075   
1076    if (dev_cont)
1077    dev_cont->dev_draw(v); 
1078    if (cash.in_use())
1079    cash.img(vmm_image)->put_image(screen,v->cx1,v->cy2-cash.img(vmm_image)->height()+1); 
1080
1081    if (dev&DRAW_LIGHTS)
1082    { 
1083      if (small_render)
1084      {
1085        double_light_screen(screen,xoff,yoff,white_light,v->ambient,old_screen,old_cx1,old_cy1);
1086
1087        v->cx1=old_cx1;
1088        v->cy1=old_cy1;
1089        v->cx2=old_cx2;
1090        v->cy2=old_cy2;
1091        screen=old_screen;
1092      } else
1093      {     
1094        screen->dirt_on();
1095        if (xres*yres<=64000)
1096          light_screen(screen,xoff,yoff,white_light,v->ambient);
1097        else light_screen(screen,xoff,yoff,white_light,63);            // no lighting for hi-rez
1098      }
1099
1100    } else
1101      screen->dirt_on();
1102
1103
1104
1105  }  else
1106    screen->dirt_on();
1107
1108  rand_on=ro;                // restore random start in case in draw funs moved it
1109                               // ... not every machine will draw the same thing
1110
1111  post_render();
1112
1113  screen->set_clip(cx1,cy1,cx2,cy2);
1114   
1115
1116
1117
1118  if (playing_state(state))        // draw stuff outside the clipping region
1119    v->draw_character_damage();
1120
1121  if (profiling())
1122    profile_update();
1123
1124  sbar.draw_update();
1125}
1126
1127void game::put_fg(int x, int y, int type)
1128{
1129  if (current_level->get_fg(x,y)!=type)
1130  {
1131    current_level->put_fg(x,y,type);
1132    for (view *f=first_view;f;f=f->next)
1133      if (f->drawable())
1134        draw_map(f);   
1135/*    put_block_bg(x,y,get_bg(current_level->get_bg(x/ASPECT,y/ASPECT))->im);
1136    if (type>BLACK)
1137      put_block_fg(x,y,get_fg(type)->im); */
1138  }
1139}
1140
1141void game::put_bg(int x, int y, int type)
1142{
1143  if (current_level->get_bg(x,y)!=type)
1144  {
1145    current_level->put_bg(x,y,type);
1146    for (view *f=first_view;f;f=f->next)
1147      if (f->drawable())
1148        draw_map(f);   
1149/*    put_block_bg(x,y,get_bg(type)->im);
1150    if (current_level->get_fg(x,y)>BLACK)
1151      put_block_fg(x,y,get_fg(current_level->get_fg(x,y))->im);*/
1152  }
1153}
1154
1155int game::in_area(event &ev, int x1, int y1, int x2, int y2)
1156{
1157  return (last_demo_mx>=x1 && last_demo_mx<=x2 &&
1158          last_demo_my>=y1 && last_demo_my<=y2);
1159}
1160
1161void game::request_level_load(char *name)
1162{
1163  strcpy(req_name,name);
1164}
1165
1166extern int start_doubled;
1167
1168void fade_in(image *im, int steps)
1169{
1170  palette *old_pal=pal->copy();
1171  int i;
1172  if (im)
1173  {
1174    screen->clear();
1175    im->put_image(screen,(xres+1)/2-im->width()/2,(yres+1)/2-im->height()/2);
1176  }
1177
1178  for (i=0;i<steps;i++)
1179  {
1180    uchar *sl1=(uchar *)pal->addr();   
1181    uchar *sl2=(uchar *)old_pal->addr();   
1182    int j;
1183    int r,g,b;
1184    int v=(i+1)*256/steps;
1185    for (j=0;j<256;j++)
1186    {
1187      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1188      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1189      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1190    }
1191    pal->load();
1192    eh->flush_screen();
1193    milli_wait(25);
1194  }
1195  delete pal;
1196  pal=old_pal;
1197}
1198
1199void fade_out(int steps)
1200{
1201  palette *old_pal=pal->copy();
1202  int i;
1203  for (i=0;i<steps;i++)
1204  {
1205    uchar *sl1=(uchar *)pal->addr();   
1206    uchar *sl2=(uchar *)old_pal->addr();   
1207    int j;
1208    int r,g,b;
1209    int v=(steps-i)*256/steps;
1210    for (j=0;j<256;j++)
1211    {
1212      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1213      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1214      *(sl1)=((int)*(sl2))*v/256;  sl1++; sl2++;
1215    }
1216    pal->load();
1217    eh->flush_screen();
1218    milli_wait(25);
1219  }
1220  screen->clear();
1221  eh->flush_screen();
1222  delete pal;
1223  pal=old_pal;
1224 
1225  pal->load();
1226}
1227
1228int text_draw(int y, int x1, int y1, int x2, int y2, char *buf, JCFont *font, uchar *cmap, char color);
1229
1230void do_title()
1231{
1232  if (cdc_logo!=-1)
1233  {
1234    if (sound_avail&MUSIC_INITIALIZED)
1235    {
1236      if (current_song) { current_song->stop(); delete current_song; }
1237      current_song=new song("music/intro.hmi");
1238      current_song->play(music_volume);
1239    }
1240
1241    void *logo_snd=symbol_value(make_find_symbol("LOGO_SND"));
1242
1243    if (DEFINEDP(logo_snd) && (sound_avail&SFX_INITIALIZED))
1244      cash.sfx(lnumber_value(logo_snd))->play(sfx_volume);
1245
1246    image blank(2,2); blank.clear();
1247    eh->set_mouse_shape(blank.copy(),0,0);      // don't show mouse
1248    fade_in(cash.img(cdc_logo),32);
1249   
1250    milli_wait(900);
1251
1252    void *space_snd=symbol_value(make_find_symbol("SPACE_SND"));
1253
1254    fade_out(32);
1255    milli_wait(300);
1256
1257    int i,abort=0;
1258    char *str=lstring_value(eval(make_find_symbol("plot_start")));
1259   
1260    bFILE *fp=open_file("art/smoke.spe","rb");
1261    if (!fp->open_failure())
1262    {
1263      spec_directory sd(fp);
1264      palette *old_pal=pal;
1265      pal=new palette(sd.find(SPEC_PALETTE),fp);
1266      pal->shift(1);
1267
1268      image *gray=new image(sd.find("gray_pict"),fp);
1269      image *smoke[5];
1270
1271      char nm[20];
1272      for (i=0;i<5;i++)
1273      {
1274        sprintf(nm,"smoke%04d.pcx",i+1);
1275        smoke[i]=new image(sd.find(nm),fp);
1276      }
1277
1278      screen->clear();
1279      pal->load();
1280
1281      int dx=(xres+1)/2-gray->width()/2,dy=(yres+1)/2-gray->height()/2;
1282      gray->put_image(screen,dx,dy);
1283      smoke[0]->put_image(screen,dx+24,dy+5);
1284
1285      fade_in(NULL,16);
1286      uchar cmap[32];
1287      for (i=0;i<32;i++)
1288        cmap[i]=pal->find_closest(i*256/32,i*256/32,i*256/32);
1289
1290      event ev; ev.type=EV_SPURIOUS;
1291      time_marker start;
1292
1293
1294      for (i=0;i<320 && ev.type!=EV_KEY;i++)
1295      {
1296        gray->put_image(screen,dx,dy);
1297        smoke[i%5]->put_image(screen,dx+24,dy+5);
1298        text_draw(205-i,dx+15,dy,dx+320-15,dy+199,str,eh->font(),cmap,eh->bright_color());
1299        eh->flush_screen();
1300        time_marker now;
1301        while (now.diff_time(&start)<0.18)
1302          now.get_time();
1303        start.get_time();
1304
1305        while (eh->event_waiting() && ev.type!=EV_KEY) eh->get_event(ev);
1306        if ((i%5)==0 && DEFINEDP(space_snd) && (sound_avail&SFX_INITIALIZED))
1307          cash.sfx(lnumber_value(space_snd))->play(sfx_volume*90/127);
1308
1309      }
1310
1311      the_game->reset_keymap();
1312
1313      fade_out(16);
1314
1315      for (i=0;i<5;i++) delete smoke[i];
1316      delete gray;
1317
1318      delete pal;
1319      pal=old_pal;
1320    }
1321    delete fp;
1322
1323    for (i=0;i<100 && !abort;i++)
1324    {
1325     
1326    }
1327
1328
1329
1330    if (title_screen>=0)
1331      fade_in(cash.img(title_screen),32);
1332
1333    eh->set_mouse_shape(cash.img(c_normal)->copy(),1,1);
1334  }
1335}
1336
1337extern int start_edit;
1338
1339void game::request_end()
1340{
1341  req_end=1;
1342}
1343
1344extern void fast_load_start_recording(char *name);
1345extern void fast_load_stop_recording();
1346extern void fast_load_start_reloading(char *name);
1347extern void fast_load_stop_reloading();
1348
1349game::game(int argc, char **argv)
1350{
1351  int i;
1352  req_name[0]=0;
1353  bg_xmul=bg_ymul=1;
1354  bg_xdiv=bg_ydiv=8;
1355  last_input=NULL;
1356  current_automap=NULL;
1357  current_level=NULL;
1358  refresh=1; 
1359  the_game=this; 
1360  top_menu=joy_win=NULL;
1361  old_view=first_view=NULL;
1362  nplayers=1;
1363
1364  help_text_frames=0; 
1365  strcpy(help_text,"");
1366
1367 
1368  for (i=1;i<argc;i++)
1369    if (!strcmp(argv[i],"-no_delay"))
1370    {
1371      no_delay=1;
1372      dprintf("Frame delay off (-nodelay)\n");
1373    }
1374
1375 
1376  image_init(); 
1377  zoom=15; 
1378  no_delay=0;
1379
1380  if (get_option("-use_joy")) 
1381  {
1382    has_joystick=joy_init(argc,argv);
1383    dprintf("Joystick : ");
1384    if (has_joystick) dprintf("detected\n");
1385    else dprintf("not detected\n");
1386  }
1387  else has_joystick=0;
1388
1389//      ProfilerInit(collectDetailed, bestTimeBase, 2000, 200); //prof
1390        fast_load_start_recording("fastload.dat");
1391  load_data(argc,argv); 
1392        fast_load_stop_recording();
1393//      ProfilerDump("\pabuse.prof");  //prof   
1394//      ProfilerTerm();
1395
1396  get_key_bindings();
1397
1398  reset_keymap();                   // we think all the keys are up right now
1399  finished=0;
1400
1401  calc_light_table(pal);
1402
1403  if (current_level==NULL && net_start())  // if we joined a net game get level from server
1404  {
1405    if (!request_server_entry())
1406    {
1407      exit(0);
1408    }
1409    net_reload();
1410//    load_level(NET_STARTFILE);
1411  }
1412
1413
1414  set_mode(19,argc,argv);
1415  if (get_option("-2") && (xres<639 || yres<399))
1416  {
1417    close_graphics();
1418    fprintf(stderr,"Resolution must be > 640x400 to use -2 option\n");   
1419    exit(0);
1420  }
1421  pal->load();
1422 
1423  recalc_local_view_space();   // now that we know what size the screen is...
1424
1425  dark_color=get_color(cash.img(window_colors)->pixel(2,0));
1426  bright_color=get_color(cash.img(window_colors)->pixel(0,0));
1427  med_color=get_color(cash.img(window_colors)->pixel(1,0));
1428
1429  morph_dark_color=get_color(cash.img(window_colors)->pixel(2,1));
1430  morph_bright_color=get_color(cash.img(window_colors)->pixel(0,1));
1431  morph_med_color=get_color(cash.img(window_colors)->pixel(1,1));
1432  morph_sel_frame_color=pal->find_closest(255,255,0);
1433  light_connection_color=morph_sel_frame_color;
1434
1435  if (NILP(symbol_value(l_default_font)))
1436  {
1437    printf("No font defined, set symbol default-font to an image name\n");
1438    exit(0);
1439  }
1440  int font_pict;
1441  if (big_font_pict!=-1)
1442  {
1443    if (small_font_pict!=-1)
1444    {
1445      if (xres/(start_doubled ? 2 : 1)>400)
1446      {
1447        font_pict=big_font_pict;
1448      }
1449      else font_pict=small_font_pict;
1450    } else font_pict=big_font_pict;
1451  } else font_pict=small_font_pict;
1452 
1453  if (console_font_pict==-1) console_font_pict=font_pict;
1454  game_font=new JCFont(cash.img(font_pict));
1455
1456  console_font=new JCFont(cash.img(console_font_pict));
1457
1458  eh=new window_manager(screen,pal,bright_color,
1459                                   med_color,
1460                                   dark_color,
1461                                   game_font); 
1462
1463  delete stat_man;  // move to a graphical status manager
1464  gui_status_manager *gstat=new gui_status_manager(eh);
1465  gstat->set_window_title("status");
1466  stat_man=gstat;
1467
1468
1469  chat=new chat_console(eh,console_font,50,6);
1470
1471  if (!eh->has_mouse())
1472  {
1473    close_graphics();
1474    image_uninit();
1475    printf("No mouse driver detected, please rectify.\n");
1476    exit(0);
1477  }
1478
1479
1480  gamma_correct(pal);
1481
1482  if (main_net_cfg==NULL || (main_net_cfg->state!=net_configuration::SERVER &&
1483                             main_net_cfg->state!=net_configuration::CLIENT))
1484  {
1485    if (!start_edit && !net_start())
1486      do_title();
1487  } else if (main_net_cfg && main_net_cfg->state==net_configuration::SERVER)
1488  {
1489    the_game->load_level(level_file);
1490    start_running=1;
1491  }
1492   
1493
1494  dev|= DRAW_FG_LAYER | DRAW_BG_LAYER | DRAW_PEOPLE_LAYER | DRAW_HELP_LAYER | DRAW_LIGHTS | DRAW_LINKS;
1495
1496  if (dev & EDIT_MODE)
1497    set_frame_size(0);
1498//  do_intro();
1499  state=START_STATE;         // first set the state to one that has windows
1500
1501
1502  if (start_running)
1503    set_state(RUN_STATE);
1504  else
1505  {
1506    screen->clear(); 
1507    if (title_screen>=0)
1508    {
1509      image *tit=cash.img(title_screen);
1510      tit->put_image(screen,screen->width()/2-tit->width()/2,
1511                            screen->height()/2-tit->height()/2);
1512    }   
1513    set_state(MENU_STATE);   // then go to menu state so windows will turn off
1514  }
1515}
1516
1517
1518
1519time_marker *led_last_time=NULL,*fps_mark_start=NULL;
1520double avg_fps=15.0,possible_fps=15.0;
1521
1522void game::toggle_delay()
1523{
1524  no_delay=!no_delay;
1525  if (no_delay)
1526    show_help(symbol_str("delay_off"));
1527  else show_help(symbol_str("delay_on"));
1528  avg_fps=possible_fps=15.0;
1529}
1530
1531void game::show_time()
1532{
1533  if (first_view && fps_on)
1534  {
1535    char str[10];
1536    sprintf(str,"%d",(long)(avg_fps*10.0));
1537    console_font->put_string(screen,first_view->cx1,first_view->cy1,str);
1538
1539    sprintf(str,"%d",total_active);
1540    console_font->put_string(screen,first_view->cx1,first_view->cy1+10,str);
1541  }
1542}
1543
1544void game::update_screen()
1545{
1546  if (state==HELP_STATE)
1547    draw_help();
1548  else if (current_level)
1549  {   
1550    if (!(dev & EDIT_MODE) || refresh)   
1551    {   
1552      view *f=first_view;
1553      current_level->clear_active_list();
1554      for (;f;f=f->next)
1555      {
1556        if (f->focus)           
1557        {
1558          int w,h;
1559
1560          w=(f->cx2-f->cx1+1);
1561          h=(f->cy2-f->cy1+1);
1562
1563          total_active+=current_level->add_drawables(f->xoff()-w/4,f->yoff()-h/4,
1564                                                     f->xoff()+w+w/4,f->yoff()+h+h/4);
1565
1566        }
1567      }
1568
1569      for (f=first_view;f;f=f->next)
1570      {
1571        if (f->drawable())
1572        {
1573          if (interpolate_draw)
1574          {
1575            draw_map(f,1);
1576            eh->flush_screen();
1577          }
1578          draw_map(f,0);
1579        }
1580      }
1581      if (current_automap)
1582      current_automap->draw();
1583    } 
1584    if (state==PAUSE_STATE)
1585    {
1586      for (view *f=first_view;f;f=f->next)
1587        cash.img(pause_image)->put_image(screen,(f->cx1+f->cx2)/2-cash.img(pause_image)->width()/2,
1588                               f->cy1+5,1);
1589    }
1590   
1591    show_time();
1592  }
1593
1594  if (state==RUN_STATE && cash.prof_is_on())
1595    cash.prof_poll_end();
1596
1597  eh->flush_screen();
1598
1599}
1600
1601void game::do_intro()
1602{
1603
1604}
1605
1606int game::calc_speed()
1607{
1608  int ret=0;
1609  if (fps_mark_start)
1610  {
1611
1612    time_marker t;
1613
1614    // find average fps for last 10 frames
1615    double td=t.diff_time(fps_mark_start);
1616    if (td<0.001)     // something is rotten in the state of demark
1617      td=0.001;
1618
1619    avg_fps=avg_fps*9.0/10.0+1.0/(td*10.0); 
1620    possible_fps=possible_fps*9.0/10.0+1.0/(td*10.0); 
1621
1622    if (avg_fps>14)
1623    {
1624      if (massive_frame_panic>20)
1625        massive_frame_panic=20;
1626      else if (massive_frame_panic)
1627        massive_frame_panic--;
1628    }
1629
1630    if (avg_fps>15 && ((dev&EDIT_MODE)==0 || need_delay))
1631    {
1632      frame_panic=0;
1633      long stime=(long)((1/15.0-1.0/possible_fps)*1000.0);
1634      if (stime>0 && !no_delay)
1635      {
1636        milli_wait(stime);
1637        avg_fps-=1.0/(td*10.0);        // subtract out old estimate
1638
1639        time_marker t;
1640       
1641        // find average fps for last 10 frames
1642        double td=t.diff_time(fps_mark_start);
1643        if (td<0.00001)     // something is rotten in the state of demark
1644          td=0.00001;
1645
1646        avg_fps+=1.0/(td*10.0);       // add in new estimate
1647      }
1648    } else if (avg_fps<14)
1649    {
1650      if (avg_fps<10)
1651        massive_frame_panic++;
1652      frame_panic++;
1653      ret=1;
1654    }
1655   
1656    delete fps_mark_start;   
1657  }
1658  fps_mark_start=new time_marker;
1659  return ret;
1660}
1661
1662extern int start_edit;
1663
1664void single_render();
1665void double_render();
1666
1667void game::get_input()
1668{
1669  event ev; 
1670  idle_ticks++;
1671  while (event_waiting(eh))
1672  {
1673    get_event(ev,eh);
1674
1675    if (ev.type==EV_MOUSE_MOVE) last_input=ev.window;
1676    // don't process repeated keys in the main window, it will slow down the game handle such
1677    // useless events. However in other windows it might be useful, such as in input windows
1678    // where you want to repeatedly scroll down..
1679    if (ev.type!=EV_KEY || !key_down(ev.key) || ev.window || (dev&EDIT_MODE))
1680    {
1681      if (ev.type==EV_KEY)     
1682      {
1683        set_key_down(ev.key,1);
1684        if (playing_state(state))
1685        {       
1686          if (ev.key<256)
1687          {
1688            if (chat && chat->chat_event(ev))
1689              base->packet.write_byte(SCMD_CHAT_KEYPRESS);
1690            else
1691              base->packet.write_byte(SCMD_KEYPRESS);
1692          }
1693          else
1694            base->packet.write_byte(SCMD_EXT_KEYPRESS);
1695          base->packet.write_byte(client_number());
1696          if (ev.key>256)
1697            base->packet.write_byte(ev.key-256);
1698          else
1699            base->packet.write_byte(ev.key);     
1700        }
1701      }
1702      else if (ev.type==EV_KEYRELEASE)
1703      {
1704        set_key_down(ev.key,0);
1705        if (playing_state(state))
1706        {       
1707          if (ev.key<256)
1708            base->packet.write_byte(SCMD_KEYRELEASE);
1709          else
1710            base->packet.write_byte(SCMD_EXT_KEYRELEASE);
1711          base->packet.write_byte(client_number());
1712          if (ev.key>255)
1713            base->packet.write_byte(ev.key-256);
1714          else
1715            base->packet.write_byte(ev.key);     
1716        }       
1717      }
1718     
1719      if ((dev&EDIT_MODE) || start_edit || ev.type==EV_MESSAGE)
1720        dev_cont->handle_event(ev);
1721
1722      view *v=first_view;
1723      for (;v;v=v->next)
1724        if (v->local_player() && v->handle_event(ev))
1725          ev.type=EV_SPURIOUS;       // if the event was used by the view, gobble it up
1726
1727
1728      if (current_automap)
1729        current_automap->handle_event(ev);
1730     
1731      help_handle_event(ev);   
1732      mousex=last_demo_mx;
1733      mousey=last_demo_my;
1734
1735      if (ev.type==EV_MESSAGE)
1736      {
1737        switch (ev.message.id)
1738        {
1739          case CALB_JOY :
1740          {
1741            if (!joy_win)
1742            {
1743              int wx=WINDOW_FRAME_LEFT,wy=WINDOW_FRAME_TOP;
1744             
1745              joy_win=eh->new_window(80,50,-1,-1,
1746                                     new button(wx+70,wy+9,JOY_OK,"OK",
1747                                     new info_field(wx,wy+30,DEV_NULL,
1748                                                    " Center joystick and\n"
1749                                                    "press the fire button",NULL)),
1750
1751                                     "Joystick");
1752              set_state(JOY_CALB_STATE);
1753            }
1754          }
1755          case TOP_MENU :
1756          { menu_select(ev); } break;
1757          case DEV_QUIT :
1758          { finished=1; } break;
1759
1760        }
1761      }     
1762      else if (ev.type==EV_CLOSE_WINDOW && ev.window==top_menu)
1763      {
1764        eh->close_window(top_menu);
1765        top_menu=NULL;
1766      }
1767   
1768      switch (state)
1769      {
1770        case JOY_CALB_STATE :
1771        { joy_calb(ev); } break;
1772        case INTRO_START_STATE :
1773        { do_intro();
1774          if (dev & EDIT_MODE)
1775            set_state(RUN_STATE);
1776          else
1777            set_state(MENU_STATE);
1778        } break;     
1779        case PAUSE_STATE : if (ev.type==EV_KEY && (ev.key==JK_SPACE || ev.key==JK_ENTER))
1780                                { set_state(RUN_STATE); } break;
1781        case RUN_STATE :
1782        {
1783          if (ev.window==NULL)
1784          {
1785         
1786          switch (ev.type)
1787          {
1788            case EV_KEY :
1789              { switch (ev.key)
1790                {
1791                  case 'm' :
1792                  {
1793                    if (dev&MAP_MODE) dev-=MAP_MODE;
1794                    else if ((player_list && player_list->next) || dev&EDIT_MODE) dev|=MAP_MODE;
1795
1796                    if (!(dev&MAP_MODE))
1797                    {
1798                      if (dev_cont->tbw) dev_cont->toggle_toolbar();
1799                      edit_mode=ID_DMODE_DRAW;
1800                    }
1801                    need_refresh();     
1802                  } break;
1803                  case 'v' :
1804                  { eh->push_event(new event(DO_VOLUME,NULL)); } break;
1805                  case 'p' :
1806                  { if (!(dev&EDIT_MODE) && (!main_net_cfg ||
1807                                             (main_net_cfg->state!=net_configuration::SERVER &&
1808                                              main_net_cfg->state!=net_configuration::CLIENT))) 
1809                    set_state(PAUSE_STATE);
1810                  } break;
1811                  case 'S' :
1812                  if (start_edit)
1813                  { eh->push_event(new event(ID_LEVEL_SAVE,NULL)); } break;
1814                  case JK_TAB :
1815                  { if (start_edit) toggle_edit_mode(); need_refresh(); } break;
1816                  case 'c' :             
1817                  { if (chatting_enabled && (!(dev&EDIT_MODE) && chat))
1818                      chat->toggle();
1819                  } break;
1820                  case '9' :
1821                  { dev=dev^PERFORMANCE_TEST_MODE; need_refresh(); } break;
1822
1823/*
1824                  case '=' :
1825                  case '+' :
1826                  { if (!dev_cont->need_plus_minus())
1827                    {
1828                      if (eh->key_pressed(JK_CTRL_L))
1829                        grow_views(20);
1830                      else
1831                        grow_views(5);
1832                      draw(state==SCENE_STATE);
1833                    }
1834                  } break;
1835                  case JK_F10 : make_screen_size(311,160); break;
1836                  case '_' :
1837                  case '-' :
1838                  {
1839                    if (!dev_cont->need_plus_minus())               
1840                    {
1841                      if (eh->key_pressed(JK_CTRL_L))
1842                        grow_views(-20);
1843                      else
1844                        grow_views(-5);
1845                      draw(state==SCENE_STATE);
1846                    }
1847                  } break; */
1848
1849                }
1850              } break;           
1851              case EV_RESIZE :
1852              {
1853                view *v;
1854                for (v=first_view;v;v=v->next)  // see if any views need to change size
1855                {
1856                  if (v->local_player())
1857                  {
1858                    int w=(xres-10)/(small_render ? 2 : 1);
1859                    int h=(yres-10)/(small_render ? 2 : 1);
1860
1861                    v->suggest.send_view=1;
1862                    v->suggest.cx1=5;
1863                    v->suggest.cx2=5+w;
1864                    v->suggest.cy1=5;
1865                    v->suggest.cy2=5+h;
1866                    v->suggest.pan_x=v->pan_x;
1867                    v->suggest.pan_y=v->pan_y;
1868                    v->suggest.shift_down=v->shift_down;
1869                    v->suggest.shift_right=v->shift_right;
1870                  }               
1871                }
1872                draw();
1873              } break;
1874              case EV_REDRAW : screen->add_dirty(ev.redraw.x1,ev.redraw.y1,
1875                                               ev.redraw.x2,ev.redraw.y2); break;
1876              case EV_MESSAGE :     
1877                switch (ev.message.id)
1878                {
1879                  case RAISE_SFX :
1880                  case LOWER_SFX :
1881                  case RAISE_MUSIC :
1882                  case LOWER_MUSIC :
1883                    if (ev.message.id==RAISE_SFX && sfx_volume!=127) sfx_volume=min(127,sfx_volume+16);
1884                    if (ev.message.id==LOWER_SFX && sfx_volume!=0) sfx_volume=max(sfx_volume-16,0);
1885                    if (ev.message.id==RAISE_MUSIC && music_volume!=126)
1886                    {               
1887                      music_volume=min(music_volume+16,127);
1888                      if (current_song && (sound_avail&MUSIC_INITIALIZED))
1889                        current_song->set_volume(music_volume);
1890                    }
1891                 
1892                    if (ev.message.id==LOWER_MUSIC && music_volume!=0)
1893                    {               
1894                      music_volume=max(music_volume-16,0);
1895                      if (current_song && (sound_avail&MUSIC_INITIALIZED))
1896                        current_song->set_volume(music_volume);
1897                    }               
1898                 
1899                    ((button *)ev.message.data)->push();             
1900/*                  volume_window->inm->redraw();
1901                    draw_value(volume_window->screen,WINDOW_FRAME_LEFT+2,WINDOW_FRAME_TOP+43,
1902                                                   (volume_window->x2()-volume_window->x1()-1),8,
1903                                                   sfx_volume,127);
1904                    draw_value(volume_window->screen,WINDOW_FRAME_LEFT+2,WINDOW_FRAME_TOP+94,
1905                                                   (volume_window->x2()-volume_window->x1()-1),8,
1906                                                   music_volume,127); */
1907                    break;
1908                }
1909                         
1910            }     
1911          }
1912        } break;
1913      }
1914    }
1915  }
1916}
1917
1918
1919void net_send(int force=0)
1920{
1921  if ( (!(dev&EDIT_MODE)) || force)
1922  {
1923    if (demo_man.state==demo_manager::PLAYING)
1924    {
1925      base->input_state=INPUT_PROCESSING;
1926    } else
1927    {
1928     
1929
1930
1931      if (!player_list->focus)
1932      {
1933        dprintf("Players have not been created\ncall create_players");
1934        exit(0);
1935      }
1936
1937
1938      view *p=player_list;
1939      for (;p;p=p->next)
1940        if (p->local_player())
1941          p->get_input();
1942
1943
1944      base->packet.write_byte(SCMD_SYNC);
1945      base->packet.write_short(make_sync());
1946
1947      if (base->join_list)
1948      base->packet.write_byte(SCMD_RELOAD);
1949
1950      //      printf("save tick %d, pk size=%d, rand_on=%d, sync=%d\n",current_level->tick_counter(),
1951      //             base->packet.packet_size(),rand_on,make_sync());
1952      send_local_request();
1953    }
1954  }
1955}
1956
1957void net_receive()
1958{
1959  if (!(dev&EDIT_MODE) && current_level)
1960  {
1961    uchar buf[PACKET_MAX_SIZE+1];
1962    int size;
1963
1964    if (demo_man.state==demo_manager::PLAYING)
1965    {
1966      if (!demo_man.get_packet(buf,size))
1967        size=0;
1968      base->packet.packet_reset();
1969      base->mem_lock=0;
1970    } else
1971    {
1972      size=get_inputs_from_server(buf);
1973      if (demo_man.state==demo_manager::RECORDING)
1974        demo_man.save_packet(buf,size);
1975    }
1976
1977    process_packet_commands(buf,size);
1978  }
1979}
1980
1981void game::step()
1982{
1983  clear_tmp();
1984  if (current_level)
1985  {
1986    current_level->unactivate_all();
1987    total_active=0;
1988    for (view *f=first_view;f;f=f->next)
1989    {
1990      if (f->focus)           
1991      {
1992        f->update_scroll();
1993        int w,h;
1994
1995        w=(f->cx2-f->cx1+1);
1996        h=(f->cy2-f->cy1+1);
1997        total_active+=current_level->add_actives(f->xoff()-w/4,f->yoff()-h/4,
1998                                                 f->xoff()+w+w/4,f->yoff()+h+h/4);
1999      }
2000    }
2001  }
2002
2003  if (state==RUN_STATE)
2004  {   
2005    if ((dev&EDIT_MODE) || (main_net_cfg && (main_net_cfg->state==net_configuration::CLIENT ||
2006                                             main_net_cfg->state==net_configuration::SERVER)))
2007      idle_ticks=0;
2008
2009    if (demo_man.current_state()==demo_manager::NORMAL && idle_ticks>420 && demo_start)
2010    {
2011      idle_ticks=0;
2012      set_state(MENU_STATE);   
2013    }
2014    else if (!(dev & EDIT_MODE))               // if edit mode, then don't step anything
2015    {
2016      if (key_down(JK_ESC))
2017      {
2018        set_state(MENU_STATE);
2019        set_key_down(JK_ESC,0);
2020      }
2021      ambient_ramp=0;
2022      view *v;
2023      for (v=first_view;v;v=v->next)
2024        v->update_scroll();
2025
2026      cash.prof_poll_start();
2027      current_level->tick();
2028      sbar.step();
2029    } else   
2030      dev_scroll(); 
2031  } else if (state==JOY_CALB_STATE)
2032  {
2033    event ev;
2034    joy_calb(ev);
2035  } else if (state==MENU_STATE) 
2036    main_menu(); 
2037   
2038  if (key_down('x') && (key_down(JK_ALT_L) || key_down(JK_ALT_R)) && confirm_quit()) finished=1;
2039}
2040
2041extern void *current_demo;
2042
2043game::~game()
2044{
2045  current_demo=NULL;
2046  if (first_view==player_list) first_view=NULL;
2047  while (player_list)
2048  {
2049    view *p=player_list;
2050    game_object *o=p->focus;
2051    player_list=player_list->next;
2052    delete p;
2053    o->set_controller(NULL);
2054    if (current_level && o)
2055      current_level->delete_object(o);
2056    else delete o;
2057  }
2058
2059  if (current_level) { delete current_level; current_level=NULL; }
2060
2061  if (first_view!=player_list)
2062  {
2063    while (player_list)
2064    {
2065      view *p=player_list;
2066      player_list=player_list->next;
2067      delete p;
2068    }
2069  }
2070
2071  while (first_view)
2072  {
2073    view *p=first_view;
2074    first_view=first_view->next;
2075    delete p;
2076  }
2077
2078  player_list=NULL; 
2079
2080  if (old_view)
2081  {
2082    first_view=old_view;
2083    while (first_view)
2084    {
2085      view *p=first_view;
2086      first_view=first_view->next;
2087      delete p;
2088    }
2089  }
2090  old_view=NULL;
2091
2092  int i=0;
2093  for (;i<total_objects;i++)
2094  {
2095    jfree(object_names[i]);
2096    delete figures[i];
2097  }
2098  free_pframes();
2099  if (fps_mark_start) delete fps_mark_start; fps_mark_start=NULL;
2100  delete pal;
2101  jfree(object_names);
2102  jfree(figures);
2103
2104  jfree(backtiles);
2105  jfree(foretiles);
2106  if (total_weapons)
2107    jfree(weapon_types);
2108
2109  config_cleanup();
2110  delete color_table;
2111  delete eh;
2112  delete game_font;
2113  delete big_font;
2114  delete console_font;
2115  if (total_help_screens)
2116    jfree(help_screens);
2117   
2118  close_graphics();
2119  image_uninit();
2120}
2121
2122
2123
2124void game::draw(int scene_mode)
2125{
2126  screen->add_dirty(0,0,xres,yres);
2127  image *bt=cash.img(border_tile);
2128  int tw=bt->width(),th=bt->height(),dx,dy=0;
2129  int xt=screen->width()/tw+1,yt=screen->height()/th+1,x,y;
2130  screen->clear();
2131//  for (y=0;y<yt;y++,dy+=th)
2132//    for (x=0,dx=0;x<xt;x++,dx+=tw)
2133//      bt->put_image(screen,dx,dy);
2134  int lr=eh->bright_color(),
2135      mr=eh->medium_color();
2136
2137  if (scene_mode)
2138  {
2139    char *helpstr="ARROW KEYS CHANGE TEXT SPEED";
2140    eh->font()->put_string(screen,screen->width()/2-(eh->font()->width()*strlen(helpstr))/2+1,
2141                           screen->height()-eh->font()->height()-5+1,helpstr,eh->dark_color());   
2142    eh->font()->put_string(screen,screen->width()/2-(eh->font()->width()*strlen(helpstr))/2,
2143                           screen->height()-eh->font()->height()-5,helpstr,eh->bright_color());   
2144  }
2145/*  else
2146  {
2147    char *helpstr="PRESS h FOR HELP";
2148    eh->font()->put_string(screen,screen->width()-eh->font()->width()*strlen(helpstr)-5,
2149                         screen->height()-eh->font()->height()-5,helpstr);
2150  }*/
2151/*  int dc=cash.img(window_colors)->pixel(0,2);
2152  int mc=cash.img(window_colors)->pixel(1,2);
2153  int bc=cash.img(window_colors)->pixel(2,2);
2154  screen->line(0,0,screen->width()-1,0,dc);
2155  screen->line(0,0,0,screen->height()-1,dc);
2156  screen->line(0,screen->height()-1,screen->width()-1,screen->height()-1,bc);
2157  screen->line(screen->width()-1,0,screen->width()-1,screen->height()-1,bc);*/
2158  for (view *f=first_view;f;f=f->next)
2159    draw_map(f,0);
2160
2161  sbar.redraw(screen);
2162}
2163
2164int external_print=0;
2165
2166void start_sound(int argc, char **argv)
2167{
2168  sfx_volume=music_volume=127;
2169
2170  for (int i=1;i<argc;i++)
2171    if (!strcmp(argv[i],"-sfx_volume"))
2172    {
2173      i++;
2174      if (atoi(argv[i])>=0 && atoi(argv[i])<127)
2175        sfx_volume=atoi(argv[i]);
2176      else printf("Bad sound effects volume level, use 0..127\n");     
2177    }
2178    else if (!strcmp(argv[i],"-music_volume"))
2179    {
2180      i++;
2181      if (atoi(argv[i])>=0 && atoi(argv[i])<127)
2182        music_volume=atoi(argv[i]);
2183      else printf("Bad music volume level, use 0..127\n");     
2184    }
2185
2186  sound_avail=sound_init(argc,argv);
2187}
2188
2189void game_printer(char *st)
2190{
2191  if (dev_console && !external_print)
2192  {
2193    dev_console->put_string(st);
2194  }
2195  else fprintf(stderr,"%s",st);
2196}
2197
2198
2199void game_getter(char *st, int max)
2200{
2201  if (!max) return ;
2202  max--;
2203  *st=0;
2204  if (dev_console && !external_print)
2205  {   
2206    dev_console->show();
2207    int t=0;
2208    event ev;
2209    do
2210    {
2211      get_event(ev,eh);
2212      if (ev.type==EV_KEY)
2213      {
2214        if (ev.key==JK_BACKSPACE)
2215        {
2216          if (t)
2217          {
2218            dev_console->printf("%c",ev.key);
2219            t--;
2220            st--;
2221            *st=0;
2222            max++;
2223          }
2224        } else if (ev.key>=' ' && ev.key<='~')
2225        {
2226          dev_console->printf("%c",ev.key);
2227          *st=ev.key;
2228          t++;
2229          max--;
2230          st++;
2231          *st=0;
2232        }                         
2233      }
2234      eh->flush_screen();
2235    } while (ev.type!=EV_KEY || ev.key!=JK_ENTER);   
2236    dprintf("\n");
2237  }
2238  else
2239  {
2240    if (fgets(st,max,stdin))
2241    {
2242      if (*st)
2243        st[strlen(st)-1]=0;
2244    }
2245  }
2246}
2247
2248
2249void show_startup()
2250{
2251  show_verinfo(start_argc,start_argv);
2252}
2253
2254char *get_line(int open_braces)
2255{
2256  char *line=(char *)jmalloc(1000,"lstring");
2257  fgets(line,1000,stdin);
2258
2259  char prev=' ';
2260  for (char *s=line;*s && (prev!=' ' || *s!=';');s++)
2261  {
2262    prev=*s;
2263    if (*s=='(') open_braces++;
2264    else if (*s==')') open_braces--;
2265  }
2266  if (open_braces<0)   
2267    fprintf(stderr,"\nToo many )'s\n");
2268  else if (open_braces>0)
2269  {
2270    char *s2=get_line(open_braces);
2271    line=(char *)jrealloc(line,strlen(line)+strlen(s2)+1,"lstring");
2272    strcat(line,s2);
2273    jfree(s2);   
2274  } 
2275  return line;
2276}
2277
2278void check_for_upgrade(int argc, char **argv)
2279{
2280  for (int i=1;i<argc;i++)
2281    if (!strcmp(argv[i],"-upgrade"))
2282    {
2283      lisp_init(0xf000,0x30000);
2284      char *prog="(load \"lisp/upgrade.lsp\")",*cs;
2285      cs=prog;
2286      if (!eval(compile(cs)))
2287        printf("file does not exists : lisp/upgrade.lsp, cannot upgrade\n");
2288
2289      exit(0);
2290    }       
2291}
2292
2293void check_for_lisp(int argc, char **argv)
2294{
2295  for (int i=1;i<argc;i++)
2296  {
2297    if (!strcmp(argv[i],"-lisp"))
2298    {
2299      lisp_init(0xf000,0x30000);
2300
2301#ifdef __WATCOMC__
2302      char *eof_char="CTRL-Z";
2303#else
2304      char *eof_char="CTRL-D";
2305#endif
2306      fprintf(stderr,
2307              " CLIVE (C) 1995 Jonathan Clark, all rights reserved\n"
2308              "   (C LISP interpreter and various extentions)\n"
2309              "Type (%s) to exit\n",eof_char);
2310
2311      while (!feof(stdin))
2312      {
2313        fprintf(stderr,"Lisp> ");
2314        char *l=get_line(0);
2315        char *s=l;
2316        while (*s)
2317        {
2318          void *prog=compile(s);
2319          l_user_stack.push(prog);
2320          while (*s==' ' || *s=='\t' || *s=='\r' || *s=='\n') s++;
2321          lprint(eval(prog));
2322          l_user_stack.pop(1);
2323        }
2324        jfree(l);
2325      }     
2326
2327      fprintf(stderr,"End of input : bye\n");
2328      exit(0);
2329    }
2330  }
2331}
2332
2333
2334void music_check()
2335{
2336  if (sound_avail&MUSIC_INITIALIZED)
2337  {
2338    if (current_song && !current_song->playing())
2339    {
2340      current_song->play();
2341      dprintf("song finished\n");
2342    }
2343    if (!current_song)
2344    {
2345
2346      current_song=new song("music/intro.hmi");
2347      current_song->play(music_volume);
2348
2349/*      if (DEFINEDP(symbol_function(l_next_song)))  // if user function installed, call it to load up next song
2350      {
2351        int sp=current_space;
2352        current_space=PERM_SPACE;
2353        eval_function((lisp_symbol *)l_next_song,NULL);
2354        current_space=sp;
2355      } */
2356    }
2357  }
2358}
2359
2360void setup(int argc, char **argv);
2361
2362void share_end();
2363void show_end();
2364
2365void show_sell(int abortable);
2366
2367extern pmenu *dev_menu;
2368
2369
2370extern int jmalloc_max_size;
2371extern int jmalloc_min_low_size;
2372
2373extern int (*verify_file_fun)(char *,char *);
2374
2375int registered_ok(char *filename, char *mode)
2376{
2377  if (registered) return 1;
2378
2379  char name[256],*c;
2380  c=name;
2381  while (*filename) { *c=*(filename++); *c=toupper(*c); c++; } *c=0;
2382  if (strstr(name,"REGISTER"))
2383    return 0;
2384  else return 1;
2385}
2386
2387void game_net_init(int argc, char **argv)
2388{
2389  int nonet=!net_init(argc, argv);
2390  if (nonet)
2391    dprintf("No network driver, or network driver returned failure\n");
2392  else
2393  {
2394    set_file_opener(open_nfs_file);
2395    if (main_net_cfg && main_net_cfg->state==net_configuration::CLIENT)
2396    {
2397      if (set_file_server(net_server))
2398      start_running=1;
2399      else
2400      {
2401                                dprintf("Unable to attach to server, quiting\n");
2402                                exit(0);
2403      }
2404    } else
2405    {
2406      int i;
2407      for (i=1;i<argc-1;i++)
2408      if (!strcmp(argv[i],"-fs"))
2409      if (!set_file_server(argv[i+1]))
2410      dprintf("could not set defualt file server to %s\n",argv[i+1]);
2411    }
2412  }     
2413
2414}
2415
2416#ifdef __POWERPC__
2417extern int PixMult;
2418#if 1
2419char cmdline[256];
2420#elif 1
2421char cmdline[] = "";
2422#elif 1
2423char cmdline[] = "abuse -server -a deathmat";
2424#else
2425char cmdline[] = "abuse -net 193.246.40.9";
2426#endif
2427char delims[] = " ";
2428char *tmp_argv[255];
2429
2430void GetArgs(int &argc, char **(&argv))
2431{
2432        char *s;
2433
2434        printf( "Usage:\n"
2435                                        "  abuse [-options]\n\n"
2436                                        "  Options:\n"
2437                                        "    -server -a deathmat        become a server for deathmatch game\n"
2438                                        "    -net <dotted ip address>   connect to a server\n\n"
2439                                        "Options for mac:\n"
2440                                        "  Hold down <control> for single pixel mode\n"
2441                                        "  Hold down <option> for edit mode\n"
2442                                        "  Hold down <left shift> for double size mode\n\n"
2443                                        "If started with no command line options, networking will attempt\n"
2444                                        "  to search the local network for servers\n\n"
2445        );
2446        printf("Enter command line:\n");
2447        gets(cmdline);
2448       
2449        argc = 0;
2450        argv = tmp_argv;
2451        s = strtok(cmdline, delims);
2452        while (s)
2453        {
2454                argv[argc] = s;
2455                argc++;
2456                s = strtok(0, delims);
2457        }
2458        argv[argc] = 0;
2459}
2460
2461#endif
2462
2463int main(int argc, char **argv)
2464{
2465#ifdef __POWERPC__
2466        GetArgs(argc,argv);
2467#endif
2468
2469  start_argc=argc;
2470  start_argv=argv;
2471 
2472  { for (int i=0;i<argc;i++)
2473    {
2474      if (!strcmp(argv[i],"-cprint"))
2475        external_print=1;
2476      if (!strcmp(argv[i],"-min_low"))
2477      {
2478                                i++;
2479        jmalloc_min_low_size=atoi(argv[i]);
2480      }
2481    }
2482  }
2483
2484//  jmalloc_max_size=0x150000;
2485  jmalloc_init(0x150000);
2486//  jmalloc_init(100000);
2487
2488#ifdef __POWERPC__
2489        unsigned char km[16];
2490       
2491        fprintf(stderr,"Mac Options: ");
2492        xres = 320; yres = 200;
2493        GetKeys((unsigned long*)&km);
2494        if ((km[ 0x3a >>3] >> (0x3a & 7)) &1 != 0)
2495        {
2496                dev|=EDIT_MODE;   
2497                start_edit=1;
2498                start_running=1;
2499                disable_autolight=1;
2500                fprintf(stderr,"Edit Mode...");
2501        }
2502        if ((km[ 0x3b >>3] >> (0x3b & 7)) &1 != 0)
2503        {
2504                PixMult = 1;
2505                fprintf(stderr,"Single Pixel...");
2506        }
2507        else
2508        {
2509                PixMult = 2;
2510                fprintf(stderr,"Double Pixel...");
2511        }
2512        if ((km[ 0x38 >>3] >> (0x38 & 7)) &1 != 0)
2513        {
2514                xres *= 2;  yres *= 2;
2515                fprintf(stderr,"Double Size...");
2516        }
2517        fprintf(stderr,"\n");
2518       
2519        if (tcpip.installed())
2520                fprintf(stderr, "Using %s\n", tcpip.name());
2521#endif
2522
2523  set_dprinter(game_printer);
2524  set_dgetter(game_getter);
2525  set_no_space_handler(handle_no_space);
2526
2527  setup(argc,argv);
2528
2529  show_startup();
2530
2531  start_sound(argc,argv);
2532
2533  stat_man=new text_status_manager();
2534  if (!get_option("-no_timer"))
2535  {
2536    timer_init();
2537  }
2538
2539  if (getenv("ABUSE_PATH"))       // look to see if we are supposed to fetch the data elsewhere
2540    set_filename_prefix(getenv("ABUSE_PATH"));   
2541
2542  if (getenv("ABUSE_SAVE_PATH"))       // look to see if we are supposed to fetch the data elsewhere
2543    set_save_filename_prefix(getenv("ABUSE_SAVE_PATH"));   
2544
2545  if (!get_option("-share"))
2546  {
2547    jFILE *fp=new jFILE("register/micron.vcd","rb");
2548    if (!fp->open_failure())
2549    {
2550      spec_directory sd(fp);
2551      if (sd.find("Copyright (C) 1995 Crack dot Com, All Rights reserved"))
2552        registered=1;
2553    }
2554    delete fp;
2555  }
2556
2557  verify_file_fun=registered_ok;
2558
2559
2560
2561  jrand_init();
2562  jrand();  // so compiler doesn't complain
2563
2564
2565  set_spec_main_file("abuse.spe");
2566
2567  check_for_lisp(argc,argv);
2568  check_for_upgrade(argc,argv);
2569
2570  do
2571  {
2572    if (main_net_cfg)
2573    {
2574      if (!main_net_cfg->notify_reset())
2575      {
2576        if (!get_option("-no_timer"))
2577          timer_uninit();
2578        sound_uninit();
2579        exit(0);
2580      }
2581    }
2582
2583    game_net_init(argc,argv);
2584    lisp_init(0x16000,0x94000);
2585    //  lisp_init(0x100000,0x10000);
2586
2587    dev_init(argc,argv);
2588
2589
2590    game *g=new game(argc,argv);
2591
2592
2593
2594
2595    dev_cont=new dev_controll();
2596    dev_cont->load_stuff();
2597
2598
2599
2600    g->get_input();      // prime the net
2601
2602    int xx;
2603    for (xx=1;xx<argc;xx++)
2604      if (!strcmp(argv[xx],"-server"))
2605      {
2606                                xx++;
2607                                if (!become_server(argv[xx]))
2608                                {     
2609                                  dprintf("unable to become a server\n");
2610                                  exit(0);
2611                                }
2612                                xx=argc+1;
2613      }
2614
2615    if (main_net_cfg)
2616      wait_min_players();
2617
2618    net_send(1);
2619    if (net_start())
2620    {
2621      g->step();                        // process all the objects in the
2622      g->calc_speed();
2623      g->update_screen();               // redraw the screen with any changes
2624    }
2625
2626    while (!g->done())
2627    {   
2628      music_check();
2629
2630      if (req_end)
2631      {
2632                                delete current_level;
2633                                current_level=NULL;
2634                               
2635                                if (!registered)
2636                                share_end();
2637                                else show_end();
2638                       
2639                                the_game->set_state(MENU_STATE);
2640                                req_end=0;
2641      }
2642     
2643
2644      if (demo_man.current_state()==demo_manager::NORMAL)
2645      {
2646                                net_receive();
2647      }
2648
2649      if (req_name[0])            // see if a request for a level load was made during the last tick
2650      {
2651                                g->load_level(req_name);
2652                                req_name[0]=0;
2653                                g->draw(g->state==SCENE_STATE);
2654      }
2655
2656      //    if (demo_man.current_state()!=demo_manager::PLAYING)
2657      g->get_input();
2658     
2659      if (demo_man.current_state()==demo_manager::NORMAL)
2660      net_send();
2661      else demo_man.do_inputs();
2662
2663      service_net_request();
2664
2665      g->step();                        // process all the objects in the
2666
2667      server_check();
2668
2669      g->calc_speed();
2670      if (!req_name[0])                // see if a request for a level load was made during the last tick
2671        g->update_screen();               // redraw the screen with any changes
2672
2673
2674    }
2675
2676    net_uninit();
2677
2678    if (net_crcs)
2679    {
2680      net_crcs->clean_up();
2681      delete net_crcs;
2682      net_crcs=NULL;
2683    }
2684
2685    delete chat;
2686
2687    if (!registered)
2688    show_sell(0);
2689    else milli_wait(500);
2690
2691
2692    if (small_render) { delete small_render; small_render=NULL; }
2693
2694    if (current_song)
2695    { current_song->stop();
2696      delete current_song;
2697      current_song=NULL;
2698    }
2699
2700
2701    cash.empty();
2702
2703
2704    if (dev_console)
2705    {
2706      delete dev_console;
2707      dev_console=NULL;
2708    }
2709
2710    if (dev_menu)
2711    {
2712      delete dev_menu;
2713      dev_menu=NULL;
2714    }
2715
2716    delete g;
2717    if (old_pal) delete old_pal; old_pal=NULL;
2718    compiled_uninit();
2719    delete_all_lights();
2720    jfree(white_light_initial);
2721
2722    for (int i=0;i<TTINTS;i++) jfree(tints[i]);
2723
2724
2725    dev_cleanup();
2726    delete dev_cont; dev_cont=NULL;
2727    delete stat_man;
2728    stat_man=new text_status_manager();
2729
2730    if (!(main_net_cfg && main_net_cfg->restart_state()))
2731    {
2732      void *end_msg=make_find_symbol("end_msg");
2733      if (DEFINEDP(symbol_value(end_msg)))
2734      printf("%s\n",lstring_value(symbol_value(end_msg)));
2735    }
2736
2737    lisp_uninit();
2738
2739    base->packet.packet_reset();
2740    mem_report("end.mem");
2741  } while (main_net_cfg && main_net_cfg->restart_state());
2742
2743
2744  delete stat_man;
2745
2746  if (main_net_cfg) { delete main_net_cfg; main_net_cfg=NULL; }
2747  set_filename_prefix(NULL);  // dealloc this mem if there was any
2748  set_save_filename_prefix(NULL);
2749
2750  if (!get_option("-no_timer"))
2751    timer_uninit();
2752
2753  mem_report("end.mem");
2754
2755//  jmalloc_uninit();
2756  l_user_stack.clean_up();
2757  l_ptr_stack.clean_up();
2758
2759  sound_uninit();
2760
2761  exit(0);
2762
2763  return 0; 
2764}
2765
2766
Note: See TracBrowser for help on using the repository browser.