source: abuse/trunk/src/game.cpp @ 2

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