1 /* Sarien - A Sierra AGI resource interpreter engine
2 * Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka
3 *
4 * $Id: op_cmd.c,v 1.118 2001/11/03 20:16:10 cmatsuoka Exp $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; see docs/COPYING for further details.
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include "sarien.h"
14 #include "agi.h"
15 #include "rand.h"
16 #include "sprite.h"
17 #include "graphics.h"
18 #include "keyboard.h"
19 #include "opcodes.h"
20 #include "menu.h"
21 #include "savegame.h"
22 #include "text.h"
23
24 #define p0 (p[0])
25 #define p1 (p[1])
26 #define p2 (p[2])
27 #define p3 (p[3])
28 #define p4 (p[4])
29 #define p5 (p[5])
30 #define p6 (p[6])
31
32 #define ip cur_logic->cIP
33 #define vt game.view_table[p0]
34
35 static struct agi_logic *cur_logic;
36
37 int timer_hack; /* Workaround for timer loop in MH1 */
38
39 #define _v game.vars
40 #define cmd(x) static void cmd_##x (UINT8 *p)
41
cmd(increment)42 cmd(increment) { if (_v[p0] != 0xff) ++_v[p0]; }
cmd(decrement)43 cmd(decrement) { if (_v[p0] != 0) --_v[p0]; }
cmd(assignn)44 cmd(assignn) { _v[p0] = p1; }
cmd(addn)45 cmd(addn) { _v[p0] += p1; }
cmd(subn)46 cmd(subn) { _v[p0] -= p1; }
cmd(assignv)47 cmd(assignv) { _v[p0] = _v[p1]; }
cmd(addv)48 cmd(addv) { _v[p0] += _v[p1]; }
cmd(subv)49 cmd(subv) { _v[p0] -= _v[p1]; }
cmd(mul_n)50 cmd(mul_n) { _v[p0] *= p1; }
cmd(mul_v)51 cmd(mul_v) { _v[p0] *= _v[p1]; }
cmd(div_n)52 cmd(div_n) { _v[p0] /= p1; }
cmd(div_v)53 cmd(div_v) { _v[p0] /= _v[p1]; }
cmd(random)54 cmd(random) { _v[p2] = rnd (1 + (p1 - p0)) + p0; }
cmd(lindirectn)55 cmd(lindirectn) { _v[_v[p0]] = p1; }
cmd(lindirectv)56 cmd(lindirectv) { _v[_v[p0]] = _v[p1]; }
cmd(rindirect)57 cmd(rindirect) { _v[p0] = _v[_v[p1]]; }
cmd(set)58 cmd(set) { setflag (*p, TRUE); }
cmd(reset)59 cmd(reset) { setflag (*p, FALSE); }
cmd(toggle)60 cmd(toggle) { setflag (*p, !getflag (*p)); }
cmd(set_v)61 cmd(set_v) { setflag (_v[p0], TRUE); }
cmd(reset_v)62 cmd(reset_v) { setflag (_v[p0], FALSE); }
cmd(toggle_v)63 cmd(toggle_v) { setflag (_v[p0], !getflag (*p)); }
cmd(new_room)64 cmd(new_room) { new_room (p0); }
cmd(new_room_f)65 cmd(new_room_f) { new_room (_v[p0]); }
cmd(load_view)66 cmd(load_view) { agi_load_resource (rVIEW, p0); }
cmd(load_logic)67 cmd(load_logic) { agi_load_resource (rLOGIC, p0); }
cmd(load_sound)68 cmd(load_sound) { agi_load_resource (rSOUND, p0); }
cmd(load_view_f)69 cmd(load_view_f) { agi_load_resource (rVIEW, _v[p0]); }
cmd(load_logic_f)70 cmd(load_logic_f) { agi_load_resource (rLOGIC, _v[p0] ); }
cmd(discard_view)71 cmd(discard_view) { agi_unload_resource (rVIEW, p0); }
cmd(object_on_anything)72 cmd(object_on_anything) { vt.flags &= ~(ON_WATER | ON_LAND); }
cmd(object_on_land)73 cmd(object_on_land) { _D ("p0 = %d", p0); vt.flags |= ON_LAND; }
cmd(object_on_water)74 cmd(object_on_water) { _D ("p0 = %d", p0); vt.flags |= ON_WATER; }
cmd(observe_horizon)75 cmd(observe_horizon) { _D ("p0 = %d", p0); vt.flags &= ~IGNORE_HORIZON; }
cmd(ignore_horizon)76 cmd(ignore_horizon) { _D ("p0 = %d", p0); vt.flags |= IGNORE_HORIZON; }
cmd(observe_objs)77 cmd(observe_objs) { _D ("p0 = %d", p0); vt.flags &= ~IGNORE_OBJECTS; }
cmd(ignore_objs)78 cmd(ignore_objs) { _D ("p0 = %d", p0); vt.flags |= IGNORE_OBJECTS; }
cmd(observe_blocks)79 cmd(observe_blocks) { _D ("p0 = %d", p0); vt.flags &= ~IGNORE_BLOCKS; }
cmd(ignore_blocks)80 cmd(ignore_blocks) { _D ("p0 = %d", p0); vt.flags |= IGNORE_BLOCKS; }
cmd(set_horizon)81 cmd(set_horizon) { _D ("p0 = %d", p0); game.horizon = p0; }
cmd(get_priority)82 cmd(get_priority) { _v[p1] = vt.priority; }
cmd(set_priority)83 cmd(set_priority) { vt.flags |= FIXED_PRIORITY; vt.priority = p1; }
cmd(set_priority_f)84 cmd(set_priority_f) { vt.flags |= FIXED_PRIORITY; vt.priority = _v[p1]; }
cmd(release_priority)85 cmd(release_priority) { vt.flags &= ~FIXED_PRIORITY; }
cmd(set_upper_left)86 cmd(set_upper_left) { /* do nothing (AGI 2.917) */ }
cmd(start_update)87 cmd(start_update) { start_update (&vt); }
cmd(stop_update)88 cmd(stop_update) { stop_update (&vt); }
cmd(current_view)89 cmd(current_view) { _v[p1] = vt.current_view; }
cmd(current_cel)90 cmd(current_cel) { _v[p1] = vt.current_cel; _D ("v%d=%d", p1, _v[p1]); }
cmd(current_loop)91 cmd(current_loop) { _v[p1] = vt.current_loop; }
cmd(last_cel)92 cmd(last_cel) { _v[p1] = vt.loop_data->num_cels - 1; }
cmd(set_cel)93 cmd(set_cel) { set_cel (&vt, p1); vt.flags &= ~DONTUPDATE; }
cmd(set_cel_f)94 cmd(set_cel_f) { set_cel (&vt, _v[p1]); vt.flags &= ~DONTUPDATE; }
cmd(set_view)95 cmd(set_view) { set_view (&vt, p1); }
cmd(set_view_f)96 cmd(set_view_f) { set_view (&vt, _v[p1]); }
cmd(set_loop)97 cmd(set_loop) { set_loop (&vt, p1); }
cmd(set_loop_f)98 cmd(set_loop_f) { set_loop (&vt, _v[p1]); }
cmd(number_of_loops)99 cmd(number_of_loops) { _v[p1] = vt.num_loops; }
cmd(fix_loop)100 cmd(fix_loop) { vt.flags |= FIX_LOOP; }
cmd(release_loop)101 cmd(release_loop) { vt.flags &= ~FIX_LOOP; }
cmd(step_size)102 cmd(step_size) { vt.step_size = _v[p1]; }
cmd(step_time)103 cmd(step_time) { vt.step_time = vt.step_time_count = _v[p1]; }
cmd(cycle_time)104 cmd(cycle_time) { vt.cycle_time = vt.cycle_time_count = _v[p1]; }
cmd(stop_cycling)105 cmd(stop_cycling) { vt.flags &= ~CYCLING; }
cmd(start_cycling)106 cmd(start_cycling) { vt.flags |= CYCLING; }
cmd(normal_cycle)107 cmd(normal_cycle) { vt.cycle = CYCLE_NORMAL; vt.flags |= CYCLING; }
cmd(reverse_cycle)108 cmd(reverse_cycle) { vt.cycle = CYCLE_REVERSE; vt.flags |= CYCLING; }
cmd(set_dir)109 cmd(set_dir) { vt.direction = _v[p1]; }
cmd(get_dir)110 cmd(get_dir) { _v[p1] = vt.direction; }
cmd(get_room_f)111 cmd(get_room_f) { _v[p1] = object_get_location (_v[p0]); }
cmd(put)112 cmd(put) { object_set_location (p0, _v[p1]); }
cmd(put_f)113 cmd(put_f) { object_set_location (_v[p0], _v[p1]); }
cmd(drop)114 cmd(drop) { object_set_location (p0, 0); }
cmd(get)115 cmd(get) { object_set_location (p0, EGO_OWNED); }
cmd(get_f)116 cmd(get_f) { object_set_location (_v[p0], EGO_OWNED); }
cmd(parse)117 cmd(parse) { dictionary_words (agi_sprintf(game.strings[p0])); }
cmd(set_text_attribute)118 cmd(set_text_attribute) { game.color_fg = p0; game.color_bg = p1; }
cmd(shake_screen)119 cmd(shake_screen) { shake_screen (p0); }
cmd(word_to_string)120 cmd(word_to_string) { strcpy (game.strings[p0], game.ego_words[p1].word); }
cmd(open_dialogue)121 cmd(open_dialogue) { _D ("p0 = %d", p0); game.has_window = TRUE; }
cmd(close_dialogue)122 cmd(close_dialogue) { _D ("p0 = %d", p0); game.has_window = FALSE; }
cmd(close_window)123 cmd(close_window) { close_window (); }
cmd(status_line_on)124 cmd(status_line_on) { game.status_line = TRUE; write_status (); }
cmd(status_line_off)125 cmd(status_line_off) { game.status_line = FALSE; write_status (); }
cmd(show_obj)126 cmd(show_obj) { show_obj (p0); }
cmd(show_obj_v)127 cmd(show_obj_v) { show_obj (_v[p0]); }
cmd(sound)128 cmd(sound) { start_sound (p0, p1); }
cmd(stop_sound)129 cmd(stop_sound) { stop_sound (); }
cmd(accept_input)130 cmd(accept_input) { new_input_mode (INPUT_NORMAL); }
cmd(prevent_input)131 cmd(prevent_input) { new_input_mode (INPUT_NONE); }
cmd(menu_input)132 cmd(menu_input) { new_input_mode (INPUT_MENU); }
cmd(enable_item)133 cmd(enable_item) { menu_set_item (p0, TRUE); }
cmd(disable_item)134 cmd(disable_item) { menu_set_item (p0, FALSE); }
cmd(submit_menu)135 cmd(submit_menu) { submit_menu (); }
cmd(set_scan_start)136 cmd(set_scan_start) { cur_logic->sIP = cur_logic->cIP; }
cmd(reset_scan_start)137 cmd(reset_scan_start) { cur_logic->sIP = 2; }
cmd(save_game)138 cmd(save_game) { savegame_dialog (); }
cmd(load_game)139 cmd(load_game) { loadgame_dialog (); }
cmd(init_disk)140 cmd(init_disk) { /* do nothing */ }
cmd(log)141 cmd(log) { /* do nothing */ }
cmd(trace_on)142 cmd(trace_on) { /* do nothing */ }
cmd(trace_info)143 cmd(trace_info) { /* do nothing */ }
cmd(show_mem)144 cmd(show_mem) { message_box ("Enough memory"); }
cmd(init_joy)145 cmd(init_joy) { /* do nothing */; }
cmd(script_size)146 cmd(script_size) { report ("script.size(%d)\n", p0); }
cmd(cancel_line)147 cmd(cancel_line) { report ("cancel.line\n"); }
cmd(obj_status_f)148 cmd(obj_status_f) { report ("obj.status.f\n"); }
149
150 /* unknown commands:
151 * unk_170: Force savegame name -- j5
152 * unk_171: script save -- j5
153 * unk_172: script restore -- j5
154 * unk_173: Activate keypressed control (ego only moves while key is pressed)
155 * unk_174: Change priority table (used in KQ4) -- j5
156 * unk_177: Disable menus completely -- j5
157 * unk_181: Deactivate keypressed control (default control of ego)
158 */
cmd(set_simple)159 cmd(set_simple) { report ("set.simple\n"); }
cmd(pop_script)160 cmd(pop_script) { report ("pop.script\n"); }
cmd(hold_key)161 cmd(hold_key) { report ("hold.key\n"); }
cmd(discard_sound)162 cmd(discard_sound) { report ("discard.sound\n"); }
cmd(hide_mouse)163 cmd(hide_mouse) { report ("hide.mouse\n"); }
cmd(allow_menu)164 cmd(allow_menu) { report ("allow.menu\n"); }
cmd(show_mouse)165 cmd(show_mouse) { report ("show.mouse\n"); }
cmd(fence_mouse)166 cmd(fence_mouse) { report ("fence.mouse\n"); }
cmd(release_key)167 cmd(release_key) { report ("release.key\n"); }
cmd(adj_ego_move_to_xy)168 cmd(adj_ego_move_to_xy) { game.view_table[0].flags |= ADJ_EGO_XY; }
169
170
cmd(call)171 cmd(call) {
172 int old_cIP;
173 int old_lognum;
174
175 /* CM: we don't save sIP because set.scan.start can be
176 * used in a called script (fixes xmas demo)
177 */
178 old_cIP = cur_logic->cIP;
179 old_lognum = game.lognum;
180
181 run_logic (p0);
182
183 game.lognum = old_lognum;
184 cur_logic = &game.logics[game.lognum];
185 cur_logic->cIP = old_cIP;
186 }
187
cmd(call_f)188 cmd(call_f) {
189 cmd_call (&_v[p0]);
190 }
191
cmd(draw_pic)192 cmd(draw_pic) {
193 _D (_D_WARN "=== draw pic %d ===", _v[p0]);
194 erase_both ();
195 decode_picture (_v[p0], TRUE);
196 blit_both ();
197 game.picture_shown = 0;
198 _D (_D_WARN "--- end of draw pic %d ---", _v[p0]);
199 }
200
cmd(show_pic)201 cmd(show_pic) {
202 _D (_D_WARN "=== show pic ===");
203 setflag (F_output_mode, FALSE);
204 cmd_close_window (NULL);
205 show_pic ();
206 game.picture_shown = 1;
207 _D (_D_WARN "--- end of show pic ---");
208 }
209
cmd(load_pic)210 cmd(load_pic) {
211 erase_both ();
212 agi_load_resource (rPICTURE, _v[p0]);
213 blit_both ();
214 }
215
cmd(discard_pic)216 cmd(discard_pic) {
217 _D (_D_WARN "--- discard pic ---");
218 /* do nothing */
219 }
220
cmd(overlay_pic)221 cmd(overlay_pic) {
222 _D (_D_WARN "--- overlay pic ---");
223 erase_both ();
224 decode_picture (_v[p0], FALSE);
225 blit_both ();
226 game.picture_shown = 0;
227 commit_both ();
228 }
229
cmd(show_pri_screen)230 cmd(show_pri_screen) {
231 #ifdef USE_CONSOLE
232 debug.priority = 1;
233 erase_both();
234 show_pic ();
235 blit_both ();
236 wait_key ();
237 debug.priority = 0;
238 erase_both();
239 show_pic ();
240 blit_both ();
241 #endif
242 }
243
cmd(animate_obj)244 cmd(animate_obj) {
245 if (vt.flags & ANIMATED)
246 return;
247
248 _D (_D_WARN "animate vt entry #%d", p0);
249 vt.flags = ANIMATED | UPDATE | CYCLING;
250 vt.motion = MOTION_NORMAL;
251 vt.cycle = CYCLE_NORMAL;
252 vt.direction = 0;
253 }
254
cmd(unanimate_all)255 cmd(unanimate_all) {
256 int i;
257 for (i = 0; i < MAX_VIEWTABLE; i++)
258 game.view_table[i].flags &= ~(ANIMATED | DRAWN);
259 }
260
cmd(draw)261 cmd(draw) {
262 if (vt.flags & DRAWN)
263 return;
264
265 if (vt.y_size <= 0 || vt.x_size <= 0)
266 return;
267
268 vt.flags |= UPDATE;
269 fix_position (p0);
270 vt.x_pos2 = vt.x_pos;
271 vt.y_pos2 = vt.y_pos;
272 vt.cel_data_2 = vt.cel_data;
273 erase_upd_sprites ();
274 vt.flags |= DRAWN;
275 blit_upd_sprites ();
276 vt.flags &= ~DONTUPDATE;
277
278 commit_block (vt.x_pos, vt.y_pos - vt.y_size + 1,
279 vt.x_pos + vt.x_size - 1, vt.y_pos);
280
281 _D ("vt entry #%d flags = %02x", p0, vt.flags);
282 }
283
cmd(erase)284 cmd(erase) {
285 if (~vt.flags & DRAWN)
286 return;
287
288 erase_upd_sprites ();
289 if (vt.flags & UPDATE) {
290 vt.flags &= ~DRAWN;
291 } else {
292 erase_nonupd_sprites ();
293 vt.flags &= ~DRAWN;
294 blit_nonupd_sprites ();
295 }
296 blit_upd_sprites ();
297
298 commit_block (vt.x_pos, vt.y_pos - vt.y_size + 1,
299 vt.x_pos + vt.x_size - 1, vt.y_pos);
300 }
301
cmd(position)302 cmd(position) {
303 vt.x_pos = vt.x_pos2 = p1;
304 vt.y_pos = vt.y_pos2 = p2;
305 }
306
cmd(position_f)307 cmd(position_f) {
308 vt.x_pos = vt.x_pos2 = _v[p1];
309 vt.y_pos = vt.y_pos2 = _v[p2];
310 }
311
cmd(get_posn)312 cmd(get_posn) {
313 game.vars[p1] = (unsigned char)vt.x_pos;
314 game.vars[p2] = (unsigned char)vt.y_pos;
315 }
316
cmd(reposition)317 cmd(reposition) {
318 int dx = (SINT8)_v[p1], dy = (SINT8)_v[p2];
319
320 _D ("dx=%d, dy=%d", dx, dy);
321 vt.flags |= UPDATE_POS;
322
323 if (dx < 0 && vt.x_pos < dx)
324 vt.x_pos = 0;
325 else
326 vt.x_pos += dx;
327
328 if (dy < 0 && vt.y_pos < dy)
329 vt.y_pos = 0;
330 else
331 vt.y_pos += dy;
332
333 fix_position (p0);
334 }
335
cmd(reposition_to)336 cmd(reposition_to) {
337 vt.x_pos = p1;
338 vt.y_pos = p2;
339 vt.flags |= UPDATE_POS;
340 fix_position (p0);
341 }
342
cmd(reposition_to_f)343 cmd(reposition_to_f) {
344 vt.x_pos = _v[p1];
345 vt.y_pos = _v[p2];
346 vt.flags |= UPDATE_POS;
347 fix_position (p0);
348 }
349
cmd(add_to_pic)350 cmd(add_to_pic) {
351 add_to_pic (p0, p1, p2, p3, p4, p5, p6);
352 }
353
cmd(add_to_pic_f)354 cmd(add_to_pic_f) {
355 add_to_pic (_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]);
356 }
357
cmd(force_update)358 cmd(force_update) {
359 erase_both ();
360 blit_both ();
361 commit_both ();
362 }
363
cmd(reverse_loop)364 cmd(reverse_loop) {
365 vt.cycle = CYCLE_REV_LOOP;
366 vt.flags |= (DONTUPDATE|UPDATE|CYCLING);
367 vt.parm1 = p1;
368 setflag (p1, FALSE);
369 }
370
cmd(end_of_loop)371 cmd(end_of_loop) {
372 _D (_D_WARN "p0 = %d", p0);
373 vt.flags |= (DONTUPDATE|UPDATE|CYCLING);
374 vt.cycle = CYCLE_END_OF_LOOP;
375 vt.parm1 = p1;
376 }
377
cmd(block)378 cmd(block) {
379 _D (_D_WARN "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3);
380 game.block.active = TRUE;
381 game.block.x1 = p0;
382 game.block.y1 = p1;
383 game.block.x2 = p2;
384 game.block.y2 = p4;
385 }
386
cmd(unblock)387 cmd(unblock) {
388 game.block.active = FALSE;
389 }
390
cmd(normal_motion)391 cmd(normal_motion) {
392 vt.motion = MOTION_NORMAL;
393 }
394
cmd(stop_motion)395 cmd(stop_motion) {
396 vt.direction = 0;
397 vt.motion = MOTION_NORMAL;
398 if (p0 == 0) { /* ego only */
399 _v[V_ego_dir] = 0;
400 game.player_control = FALSE;
401 }
402 }
403
cmd(start_motion)404 cmd(start_motion) {
405 vt.motion = MOTION_NORMAL;
406 if (p0 == 0) { /* ego only */
407 _v[V_ego_dir] = 0;
408 game.player_control = TRUE;
409 }
410 }
411
cmd(player_control)412 cmd(player_control) {
413 game.player_control = TRUE;
414 game.view_table[0].motion = MOTION_NORMAL;
415 }
416
cmd(program_control)417 cmd(program_control) {
418 game.player_control = FALSE;
419 }
420
cmd(follow_ego)421 cmd(follow_ego) {
422 vt.motion = MOTION_FOLLOW_EGO;
423 vt.parm1 = p1 > vt.step_size ? p1 : vt.step_size;
424 vt.parm2 = p2;
425 vt.parm3 = 0xff;
426 setflag (p2, FALSE);
427 vt.flags |= UPDATE;
428 }
429
cmd(move_obj)430 cmd(move_obj) {
431 _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4);
432
433 vt.motion = MOTION_MOVE_OBJ;
434 vt.parm1 = p1;
435 vt.parm2 = p2;
436 vt.parm3 = vt.step_size;
437 vt.parm4 = p4;
438
439 if (p3 != 0)
440 vt.step_size = p3;
441
442 setflag (p4, FALSE);
443 vt.flags |= UPDATE;
444
445 if (p0 == 0)
446 game.player_control = FALSE;
447
448 move_obj (&vt);
449 }
450
cmd(move_obj_f)451 cmd(move_obj_f) {
452 vt.motion = MOTION_MOVE_OBJ;
453 vt.parm1 = _v[p1];
454 vt.parm2 = _v[p2];
455 vt.parm3 = vt.step_size;
456 vt.parm4 = p4;
457
458 if (_v[p3] != 0)
459 vt.step_size = _v[p3];
460
461 setflag (p4, FALSE);
462 vt.flags |= UPDATE;
463
464 if (p0 == 0)
465 game.player_control = FALSE;
466
467 move_obj (&vt);
468 }
469
cmd(wander)470 cmd(wander) {
471 if (p0 == 0)
472 game.player_control = FALSE;
473 vt.motion = MOTION_WANDER;
474 vt.flags |= UPDATE;
475 }
476
477
cmd(set_game_id)478 cmd(set_game_id) {
479 if (cur_logic->texts && (p0 - 1) <= cur_logic->num_texts)
480 strncpy (game.id, cur_logic->texts[p0 - 1], 8);
481 else
482 game.id[0] = 0;
483
484 report ("Game ID: \"%s\"\n", game.id);
485 }
486
cmd(pause)487 cmd(pause) {
488 int tmp = game.clock_enabled;
489 char *b[] = { "Continue", NULL };
490
491 game.clock_enabled = FALSE;
492 selection_box (" Game is paused. \n\n\n", b);
493 game.clock_enabled = tmp;
494 }
495
cmd(set_menu)496 cmd(set_menu) {
497 _D ("text %02x of %02x", p0, cur_logic->num_texts);
498 if (cur_logic->texts != NULL && p0 < cur_logic->num_texts)
499 add_menu (cur_logic->texts[p0 - 1]);
500 }
501
cmd(set_menu_item)502 cmd(set_menu_item) {
503 _D ("text %02x of %02x", p0, cur_logic->num_texts);
504 if (cur_logic->texts != NULL && p0 < cur_logic->num_texts)
505 add_menu_item (cur_logic->texts[p0 - 1], p1);
506 }
507
cmd(version)508 cmd(version) {
509 char ver_msg[] = TITLE " v" VERSION;
510 char ver2_msg[] =
511 "\n"
512 " \n\n"
513 "Emulating Sierra AGI v%x.%03x\n";
514 char ver3_msg[]=
515 "\n"
516 " \n\n"
517 " Emulating AGI v%x.002.%03x\n";
518 /* no Sierra as it wraps textbox */
519 char *r, *q;
520 int ver, maj, min;
521 char msg[256];
522
523 ver = agi_get_release ();
524 maj = (ver >> 12) & 0xf;
525 min = ver & 0xfff;
526
527 q = maj == 2 ? ver2_msg : ver3_msg;
528 r = strchr (q+1, '\n');
529
530 strncpy (q+1 + ((r-q > 0 ? r - q : 1) / 4), ver_msg, strlen (ver_msg));
531 sprintf (msg, q, maj, min);
532 message_box (msg);
533 }
534
cmd(configure_screen)535 cmd(configure_screen) {
536 game.line_min_print = p0;
537 game.line_user_input = p1;
538 game.line_status = p2;
539 }
540
cmd(text_screen)541 cmd(text_screen) {
542 _D (_D_WARN "switching to text mode");
543 game.gfx_mode = FALSE;
544 /*
545 * Simulates the "bright background bit" of the PC video
546 * controller.
547 */
548 if (game.color_bg)
549 game.color_bg |= 0x08;
550 clear_screen (game.color_bg);
551 }
552
cmd(graphics)553 cmd(graphics) {
554 _D (_D_WARN "switching to graphics mode");
555 if (!game.gfx_mode) {
556 game.gfx_mode = TRUE;
557 clear_screen (0);
558 show_pic ();
559 write_status ();
560 }
561 }
562
cmd(status)563 cmd(status) {
564 inventory();
565 }
566
cmd(quit)567 cmd(quit) {
568 char *buttons[] = { "Quit", "Continue", NULL };
569
570 stop_sound ();
571 if (p0) {
572 game.quit_prog_now = TRUE;
573 } else {
574 if (selection_box (" Quit the game, or continue? \n\n\n",
575 buttons) == 0)
576 {
577 game.quit_prog_now = TRUE;
578 }
579 }
580 }
581
cmd(restart_game)582 cmd(restart_game) {
583 char *buttons[] = { "Restart", "Continue", NULL };
584
585 stop_sound ();
586 /* FIXME: Test flag 16 */
587
588 if (selection_box (" Restart game, or continue? \n\n\n",
589 buttons) == 0)
590 {
591 game.quit_prog_now = 0xff;
592 setflag (F_restart_game, TRUE);
593 }
594 }
595
cmd(distance)596 cmd(distance) {
597 SINT16 x1, y1, x2, y2, d;
598 struct vt_entry *v0 = &game.view_table[p0];
599 struct vt_entry *v1 = &game.view_table[p1];
600
601 if (v0->flags & DRAWN && v1->flags & DRAWN) {
602 x1 = v0->x_pos + v0->x_size / 2;
603 y1 = v0->y_pos;
604 x2 = v1->x_pos + v1->x_size / 2;
605 y2 = v1->y_pos;
606 d = abs (x1 - x2) + abs (y1 - y2);
607 if (d > 0xfe) d = 0xfe;
608 } else {
609 d = 0xff;
610 }
611 _v[p2] = (unsigned char)d;
612 }
613
cmd(get_string)614 cmd(get_string) {
615 _D ("%d %d %d %d %d", p0, p1, p2, p3, p4);
616 new_input_mode (INPUT_GETSTRING);
617
618 if (cur_logic->texts != NULL && cur_logic->num_texts >= (p1 - 1)) {
619 int len = strlen (cur_logic->texts[p1 - 1]);
620 print_text (cur_logic->texts[p1 - 1], 0, p3,
621 p2, len, game.color_fg, game.color_bg);
622 get_string (p3 + len - 1, p2, p4, p0);
623
624 /* SGEO : display input char */
625 print_character ((p3 + len ), p2, game.cursor_char,
626 game.color_fg, game.color_bg);
627 }
628
629 do {
630 main_cycle ();
631 } while (game.input_mode == INPUT_GETSTRING);
632 }
633
634
cmd(get_num)635 cmd(get_num) {
636 _D ("%d %d", p0, p1);
637 new_input_mode (INPUT_GETSTRING);
638
639 if (cur_logic->texts != NULL && cur_logic->num_texts >= (p0 - 1)) {
640 int len = strlen (cur_logic->texts[p0 - 1]);
641 print_text (cur_logic->texts[p0 - 1], 0, 0, 22, len,
642 game.color_fg, game.color_bg);
643 get_string (len - 1, 22, 3, MAX_WORDS2);
644 }
645
646 do {
647 main_cycle ();
648 } while (game.input_mode == INPUT_GETSTRING);
649
650 _v[p1] = atoi (game.strings[MAX_WORDS2]);
651 _D (_D_WARN "[%s] -> %d", game.strings[MAX_WORDS2], _v[p1]);
652 clear_lines (22, 22, game.color_bg);
653 flush_lines (22, 22);
654 }
655
cmd(set_cursor_char)656 cmd(set_cursor_char)
657 {
658 if (cur_logic->texts != NULL && (p0 - 1) <= cur_logic->num_texts) {
659 game.cursor_char = *cur_logic->texts[p0 - 1];
660 } else {
661 /* default */
662 game.cursor_char = '_';
663 }
664 }
665
cmd(set_key)666 cmd(set_key) {
667 _D ("%d %d %d", p0, p1, p2);
668 if (p0 && p1) {
669 _D (_D_WARN "FIXME: not registered!");
670 return;
671 }
672 if (p0) { /* keypress */
673 game.ev_keyp[p2].data = p0;
674 game.ev_keyp[p2].occured = FALSE;
675 } else { /* scancode */
676 game.ev_scan[p2].data = p1;
677 game.ev_scan[p2].occured = FALSE;
678 }
679 }
680
cmd(set_string)681 cmd(set_string) {
682 /* CM: to avoid crash in Groza (str = 150) */
683 if (p0 > MAX_WORDS1) return;
684 strcpy (game.strings[p0], cur_logic->texts[p1 - 1]);
685 }
686
cmd(display)687 cmd(display) {
688 print_text (cur_logic->texts[p2 - 1], p1, 0, p0, 40,
689 game.color_fg, game.color_bg);
690 }
691
cmd(display_f)692 cmd(display_f) {
693 _D ("p0 = %d", p0);
694 print_text (cur_logic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40,
695 game.color_fg, game.color_bg);
696 }
697
cmd(clear_text_rect)698 cmd(clear_text_rect) {
699 int c, x1, y1, x2, y2;
700
701 if ((c = p4) != 0) c = 15;
702 x1 = p1 * CHAR_COLS;
703 y1 = p0 * CHAR_LINES;
704 x2 = (p3 + 1) * CHAR_COLS - 1;
705 y2 = (p2 + 1) * CHAR_LINES - 1;
706
707 /* Added to prevent crash with x2 = 40 in the iigs demo */
708 if (x1 > GFX_WIDTH) x1 = GFX_WIDTH - 1;
709 if (x2 > GFX_WIDTH) x2 = GFX_WIDTH - 1;
710 if (y1 > GFX_HEIGHT) y1 = GFX_HEIGHT - 1;
711 if (y2 > GFX_HEIGHT) y2 = GFX_HEIGHT - 1;
712
713 draw_rectangle (x1, y1, x2, y2, c);
714 flush_block (x1, y1, x2, y2);
715 }
716
cmd(toggle_monitor)717 cmd(toggle_monitor)
718 {
719 report ("toggle.monitor\n");
720 #ifdef USE_HIRES
721 opt.hires = !opt.hires;
722 erase_both();
723 show_pic ();
724 blit_both ();
725 #endif
726 }
727
cmd(echo_line)728 cmd(echo_line) {
729 strcpy (game.input_buffer, game.echo_buffer);
730 game.cursor_pos = strlen ((char*)game.input_buffer);
731 game.has_prompt = 0;
732 }
733
cmd(clear_lines)734 cmd(clear_lines) {
735 clear_lines (p0, p1, p2);
736 flush_lines (p0, p1);
737 }
738
cmd(print)739 cmd(print) {
740 int n = p0 < 1 ? 1 : p0;
741 print (cur_logic->texts[n - 1], 0, 0, 0);
742 }
743
cmd(print_f)744 cmd(print_f) {
745 int n = _v[p0] < 1 ? 1 : _v[p0];
746 print (cur_logic->texts[n - 1], 0, 0, 0);
747 }
748
cmd(print_at)749 cmd(print_at) {
750 int n = p0 < 1 ? 1 : p0;
751 print (cur_logic->texts[n - 1], p1, p2, p3);
752 }
753
cmd(print_at_v)754 cmd(print_at_v) {
755 int n = _v[p0] < 1 ? 1 : _v[p0];
756 print (cur_logic->texts[n - 1], p1, p2, p3);
757 }
758
cmd(push_script)759 cmd(push_script) {
760 #ifdef USE_MOUSE
761 if (opt.agimouse) {
762 game.vars[27] = mouse.button ? 1 : 0;
763 game.vars[28] = mouse.x;
764 game.vars[29] = mouse.y;
765 } else
766 #endif
767 report ("push.script\n");
768 }
769
cmd(set_pri_base)770 cmd(set_pri_base) {
771 int i, x, pri;
772
773 report ("Priority base set to %d\n", p0);
774
775 game.alt_pri = TRUE;
776 x = (_HEIGHT - p0) * _HEIGHT / 10;
777
778 for (i = 0; i < _HEIGHT; i++) {
779 pri = (i - p0) < 0 ? 4 : (i - p0) * _HEIGHT / x + 5;
780 if (pri > 15)
781 pri = 15;
782 game.pri_table[i] = pri;
783 }
784 }
785
cmd(mouse_posn)786 cmd(mouse_posn) {
787 #ifdef USE_MOUSE
788 _v[p0] = WIN_TO_PIC_X(mouse.x);
789 _v[p1] = WIN_TO_PIC_Y(mouse.y);
790 #endif
791 }
792
793
794 static void (*agi_command[183])(UINT8 *) = {
795 NULL, /* 0x00 */
796 cmd_increment,
797 cmd_decrement,
798 cmd_assignn,
799 cmd_assignv,
800 cmd_addn,
801 cmd_addv,
802 cmd_subn,
803 cmd_subv, /* 0x08 */
804 cmd_lindirectv,
805 cmd_rindirect,
806 cmd_lindirectn,
807 cmd_set,
808 cmd_reset,
809 cmd_toggle,
810 cmd_set_v,
811 cmd_reset_v, /* 0x10 */
812 cmd_toggle_v,
813 cmd_new_room,
814 cmd_new_room_f,
815 cmd_load_logic,
816 cmd_load_logic_f,
817 cmd_call,
818 cmd_call_f,
819 cmd_load_pic, /* 0x18 */
820 cmd_draw_pic,
821 cmd_show_pic,
822 cmd_discard_pic,
823 cmd_overlay_pic,
824 cmd_show_pri_screen,
825 cmd_load_view,
826 cmd_load_view_f,
827 cmd_discard_view, /* 0x20 */
828 cmd_animate_obj,
829 cmd_unanimate_all,
830 cmd_draw,
831 cmd_erase,
832 cmd_position,
833 cmd_position_f,
834 cmd_get_posn,
835 cmd_reposition, /* 0x28 */
836 cmd_set_view,
837 cmd_set_view_f,
838 cmd_set_loop,
839 cmd_set_loop_f,
840 cmd_fix_loop,
841 cmd_release_loop,
842 cmd_set_cel,
843 cmd_set_cel_f, /* 0x30 */
844 cmd_last_cel,
845 cmd_current_cel,
846 cmd_current_loop,
847 cmd_current_view,
848 cmd_number_of_loops,
849 cmd_set_priority,
850 cmd_set_priority_f,
851 cmd_release_priority, /* 0x38 */
852 cmd_get_priority,
853 cmd_stop_update,
854 cmd_start_update,
855 cmd_force_update,
856 cmd_ignore_horizon,
857 cmd_observe_horizon,
858 cmd_set_horizon,
859 cmd_object_on_water, /* 0x40 */
860 cmd_object_on_land,
861 cmd_object_on_anything,
862 cmd_ignore_objs,
863 cmd_observe_objs,
864 cmd_distance,
865 cmd_stop_cycling,
866 cmd_start_cycling,
867 cmd_normal_cycle, /* 0x48 */
868 cmd_end_of_loop,
869 cmd_reverse_cycle,
870 cmd_reverse_loop,
871 cmd_cycle_time,
872 cmd_stop_motion,
873 cmd_start_motion,
874 cmd_step_size,
875 cmd_step_time, /* 0x50 */
876 cmd_move_obj,
877 cmd_move_obj_f,
878 cmd_follow_ego,
879 cmd_wander,
880 cmd_normal_motion,
881 cmd_set_dir,
882 cmd_get_dir,
883 cmd_ignore_blocks, /* 0x58 */
884 cmd_observe_blocks,
885 cmd_block,
886 cmd_unblock,
887 cmd_get,
888 cmd_get_f,
889 cmd_drop,
890 cmd_put,
891 cmd_put_f, /* 0x60 */
892 cmd_get_room_f,
893 cmd_load_sound,
894 cmd_sound,
895 cmd_stop_sound,
896 cmd_print,
897 cmd_print_f,
898 cmd_display,
899 cmd_display_f, /* 0x68 */
900 cmd_clear_lines,
901 cmd_text_screen,
902 cmd_graphics,
903 cmd_set_cursor_char,
904 cmd_set_text_attribute,
905 cmd_shake_screen,
906 cmd_configure_screen,
907 cmd_status_line_on, /* 0x70 */
908 cmd_status_line_off,
909 cmd_set_string,
910 cmd_get_string,
911 cmd_word_to_string,
912 cmd_parse,
913 cmd_get_num,
914 cmd_prevent_input,
915 cmd_accept_input, /* 0x78 */
916 cmd_set_key,
917 cmd_add_to_pic,
918 cmd_add_to_pic_f,
919 cmd_status,
920 cmd_save_game,
921 cmd_load_game,
922 cmd_init_disk,
923 cmd_restart_game, /* 0x80 */
924 cmd_show_obj,
925 cmd_random,
926 cmd_program_control,
927 cmd_player_control,
928 cmd_obj_status_f,
929 cmd_quit,
930 cmd_show_mem,
931 cmd_pause, /* 0x88 */
932 cmd_echo_line,
933 cmd_cancel_line,
934 cmd_init_joy,
935 cmd_toggle_monitor,
936 cmd_version,
937 cmd_script_size,
938 cmd_set_game_id,
939 cmd_log, /* 0x90 */
940 cmd_set_scan_start,
941 cmd_reset_scan_start,
942 cmd_reposition_to,
943 cmd_reposition_to_f,
944 cmd_trace_on,
945 cmd_trace_info,
946 cmd_print_at,
947 cmd_print_at_v, /* 0x98 */
948 cmd_discard_view,
949 cmd_clear_text_rect,
950 cmd_set_upper_left,
951 cmd_set_menu,
952 cmd_set_menu_item,
953 cmd_submit_menu,
954 cmd_enable_item,
955 cmd_disable_item, /* 0xa0 */
956 cmd_menu_input,
957 cmd_show_obj_v,
958 cmd_open_dialogue,
959 cmd_close_dialogue,
960 cmd_mul_n,
961 cmd_mul_v,
962 cmd_div_n,
963 cmd_div_v, /* 0xa8 */
964 cmd_close_window,
965 cmd_set_simple,
966 cmd_push_script,
967 cmd_pop_script,
968 cmd_hold_key,
969 cmd_set_pri_base,
970 cmd_discard_sound,
971 cmd_hide_mouse, /* 0xb0 */
972 cmd_allow_menu,
973 cmd_show_mouse,
974 cmd_fence_mouse,
975 cmd_mouse_posn,
976 cmd_release_key,
977 cmd_adj_ego_move_to_xy
978 };
979
980
981 #define CMD_BSIZE 12
982
983 /**
984 * Execute a logic script
985 * @param n Number of the logic resource to execute
986 */
run_logic(int n)987 int run_logic (int n)
988 {
989 UINT8 op = 0;
990 UINT8 p[CMD_BSIZE] = {0};
991 UINT8 *code = NULL;
992 int num = 0;
993
994 /* If logic not loaded, load it */
995 if (~game.dir_logic[n].flags & RES_LOADED) {
996 _D (_D_WARN "logic %d not loaded!", n);
997 agi_load_resource (rLOGIC, n);
998 }
999
1000 game.lognum = n;
1001 cur_logic = &game.logics[game.lognum];
1002
1003 code = cur_logic->data;
1004 cur_logic->cIP = cur_logic->sIP;
1005
1006 timer_hack = 0;
1007 while (ip < game.logics[n].size && !game.quit_prog_now) {
1008 #ifdef USE_CONSOLE
1009 if (debug.enabled) {
1010 if (debug.steps > 0) {
1011 if (debug.logic0 || n) {
1012 debug_console (n,
1013 lCOMMAND_MODE, NULL);
1014 debug.steps--;
1015 }
1016 } else {
1017 blit_both ();
1018 console_prompt ();
1019 do {
1020 main_cycle ();
1021 } while (!debug.steps && debug.enabled);
1022 console_lock ();
1023 erase_both ();
1024 }
1025 }
1026 #endif
1027
1028 switch (op = *(code + ip++)) {
1029 case 0xff: /* if (open/close) */
1030 test_if_code (n);
1031 break;
1032 case 0xfe: /* goto */
1033 /* +2 covers goto size */
1034 ip += 2 + ((SINT16)lohi_getword (code + ip));
1035 /* timer must keep running even in goto loops,
1036 * but Sarien can't do that :(
1037 */
1038 if (timer_hack > 20) {
1039 poll_timer ();
1040 update_timer ();
1041 timer_hack = 0;
1042 }
1043 break;
1044 case 0x00: /* return */
1045 return 1;
1046 default:
1047 num = logic_names_cmd[op].num_args;
1048 memmove (p, code + ip, num);
1049 memset (p + num, 0, CMD_BSIZE - num);
1050 agi_command[op](p);
1051 ip += num;
1052 }
1053
1054 if (game.exit_all_logics)
1055 break;
1056 }
1057
1058 return 0; /* after executing new.room() */
1059 }
1060
1061
execute_agi_command(UINT8 op,UINT8 * p)1062 void execute_agi_command (UINT8 op, UINT8 *p)
1063 {
1064 _D (_D_WARN "%s %d %d %d", logic_names_cmd[op].name, p[0], p[1], p[2]);
1065 agi_command[op](p);
1066 }
1067
1068