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

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