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

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