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

Last change on this file since 507 was 507, checked in by Sam Hocevar, 7 years ago

game: coding style fixes to the main loop.

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