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

Last change on this file since 56 was 56, checked in by Sam Hocevar, 14 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
File size: 63.1 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 single_render();
1720void double_render();
1721
1722void game::get_input()
1723{
1724        event ev;
1725        idle_ticks++;
1726        while( event_waiting( eh ) )
1727        {
1728                get_event(ev,eh);
1729
1730                if(ev.type == EV_MOUSE_MOVE )
1731                {
1732                        last_input = ev.window;
1733                }
1734                // don't process repeated keys in the main window, it will slow down the game to handle such
1735                // useless events. However in other windows it might be useful, such as in input windows
1736                // where you want to repeatedly scroll down...
1737                if( ev.type != EV_KEY || !key_down( ev.key ) || ev.window || ( dev & EDIT_MODE ) )
1738                {
1739                        if( ev.type == EV_KEY )
1740                        {
1741                                set_key_down( ev.key, 1 );
1742                                if( playing_state( state ) )
1743                                {
1744                                        if(ev.key < 256 )
1745                                        {
1746                                                if( chat && chat->chat_event( ev ) )
1747                                                        base->packet.write_uint8( SCMD_CHAT_KEYPRESS );
1748                                                else
1749                                                        base->packet.write_uint8( SCMD_KEYPRESS );
1750                                        }
1751                                        else
1752                                                base->packet.write_uint8( SCMD_EXT_KEYPRESS );
1753                                        base->packet.write_uint8( client_number() );
1754                                        if( ev.key > 256 )
1755                                                base->packet.write_uint8( ev.key - 256 );
1756                                        else
1757                                                base->packet.write_uint8( ev.key );
1758                                }
1759                        }
1760                        else if(ev.type == EV_KEYRELEASE )
1761                        {
1762                                set_key_down( ev.key, 0 );
1763                                if( playing_state( state ) )
1764                                {
1765                                        if( ev.key < 256 )
1766                                                base->packet.write_uint8( SCMD_KEYRELEASE );
1767                                        else
1768                                                base->packet.write_uint8( SCMD_EXT_KEYRELEASE );
1769                                        base->packet.write_uint8( client_number() );
1770                                        if( ev.key > 255 )
1771                                                base->packet.write_uint8( ev.key - 256 );
1772                                        else
1773                                                base->packet.write_uint8( ev.key );
1774                                }
1775                        }
1776
1777                        if( (dev & EDIT_MODE) || start_edit || ev.type == EV_MESSAGE )
1778                        {
1779                                dev_cont->handle_event( ev );
1780                        }
1781
1782                        view *v = first_view;
1783                        for( ; v; v = v->next )
1784                        {
1785                                if( v->local_player() && v->handle_event( ev ) )
1786                                        ev.type=EV_SPURIOUS;       // if the event was used by the view, gobble it up
1787                        }
1788
1789                        if( current_automap )
1790                        {
1791                                current_automap->handle_event( ev );
1792                        }
1793
1794                        help_handle_event( ev );
1795                        mousex = last_demo_mx;
1796                        mousey = last_demo_my;
1797
1798                        if(ev.type == EV_MESSAGE )
1799                        {
1800                                switch (ev.message.id)
1801                                {
1802                                        case CALB_JOY:
1803                                        {
1804                                                if (!joy_win)
1805                                                {
1806                                                        int wx=WINDOW_FRAME_LEFT,wy=WINDOW_FRAME_TOP;
1807
1808                                                        joy_win=eh->new_window(80,50,-1,-1,
1809                                                                        new button(wx+70,wy+9,JOY_OK,"OK",
1810                                                                        new info_field(wx,wy+30,DEV_NULL,
1811                                                                        " Center joystick and\n"
1812                                                                        "press the fire button",NULL)),
1813                                                                        "Joystick");
1814                                                        set_state(JOY_CALB_STATE);
1815                                                }
1816                                        }
1817                                        case TOP_MENU:
1818                                        {
1819                                                menu_select(ev);
1820                                        } break;
1821                                        case DEV_QUIT:
1822                                        {
1823                                                finished = 1;
1824                                        } break;
1825                                }
1826                        }
1827                        else if(ev.type == EV_CLOSE_WINDOW && ev.window == top_menu )
1828                        {
1829                                eh->close_window( top_menu );
1830                                top_menu = NULL;
1831                        }
1832
1833                        switch( state )
1834                        {
1835                                case JOY_CALB_STATE:
1836                                {
1837                                        joy_calb(ev);
1838                                } break;
1839                                case INTRO_START_STATE:
1840                                {
1841                                        do_intro();
1842                                        if (dev & EDIT_MODE)
1843                                                set_state(RUN_STATE);
1844                                        else
1845                                                set_state(MENU_STATE);
1846                                } break;
1847                                case PAUSE_STATE:
1848                                {
1849                                        if( ev.type == EV_KEY && ( ev.key == JK_SPACE || ev.key == JK_ENTER ) )
1850                                        {
1851                                                set_state( RUN_STATE );
1852                                        }
1853                                } break;
1854                                case RUN_STATE:
1855                                {
1856                                        if (ev.window==NULL)
1857                                        {
1858                                                switch (ev.type)
1859                                                {
1860                                                        case EV_KEY:
1861                                                        {
1862                                                                switch (ev.key)
1863                                                                {
1864                                                                        case 'm':
1865                                                                        {
1866                                                                                if( dev & MAP_MODE )
1867                                                                                        dev -= MAP_MODE;
1868                                                                                else if( ( player_list && player_list->next ) || dev & EDIT_MODE )
1869                                                                                        dev |= MAP_MODE;
1870
1871                                                                                if( !( dev & MAP_MODE ) )
1872                                                                                {
1873                                                                                        if( dev_cont->tbw )
1874                                                                                                dev_cont->toggle_toolbar();
1875                                                                                        edit_mode = ID_DMODE_DRAW;
1876                                                                                }
1877                                                                                need_refresh();
1878                                                                        } break;
1879                                                                        case 'v':
1880                                                                        {
1881                                                                                eh->push_event(new event(DO_VOLUME,NULL));
1882                                                                        } break;
1883                                                                        case 'p':
1884                                                                        {
1885                                                                                if (!(dev&EDIT_MODE) && (!main_net_cfg ||
1886                                                                                        (main_net_cfg->state!=net_configuration::SERVER &&
1887                                                                                        main_net_cfg->state!=net_configuration::CLIENT)))
1888                                                                                {
1889                                                                                        set_state(PAUSE_STATE);
1890                                                                                }
1891                                                                        } break;
1892                                                                        case 'S':
1893                                                                        {
1894                                                                                if( start_edit )
1895                                                                                {
1896                                                                                        eh->push_event(new event(ID_LEVEL_SAVE,NULL));
1897                                                                                }
1898                                                                        } break;
1899                                                                        case JK_TAB:
1900                                                                        {
1901                                                                                if( start_edit )
1902                                                                                        toggle_edit_mode();
1903                                                                                need_refresh();
1904                                                                        } break;
1905                                                                        case 'c':
1906                                                                        {
1907                                                                                if( chatting_enabled && (!(dev&EDIT_MODE) && chat))
1908                                                                                        chat->toggle();
1909                                                                        } break;
1910                                                                        case '9':
1911                                                                        {
1912                                                                                dev = dev^PERFORMANCE_TEST_MODE;
1913                                                                                need_refresh();
1914                                                                        } break;
1915/*                                                                      case '=':
1916                                                                        case '+':
1917                                                                        {
1918                                                                                if (!dev_cont->need_plus_minus())
1919                                                                                {
1920                                                                                        if (eh->key_pressed(JK_CTRL_L))
1921                                                                                                grow_views(20);
1922                                                                                        else
1923                                                                                                grow_views(5);
1924                                                                                        draw(state==SCENE_STATE);
1925                                                                                }
1926                                                                        } break;
1927                                                                        case JK_F10:
1928                                                                        {
1929                                                                                make_screen_size(311,160);
1930                                                                        } break;
1931                                                                        case '_':
1932                                                                        case '-' :
1933                                                                        {
1934                                                                                if (!dev_cont->need_plus_minus())
1935                                                                                {
1936                                                                                        if (eh->key_pressed(JK_CTRL_L))
1937                                                                                                grow_views(-20);
1938                                                                                        else
1939                                                                                                grow_views(-5);
1940                                                                                        draw(state==SCENE_STATE);
1941                                                                                }
1942                                                                        } break;
1943*/
1944                                                                }
1945                                                        } break;
1946                                                        case EV_RESIZE:
1947                                                        {
1948                                                                view *v;
1949                                                                for( v = first_view; v; v = v->next )  // see if any views need to change size
1950                                                                {
1951                                                                        if (v->local_player())
1952                                                                        {
1953                                                                                int w = (xres-10)/(small_render ? 2 : 1);
1954                                                                                int h = (yres-10)/(small_render ? 2 : 1);
1955
1956                                                                                v->suggest.send_view = 1;
1957                                                                                v->suggest.cx1 = 5;
1958                                                                                v->suggest.cx2 = 5 + w;
1959                                                                                v->suggest.cy1 = 5;
1960                                                                                v->suggest.cy2 = 5 + h;
1961                                                                                v->suggest.pan_x = v->pan_x;
1962                                                                                v->suggest.pan_y = v->pan_y;
1963                                                                                v->suggest.shift_down = v->shift_down;
1964                                                                                v->suggest.shift_right = v->shift_right;
1965                                                                        }
1966                                                                }
1967                                                                draw();
1968                                                        } break;
1969                                                        case EV_REDRAW:
1970                                                        {
1971                                                                screen->add_dirty(ev.redraw.x1,ev.redraw.y1,
1972                                                                        ev.redraw.x2,ev.redraw.y2);
1973                                                        } break;
1974                                                        case EV_MESSAGE:
1975                                                        {
1976                                                                switch (ev.message.id)
1977                                                                {
1978                                                                        case RAISE_SFX:
1979                                                                        case LOWER_SFX:
1980                                                                        case RAISE_MUSIC:
1981                                                                        case LOWER_MUSIC:
1982                                                                        {
1983                                                                                if( ev.message.id == RAISE_SFX && sfx_volume != 127 )
1984                                                                                        sfx_volume = min( 127, sfx_volume + 16 );
1985                                                                                if( ev.message.id == LOWER_SFX && sfx_volume != 0 )
1986                                                                                        sfx_volume = max( sfx_volume - 16,0 );
1987                                                                                if( ev.message.id == RAISE_MUSIC && music_volume != 126 )
1988                                                                                {
1989                                                                                        music_volume = min( music_volume + 16, 127 );
1990                                                                                        if( current_song && ( sound_avail & MUSIC_INITIALIZED ) )
1991                                                                                                current_song->set_volume( music_volume );
1992                                                                                }
1993
1994                                                                                if( ev.message.id == LOWER_MUSIC && music_volume != 0 )
1995                                                                                {
1996                                                                                        music_volume = max( music_volume - 16, 0 );
1997                                                                                        if( current_song && (sound_avail & MUSIC_INITIALIZED ) )
1998                                                                                                current_song->set_volume( music_volume );
1999                                                                                }
2000
2001                                                                                ((button *)ev.message.data)->push();
2002/*                                                                              volume_window->inm->redraw();
2003                                                                                draw_value(volume_window->screen,WINDOW_FRAME_LEFT+2,WINDOW_FRAME_TOP+43,
2004                                                                                                (volume_window->x2()-volume_window->x1()-1),8, sfx_volume,127);
2005                                                                                draw_value(volume_window->screen,WINDOW_FRAME_LEFT+2,WINDOW_FRAME_TOP+94,
2006                                                                                                (volume_window->x2()-volume_window->x1()-1),8, music_volume,127);
2007*/
2008                                                                                break;
2009                                                                        }
2010                                                                }
2011                                                        }
2012                                                }
2013                                        }
2014                                } break;
2015                        }
2016                }
2017        }
2018}
2019
2020
2021void net_send(int force=0)
2022{
2023  if ( (!(dev&EDIT_MODE)) || force)
2024  {
2025    if (demo_man.state==demo_manager::PLAYING)
2026    {
2027      base->input_state=INPUT_PROCESSING;
2028    } else
2029    {
2030     
2031
2032
2033      if (!player_list->focus)
2034      {
2035        dprintf("Players have not been created\ncall create_players");
2036        exit(0);
2037      }
2038
2039
2040      view *p=player_list;
2041      for (;p;p=p->next)
2042        if (p->local_player())
2043          p->get_input();
2044
2045
2046      base->packet.write_uint8(SCMD_SYNC);
2047      base->packet.write_uint16(make_sync());
2048
2049      if (base->join_list)
2050      base->packet.write_uint8(SCMD_RELOAD);
2051
2052      //      printf("save tick %d, pk size=%d, rand_on=%d, sync=%d\n",current_level->tick_counter(),
2053      //             base->packet.packet_size(),rand_on,make_sync());
2054      send_local_request();
2055    }
2056  }
2057}
2058
2059void net_receive()
2060{
2061  if (!(dev&EDIT_MODE) && current_level)
2062  {
2063    uint8_t buf[PACKET_MAX_SIZE+1];
2064    int size;
2065
2066    if (demo_man.state==demo_manager::PLAYING)
2067    {
2068      if (!demo_man.get_packet(buf,size))
2069        size=0;
2070      base->packet.packet_reset();
2071      base->mem_lock=0;
2072    } else
2073    {
2074      size=get_inputs_from_server(buf);
2075      if (demo_man.state==demo_manager::RECORDING)
2076        demo_man.save_packet(buf,size);
2077    }
2078
2079    process_packet_commands(buf,size);
2080  }
2081}
2082
2083void game::step()
2084{
2085  clear_tmp();
2086  if (current_level)
2087  {
2088    current_level->unactivate_all();
2089    total_active=0;
2090    for (view *f=first_view;f;f=f->next)
2091    {
2092      if (f->focus)           
2093      {
2094        f->update_scroll();
2095        int w,h;
2096
2097        w=(f->cx2-f->cx1+1);
2098        h=(f->cy2-f->cy1+1);
2099        total_active+=current_level->add_actives(f->xoff()-w/4,f->yoff()-h/4,
2100                                                 f->xoff()+w+w/4,f->yoff()+h+h/4);
2101      }
2102    }
2103  }
2104
2105  if (state==RUN_STATE)
2106  {   
2107    if ((dev&EDIT_MODE) || (main_net_cfg && (main_net_cfg->state==net_configuration::CLIENT ||
2108                                             main_net_cfg->state==net_configuration::SERVER)))
2109      idle_ticks=0;
2110
2111    if (demo_man.current_state()==demo_manager::NORMAL && idle_ticks>420 && demo_start)
2112    {
2113      idle_ticks=0;
2114      set_state(MENU_STATE);   
2115    }
2116    else if (!(dev & EDIT_MODE))               // if edit mode, then don't step anything
2117    {
2118      if (key_down(JK_ESC))
2119      {
2120        set_state(MENU_STATE);
2121        set_key_down(JK_ESC,0);
2122      }
2123      ambient_ramp=0;
2124      view *v;
2125      for (v=first_view;v;v=v->next)
2126        v->update_scroll();
2127
2128      cash.prof_poll_start();
2129      current_level->tick();
2130      sbar.step();
2131    } else   
2132      dev_scroll(); 
2133  } else if (state==JOY_CALB_STATE)
2134  {
2135    event ev;
2136    joy_calb(ev);
2137  } else if (state==MENU_STATE) 
2138    main_menu(); 
2139   
2140  if (key_down('x') && (key_down(JK_ALT_L) || key_down(JK_ALT_R)) && confirm_quit()) finished=1;
2141}
2142
2143extern void *current_demo;
2144
2145game::~game()
2146{
2147  current_demo=NULL;
2148  if (first_view==player_list) first_view=NULL;
2149  while (player_list)
2150  {
2151    view *p=player_list;
2152    game_object *o=p->focus;
2153    player_list=player_list->next;
2154    delete p;
2155    o->set_controller(NULL);
2156    if (current_level && o)
2157      current_level->delete_object(o);
2158    else delete o;
2159  }
2160
2161  if (current_level) { delete current_level; current_level=NULL; }
2162
2163  if (first_view!=player_list)
2164  {
2165    while (player_list)
2166    {
2167      view *p=player_list;
2168      player_list=player_list->next;
2169      delete p;
2170    }
2171  }
2172
2173  while (first_view)
2174  {
2175    view *p=first_view;
2176    first_view=first_view->next;
2177    delete p;
2178  }
2179
2180  player_list=NULL; 
2181
2182  if (old_view)
2183  {
2184    first_view=old_view;
2185    while (first_view)
2186    {
2187      view *p=first_view;
2188      first_view=first_view->next;
2189      delete p;
2190    }
2191  }
2192  old_view=NULL;
2193
2194  int i=0;
2195  for (;i<total_objects;i++)
2196  {
2197    jfree(object_names[i]);
2198    delete figures[i];
2199  }
2200  free_pframes();
2201  if (fps_mark_start) delete fps_mark_start; fps_mark_start=NULL;
2202  delete pal;
2203  jfree(object_names);
2204  jfree(figures);
2205
2206  jfree(backtiles);
2207  jfree(foretiles);
2208  if (total_weapons)
2209    jfree(weapon_types);
2210
2211  config_cleanup();
2212  delete color_table;
2213  delete eh;
2214  delete game_font;
2215  delete big_font;
2216  delete console_font;
2217  if (total_help_screens)
2218    jfree(help_screens);
2219   
2220  close_graphics();
2221  image_uninit();
2222}
2223
2224
2225
2226void game::draw(int scene_mode)
2227{
2228        screen->add_dirty( 0, 0, xres, yres );
2229//      image *bt=cash.img(border_tile);
2230//      int tw=bt->width(),th=bt->height();
2231  screen->clear();
2232//  for (y=0;y<yt;y++,dy+=th)
2233//    for (x=0,dx=0;x<xt;x++,dx+=tw)
2234//      bt->put_image(screen,dx,dy);
2235
2236        if( scene_mode )
2237        {
2238                char const *helpstr = "ARROW KEYS CHANGE TEXT SPEED";
2239                eh->font()->put_string(screen,screen->width()/2-(eh->font()->width()*strlen(helpstr))/2+1,
2240                        screen->height()-eh->font()->height()-5+1,helpstr,eh->dark_color());
2241                eh->font()->put_string(screen,screen->width()/2-(eh->font()->width()*strlen(helpstr))/2,
2242                        screen->height()-eh->font()->height()-5,helpstr,eh->bright_color());   
2243        }
2244/*      else
2245        {
2246                char *helpstr="PRESS h FOR HELP";
2247                eh->font()->put_string(screen,screen->width()-eh->font()->width()*strlen(helpstr)-5,
2248                        screen->height()-eh->font()->height()-5,helpstr);
2249        }*/
2250/*      int dc=cash.img(window_colors)->pixel(0,2);
2251        int mc=cash.img(window_colors)->pixel(1,2);
2252        int bc=cash.img(window_colors)->pixel(2,2);
2253        screen->line(0,0,screen->width()-1,0,dc);
2254        screen->line(0,0,0,screen->height()-1,dc);
2255        screen->line(0,screen->height()-1,screen->width()-1,screen->height()-1,bc);
2256        screen->line(screen->width()-1,0,screen->width()-1,screen->height()-1,bc); */
2257
2258        for( view *f = first_view; f; f = f->next )
2259                draw_map( f, 0 );
2260
2261        sbar.redraw( screen );
2262}
2263
2264int external_print=0;
2265
2266void start_sound(int argc, char **argv)
2267{
2268  sfx_volume=music_volume=127;
2269
2270  for (int i=1;i<argc;i++)
2271    if (!strcmp(argv[i],"-sfx_volume"))
2272    {
2273      i++;
2274      if (atoi(argv[i])>=0 && atoi(argv[i])<127)
2275        sfx_volume=atoi(argv[i]);
2276      else printf("Bad sound effects volume level, use 0..127\n");     
2277    }
2278    else if (!strcmp(argv[i],"-music_volume"))
2279    {
2280      i++;
2281      if (atoi(argv[i])>=0 && atoi(argv[i])<127)
2282        music_volume=atoi(argv[i]);
2283      else printf("Bad music volume level, use 0..127\n");     
2284    }
2285
2286  sound_avail=sound_init(argc,argv);
2287}
2288
2289void game_printer(char *st)
2290{
2291  if (dev_console && !external_print)
2292  {
2293    dev_console->put_string(st);
2294  }
2295  else fprintf(stderr,"%s",st);
2296}
2297
2298
2299void game_getter(char *st, int max)
2300{
2301  if (!max) return ;
2302  max--;
2303  *st=0;
2304  if (dev_console && !external_print)
2305  {   
2306    dev_console->show();
2307    int t=0;
2308    event ev;
2309    do
2310    {
2311      get_event(ev,eh);
2312      if (ev.type==EV_KEY)
2313      {
2314        if (ev.key==JK_BACKSPACE)
2315        {
2316          if (t)
2317          {
2318            dev_console->print_f("%c",ev.key);
2319            t--;
2320            st--;
2321            *st=0;
2322            max++;
2323          }
2324        } else if (ev.key>=' ' && ev.key<='~')
2325        {
2326          dev_console->print_f("%c",ev.key);
2327          *st=ev.key;
2328          t++;
2329          max--;
2330          st++;
2331          *st=0;
2332        }                         
2333      }
2334      eh->flush_screen();
2335    } while (ev.type!=EV_KEY || ev.key!=JK_ENTER);   
2336    dprintf("\n");
2337  }
2338  else
2339  {
2340    if (fgets(st,max,stdin))
2341    {
2342      if (*st)
2343        st[strlen(st)-1]=0;
2344    }
2345  }
2346}
2347
2348
2349void show_startup()
2350{
2351  show_verinfo(start_argc,start_argv);
2352}
2353
2354char *get_line(int open_braces)
2355{
2356  char *line=(char *)jmalloc(1000,"lstring");
2357  fgets(line,1000,stdin);
2358
2359  char prev=' ';
2360  for (char *s=line;*s && (prev!=' ' || *s!=';');s++)
2361  {
2362    prev=*s;
2363    if (*s=='(') open_braces++;
2364    else if (*s==')') open_braces--;
2365  }
2366  if (open_braces<0)   
2367    fprintf(stderr,"\nToo many )'s\n");
2368  else if (open_braces>0)
2369  {
2370    char *s2=get_line(open_braces);
2371    line=(char *)jrealloc(line,strlen(line)+strlen(s2)+1,"lstring");
2372    strcat(line,s2);
2373    jfree(s2);   
2374  } 
2375  return line;
2376}
2377
2378void check_for_upgrade(int argc, char **argv)
2379{
2380  for (int i=1;i<argc;i++)
2381    if (!strcmp(argv[i],"-upgrade"))
2382    {
2383      lisp_init(0xf000,0x30000);
2384      char const *prog="(load \"lisp/upgrade.lsp\")";
2385      char const *cs = prog;
2386      if (!eval(compile(cs)))
2387        printf("file does not exists : lisp/upgrade.lsp, cannot upgrade\n");
2388
2389      exit(0);
2390    }       
2391}
2392
2393void check_for_lisp(int argc, char **argv)
2394{
2395        for( int i = 1; i < argc; i++ )
2396        {
2397                if( !strcmp( argv[i], "-lisp" ) )
2398                {
2399                        lisp_init(0xf000,0x30000);
2400                        char const *eof_char = "CTRL-D";
2401                        fprintf(stderr,
2402                                        " CLIVE (C) 1995 Jonathan Clark, all rights reserved\n"
2403                                        "   (C LISP interpreter and various extentions)\n"
2404                                        "Type (%s) to exit\n",eof_char);
2405
2406                        while (!feof(stdin))
2407                        {
2408                                fprintf(stderr,"Lisp> ");
2409                                char *l = get_line(0);
2410                                char const *s = l;
2411                                while (*s)
2412                                {
2413                                        void *prog=compile(s);
2414                                        l_user_stack.push(prog);
2415                                        while (*s==' ' || *s=='\t' || *s=='\r' || *s=='\n') s++;
2416                                        lprint(eval(prog));
2417                                        l_user_stack.pop(1);
2418                                }
2419                                jfree(l);
2420                        }
2421                        fprintf(stderr,"End of input : bye\n");
2422                        exit(0);
2423                }
2424        }
2425}
2426
2427
2428void music_check()
2429{
2430  if (sound_avail&MUSIC_INITIALIZED)
2431  {
2432    if (current_song && !current_song->playing())
2433    {
2434      current_song->play();
2435      dprintf("song finished\n");
2436    }
2437    if (!current_song)
2438    {
2439
2440      current_song=new song("music/intro.hmi");
2441      current_song->play(music_volume);
2442
2443/*      if (DEFINEDP(symbol_function(l_next_song)))  // if user function installed, call it to load up next song
2444      {
2445        int sp=current_space;
2446        current_space=PERM_SPACE;
2447        eval_function((lisp_symbol *)l_next_song,NULL);
2448        current_space=sp;
2449      } */
2450    }
2451  }
2452}
2453
2454void setup(int argc, char **argv);
2455
2456void share_end();
2457void show_end();
2458
2459void show_sell(int abortable);
2460
2461extern pmenu *dev_menu;
2462
2463
2464extern int jmalloc_max_size;
2465extern int jmalloc_min_low_size;
2466
2467extern int (*verify_file_fun)(char *,char *);
2468
2469int registered_ok(char *filename, char *mode)
2470{
2471  if (registered) return 1;
2472
2473  char name[256],*c;
2474  c=name;
2475  while (*filename) { *c=*(filename++); *c=toupper(*c); c++; } *c=0;
2476  if (strstr(name,"REGISTER"))
2477    return 0;
2478  else return 1;
2479}
2480
2481void game_net_init(int argc, char **argv)
2482{
2483  int nonet=!net_init(argc, argv);
2484  if (nonet)
2485    dprintf("No network driver, or network driver returned failure\n");
2486  else
2487  {
2488    set_file_opener(open_nfs_file);
2489    if (main_net_cfg && main_net_cfg->state==net_configuration::CLIENT)
2490    {
2491      if (set_file_server(net_server))
2492      start_running=1;
2493      else
2494      {
2495                                dprintf("Unable to attach to server, quiting\n");
2496                                exit(0);
2497      }
2498    } else
2499    {
2500      int i;
2501      for (i=1;i<argc-1;i++)
2502      if (!strcmp(argv[i],"-fs"))
2503      if (!set_file_server(argv[i+1]))
2504      dprintf("could not set defualt file server to %s\n",argv[i+1]);
2505    }
2506  }     
2507
2508}
2509
2510#if (defined(__APPLE__) && !defined(__MACH__))
2511extern int PixMult;
2512#if 1
2513char cmdline[256];
2514#elif 1
2515char cmdline[] = "";
2516#elif 1
2517char cmdline[] = "abuse -server -a deathmat";
2518#else
2519char cmdline[] = "abuse -net 193.246.40.9";
2520#endif
2521char delims[] = " ";
2522char *tmp_argv[255];
2523
2524void GetArgs(int &argc, char **(&argv))
2525{
2526        char *s;
2527
2528        printf( "Usage:\n"
2529                                        "  abuse [-options]\n\n"
2530                                        "  Options:\n"
2531                                        "    -server -a deathmat        become a server for deathmatch game\n"
2532                                        "    -net <dotted ip address>   connect to a server\n\n"
2533                                        "Options for mac:\n"
2534                                        "  Hold down <control> for single pixel mode\n"
2535                                        "  Hold down <option> for edit mode\n"
2536                                        "  Hold down <left shift> for double size mode\n\n"
2537                                        "If started with no command line options, networking will attempt\n"
2538                                        "  to search the local network for servers\n\n"
2539        );
2540        printf("Enter command line:\n");
2541        gets(cmdline);
2542       
2543        argc = 0;
2544        argv = tmp_argv;
2545        s = strtok(cmdline, delims);
2546        while (s)
2547        {
2548                argv[argc] = s;
2549                argc++;
2550                s = strtok(0, delims);
2551        }
2552        argv[argc] = 0;
2553}
2554
2555#endif
2556
2557int main(int argc, char **argv)
2558{
2559#if (defined(__APPLE__) && !defined(__MACH__))
2560        GetArgs(argc,argv);
2561#endif
2562
2563        start_argc = argc;
2564        start_argv = argv;
2565
2566        for( int i = 0; i < argc; i++ )
2567        {
2568                if( !strcmp( argv[i], "-cprint" ) )
2569                {
2570                        external_print = 1;
2571                }
2572
2573                if( !strcmp( argv[i], "-min_low" ) )
2574                {
2575                        i++;
2576                        jmalloc_min_low_size = atoi( argv[i] );
2577                }
2578        }
2579
2580//  jmalloc_max_size=0x150000;
2581        jmalloc_init( 0x150000 );
2582//  jmalloc_init(100000);
2583
2584#if (defined(__APPLE__) && !defined(__MACH__))
2585        unsigned char km[16];
2586
2587        fprintf(stderr,"Mac Options: ");
2588        xres = 320; yres = 200;
2589        GetKeys((uint32_t*)&km);
2590        if ((km[ 0x3a >>3] >> (0x3a & 7)) &1 != 0)
2591        {
2592                dev|=EDIT_MODE;   
2593                start_edit=1;
2594                start_running=1;
2595                disable_autolight=1;
2596                fprintf(stderr,"Edit Mode...");
2597        }
2598        if ((km[ 0x3b >>3] >> (0x3b & 7)) &1 != 0)
2599        {
2600                PixMult = 1;
2601                fprintf(stderr,"Single Pixel...");
2602        }
2603        else
2604        {
2605                PixMult = 2;
2606                fprintf(stderr,"Double Pixel...");
2607        }
2608        if ((km[ 0x38 >>3] >> (0x38 & 7)) &1 != 0)
2609        {
2610                xres *= 2;  yres *= 2;
2611                fprintf(stderr,"Double Size...");
2612        }
2613        fprintf(stderr,"\n");
2614       
2615        if (tcpip.installed())
2616                fprintf(stderr, "Using %s\n", tcpip.name());
2617#endif
2618
2619        set_dprinter(game_printer);
2620        set_dgetter(game_getter);
2621        set_no_space_handler(handle_no_space);
2622
2623        setup(argc,argv);
2624
2625        show_startup();
2626
2627        start_sound(argc,argv);
2628
2629        stat_man = new text_status_manager();
2630        if( !get_option("-no_timer") )
2631        {
2632                timer_init();
2633        }
2634
2635        // look to see if we are supposed to fetch the data elsewhere
2636        if( getenv("ABUSE_PATH") )
2637        {
2638                set_filename_prefix( getenv( "ABUSE_PATH" ) );
2639        }
2640
2641        // look to see if we are supposed to save the data elsewhere
2642        if( getenv( "ABUSE_SAVE_PATH" ) )
2643        {
2644                set_save_filename_prefix( getenv( "ABUSE_SAVE_PATH" ) );
2645        }
2646
2647        if( !get_option( "-share" ) )
2648        {
2649                jFILE *fp = new jFILE( "register/micron.vcd", "rb" );
2650                if( !fp->open_failure() )
2651                {
2652                        spec_directory sd( fp );
2653                        if( sd.find( "Copyright (C) 1995 Crack dot Com, All Rights reserved" ) )
2654                        {
2655                                registered = 1;
2656                        }
2657                }
2658                delete fp;
2659        }
2660
2661        verify_file_fun = registered_ok;
2662
2663        jrand_init();
2664        jrand();                // so compiler doesn't complain
2665
2666        set_spec_main_file("abuse.spe");
2667
2668        check_for_lisp( argc, argv );
2669        check_for_upgrade( argc, argv );
2670
2671        do
2672        {
2673                if( main_net_cfg )
2674                {
2675                        if( !main_net_cfg->notify_reset() )
2676                        {
2677                                if( !get_option( "-no_timer" ) )
2678                                        timer_uninit();
2679                                sound_uninit();
2680                                exit(0);
2681                        }
2682                }
2683
2684                game_net_init(argc,argv);
2685                lisp_init(0x16000,0x94000);
2686//              lisp_init(0x100000,0x10000);
2687
2688                dev_init(argc,argv);
2689
2690                game *g = new game( argc, argv );
2691
2692                dev_cont=new dev_controll();
2693                dev_cont->load_stuff();
2694
2695                g->get_input();         // prime the net
2696
2697                int xx;
2698                for( xx = 1; xx < argc; xx++ )
2699                {
2700                        if (!strcmp(argv[xx],"-server"))
2701                        {
2702                                xx++;
2703                                if( !become_server( argv[xx] ) )
2704                                {
2705                                        dprintf( "unable to become a server\n" );
2706                                        exit(0);
2707                                }
2708                                xx = argc + 1;
2709                        }
2710                }
2711
2712                if( main_net_cfg )
2713                {
2714                        wait_min_players();
2715                }
2716
2717                net_send( 1 );
2718                if( net_start() )
2719                {
2720                        g->step();                              // process all the objects in the
2721                        g->calc_speed();
2722                        g->update_screen();             // redraw the screen with any changes
2723                }
2724
2725    while (!g->done())
2726    {
2727      music_check();
2728
2729      if (req_end)
2730      {
2731                                delete current_level;
2732                                current_level=NULL;
2733                               
2734                                if (!registered)
2735                                share_end();
2736                                else show_end();
2737                       
2738                                the_game->set_state(MENU_STATE);
2739                                req_end=0;
2740      }
2741
2742      if (demo_man.current_state()==demo_manager::NORMAL)
2743      {
2744                                net_receive();
2745      }
2746
2747      if (req_name[0])            // see if a request for a level load was made during the last tick
2748      {
2749        g->load_level(req_name);
2750        req_name[0]=0;
2751        g->draw(g->state==SCENE_STATE);
2752      }
2753
2754      //    if (demo_man.current_state()!=demo_manager::PLAYING)
2755      g->get_input();
2756
2757      if (demo_man.current_state()==demo_manager::NORMAL)
2758      net_send();
2759      else demo_man.do_inputs();
2760
2761      service_net_request();
2762
2763      g->step();                        // process all the objects in the
2764
2765      server_check();
2766
2767      g->calc_speed();
2768      if (!req_name[0])                // see if a request for a level load was made during the last tick
2769        g->update_screen();               // redraw the screen with any changes
2770
2771
2772    }
2773
2774    net_uninit();
2775
2776    if (net_crcs)
2777    {
2778      net_crcs->clean_up();
2779      delete net_crcs;
2780      net_crcs=NULL;
2781    }
2782
2783    delete chat;
2784
2785    if (!registered)
2786    show_sell(0);
2787    else milli_wait(500);
2788
2789
2790    if (small_render) { delete small_render; small_render=NULL; }
2791
2792    if (current_song)
2793    { current_song->stop();
2794      delete current_song;
2795      current_song=NULL;
2796    }
2797
2798
2799    cash.empty();
2800
2801
2802    if (dev_console)
2803    {
2804      delete dev_console;
2805      dev_console=NULL;
2806    }
2807
2808    if (dev_menu)
2809    {
2810      delete dev_menu;
2811      dev_menu=NULL;
2812    }
2813
2814    delete g;
2815    if (old_pal) delete old_pal; old_pal=NULL;
2816    compiled_uninit();
2817    delete_all_lights();
2818    jfree(white_light_initial);
2819
2820    for (int i=0;i<TTINTS;i++) jfree(tints[i]);
2821
2822
2823    dev_cleanup();
2824    delete dev_cont; dev_cont=NULL;
2825    delete stat_man;
2826    stat_man=new text_status_manager();
2827
2828    if (!(main_net_cfg && main_net_cfg->restart_state()))
2829    {
2830      void *end_msg=make_find_symbol("end_msg");
2831      if (DEFINEDP(symbol_value(end_msg)))
2832      printf("%s\n",lstring_value(symbol_value(end_msg)));
2833    }
2834
2835    lisp_uninit();
2836
2837    base->packet.packet_reset();
2838    mem_report("end.mem");
2839  } while (main_net_cfg && main_net_cfg->restart_state());
2840
2841        delete stat_man;
2842
2843        if( main_net_cfg )
2844        {
2845                delete main_net_cfg;
2846                main_net_cfg=NULL;
2847        }
2848        set_filename_prefix(NULL);  // dealloc this mem if there was any
2849        set_save_filename_prefix(NULL);
2850
2851        if( !get_option( "-no_timer" ) )
2852        {
2853                timer_uninit();
2854        }
2855
2856// AK -> Commented this out to stop a crash as the file prefix has already
2857//       been released.  Need to fix this.
2858//      mem_report("end.mem");
2859
2860//      jmalloc_uninit();
2861        l_user_stack.clean_up();
2862        l_ptr_stack.clean_up();
2863
2864        sound_uninit();
2865
2866        exit(0);
2867
2868        return 0;
2869}
2870
2871
Note: See TracBrowser for help on using the repository browser.