source: abuse/branches/pd/macabuse/src/game.c @ 98

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