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

Last change on this file since 562 was 562, checked in by Sam Hocevar, 8 years ago

music: fix incorrect music volume set upon restart.

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