From c068f22329d5cc722622a2183bbb22eef2093df7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Aug 2026 11:16:07 +0200 Subject: initial import --- src/parsec/e_events.cpp | 351 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 src/parsec/e_events.cpp (limited to 'src/parsec/e_events.cpp') diff --git a/src/parsec/e_events.cpp b/src/parsec/e_events.cpp new file mode 100644 index 0000000..855f883 --- /dev/null +++ b/src/parsec/e_events.cpp @@ -0,0 +1,351 @@ +/* + * PARSEC - Event Management + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:34 $ + * + * Orginally written by: + * Copyright (c) Clemens Beer 1999 + * + * 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 + */ + +// C library +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "sys_defs.h" + +// local module header +#include "e_events.h" + +// proprietary module headers +#include "con_com.h" +#include "con_main.h" + + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// init flag ------------------------------------------------------------------ +// +static int manager_init_done = FALSE; + + +// list of all pending events ------------------------------------------------- +// +static event_s* eventlist_head; +static event_s* eventlist_tail; + +static int num_events; +static event_s* current_event; + + +// initialize the event manager ----------------------------------------------- +// +int EVT_InitManager() +{ + ASSERT( !manager_init_done ); + if ( manager_init_done ) { + return FALSE; + } + + eventlist_head = NULL; + eventlist_tail = NULL; + num_events = 0; + + manager_init_done = TRUE; + + return TRUE; +} + + +// kill the event manager ----------------------------------------------------- +// +int EVT_KillManager() +{ + if ( !manager_init_done ) { + return FALSE; + } + + // an event-callback must not call this function + ASSERT( current_event == NULL ); + + // kill all autofree marked events + for ( event_s* event = eventlist_head; event; ) { + + event_s* nextevent = event->next; + + if ( event->flags & EVENT_PARAM_AUTOFREE ) { + if ( event->flags & EVENT_PARAM_AUTOFREE_CALLBACK ) { + FREEMEM( event->callback_params ); + } + + FREEMEM( event ); + } + + event = nextevent; + } + + eventlist_head = NULL; + eventlist_tail = NULL; + + num_events = 0; + + manager_init_done = FALSE; + + return TRUE; +} + + +// add an event --------------------------------------------------------------- +// +size_t EVT_AddEvent( event_s *event ) +{ + // check whether any other event of same type is to be deleted + if ( event->flags & EVENT_PARAM_ONE_PER_TYPE ) { + for ( event_s* otherevent = eventlist_head; otherevent; ) { + event_s* nextevent = otherevent->next; + + if ( otherevent->type == event->type ) { + EVT_RemoveEvent( (size_t)otherevent ); + } + + otherevent = nextevent; + } + } + + // add the event to the list + if ( eventlist_tail != NULL ) { + eventlist_tail->next = event; + event->prec = eventlist_tail; + } else { + event->prec = NULL; + } + + event->next = NULL; + eventlist_tail = event; + if ( eventlist_head == NULL ) { + eventlist_head = event; + } + + // increase the number of events + num_events++; + + if ( event->flags & EVENT_PARAM_AUTOTRIGGER ) { + // set the trigger time to the current refframe + event->refframe_trigger = SYSs_GetRefFrameCount(); + } else { + // set to not-triggered + event->refframe_trigger = EVENT_UNTRIGGERED; + } + + return (size_t)event; +} + + +// remove an event ------------------------------------------------------------ +// +void EVT_RemoveEvent( size_t id ) +{ + ASSERT( eventlist_head != NULL ); + ASSERT( eventlist_tail != NULL ); + + event_s *event = (event_s *) id; + ASSERT( event != NULL ); + + // an event-callback must not delete its own event + ASSERT( current_event != event ); + + if ( eventlist_head == event ) + eventlist_head = event->next; + + if ( eventlist_tail == event ) + eventlist_tail = event->prec; + + if ( event->prec != NULL ) + event->prec->next = event->next; + + if ( event->next != NULL ) + event->next->prec = event->prec; + + if ( event->flags & EVENT_PARAM_AUTOFREE ) { + if ( event->flags & EVENT_PARAM_AUTOFREE_CALLBACK ) { + if ( event->callback_params != NULL ) { + FREEMEM( event->callback_params ); + } + } + FREEMEM( event ); + } + + // decrease the number of events + num_events--; +} + + +// remove all events for a specific type -------------------------------------- +// +void EVT_RemoveEventType( dword type ) +{ + for ( event_s* event = eventlist_head; event; ) { + + event_s* nextevent = event->next; + + if ( ( event->type & type ) == type ) { + EVT_RemoveEvent( (size_t) event ); + } + + event = nextevent; + } +} + + +// maintain the list of events to be triggered/fired -------------------------- +// +void EVT_Maintain() +{ + //FIXME: introduce a frequency for issueing events (e.g. 100Hz = 6 Refframes) + + event_s* nextevent; + for ( event_s* event = eventlist_head; event; event = nextevent ) { + + // store the next event + nextevent = event->next; + + if ( event->refframe_trigger == EVENT_UNTRIGGERED ) + continue; + + // check whether event is triggered + refframe_t refframecount = SYSs_GetRefFrameCount(); + if ( event->refframe_trigger > refframecount ) + continue; + + // check whether the event is to be fired + if ( ( event->refframe_trigger + event->refframe_delay ) > refframecount ) + continue; + + // check whether the event depends on another event that must be triggered + if ( event->flags & EVENT_PARAM_DEPENDENT ) { + event_s* parentevent = (event_s*)event->dependent_on; + + //FIXME: in order to have this work properly we must first + // go through all the events, resolve all dependencies + // and then check all the triggered events + + ASSERT( FALSE ); + } + + ASSERT( event->callback != NULL ); + + // save the current event pointer + current_event = event; + + // call the callback function + int keepalive = event->callback( event->callback_params ); + + // remove the current event pointer + current_event = NULL; + + // might have been changed implicitly by callback function + nextevent = event->next; + + // check whether event is to be looped + dword loops = event->flags & EVENT_PARAM_LOOP_MASK; + + switch ( loops ) { + + case EVENT_PARAM_ONESHOT: + event->loopcount = 0; + break; + case EVENT_PARAM_LOOP_COUNT: + if ( event->loopcount > 0 ) + event->loopcount--; + event->refframe_trigger = refframecount; + break; + case EVENT_PARAM_LOOP_INDEFINITE: + event->loopcount = 1; + event->refframe_trigger = refframecount; + break; + default: + ASSERT(FALSE); + } + + // remove event if specified by callback or loopcount exceeded + if ( !keepalive || ( event->loopcount == 0 ) ) { + EVT_RemoveEvent( (size_t)event ); + } + } +} + + +// list all pending events ---------------------------------------------------- +// +PRIVATE +int CMD_EVT_LIST( char *paramstr ) +{ + ASSERT( paramstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( paramstr ); + + for ( event_s* event = eventlist_head; event; ) { + + sprintf( paste_str, "type:%04xd delay:%u flags:%04xd loop:%u trigger:%u", + (unsigned int)event->type, + (unsigned int)event->refframe_delay, + (unsigned int)event->flags, + (unsigned int)event->loopcount, + (unsigned int)event->refframe_trigger ); + CON_AddLine( paste_str ); + + // advance in the list + event = event->next; + } + + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( E_EVENTS ) +{ + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + // register "evt.list" command + regcom.command = "evt.list"; + regcom.numparams = 0; + regcom.execute = CMD_EVT_LIST; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); +} + + + -- cgit v1.2.3