aboutsummaryrefslogtreecommitdiff
path: root/engines/agi/cycle.cpp
diff options
context:
space:
mode:
authorPaweł Kołodziejski2006-05-23 23:43:52 +0000
committerPaweł Kołodziejski2006-05-23 23:43:52 +0000
commit107073537e4ad24e294e28a2a62f8d3ad33008ff (patch)
tree9eade8ff944f701d2676aa2ddd94e3585be9c813 /engines/agi/cycle.cpp
parent3a025038da6d351789d5daf29e4751678c47fed1 (diff)
downloadscummvm-rg350-107073537e4ad24e294e28a2a62f8d3ad33008ff.tar.gz
scummvm-rg350-107073537e4ad24e294e28a2a62f8d3ad33008ff.tar.bz2
scummvm-rg350-107073537e4ad24e294e28a2a62f8d3ad33008ff.zip
imported AGI engine
svn-id: r22588
Diffstat (limited to 'engines/agi/cycle.cpp')
-rw-r--r--engines/agi/cycle.cpp423
1 files changed, 423 insertions, 0 deletions
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
new file mode 100644
index 0000000000..1c5365e4d1
--- /dev/null
+++ b/engines/agi/cycle.cpp
@@ -0,0 +1,423 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * Copyright (C) 1999-2003 Sarien Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "agi/agi.h"
+#include "agi/text.h"
+#include "agi/sprite.h"
+#include "agi/graphics.h"
+#include "agi/keyboard.h"
+#include "agi/menu.h"
+#include "agi/savegame.h"
+
+namespace Agi {
+
+#define TICK_SECONDS 20
+
+#ifdef USE_MOUSE
+struct mouse mouse;
+#endif
+
+volatile uint32 clock_ticks;
+volatile uint32 clock_count;
+
+/**
+ * Set up new room.
+ * This function is called when ego enters a new room.
+ * @param n room number
+ */
+void new_room(int n) {
+ struct vt_entry *v;
+ int i;
+
+ debugC(4, kDebugLevelMain, "*** room %d ***", n);
+ stop_sound();
+
+ i = 0;
+ for (v = game.view_table; v < &game.view_table[MAX_VIEWTABLE]; v++) {
+ v->entry = i++;
+ v->flags &= ~(ANIMATED | DRAWN);
+ v->flags |= UPDATE;
+ v->step_time = 1;
+ v->step_time_count = 1;
+ v->cycle_time = 1;
+ v->cycle_time_count = 1;
+ v->step_size = 1;
+ }
+ agi_unload_resources();
+
+ game.player_control = true;
+ game.block.active = false;
+ game.horizon = 36;
+ game.vars[V_prev_room] = game.vars[V_cur_room];
+ game.vars[V_cur_room] = n;
+ game.vars[V_border_touch_obj] = 0;
+ game.vars[V_border_code] = 0;
+ game.vars[V_ego_view_resource] = game.view_table[0].current_view;
+
+ agi_load_resource(rLOGIC, n);
+
+ /* Reposition ego in the new room */
+ switch (game.vars[V_border_touch_ego]) {
+ case 1:
+ game.view_table[0].y_pos = _HEIGHT - 1;
+ break;
+ case 2:
+ game.view_table[0].x_pos = 0;
+ break;
+ case 3:
+ game.view_table[0].y_pos = HORIZON + 1;
+ break;
+ case 4:
+ game.view_table[0].x_pos = _WIDTH - game.view_table[0].x_size;
+ break;
+ }
+
+ game.vars[V_border_touch_ego] = 0;
+ setflag(F_new_room_exec, true);
+
+ game.exit_all_logics = true;
+
+ write_status();
+ write_prompt();
+}
+
+static void reset_controllers() {
+ int i;
+
+ for (i = 0; i < MAX_DIRS; i++) {
+ game.ev_keyp[i].occured = false;
+ }
+}
+
+static void interpret_cycle() {
+ int old_sound, old_score;
+
+ if (game.player_control)
+ game.vars[V_ego_dir] = game.view_table[0].direction;
+ else
+ game.view_table[0].direction = game.vars[V_ego_dir];
+
+ check_all_motions();
+
+ old_score = game.vars[V_score];
+ old_sound = getflag(F_sound_on);
+
+ game.exit_all_logics = false;
+ while (run_logic(0) == 0 && !game.quit_prog_now) {
+ game.vars[V_word_not_found] = 0;
+ game.vars[V_border_touch_obj] = 0;
+ game.vars[V_border_code] = 0;
+ old_score = game.vars[V_score];
+ setflag(F_entered_cli, false);
+ game.exit_all_logics = false;
+ reset_controllers();
+ }
+ reset_controllers();
+
+ game.view_table[0].direction = game.vars[V_ego_dir];
+
+ if (game.vars[V_score] != old_score || getflag(F_sound_on) != old_sound)
+ write_status();
+
+ game.vars[V_border_touch_obj] = 0;
+ game.vars[V_border_code] = 0;
+ setflag(F_new_room_exec, false);
+ setflag(F_restart_game, false);
+ setflag(F_restore_just_ran, false);
+
+ if (game.gfx_mode) {
+ update_viewtable();
+ do_update();
+ }
+}
+
+/**
+ * Update AGI interpreter timer.
+ */
+void update_timer() {
+ clock_count++;
+ if (clock_count <= TICK_SECONDS)
+ return;
+
+ clock_count -= TICK_SECONDS;
+
+ if (!game.clock_enabled)
+ return;
+
+ setvar(V_seconds, getvar(V_seconds) + 1);
+ if (getvar(V_seconds) < 60)
+ return;
+
+ setvar(V_seconds, 0);
+ setvar(V_minutes, getvar(V_minutes) + 1);
+ if (getvar(V_minutes) < 60)
+ return;
+
+ setvar(V_minutes, 0);
+ setvar(V_hours, getvar(V_hours) + 1);
+ if (getvar(V_hours) < 24)
+ return;
+
+ setvar(V_hours, 0);
+ setvar(V_days, getvar(V_days) + 1);
+}
+
+static int old_mode = -1;
+
+void new_input_mode(int i) {
+ old_mode = game.input_mode;
+ game.input_mode = i;
+}
+
+void old_input_mode() {
+ game.input_mode = old_mode;
+}
+
+/* If main_cycle returns false, don't process more events! */
+int main_cycle() {
+ unsigned int key, kascii;
+ struct vt_entry *v = &game.view_table[0];
+
+ poll_timer(); /* msdos driver -> does nothing */
+ update_timer();
+
+ if (game.ver == 0) {
+ message_box("Warning: game CRC not listed, assuming AGI version 2.917.");
+ game.ver = -1;
+ }
+
+ key = do_poll_keyboard();
+
+#ifdef USE_MOUSE
+ /* In AGI Mouse emulation mode we must update the mouse-related
+ * vars in every interpreter cycle.
+ */
+ if (opt.agimouse) {
+ game.vars[28] = mouse.x / 2;
+ game.vars[29] = mouse.y;
+ }
+#endif
+
+#ifdef USE_CONSOLE
+ if (key == KEY_PRIORITY) {
+ erase_both();
+ debug_.priority = !debug_.priority;
+ show_pic();
+ blit_both();
+ commit_both();
+ key = 0;
+ }
+
+ if (key == KEY_STATUSLN) {
+ debug_.statusline = !debug_.statusline;
+ write_status();
+ key = 0;
+ }
+#endif
+
+ /* Click-to-walk mouse interface */
+ if (game.player_control && v->flags & ADJ_EGO_XY) {
+ v->direction = get_direction(v->x_pos, v->y_pos, v->parm1, v->parm2, v->step_size);
+
+ if (v->direction == 0)
+ in_destination(v);
+ }
+
+ kascii = KEY_ASCII(key);
+
+ if (!console_keyhandler(key)) {
+ if (kascii)
+ setvar(V_key, kascii);
+ process_key:
+ switch (game.input_mode) {
+ case INPUT_NORMAL:
+ if (!handle_controller(key)) {
+ if (key == 0 || !game.input_enabled)
+ break;
+ handle_keys(key);
+
+ /* if ESC pressed, activate menu before
+ * accept.input from the interpreter cycle
+ * sets the input mode to normal again
+ * (closes: #540856)
+ */
+ if (key == KEY_ESCAPE) {
+ key = 0;
+ goto process_key;
+ }
+
+ /* commented out to close bug #438872
+ * if (key) game.keypress = key;
+ */
+ }
+ break;
+ case INPUT_GETSTRING:
+ handle_controller(key);
+ handle_getstring(key);
+ setvar(V_key, 0); /* clear ENTER key */
+ break;
+ case INPUT_MENU:
+ menu_keyhandler(key);
+ console_cycle();
+ return false;
+ case INPUT_NONE:
+ handle_controller(key);
+ if (key)
+ game.keypress = key;
+ break;
+ }
+ } else {
+ if (game.input_mode == INPUT_MENU) {
+ console_cycle();
+ return false;
+ }
+ }
+
+ console_cycle();
+
+ if (game.msg_box_ticks > 0)
+ game.msg_box_ticks--;
+
+ return true;
+}
+
+static int play_game() {
+ int ec = err_OK;
+
+ debugC(2, kDebugLevelMain, "initializing...");
+ debugC(2, kDebugLevelMain, "game.ver = 0x%x", game.ver);
+
+ stop_sound();
+ clear_screen(0);
+
+ game.horizon = HORIZON;
+ game.player_control = false;
+
+ setflag(F_logic_zero_firsttime, true); /* not in 2.917 */
+ setflag(F_new_room_exec, true); /* needed for MUMG and SQ2! */
+ setflag(F_sound_on, true); /* enable sound */
+ setvar(V_time_delay, 2); /* "normal" speed */
+
+ game.gfx_mode = true;
+ game.quit_prog_now = false;
+ game.clock_enabled = true;
+ game.line_user_input = 22;
+
+#ifdef USE_MOUSE
+ if (opt.agimouse)
+ report("Using AGI Mouse 1.0 protocol\n");
+#endif
+
+ report("Running AGI script.\n");
+
+#ifdef USE_CONSOLE
+ console.count = 5;
+ console_prompt();
+#endif
+
+ setflag(F_entered_cli, false);
+ setflag(F_said_accepted_input, false);
+ game.vars[V_word_not_found] = 0;
+ game.vars[V_key] = 0;
+
+ debugC(2, kDebugLevelMain, "Entering main loop");
+ do {
+
+ if (!main_cycle())
+ continue;
+
+ if (getvar(V_time_delay) == 0 ||
+ (1 + clock_count) % getvar(V_time_delay) == 0) {
+ if (!game.has_prompt && game.input_mode == INPUT_NORMAL) {
+ write_prompt();
+ game.has_prompt = 1;
+ } else
+ if (game.has_prompt && game.input_mode == INPUT_NONE) {
+ write_prompt();
+ game.has_prompt = 0;
+ }
+
+ interpret_cycle();
+
+ setflag(F_entered_cli, false);
+ setflag(F_said_accepted_input, false);
+ game.vars[V_word_not_found] = 0;
+ game.vars[V_key] = 0;
+ }
+
+ if (game.quit_prog_now == 0xff)
+ ec = err_RestartGame;
+
+ } while (game.quit_prog_now == 0);
+
+ stop_sound();
+
+ return ec;
+}
+
+int run_game() {
+ int i, ec = err_OK;
+
+#ifdef USE_HIRES
+ if (opt.cgaemu)
+ opt.hires = 0;
+#endif
+
+ for (i = 0; i < MAX_DIRS; i++)
+ memset(&game.ev_keyp[i], 0, sizeof(struct agi_event));
+
+ /* Execute the game */
+ do {
+ debugC(2, kDebugLevelMain, "game loop");
+ debugC(2, kDebugLevelMain, "game.ver = 0x%x", game.ver);
+
+ if (agi_init() != err_OK)
+ break;
+ if (ec == err_RestartGame)
+ setflag(F_restart_game, true);
+
+ setvar(V_computer, 0); /* IBM PC (4 = Atari ST) */
+ setvar(V_soundgen, 1); /* IBM PC SOUND */
+ setvar(V_monitor, 0x3); /* EGA monitor */
+ setvar(V_max_input_chars, 38);
+ game.input_mode = INPUT_NONE;
+ game.input_enabled = 0;
+ game.has_prompt = 0;
+
+ game.state = STATE_RUNNING;
+ ec = play_game();
+ game.state = STATE_LOADED;
+ agi_deinit();
+ } while (ec == err_RestartGame);
+
+ menu_deinit();
+
+ release_image_stack();
+
+ return ec;
+}
+
+} // End of namespace Agi