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
65 extern CrcManager *net_crcs;
66
67 Game *the_game = NULL;
68 WindowManager *wm = NULL;
69 int dev, shift_down = SHIFT_DOWN_DEFAULT, shift_right = SHIFT_RIGHT_DEFAULT;
70 double sum_diffs = 1, total_diffs = 12;
71 int total_active = 0;
72 int32_t map_xoff = 0, map_yoff = 0;
73 int32_t current_vxadd, current_vyadd;
74 int frame_panic = 0, massive_frame_panic = 0;
75 int demo_start = 0, idle_ticks = 0;
76 int req_end = 0;
77
78 extern palette *old_pal;
79 char **start_argv;
80 int start_argc;
81 int has_joystick = 0;
82 char req_name[100];
83
84 extern uint8_t chatting_enabled;
85
86 // Enabled TCPIP driver
87 #if !defined __CELLOS_LV2__
88 #include "tcpip.h"
89 tcpip_protocol tcpip;
90 #endif
91
open_FILE(char const * filename,char const * mode)92 FILE *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
handle_no_space()103 void 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
play_sound(int id,int vol,int32_t x,int32_t y)134 void 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
get_option(char const * name)182 int 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
make_screen_size(int w,int h)196 void 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
grow_views(int amount)219 void 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
pan(int xv,int yv)256 void Game::pan(int xv, int yv)
257 {
258 first_view->pan_x += xv;
259 first_view->pan_y += yv;
260 }
261
view_in(int mousex,int mousey)262 view *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
playing_state(int state)271 int playing_state(int state)
272 {
273 return state == RUN_STATE || state == PAUSE_STATE;
274 }
275
ftile_on(int screenx,int screeny,int32_t & x,int32_t & y)276 void 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
btile_on(int screenx,int screeny,int32_t & x,int32_t & y)283 void 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
mouse_to_game(int32_t x,int32_t y,int32_t & gamex,int32_t & gamey,view * f)300 void 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
game_to_mouse(int32_t gamex,int32_t gamey,view * which,int32_t & x,int32_t & y)323 void 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
window_state(int state)371 int 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
set_state(int new_state)391 void 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
joy_calb(event & ev)463 void 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
menu_select(event & ev)492 void 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
show_help(char const * st)506 void Game::show_help(char const *st)
507 {
508 strcpy(help_text, st);
509 help_text_frames = 0;
510 refresh = 1;
511 }
512
draw_value(image * screen,int x,int y,int w,int h,int val,int max)513 void 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
set_level(level * nl)521 void Game::set_level(level *nl)
522 {
523 if(current_level)
524 delete current_level;
525 current_level = nl;
526 }
527
load_level(char const * name)528 void 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
done()558 int Game::done()
559 {
560 return finished || (main_net_cfg && main_net_cfg->restart_state());
561 }
562
end_session()563 void 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
put_block_fg(int x,int y,TransImage * im)573 void 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
put_block_bg(int x,int y,image * im)592 void 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
614 int need_delay = 1;
615
dev_scroll()616 void 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
remap_area(image * screen,int x1,int y1,int x2,int y2,uint8_t * remap)677 void 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
post_render()696 static 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
draw_map(view * v,int interpolate)708 void 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
put_fg(int x,int y,int type)1129 void 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
put_bg(int x,int y,int type)1140 void 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
in_area(event & ev,int x1,int y1,int x2,int y2)1151 int 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
request_level_load(char * name)1157 void Game::request_level_load(char *name)
1158 {
1159 strcpy(req_name, name);
1160 }
1161
1162 extern int start_doubled;
1163
Fade(image * im,int steps)1164 template<int N> static void Fade(image *im, int steps)
1165 {
1166 /* 25ms per step */
1167 float const duration = 25.f;
1168
1169 palette *old_pal = pal->copy();
1170
1171 if (im)
1172 {
1173 screen->clear();
1174 im->put_image(screen, (xres + 1) / 2 - im->Size().x / 2,
1175 (yres + 1) / 2 - im->Size().y / 2);
1176 }
1177
1178 for (Timer total; total.PollMs() < duration * steps; )
1179 {
1180 Timer frame;
1181 uint8_t *sl1 = (uint8_t *)pal->addr();
1182 uint8_t *sl2 = (uint8_t *)old_pal->addr();
1183 int i = (int)(total.PollMs() / duration);
1184 int v = (N ? i + 1 : steps - i) * 256 / steps;
1185
1186 for (int j = 0; j < 3 * 256; j++)
1187 *sl1++ = (int)*sl2++ * v / 256;
1188
1189 pal->load();
1190 wm->flush_screen();
1191 frame.WaitMs(duration);
1192 }
1193
1194 if (N == 0)
1195 {
1196 screen->clear();
1197 wm->flush_screen();
1198 old_pal->load();
1199 }
1200 delete pal;
1201 pal = old_pal;
1202 }
1203
fade_in(image * im,int steps)1204 void fade_in(image *im, int steps)
1205 {
1206 Fade<1>(im, steps);
1207 }
1208
fade_out(int steps)1209 void fade_out(int steps)
1210 {
1211 Fade<0>(NULL, steps);
1212 }
1213
1214 int text_draw(int y, int x1, int y1, int x2, int y2, char const *buf, JCFont *font, uint8_t *cmap, char color);
1215
do_title()1216 void do_title()
1217 {
1218 if(cdc_logo == -1)
1219 return;
1220
1221 if(sound_avail & MUSIC_INITIALIZED)
1222 {
1223 if(current_song)
1224 {
1225 current_song->stop();
1226 delete current_song;
1227 }
1228 current_song = new song("music/intro.hmi");
1229 current_song->play(music_volume);
1230 }
1231
1232 void *logo_snd = LSymbol::FindOrCreate("LOGO_SND")->GetValue();
1233
1234 if(DEFINEDP(logo_snd) && (sound_avail & SFX_INITIALIZED))
1235 cache.sfx(lnumber_value(logo_snd))->play(sfx_volume);
1236
1237 // This must be a dynamic allocated image because if it
1238 // is not and the window gets closed during do_title, then
1239 // exit() will try to delete (through the desctructor of
1240 // image_list in image.cpp) the image on the stack -> boom.
1241 image *blank = new image(vec2i(2, 2));
1242 blank->clear();
1243 wm->set_mouse_shape(blank->copy(), 0, 0); // hide mouse
1244 delete blank;
1245 fade_in(cache.img(cdc_logo), 32);
1246 Timer tmp; tmp.WaitMs(400);
1247 fade_out(32);
1248
1249 void *space_snd = LSymbol::FindOrCreate("SPACE_SND")->GetValue();
1250 char *str = lstring_value(LSymbol::FindOrCreate("plot_start")->Eval());
1251
1252 bFILE *fp = open_file("art/smoke.spe", "rb");
1253 if(!fp->open_failure())
1254 {
1255 spec_directory sd(fp);
1256 palette *old_pal = pal;
1257 pal = new palette(sd.find(SPEC_PALETTE), fp);
1258 pal->shift(1);
1259
1260 image *gray = new image(fp, sd.find("gray_pict"));
1261 image *smoke[5];
1262
1263 char nm[20];
1264 for (int i = 0; i < 5; i++)
1265 {
1266 sprintf(nm, "smoke%04d.pcx", i + 1);
1267 smoke[i] = new image(fp, sd.find(nm));
1268 }
1269
1270 screen->clear();
1271 pal->load();
1272
1273 int dx = (xres + 1) / 2 - gray->Size().x / 2, dy = (yres + 1) / 2 - gray->Size().y / 2;
1274 gray->put_image(screen, dx, dy);
1275 smoke[0]->put_image(screen, dx + 24, dy + 5);
1276
1277 fade_in(NULL, 16);
1278 uint8_t cmap[32];
1279 for(int i = 0; i < 32; i++)
1280 cmap[i] = pal->find_closest(i * 256 / 32, i * 256 / 32, i * 256 / 32);
1281
1282 event ev;
1283 ev.type = EV_SPURIOUS;
1284 Timer total;
1285
1286 while (ev.type != EV_KEY && ev.type != EV_MOUSE_BUTTON)
1287 {
1288 Timer frame;
1289
1290 // 120 ms per step
1291 int i = (int)(total.PollMs() / 120.f);
1292 if (i >= 400)
1293 break;
1294
1295 gray->put_image(screen, dx, dy);
1296 smoke[i % 5]->put_image(screen, dx + 24, dy + 5);
1297 text_draw(205 - i, dx + 15, dy, dx + 320 - 15, dy + 199, str, wm->font(), cmap, wm->bright_color());
1298 wm->flush_screen();
1299 time_marker now;
1300
1301 while(wm->event_waiting() && ev.type != EV_KEY)
1302 wm->get_event(ev);
1303
1304 if((i % 5) == 0 && DEFINEDP(space_snd) && (sound_avail & SFX_INITIALIZED))
1305 cache.sfx(lnumber_value(space_snd))->play(sfx_volume * 90 / 127);
1306
1307 frame.WaitMs(25.f);
1308 frame.GetMs();
1309 }
1310
1311 the_game->reset_keymap();
1312
1313 fade_out(16);
1314
1315 for (int i = 0; i < 5; i++)
1316 delete smoke[i];
1317 delete gray;
1318 delete pal;
1319 pal = old_pal;
1320 }
1321 delete fp;
1322
1323 if(title_screen >= 0)
1324 fade_in(cache.img(title_screen), 32);
1325 }
1326
1327 extern int start_edit;
1328
request_end()1329 void Game::request_end()
1330 {
1331 req_end = 1;
1332 }
1333
Game(int argc,char ** argv)1334 Game::Game(int argc, char **argv)
1335 {
1336 int i;
1337 req_name[0]=0;
1338 bg_xmul = bg_ymul = 1;
1339 bg_xdiv = bg_ydiv = 8;
1340 last_input = NULL;
1341 current_automap = NULL;
1342 current_level = NULL;
1343 refresh = 1;
1344 the_game = this;
1345 top_menu = joy_win = NULL;
1346 old_view = first_view = NULL;
1347 nplayers = 1;
1348
1349 help_text_frames = 0;
1350 strcpy(help_text, "");
1351
1352
1353 for(i = 1; i < argc; i++)
1354 if(!strcmp(argv[i], "-no_delay"))
1355 {
1356 no_delay = 1;
1357 dprintf("Frame delay off (-nodelay)\n");
1358 }
1359
1360
1361 image_init();
1362 zoom = 15;
1363 no_delay = 0;
1364
1365 if(get_option("-use_joy"))
1366 {
1367 has_joystick = joy_init(argc, argv);
1368 dprintf("Joystick : ");
1369 if(has_joystick) dprintf("detected\n");
1370 else dprintf("not detected\n");
1371 }
1372 else has_joystick = 0;
1373
1374 // Clean up that old crap
1375 char *fastpath = (char *)malloc(strlen(get_save_filename_prefix()) + 13);
1376 sprintf(fastpath, "%sfastload.dat", get_save_filename_prefix());
1377 unlink(fastpath);
1378 free(fastpath);
1379
1380 // ProfilerInit(collectDetailed, bestTimeBase, 2000, 200); //prof
1381 load_data(argc, argv);
1382 // ProfilerDump("\pabuse.prof"); //prof
1383 // ProfilerTerm();
1384
1385 get_key_bindings();
1386
1387 reset_keymap(); // we think all the keys are up right now
1388 finished = false;
1389
1390 calc_light_table(pal);
1391
1392 #if !defined __CELLOS_LV2__
1393 if(current_level == NULL && net_start()) // if we joined a net game get level from server
1394 {
1395 if(!request_server_entry())
1396 {
1397 exit(0);
1398 }
1399 net_reload();
1400 // load_level(NET_STARTFILE);
1401 }
1402 #endif
1403
1404 set_mode(19, argc, argv);
1405 if(get_option("-2") && (xres < 639 || yres < 399))
1406 {
1407 close_graphics();
1408 fprintf(stderr, "Resolution must be > 640x400 to use -2 option\n");
1409 exit(0);
1410 }
1411 pal->load();
1412
1413 recalc_local_view_space(); // now that we know what size the screen is...
1414
1415 dark_color = get_color(cache.img(window_colors)->Pixel(vec2i(2, 0)));
1416 bright_color = get_color(cache.img(window_colors)->Pixel(vec2i(0, 0)));
1417 med_color = get_color(cache.img(window_colors)->Pixel(vec2i(1, 0)));
1418
1419 morph_dark_color = get_color(cache.img(window_colors)->Pixel(vec2i(2, 1)));
1420 morph_bright_color = get_color(cache.img(window_colors)->Pixel(vec2i(0, 1)));
1421 morph_med_color = get_color(cache.img(window_colors)->Pixel(vec2i(1, 1)));
1422 morph_sel_frame_color = pal->find_closest(255, 255, 0);
1423 light_connection_color = morph_sel_frame_color;
1424
1425 if(NILP(symbol_value(l_default_font)))
1426 {
1427 printf("No font defined, set symbol default-font to an image name\n");
1428 exit(0);
1429 }
1430 int font_pict;
1431 if(big_font_pict != -1)
1432 {
1433 if(small_font_pict != -1)
1434 {
1435 if(xres/(start_doubled ? 2 : 1)>400)
1436 {
1437 font_pict = big_font_pict;
1438 }
1439 else font_pict = small_font_pict;
1440 } else font_pict = big_font_pict;
1441 } else font_pict = small_font_pict;
1442
1443 if(console_font_pict == -1) console_font_pict = font_pict;
1444 game_font = new JCFont(cache.img(font_pict));
1445
1446 console_font = new JCFont(cache.img(console_font_pict));
1447
1448 wm = new WindowManager(screen, pal, bright_color,
1449 med_color, dark_color, game_font);
1450
1451 delete stat_man; // move to a graphical status manager
1452 gui_status_manager *gstat = new gui_status_manager();
1453 gstat->set_window_title("status");
1454 stat_man = gstat;
1455
1456
1457 chat = new chat_console( console_font, 50, 6);
1458
1459 if(!wm->has_mouse())
1460 {
1461 close_graphics();
1462 image_uninit();
1463 printf("No mouse driver detected, please rectify.\n");
1464 exit(0);
1465 }
1466
1467
1468 gamma_correct(pal);
1469
1470 #if defined __CELLOS_LV2__
1471 if(!start_edit)
1472 do_title();
1473 #else
1474 if(main_net_cfg == NULL || (main_net_cfg->state != net_configuration::SERVER &&
1475 main_net_cfg->state != net_configuration::CLIENT))
1476 {
1477 if(!start_edit && !net_start())
1478 do_title();
1479 } else if(main_net_cfg && main_net_cfg->state == net_configuration::SERVER)
1480 {
1481 the_game->load_level(level_file);
1482 start_running = 1;
1483 }
1484 #endif
1485
1486
1487 dev|= DRAW_FG_LAYER | DRAW_BG_LAYER | DRAW_PEOPLE_LAYER | DRAW_HELP_LAYER | DRAW_LIGHTS | DRAW_LINKS;
1488
1489 if(dev & EDIT_MODE)
1490 set_frame_size(0);
1491 // do_intro();
1492 state = START_STATE; // first set the state to one that has windows
1493
1494
1495 if(start_running)
1496 set_state(RUN_STATE);
1497 else
1498 {
1499 screen->clear();
1500 if(title_screen >= 0)
1501 {
1502 image *tit = cache.img(title_screen);
1503 tit->put_image(screen, screen->Size().x/2 - tit->Size().x/2,
1504 screen->Size().y/2 - tit->Size().y/2);
1505 }
1506 set_state(MENU_STATE); // then go to menu state so windows will turn off
1507 }
1508 }
1509
1510 time_marker *led_last_time = NULL;
1511 static float avg_ms = 1000.0f / 15, possible_ms = 1000.0f / 15;
1512
toggle_delay()1513 void Game::toggle_delay()
1514 {
1515 no_delay = !no_delay;
1516 show_help(symbol_str(no_delay ? "delay_off" : "delay_on"));
1517 avg_ms = possible_ms = 1000.0f / 15;
1518 }
1519
show_time()1520 void Game::show_time()
1521 {
1522 if (!first_view || !fps_on)
1523 return;
1524
1525 char str[16];
1526 sprintf(str, "%ld", (long)(10000.0f / avg_ms));
1527 console_font->put_string(screen, first_view->cx1, first_view->cy1, str);
1528
1529 sprintf(str, "%d", total_active);
1530 console_font->put_string(screen, first_view->cx1, first_view->cy1 + 10, str);
1531 }
1532
update_screen()1533 void Game::update_screen()
1534 {
1535 if(state == HELP_STATE)
1536 draw_help();
1537 else if(current_level)
1538 {
1539 if(!(dev & EDIT_MODE) || refresh)
1540 {
1541 view *f = first_view;
1542 current_level->clear_active_list();
1543 for(; f; f = f->next)
1544 {
1545 if(f->focus)
1546 {
1547 int w, h;
1548
1549 w=(f->cx2 - f->cx1 + 1);
1550 h=(f->cy2 - f->cy1 + 1);
1551
1552 total_active += current_level->add_drawables(f->xoff()-w / 4, f->yoff()-h / 4,
1553 f->xoff()+w + w / 4, f->yoff()+h + h / 4);
1554
1555 }
1556 }
1557
1558 for(f = first_view; f; f = f->next)
1559 {
1560 if(f->drawable())
1561 {
1562 if(interpolate_draw)
1563 {
1564 draw_map(f, 1);
1565 wm->flush_screen();
1566 }
1567 draw_map(f, 0);
1568 }
1569 }
1570 if(current_automap)
1571 current_automap->draw();
1572 }
1573 if(state == PAUSE_STATE)
1574 {
1575 for(view *f = first_view; f; f = f->next)
1576 cache.img(pause_image)->put_image(screen, (f->cx1 + f->cx2)/2 - cache.img(pause_image)->Size().x/2,
1577 f->cy1 + 5, 1);
1578 }
1579
1580 show_time();
1581 }
1582
1583 if(state == RUN_STATE && cache.prof_is_on())
1584 cache.prof_poll_end();
1585
1586 wm->flush_screen();
1587
1588 }
1589
do_intro()1590 void Game::do_intro()
1591 {
1592
1593 }
1594
1595 // FIXME: refactor this to use the Lol Engine main fixed-framerate loop?
calc_speed()1596 int Game::calc_speed()
1597 {
1598 static Timer frame_timer;
1599 static int first = 1;
1600
1601 if (first)
1602 {
1603 first = 0;
1604 return 0;
1605 }
1606
1607 // Find average fps for last 10 frames
1608 float deltams = Max(1.0f, frame_timer.PollMs());
1609
1610 avg_ms = 0.9f * avg_ms + 0.1f * deltams;
1611 possible_ms = 0.9f * possible_ms + 0.1f * deltams;
1612
1613 if (avg_ms < 1000.0f / 14)
1614 massive_frame_panic = Max(0, Min(20, massive_frame_panic - 1));
1615
1616 int ret = 0;
1617
1618 if (dev & EDIT_MODE)
1619 {
1620 // ECS - Added this case and the wait. It's a cheap hack to ensure
1621 // that we don't exceed 30FPS in edit mode and hog the CPU.
1622 frame_timer.WaitMs(33);
1623 }
1624 else if (avg_ms < 1000.0f / 15 && need_delay)
1625 {
1626 frame_panic = 0;
1627 if (!no_delay)
1628 {
1629 frame_timer.WaitMs(1000.0f / 15);
1630 avg_ms -= 0.1f * deltams;
1631 avg_ms += 0.1f * 1000.0f / 15;
1632 }
1633 }
1634 else if (avg_ms > 1000.0f / 14)
1635 {
1636 if(avg_ms > 1000.0f / 10)
1637 massive_frame_panic++;
1638 frame_panic++;
1639 // All is lost, don't sleep during this frame
1640 ret = 1;
1641 }
1642
1643 // Ignore our wait time, we're more interested in the frame time
1644 frame_timer.GetMs();
1645 return ret;
1646 }
1647
1648 extern int start_edit;
1649
get_input()1650 void Game::get_input()
1651 {
1652 event ev;
1653 idle_ticks++;
1654 while(event_waiting())
1655 {
1656 get_event(ev);
1657
1658 if(ev.type == EV_MOUSE_MOVE)
1659 {
1660 last_input = ev.window;
1661 }
1662 // don't process repeated keys in the main window, it will slow down the game to handle such
1663 // useless events. However in other windows it might be useful, such as in input windows
1664 // where you want to repeatedly scroll down...
1665 if(ev.type != EV_KEY || !key_down(ev.key) || ev.window || (dev & EDIT_MODE))
1666 {
1667 #if !defined __CELLOS_LV2__
1668 if(ev.type == EV_KEY)
1669 {
1670 set_key_down(ev.key, 1);
1671 if(playing_state(state))
1672 {
1673 if(ev.key < 256)
1674 {
1675 if(chat && chat->chat_event(ev))
1676 base->packet.write_uint8(SCMD_CHAT_KEYPRESS);
1677 else
1678 base->packet.write_uint8(SCMD_KEYPRESS);
1679 }
1680 else
1681 base->packet.write_uint8(SCMD_EXT_KEYPRESS);
1682 base->packet.write_uint8(client_number());
1683 if(ev.key > 256)
1684 base->packet.write_uint8(ev.key - 256);
1685 else
1686 base->packet.write_uint8(ev.key);
1687 }
1688 }
1689 else if(ev.type == EV_KEYRELEASE)
1690 {
1691 set_key_down(ev.key, 0);
1692 if(playing_state(state))
1693 {
1694 if(ev.key < 256)
1695 base->packet.write_uint8(SCMD_KEYRELEASE);
1696 else
1697 base->packet.write_uint8(SCMD_EXT_KEYRELEASE);
1698 base->packet.write_uint8(client_number());
1699 if(ev.key > 255)
1700 base->packet.write_uint8(ev.key - 256);
1701 else
1702 base->packet.write_uint8(ev.key);
1703 }
1704 }
1705 #endif
1706
1707 if((dev & EDIT_MODE) || start_edit || ev.type == EV_MESSAGE)
1708 {
1709 dev_cont->handle_event(ev);
1710 }
1711
1712 view *v = first_view;
1713 for(; v; v = v->next)
1714 {
1715 if(v->local_player() && v->handle_event(ev))
1716 ev.type = EV_SPURIOUS; // if the event was used by the view, gobble it up
1717 }
1718
1719 if(current_automap)
1720 {
1721 current_automap->handle_event(ev);
1722 }
1723
1724 help_handle_event(ev);
1725 mousex = last_demo_mx;
1726 mousey = last_demo_my;
1727
1728 if(ev.type == EV_MESSAGE)
1729 {
1730 switch (ev.message.id)
1731 {
1732 case CALB_JOY:
1733 {
1734 if(!joy_win)
1735 {
1736 joy_win = wm->new_window(80, 50, -1, -1,
1737 new button(70, 9, JOY_OK, "OK",
1738 new info_field(0, 30, DEV_NULL,
1739 " Center joystick and\n"
1740 "press the fire button", NULL)),
1741 "Joystick");
1742 set_state(JOY_CALB_STATE);
1743 }
1744 }
1745 case TOP_MENU:
1746 {
1747 menu_select(ev);
1748 } break;
1749 case DEV_QUIT:
1750 {
1751 finished = true;
1752 } break;
1753 }
1754 }
1755 else if(ev.type == EV_CLOSE_WINDOW && ev.window == top_menu)
1756 {
1757 wm->close_window(top_menu);
1758 top_menu = NULL;
1759 }
1760
1761 switch(state)
1762 {
1763 case JOY_CALB_STATE:
1764 {
1765 joy_calb(ev);
1766 } break;
1767 case INTRO_START_STATE:
1768 {
1769 do_intro();
1770 if(dev & EDIT_MODE)
1771 set_state(RUN_STATE);
1772 else
1773 set_state(MENU_STATE);
1774 } break;
1775 case PAUSE_STATE:
1776 {
1777 if(ev.type == EV_KEY && (ev.key == JK_SPACE || ev.key == JK_ENTER))
1778 {
1779 set_state(RUN_STATE);
1780 }
1781 } break;
1782 case RUN_STATE:
1783 {
1784 if(ev.window == NULL)
1785 {
1786 switch (ev.type)
1787 {
1788 case EV_KEY:
1789 {
1790 switch (ev.key)
1791 {
1792 case 'm':
1793 {
1794 if(dev & MAP_MODE)
1795 dev -= MAP_MODE;
1796 else if((player_list && player_list->next) || dev & EDIT_MODE)
1797 dev |= MAP_MODE;
1798
1799 if(!(dev & MAP_MODE))
1800 {
1801 if(dev_cont->tbw)
1802 dev_cont->toggle_toolbar();
1803 edit_mode = ID_DMODE_DRAW;
1804 }
1805 need_refresh();
1806 } break;
1807 case 'v':
1808 {
1809 wm->push_event(new event(DO_VOLUME, NULL));
1810 } break;
1811 case 'p':
1812 {
1813 if(!(dev & EDIT_MODE) && (!main_net_cfg ||
1814 (main_net_cfg->state != net_configuration::SERVER &&
1815 main_net_cfg->state != net_configuration::CLIENT)))
1816 {
1817 set_state(PAUSE_STATE);
1818 }
1819 } break;
1820 case 'S':
1821 {
1822 if(start_edit)
1823 {
1824 wm->push_event(new event(ID_LEVEL_SAVE, NULL));
1825 }
1826 } break;
1827 case JK_TAB:
1828 if(start_edit)
1829 toggle_edit_mode();
1830 need_refresh();
1831 break;
1832 case 'c':
1833 case 'C':
1834 if(chatting_enabled && (!(dev & EDIT_MODE) && chat))
1835 chat->toggle();
1836 break;
1837 case '9':
1838 dev = dev ^ PERFORMANCE_TEST_MODE;
1839 need_refresh();
1840 break;
1841 }
1842 } break;
1843 case EV_RESIZE:
1844 {
1845 view *v;
1846 for(v = first_view; v; v = v->next) // see if any views need to change size
1847 {
1848 if(v->local_player())
1849 {
1850 int w = (xres - 10)/(small_render ? 2 : 1);
1851 int h = (yres - 10)/(small_render ? 2 : 1);
1852
1853 v->suggest.send_view = 1;
1854 v->suggest.cx1 = 5;
1855 v->suggest.cx2 = 5 + w;
1856 v->suggest.cy1 = 5;
1857 v->suggest.cy2 = 5 + h;
1858 v->suggest.pan_x = v->pan_x;
1859 v->suggest.pan_y = v->pan_y;
1860 v->suggest.shift_down = v->shift_down;
1861 v->suggest.shift_right = v->shift_right;
1862 }
1863 }
1864 draw();
1865 } break;
1866 case EV_REDRAW:
1867 {
1868 screen->AddDirty(ev.redraw.x1, ev.redraw.y1,
1869 ev.redraw.x2 + 1, ev.redraw.y2 + 1);
1870 } break;
1871 case EV_MESSAGE:
1872 {
1873 switch (ev.message.id)
1874 {
1875 case RAISE_SFX:
1876 case LOWER_SFX:
1877 case RAISE_MUSIC:
1878 case LOWER_MUSIC:
1879 {
1880 if(ev.message.id == RAISE_SFX && sfx_volume != 127)
1881 sfx_volume = Min(127, sfx_volume + 16);
1882 if(ev.message.id == LOWER_SFX && sfx_volume != 0)
1883 sfx_volume = Max(sfx_volume - 16, 0);
1884 if(ev.message.id == RAISE_MUSIC && music_volume != 126)
1885 {
1886 music_volume = Min(music_volume + 16, 127);
1887 if(current_song && (sound_avail & MUSIC_INITIALIZED))
1888 current_song->set_volume(music_volume);
1889 }
1890
1891 if(ev.message.id == LOWER_MUSIC && music_volume != 0)
1892 {
1893 music_volume = Max(music_volume - 16, 0);
1894 if(current_song && (sound_avail & MUSIC_INITIALIZED))
1895 current_song->set_volume(music_volume);
1896 }
1897
1898 ((button *)ev.message.data)->push();
1899 /* volume_window->inm->redraw();
1900 draw_value(volume_window->screen, 2, 43,
1901 (volume_window->x2()-volume_window->x1()-1), 8, sfx_volume, 127);
1902 draw_value(volume_window->screen, 2, 94,
1903 (volume_window->x2()-volume_window->x1()-1), 8, music_volume, 127);
1904 */
1905 break;
1906 }
1907 }
1908 }
1909 }
1910 }
1911 } break;
1912 }
1913 }
1914 }
1915 }
1916
1917
net_send(int force=0)1918 void net_send(int force = 0)
1919 {
1920 #if !defined __CELLOS_LV2__
1921 if((!(dev & EDIT_MODE)) || force)
1922 {
1923 if(demo_man.state == demo_manager::PLAYING)
1924 {
1925 base->input_state = INPUT_PROCESSING;
1926 } else
1927 {
1928
1929
1930
1931 if(!player_list->focus)
1932 {
1933 dprintf("Players have not been created\ncall create_players");
1934 exit(0);
1935 }
1936
1937
1938 view *p = player_list;
1939 for(; p; p = p->next)
1940 if(p->local_player())
1941 p->get_input();
1942
1943
1944 base->packet.write_uint8(SCMD_SYNC);
1945 base->packet.write_uint16(make_sync());
1946
1947 if(base->join_list)
1948 base->packet.write_uint8(SCMD_RELOAD);
1949
1950 // printf("save tick %d, pk size=%d, rand_on=%d, sync=%d\n", current_level->tick_counter(),
1951 // base->packet.packet_size(), rand_on, make_sync());
1952 send_local_request();
1953 }
1954 }
1955 #endif
1956 }
1957
net_receive()1958 void net_receive()
1959 {
1960 #if !defined __CELLOS_LV2__
1961 if(!(dev & EDIT_MODE) && current_level)
1962 {
1963 uint8_t buf[PACKET_MAX_SIZE + 1];
1964 int size;
1965
1966 if(demo_man.state == demo_manager::PLAYING)
1967 {
1968 if(!demo_man.get_packet(buf, size))
1969 size = 0;
1970 base->packet.packet_reset();
1971 base->mem_lock = 0;
1972 } else
1973 {
1974 size = get_inputs_from_server(buf);
1975 if(demo_man.state == demo_manager::RECORDING)
1976 demo_man.save_packet(buf, size);
1977 }
1978
1979 process_packet_commands(buf, size);
1980 }
1981 #endif
1982 }
1983
step()1984 void Game::step()
1985 {
1986 clear_tmp();
1987 if(current_level)
1988 {
1989 current_level->unactivate_all();
1990 total_active = 0;
1991 for(view *f = first_view; f; f = f->next)
1992 {
1993 if(f->focus)
1994 {
1995 f->update_scroll();
1996 int w, h;
1997
1998 w=(f->cx2 - f->cx1 + 1);
1999 h=(f->cy2 - f->cy1 + 1);
2000 total_active += current_level->add_actives(f->xoff()-w / 4, f->yoff()-h / 4,
2001 f->xoff()+w + w / 4, f->yoff()+h + h / 4);
2002 }
2003 }
2004 }
2005
2006 if(state == RUN_STATE)
2007 {
2008 if((dev & EDIT_MODE) || (main_net_cfg && (main_net_cfg->state == net_configuration::CLIENT ||
2009 main_net_cfg->state == net_configuration::SERVER)))
2010 idle_ticks = 0;
2011
2012 if(demo_man.current_state()==demo_manager::NORMAL && idle_ticks > 420 && demo_start)
2013 {
2014 idle_ticks = 0;
2015 set_state(MENU_STATE);
2016 }
2017 else if(!(dev & EDIT_MODE)) // if edit mode, then don't step anything
2018 {
2019 if(key_down(JK_ESC))
2020 {
2021 set_state(MENU_STATE);
2022 set_key_down(JK_ESC, 0);
2023 }
2024 ambient_ramp = 0;
2025 view *v;
2026 for(v = first_view; v; v = v->next)
2027 v->update_scroll();
2028
2029 cache.prof_poll_start();
2030 current_level->tick();
2031 sbar.step();
2032 } else
2033 dev_scroll();
2034 } else if(state == JOY_CALB_STATE)
2035 {
2036 event ev;
2037 joy_calb(ev);
2038 } else if(state == MENU_STATE)
2039 main_menu();
2040
2041 if((key_down('x') || key_down(JK_F4))
2042 && (key_down(JK_ALT_L) || key_down(JK_ALT_R))
2043 && confirm_quit())
2044 finished = true;
2045 }
2046
2047 extern void *current_demo;
2048
~Game()2049 Game::~Game()
2050 {
2051 current_demo = NULL;
2052 if(first_view == player_list) first_view = NULL;
2053 while(player_list)
2054 {
2055 view *p = player_list;
2056 game_object *o = p->focus;
2057 player_list = player_list->next;
2058 delete p;
2059 o->set_controller(NULL);
2060 if(current_level && o)
2061 current_level->delete_object(o);
2062 else delete o;
2063 }
2064
2065 if(current_level) { delete current_level; current_level = NULL; }
2066
2067 if(first_view != player_list)
2068 {
2069 while(player_list)
2070 {
2071 view *p = player_list;
2072 player_list = player_list->next;
2073 delete p;
2074 }
2075 }
2076
2077 while(first_view)
2078 {
2079 view *p = first_view;
2080 first_view = first_view->next;
2081 delete p;
2082 }
2083
2084 player_list = NULL;
2085
2086 if(old_view)
2087 {
2088 first_view = old_view;
2089 while(first_view)
2090 {
2091 view *p = first_view;
2092 first_view = first_view->next;
2093 delete p;
2094 }
2095 }
2096 old_view = NULL;
2097
2098 int i = 0;
2099 for(; i < total_objects; i++)
2100 {
2101 free(object_names[i]);
2102 delete figures[i];
2103 }
2104 free_pframes();
2105 delete pal;
2106 free(object_names);
2107 free(figures);
2108
2109 free(backtiles);
2110 free(foretiles);
2111 if(total_weapons)
2112 free(weapon_types);
2113
2114 config_cleanup();
2115 delete color_table;
2116 delete wm;
2117 delete game_font;
2118 delete big_font;
2119 delete console_font;
2120 if(total_help_screens)
2121 free(help_screens);
2122
2123 close_graphics();
2124 image_uninit();
2125 }
2126
2127
2128
draw(int scene_mode)2129 void Game::draw(int scene_mode)
2130 {
2131 screen->AddDirty(0, 0, xres + 1, yres + 1);
2132
2133 screen->clear();
2134
2135 if(scene_mode)
2136 {
2137 char const *helpstr = "ARROW KEYS CHANGE TEXT SPEED";
2138 wm->font()->put_string(screen, screen->Size().x/2-(wm->font()->width()*strlen(helpstr))/2 + 1,
2139 screen->Size().y-wm->font()->height()-5 + 1, helpstr, wm->dark_color());
2140 wm->font()->put_string(screen, screen->Size().x/2-(wm->font()->width()*strlen(helpstr))/2,
2141 screen->Size().y-wm->font()->height()-5, helpstr, wm->bright_color());
2142 }
2143 /* else
2144 {
2145 char *helpstr="PRESS h FOR HELP";
2146 wm->font()->put_string(screen, screen->Size().x-wm->font()->width()*strlen(helpstr)-5,
2147 screen->Size().y-wm->font()->height()-5, helpstr);
2148 }*/
2149 /* int dc = cache.img(window_colors)->pixel(0, 2);
2150 int mc = cache.img(window_colors)->pixel(1, 2);
2151 int bc = cache.img(window_colors)->pixel(2, 2);
2152 screen->line(0, 0, screen->Size().x-1, 0, dc);
2153 screen->line(0, 0, 0, screen->Size().y-1, dc);
2154 screen->line(0, screen->Size().y-1, screen->Size().x-1, screen->Size().y-1, bc);
2155 screen->line(screen->Size().x-1, 0, screen->Size().x-1, screen->Size().y-1, bc); */
2156
2157 for(view *f = first_view; f; f = f->next)
2158 draw_map(f, 0);
2159
2160 sbar.redraw(screen);
2161 }
2162
2163 int external_print = 0;
2164
start_sound(int argc,char ** argv)2165 void start_sound(int argc, char **argv)
2166 {
2167 sfx_volume = music_volume = 127;
2168
2169 for(int i = 1; i < argc; i++)
2170 if(!strcmp(argv[i], "-sfx_volume"))
2171 {
2172 i++;
2173 if(atoi(argv[i])>=0 && atoi(argv[i])<127)
2174 sfx_volume = atoi(argv[i]);
2175 else printf("Bad sound effects volume level, use 0..127\n");
2176 }
2177 else if(!strcmp(argv[i], "-music_volume"))
2178 {
2179 i++;
2180 if(atoi(argv[i])>=0 && atoi(argv[i])<127)
2181 music_volume = atoi(argv[i]);
2182 else printf("Bad music volume level, use 0..127\n");
2183 }
2184
2185 sound_avail = sound_init(argc, argv);
2186 }
2187
game_printer(char * st)2188 void game_printer(char *st)
2189 {
2190 if(dev_console && !external_print)
2191 {
2192 dev_console->put_string(st);
2193 }
2194 else fprintf(stderr, "%s", st);
2195 }
2196
2197
game_getter(char * st,int max)2198 void game_getter(char *st, int max)
2199 {
2200 if(!max) return;
2201 max--;
2202 *st = 0;
2203 if(dev_console && !external_print)
2204 {
2205 dev_console->show();
2206 int t = 0;
2207 event ev;
2208 do
2209 {
2210 get_event(ev);
2211 if(ev.type == EV_KEY)
2212 {
2213 if(ev.key == JK_BACKSPACE)
2214 {
2215 if(t)
2216 {
2217 dev_console->print_f("%c", ev.key);
2218 t--;
2219 st--;
2220 *st = 0;
2221 max++;
2222 }
2223 } else if(ev.key>=' ' && ev.key<='~')
2224 {
2225 dev_console->print_f("%c", ev.key);
2226 *st = ev.key;
2227 t++;
2228 max--;
2229 st++;
2230 *st = 0;
2231 }
2232 }
2233 wm->flush_screen();
2234 } while(ev.type != EV_KEY || ev.key != JK_ENTER);
2235 dprintf("\n");
2236 }
2237 else
2238 {
2239 if(fgets(st, max, stdin))
2240 {
2241 if(*st)
2242 st[strlen(st)-1]=0;
2243 }
2244 }
2245 }
2246
2247
show_startup()2248 void show_startup()
2249 {
2250 dprintf("Abuse version %s\n", PACKAGE_VERSION);
2251 }
2252
get_line(int open_braces)2253 char *get_line(int open_braces)
2254 {
2255 char *line=(char *)malloc(1000);
2256 fgets(line, 1000, stdin);
2257
2258 char prev=' ';
2259 for(char *s = line; *s && (prev!=' ' || *s!=';'); s++)
2260 {
2261 prev=*s;
2262 if(*s=='(') open_braces++;
2263 else if(*s==')') open_braces--;
2264 }
2265 if(open_braces < 0)
2266 fprintf(stderr, "\nToo many)'s\n");
2267 else if(open_braces > 0)
2268 {
2269 char *s2 = get_line(open_braces);
2270 line=(char *)realloc(line, strlen(line)+strlen(s2)+1);
2271 strcat(line, s2);
2272 free(s2);
2273 }
2274 return line;
2275 }
2276
check_for_lisp(int argc,char ** argv)2277 void check_for_lisp(int argc, char **argv)
2278 {
2279 for(int i = 1; i < argc; i++)
2280 {
2281 if(!strcmp(argv[i], "-lisp"))
2282 {
2283 lisp_init();
2284 char const *eof_char = "Ctrl-D";
2285 fprintf(stderr,
2286 " CLIVE (C) 1995 Jonathan Clark, all rights reserved\n"
2287 " (C LISP interpreter and various extentions)\n"
2288 "Type (%s) to exit\n", eof_char);
2289
2290 while(!feof(stdin))
2291 {
2292 fprintf(stderr, "Lisp> ");
2293 char *l = get_line(0);
2294 char const *s = l;
2295 while(*s)
2296 {
2297 LObject *prog = LObject::Compile(s);
2298 l_user_stack.push(prog);
2299 while(*s==' ' || *s=='\t' || *s=='\r' || *s=='\n') s++;
2300 prog->Eval()->Print();
2301 l_user_stack.pop(1);
2302 }
2303 free(l);
2304 }
2305 fprintf(stderr, "End of input : bye\n");
2306 exit(0);
2307 }
2308 }
2309 }
2310
2311
music_check()2312 void music_check()
2313 {
2314 if(sound_avail & MUSIC_INITIALIZED)
2315 {
2316 if(current_song && !current_song->playing())
2317 {
2318 current_song->play(music_volume);
2319 dprintf("song finished\n");
2320 }
2321 if(!current_song)
2322 {
2323
2324 current_song = new song("music/intro.hmi");
2325 current_song->play(music_volume);
2326
2327 /* if(DEFINEDP(symbol_function(l_next_song))) // if user function installed, call it to load up next song
2328 {
2329 int sp = current_space;
2330 current_space = PERM_SPACE;
2331 ((LSymbol *)l_next_song)->EvalFunction(NULL);
2332 current_space = sp;
2333 } */
2334 }
2335 }
2336 }
2337
2338 void setup(int argc, char **argv);
2339
2340 void share_end();
2341 void show_end();
2342
2343 void show_sell(int abortable);
2344
2345 extern pmenu *dev_menu;
2346
game_net_init(int argc,char ** argv)2347 void game_net_init(int argc, char **argv)
2348 {
2349 #if !defined __CELLOS_LV2__
2350 int nonet=!net_init(argc, argv);
2351 if(nonet)
2352 dprintf("No network driver, or network driver returned failure\n");
2353 else
2354 {
2355 set_file_opener(open_nfs_file);
2356 if(main_net_cfg && main_net_cfg->state == net_configuration::CLIENT)
2357 {
2358 if(set_file_server(net_server))
2359 start_running = 1;
2360 else
2361 {
2362 dprintf("Unable to attach to server, quitting\n");
2363 exit(0);
2364 }
2365 } else
2366 {
2367 int i;
2368 for(i = 1; i < argc - 1; i++)
2369 if(!strcmp(argv[i], "-fs"))
2370 if(!set_file_server(argv[i + 1]))
2371 dprintf("could not set default file server to %s\n", argv[i + 1]);
2372 }
2373 }
2374 #endif
2375 }
2376
main(int argc,char * argv[])2377 int main(int argc, char *argv[])
2378 {
2379 start_argc = argc;
2380 start_argv = argv;
2381
2382 for (int i = 0; i < argc; i++)
2383 {
2384 if (!strcmp(argv[i], "-cprint"))
2385 external_print = 1;
2386 }
2387
2388 #if (defined(__APPLE__) && !defined(__MACH__))
2389 unsigned char km[16];
2390
2391 fprintf(stderr, "Mac Options: ");
2392 xres = 320; yres = 200;
2393 GetKeys((uint32_t*)&km);
2394 if ((km[ 0x3a >>3] >> (0x3a & 7)) &1 != 0)
2395 {
2396 dev|=EDIT_MODE;
2397 start_edit = 1;
2398 start_running = 1;
2399 disable_autolight = 1;
2400 fprintf(stderr, "Edit Mode...");
2401 }
2402 if ((km[ 0x3b >>3] >> (0x3b & 7)) &1 != 0)
2403 {
2404 PixMult = 1;
2405 fprintf(stderr, "Single Pixel...");
2406 }
2407 else
2408 {
2409 PixMult = 2;
2410 fprintf(stderr, "Double Pixel...");
2411 }
2412 if ((km[ 0x38 >>3] >> (0x38 & 7)) &1 != 0)
2413 {
2414 xres *= 2; yres *= 2;
2415 fprintf(stderr, "Double Size...");
2416 }
2417 fprintf(stderr, "\n");
2418
2419 if (tcpip.installed())
2420 fprintf(stderr, "Using %s\n", tcpip.name());
2421 #endif
2422
2423 set_dprinter(game_printer);
2424 set_dgetter(game_getter);
2425 set_no_space_handler(handle_no_space);
2426
2427 setup(argc, argv);
2428
2429 show_startup();
2430
2431 start_sound(argc, argv);
2432
2433 stat_man = new text_status_manager();
2434
2435 #if !defined __CELLOS_LV2__
2436 // look to see if we are supposed to fetch the data elsewhere
2437 if (getenv("ABUSE_PATH"))
2438 set_filename_prefix(getenv("ABUSE_PATH"));
2439
2440 // look to see if we are supposed to save the data elsewhere
2441 if (getenv("ABUSE_SAVE_PATH"))
2442 set_save_filename_prefix(getenv("ABUSE_SAVE_PATH"));
2443 #endif
2444
2445 jrand_init();
2446 jrand(); // so compiler doesn't complain
2447
2448 set_spec_main_file("abuse.spe");
2449 check_for_lisp(argc, argv);
2450
2451 do
2452 {
2453 if (main_net_cfg && !main_net_cfg->notify_reset())
2454 {
2455 sound_uninit();
2456 exit(0);
2457 }
2458
2459 game_net_init(argc, argv);
2460 lisp_init();
2461
2462 dev_init(argc, argv);
2463
2464 Game *g = new Game(argc, argv);
2465
2466 dev_cont = new dev_controll();
2467 dev_cont->load_stuff();
2468
2469 g->get_input(); // prime the net
2470
2471 #if !defined __CELLOS_LV2__
2472 for (int i = 1; i + 1 < argc; i++)
2473 {
2474 if (!strcmp(argv[i], "-server"))
2475 {
2476 if (!become_server(argv[i + 1]))
2477 {
2478 dprintf("unable to become a server\n");
2479 exit(0);
2480 }
2481 break;
2482 }
2483 }
2484
2485 if (main_net_cfg)
2486 wait_min_players();
2487
2488 net_send(1);
2489 if (net_start())
2490 {
2491 g->step(); // process all the objects in the world
2492 g->calc_speed();
2493 g->update_screen(); // redraw the screen with any changes
2494 }
2495 #endif
2496
2497 while (!g->done())
2498 {
2499 music_check();
2500
2501 if (req_end)
2502 {
2503 delete current_level; current_level = NULL;
2504
2505 show_end();
2506
2507 the_game->set_state(MENU_STATE);
2508 req_end = 0;
2509 }
2510
2511 if (demo_man.current_state() == demo_manager::NORMAL)
2512 net_receive();
2513
2514 // see if a request for a level load was made during the last tick
2515 if (req_name[0])
2516 {
2517 g->load_level(req_name);
2518 req_name[0] = 0;
2519 g->draw(g->state == SCENE_STATE);
2520 }
2521
2522 //if (demo_man.current_state() != demo_manager::PLAYING)
2523 g->get_input();
2524
2525 if (demo_man.current_state() == demo_manager::NORMAL)
2526 net_send();
2527 else
2528 demo_man.do_inputs();
2529
2530 #if !defined __CELLOS_LV2__
2531 service_net_request();
2532 #endif
2533
2534 // process all the objects in the world
2535 g->step();
2536 #if !defined __CELLOS_LV2__
2537 server_check();
2538 #endif
2539 g->calc_speed();
2540
2541 // see if a request for a level load was made during the last tick
2542 if (!req_name[0])
2543 g->update_screen(); // redraw the screen with any changes
2544 }
2545
2546 #if !defined __CELLOS_LV2__
2547 net_uninit();
2548
2549 if (net_crcs)
2550 net_crcs->clean_up();
2551 delete net_crcs; net_crcs = NULL;
2552 #endif
2553
2554 delete chat;
2555
2556 Timer tmp; tmp.WaitMs(500);
2557
2558 delete small_render; small_render = NULL;
2559
2560 if (current_song)
2561 current_song->stop();
2562 delete current_song; current_song = NULL;
2563
2564 cache.empty();
2565
2566 delete dev_console; dev_console = NULL;
2567 delete dev_menu; dev_menu = NULL;
2568 delete g; g = NULL;
2569 delete old_pal; old_pal = NULL;
2570
2571 compiled_uninit();
2572 delete_all_lights();
2573 free(white_light_initial);
2574
2575 for (int i = 0; i < TTINTS; i++)
2576 free(tints[i]);
2577
2578 dev_cleanup();
2579 delete dev_cont; dev_cont = NULL;
2580 delete stat_man; stat_man = new text_status_manager();
2581
2582 if (!(main_net_cfg && main_net_cfg->restart_state()))
2583 {
2584 LSymbol *end_msg = LSymbol::FindOrCreate("end_msg");
2585 if (DEFINEDP(end_msg->GetValue()))
2586 printf("%s\n", lstring_value(end_msg->GetValue()));
2587 }
2588
2589 lisp_uninit();
2590
2591 #if !defined __CELLOS_LV2__
2592 base->packet.packet_reset();
2593 #endif
2594 }
2595 while (main_net_cfg && main_net_cfg->restart_state());
2596
2597 delete stat_man;
2598 delete main_net_cfg; main_net_cfg = NULL;
2599
2600 set_filename_prefix(NULL); // dealloc this mem if there was any
2601 set_save_filename_prefix(NULL);
2602
2603 sound_uninit();
2604
2605 return 0;
2606 }
2607
2608