aboutsummaryrefslogtreecommitdiff
path: root/saga/events.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2004-04-12 21:40:49 +0000
committerEugene Sandulenko2004-04-12 21:40:49 +0000
commitf3d340fb0ce72b9db59b8c701153bc82b595f75e (patch)
treebf250cf3a1e6aee35c7f40d766994b0c2c188e5c /saga/events.cpp
parent0a0a0c7b0609d8774cef849e7511e7b21d12c5db (diff)
downloadscummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.gz
scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.bz2
scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.zip
WIP for SAGA engine.
o text formatting is not consistent with rules, just indent utility is too dumb for that o it does not use OSystem, i.e. it runs on direct SDL calls o it may not even compile on your box o if you enable it, expect zillions of warnings o no sound Now it runs ITE intro as reinherit did svn-id: r13564
Diffstat (limited to 'saga/events.cpp')
-rw-r--r--saga/events.cpp613
1 files changed, 613 insertions, 0 deletions
diff --git a/saga/events.cpp b/saga/events.cpp
new file mode 100644
index 0000000000..6dcfe4ff06
--- /dev/null
+++ b/saga/events.cpp
@@ -0,0 +1,613 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2004 The ScummVM project
+ *
+ * The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+/*
+
+ Description:
+
+ Event management module
+
+ Notes:
+*/
+
+#include "reinherit.h"
+
+#include "yslib.h"
+
+/*
+ * Uses the following modules:
+\*--------------------------------------------------------------------------*/
+#include "animation_mod.h"
+#include "console_mod.h"
+#include "scene_mod.h"
+#include "gfx_mod.h"
+#include "interface_mod.h"
+#include "text_mod.h"
+#include "palanim_mod.h"
+#include "render_mod.h"
+#include "sndres_mod.h"
+
+/*
+ * Begin module
+\*--------------------------------------------------------------------------*/
+#include "events_mod.h"
+#include "events.h"
+
+namespace Saga {
+
+static YS_DL_LIST *EventList;
+
+int EVENT_Init(void)
+{
+ R_printf(R_STDOUT, "Initializing event subsystem...\n");
+
+ EventList = ys_dll_create();
+
+ return (EventList != NULL) ? R_SUCCESS : R_FAILURE;
+}
+
+int EVENT_Shutdown(void)
+{
+ R_printf(R_STDOUT, "Shutting down event subsystem...\n");
+
+ EVENT_FreeList();
+
+ return R_SUCCESS;
+}
+
+int EVENT_HandleEvents(long msec)
+/*--------------------------------------------------------------------------*\
+ * Function to process event list once per frame.
+ * First advances event times, then processes each event with the appropriate
+ * handler depending on the type of event.
+\*--------------------------------------------------------------------------*/
+{
+ YS_DL_NODE *walk_node;
+ YS_DL_NODE *next_node;
+
+ R_EVENT *event_p;
+
+ long delta_time;
+ int result;
+
+ /* Advance event times
+ * \*------------------------------------------------------------- */
+ ProcessEventTime(msec);
+
+ /* Process each event in list
+ * \*------------------------------------------------------------- */
+ for (walk_node = ys_dll_head(EventList);
+ walk_node != NULL; walk_node = next_node) {
+
+ event_p = (R_EVENT *)ys_dll_get_data(walk_node);
+
+ /* Save next event in case current event is handled and removed */
+ next_node = ys_dll_next(walk_node);
+
+ /* Call the appropriate event handler for the specific event type */
+ switch (event_p->type) {
+
+ case R_ONESHOT_EVENT:
+ result = HandleOneShot(event_p);
+ break;
+
+ case R_CONTINUOUS_EVENT:
+ result = HandleContinuous(event_p);
+ break;
+
+ case R_INTERVAL_EVENT:
+ result = HandleInterval(event_p);
+ break;
+
+ default:
+ result = R_EVENT_INVALIDCODE;
+ R_printf(R_STDERR,
+ "Invalid event code encountered.\n");
+ break;
+ }
+
+ /* Process the event appropriately based on result code from
+ * handler */
+ if ((result == R_EVENT_DELETE) ||
+ (result == R_EVENT_INVALIDCODE)) {
+
+ /* If there is no event chain, delete the base event. */
+ if (event_p->chain == NULL) {
+ ys_dll_delete(walk_node);
+ } else {
+ /* If there is an event chain present, move the next event
+ * in the chain up, adjust it by the previous delta time,
+ * and reprocess the event by adjusting next_node. */
+ delta_time = event_p->time;
+
+ ys_dll_replace(walk_node, event_p->chain,
+ sizeof *event_p);
+
+ event_p = (R_EVENT *)ys_dll_get_data(walk_node);
+ event_p->time += delta_time;
+
+ next_node = walk_node;
+ }
+ } else if (result == R_EVENT_BREAK) {
+
+ break;
+ }
+
+ } /* end for () */
+
+ return R_SUCCESS;
+}
+
+int HandleContinuous(R_EVENT * event)
+{
+
+ double event_pc = 0.0; /* Event completion percentage */
+ int event_done = 0;
+
+ R_BUFFER_INFO buf_info;
+ SCENE_BGINFO bg_info;
+ R_SURFACE *back_buf;
+
+ event_pc = ((double)event->duration - event->time) / event->duration;
+
+ if (event_pc >= 1.0) {
+ /* Cap percentage to 100 */
+ event_pc = 1.0;
+ event_done = 1;
+ }
+
+ if (event_pc < 0.0) {
+ /* Event not signaled, skip it */
+ return R_EVENT_CONTINUE;
+ } else if (!(event->code & R_SIGNALED)) {
+ /* Signal event */
+ event->code |= R_SIGNALED;
+ event_pc = 0.0;
+ }
+
+ switch (event->code & R_EVENT_MASK) {
+
+ case R_PAL_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_BLACKTOPAL:
+
+ back_buf = SYSGFX_GetBackBuffer();
+
+ SYSGFX_BlackToPal(back_buf, (PALENTRY *)event->data, event_pc);
+ break;
+
+ case EVENT_PALTOBLACK:
+
+ back_buf = SYSGFX_GetBackBuffer();
+
+ SYSGFX_PalToBlack(back_buf, (PALENTRY *)event->data, event_pc);
+ break;
+
+ default:
+ break;
+ } /* end switch() */
+
+ break;
+
+ case R_TRANSITION_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_DISSOLVE:
+
+ RENDER_GetBufferInfo(&buf_info);
+ SCENE_GetBGInfo(&bg_info);
+
+ TRANSITION_Dissolve(buf_info.r_bg_buf,
+ buf_info.r_bg_buf_w,
+ buf_info.r_bg_buf_h,
+ buf_info.r_bg_buf_w,
+ bg_info.bg_buf, bg_info.bg_p, 0, event_pc);
+
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case R_CONSOLE_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_ACTIVATE:
+
+ CON_DropConsole(event_pc);
+ break;
+
+ case EVENT_DEACTIVATE:
+
+ CON_RaiseConsole(event_pc);
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+
+ } /* end switch( event->event_code ) */
+
+ if (event_done) {
+ return R_EVENT_DELETE;
+ }
+
+ return R_EVENT_CONTINUE;
+}
+
+static int HandleOneShot(R_EVENT * event)
+{
+
+ R_SURFACE *back_buf;
+
+ static SCENE_BGINFO bginfo;
+
+ if (event->time > 0) {
+ return R_EVENT_CONTINUE;
+ }
+
+ /* Event has been signaled */
+
+ switch (event->code & R_EVENT_MASK) {
+
+ case R_TEXT_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_DISPLAY:
+
+ TEXT_SetDisplay((R_TEXTLIST_ENTRY *)event->data, 1);
+ break;
+
+ case EVENT_REMOVE:
+ {
+ R_SCENE_INFO scene_info;
+
+ SCENE_GetInfo(&scene_info);
+
+ TEXT_DeleteEntry(scene_info.text_list,
+ (R_TEXTLIST_ENTRY *)event->data);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case R_VOICE_EVENT:
+
+ SND_PlayVoice(event->param);
+ break;
+
+ case R_MUSIC_EVENT:
+
+ SYSMUSIC_Play(event->param, event->param2);
+ break;
+
+ case R_BG_EVENT:
+ {
+ R_BUFFER_INFO rbuf_info;
+ R_POINT bg_pt;
+
+ if (SCENE_GetMode() == R_SCENE_MODE_NORMAL) {
+
+ back_buf = SYSGFX_GetBackBuffer();
+
+ RENDER_GetBufferInfo(&rbuf_info);
+ SCENE_GetBGInfo(&bginfo);
+
+ bg_pt.x = bginfo.bg_x;
+ bg_pt.y = bginfo.bg_y;
+
+ GFX_BufToBuffer(rbuf_info.r_bg_buf,
+ rbuf_info.r_bg_buf_w,
+ rbuf_info.r_bg_buf_h,
+ bginfo.bg_buf,
+ bginfo.bg_w, bginfo.bg_h, NULL, &bg_pt);
+
+ if (event->param == SET_PALETTE) {
+
+ PALENTRY *pal_p;
+
+ SCENE_GetBGPal(&pal_p);
+ SYSGFX_SetPalette(back_buf, pal_p);
+ }
+ }
+ }
+ break;
+
+ case R_ANIM_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_FRAME:
+
+ ANIM_Play(event->param, event->time);
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case R_SCENE_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_END:
+
+ SCENE_Next();
+
+ return R_EVENT_BREAK;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case R_PALANIM_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_CYCLESTART:
+
+ PALANIM_CycleStart();
+ break;
+
+ case EVENT_CYCLESTEP:
+
+ PALANIM_CycleStep(event->time);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case R_INTERFACE_EVENT:
+
+ switch (event->op) {
+
+ case EVENT_ACTIVATE:
+
+ INTERFACE_Activate();
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+
+ } /* end switch( event->code ) */
+
+ return R_EVENT_DELETE;
+}
+
+static int HandleInterval(R_EVENT * event)
+{
+ YS_IGNORE_PARAM(event);
+
+ return R_EVENT_DELETE;
+}
+
+R_EVENT *EVENT_Queue(R_EVENT * event)
+/*--------------------------------------------------------------------------*\
+ * Schedules an event in the event list; returns a pointer to the scheduled
+ * event suitable for chaining if desired.
+\*--------------------------------------------------------------------------*/
+{
+ YS_DL_NODE *new_node;
+ R_EVENT *queued_event;
+
+ event->chain = NULL;
+
+ new_node = ys_dll_add_tail(EventList, event, sizeof *event);
+
+ if (new_node == NULL) {
+ return NULL;
+ }
+
+ queued_event = (R_EVENT *)ys_dll_get_data(new_node);
+
+ InitializeEvent(queued_event);
+
+ return queued_event;
+}
+
+R_EVENT *EVENT_Chain(R_EVENT * head_event, R_EVENT * add_event)
+/*--------------------------------------------------------------------------*\
+ * Places a 'add_event' on the end of an event chain given by 'head_event'
+ * (head_event may be in any position in the event chain)
+\*--------------------------------------------------------------------------*/
+{
+ R_EVENT *walk_event;
+ R_EVENT *new_event;
+
+ /* Allocate space for new event */
+ new_event = (R_EVENT *)malloc(sizeof *new_event);
+ if (new_event == NULL) {
+ return NULL;
+ }
+
+ /* Copy event data to new event */
+ *new_event = *add_event;
+
+ /* Walk to end of chain */
+ for (walk_event = head_event;
+ walk_event->chain != NULL; walk_event = walk_event->chain) {
+
+ continue;
+ }
+
+ /* Place new event */
+ walk_event->chain = new_event;
+ new_event->chain = NULL;
+
+ InitializeEvent(new_event);
+
+ return new_event;
+}
+
+static int InitializeEvent(R_EVENT * event)
+{
+
+ switch (event->type) {
+
+ case R_ONESHOT_EVENT:
+ break;
+
+ case R_CONTINUOUS_EVENT:
+ event->time += event->duration;
+ break;
+
+ case R_INTERVAL_EVENT:
+ break;
+
+ default:
+ return R_FAILURE;
+ break;
+ }
+
+ return R_SUCCESS;
+}
+
+int EVENT_ClearList(void)
+/*--------------------------------------------------------------------------*\
+ * Removes all events from the list except NODESTROY (engine) events
+\*--------------------------------------------------------------------------*/
+{
+ YS_DL_NODE *walk_node;
+ YS_DL_NODE *next_node;
+
+ struct R_EVENT_tag *chain_walk;
+ struct R_EVENT_tag *next_chain;
+
+ R_EVENT *event_p;
+
+ /* Walk down event list */
+ for (walk_node = ys_dll_head(EventList);
+ walk_node != NULL; walk_node = next_node) {
+
+ next_node = ys_dll_next(walk_node);
+ event_p = (R_EVENT *)ys_dll_get_data(walk_node);
+
+ /* Only remove events not marked R_NODESTROY (engine events) */
+ if (!(event_p->code & R_NODESTROY)) {
+
+ /* Remove any events chained off this one */
+ for (chain_walk = event_p->chain;
+ chain_walk != NULL; chain_walk = next_chain) {
+
+ next_chain = chain_walk->chain;
+ free(chain_walk);
+ }
+
+ ys_dll_delete(walk_node);
+ }
+ }
+
+ return R_SUCCESS;
+}
+
+int EVENT_FreeList(void)
+/*--------------------------------------------------------------------------*\
+ * Removes all events from the list (even R_NODESTROY)
+\*--------------------------------------------------------------------------*/
+{
+ YS_DL_NODE *walk_node;
+ YS_DL_NODE *next_node;
+
+ struct R_EVENT_tag *chain_walk;
+ struct R_EVENT_tag *next_chain;
+
+ R_EVENT *event_p;
+
+ /* Walk down event list */
+ for (walk_node = ys_dll_head(EventList);
+ walk_node != NULL; walk_node = next_node) {
+
+ event_p = (R_EVENT *)ys_dll_get_data(walk_node);
+
+ /* Remove any events chained off current node */
+ for (chain_walk = event_p->chain;
+ chain_walk != NULL; chain_walk = next_chain) {
+
+ next_chain = chain_walk->chain;
+ free(chain_walk);
+ }
+
+ /* Delete current node */
+ next_node = ys_dll_next(walk_node);
+ ys_dll_delete(walk_node);
+ }
+
+ return R_SUCCESS;
+}
+
+static int ProcessEventTime(long msec)
+/*--------------------------------------------------------------------------*\
+ * Walks down the event list, updating event times by 'msec'.
+\*--------------------------------------------------------------------------*/
+{
+ YS_DL_NODE *walk_node;
+ R_EVENT *event_p;
+
+ uint event_count = 0;
+
+ for (walk_node = ys_dll_head(EventList);
+ walk_node != NULL; walk_node = ys_dll_next(walk_node)) {
+
+ event_p = (R_EVENT *)ys_dll_get_data(walk_node);
+ event_p->time -= msec;
+
+ event_count++;
+
+ if (event_count > R_EVENT_WARNINGCOUNT) {
+ R_printf(R_STDERR,
+ "WARNING: Event list exceeds %u.\n");
+ }
+ }
+
+ return R_SUCCESS;
+}
+
+} // End of namespace Saga