Ejemplo n.º 1
0
event* zPacket::create_event(event_base* eb, short what, void *arg) const
{
 clear_event();
 ev= ::event_new(eb, sock, what, cb_packet, arg);
 if(ev != NULL) { ::event_add(ev, NULL); }
 return ev;
};
Ejemplo n.º 2
0
event* zPacket::create_event(event_base* eb, short what, void *arg, unsigned sec, unsigned short msec) const
{
 clear_event();
 ev= ::event_new(eb, sock, what, cb_packet, arg);
 if(ev != NULL)
 {
  tmval.tv_sec= sec; tmval.tv_usec=msec*1000;
  ::event_add(ev, &tmval);
 }
 return ev;
};
Ejemplo n.º 3
0
/*
 * Decide which event to show. Works in a cycle. Clears the display if there is a calendar event outstanding. The phone could
 * have been offline for some while and hence what is being displayed could be inaccurate.
 */
void show_next_event() {
  // Else get processing
  if (g_max_entries == 0) {
	clear_event();
  } else {
	g_entry_no++;
	if (g_entry_no > g_max_entries || g_entry_no > ROT_MAX)
	  g_entry_no = 1;
	  show_event(g_entry_no);
  } 
}
Ejemplo n.º 4
0
/*
 * Decide which event to show. Works in a cycle. Clears the display if there is a calendar event outstanding. The phone could
 * have been offline for some while and hence what is being displayed could be inaccurate.
 */
void show_next_event() {
  // Don't mess up an alert that is underway
  if (g_showing_alert)
	  return;
  // Else get processing
  if (g_max_entries == 0) {
	clear_event();
  } else {
	g_entry_no++;
	if (g_entry_no > g_max_entries || g_entry_no > ROT_MAX)
	  g_entry_no = 1;
	  show_event(g_entry_no);
  } 
}
static int mkbp_get_next_event(struct host_cmd_handler_args *args)
{
	static int last;
	int i, data_size, evt;
	uint8_t *resp = args->response;
	const struct mkbp_event_source *src;

	/*
	 * Find the next event to service.  We do this in a round-robin
	 * way to make sure no event gets starved.
	 */
	for (i = 0; i < EC_MKBP_EVENT_COUNT; ++i)
		if (event_is_set((last + i) % EC_MKBP_EVENT_COUNT))
			break;

	if (i == EC_MKBP_EVENT_COUNT)
		return EC_RES_ERROR;

	evt = (i + last) % EC_MKBP_EVENT_COUNT;
	last = evt + 1;

	/*
	 * Clear the event before retrieving the event data in case the
	 * event source wants to send the same event.
	 */
	clear_event(evt);

	for (src = __mkbp_evt_srcs; src < __mkbp_evt_srcs_end; ++src)
		if (src->event_type == evt)
			break;

	if (src == __mkbp_evt_srcs_end)
		return EC_RES_ERROR;

	resp[0] = evt; /* Event type */
	data_size = src->get_data(resp + 1);
	if (data_size < 0)
		return EC_RES_ERROR;
	args->response_size = 1 + data_size;

	if (!events)
		set_host_interrupt(0);

	return EC_RES_SUCCESS;
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
	Event event; 
	Reader reader;

	/* Init struct */
	clear_event(&event);

	reader_init(&reader, argv[1]);

	evh_register_handler(&reader, &lostRecordsHandler);
	/*
	evh_register_handler(&reader, &backInflightQueueBlockedHandler);
	evh_register_handler(&reader, &backInflightQueueUnblockedHandler);
	
	evh_register_handler(&reader, &frontSharedRingQueueBlockedHandler);
	evh_register_handler(&reader, &frontSharedRingQueueUnblockedHandler);
	
	evh_register_handler(&reader, &frontGrantQueueBlockedHandler);
	evh_register_handler(&reader, &frontGrantQueueUnblockedHandler);
	*/
	evh_register_handler(&reader, &frontRequestQueueBlockedHandler);
	evh_register_handler(&reader, &frontRequestQueueUnblockedHandler);

	evh_register_handler(&reader, &backRequestQueueBlockedHandler);
	evh_register_handler(&reader, &backRequestQueueUnblockedHandler);

	evh_register_handler(&reader, &frontSharedRingRespQueueBlockedHandler);
	evh_register_handler(&reader, &frontSharedRingRespQueueUnblockedHandler);
	
	evh_register_handler(&reader, &backRequestInterruptSendHandler);
	evh_register_handler(&reader, &backRequestInterruptReceiveHandler);

	evh_register_handler(&reader, &backResponseInterruptSendHandler);
	evh_register_handler(&reader, &backResponseInterruptReceiveHandler);
	
	reader_loop(&reader);

	reader_exit(&reader);

	return 0;
}
Ejemplo n.º 7
0
int main(int argc, char *argv[])
{
	Event event; 
	Reader reader;

	/* Init struct */
	clear_event(&event);

	reader_init(&reader, argv[1]);

	evh_register_handler(&reader, &lostRecordsHandler);
	evh_register_handler(&reader, &exitToXenHandler);
	evh_register_handler(&reader, &exitToGuestHandler);

	reader_loop(&reader);

	reader_exit(&reader);

	return 0;
}
Ejemplo n.º 8
0
int main(int argc, char *argv[])
{
	Event event; 
	Reader reader;

	/* Init struct */
	clear_event(&event);

	reader_init(&reader, argv[1]);

	evh_register_handler(&reader, &switchInfprevHandler);
	evh_register_handler(&reader, &switchInfnextHandler);
	evh_register_handler(&reader, &switchSchedHandler);
	evh_register_handler(&reader, &domainWakeHandler);
	evh_register_handler(&reader, &lostRecordsHandler);

	reader_loop(&reader);

	reader_exit(&reader);

	return 0;
}
Ejemplo n.º 9
0
/* This function is called (via check_events()) from the top level sieve
   loops (prime_sieve() etc.). It can assume that it is safe to tighten any
   sieving parameters other than p_min and p_max.
*/
void process_events(uint64_t current_prime)
{
  /* event_happened was set last in notify_event(), so clear it first which
     ensures that if some signal arrives while we are in process_events()
     it might have to wait until the next sieve iteration to get processed,
     but it won't be lost.
  */
  event_happened = 0;

  if (clear_event(initialise_events))
  {
    init_signals();
    init_progress_report(current_prime);
  }

  if (clear_event(subsequence_eliminated))
    remove_eliminated_subsequences(current_prime);

  if (clear_event(sieve_parameters_changed))
    init_progress_report(current_prime);

  if (clear_event(received_sigterm))
  {
    finish_srsieve("SIGTERM was received",current_prime);
    signal(SIGTERM,SIG_DFL);
    raise(SIGTERM);
  }

  if (clear_event(received_sigint))
  {
    finish_srsieve("SIGINT was received",current_prime);
    signal(SIGINT,SIG_DFL);
    raise(SIGINT);
  }

  if (clear_event(report_due))
    progress_report(current_prime);

  if (clear_event(save_due))
    write_save_file(current_prime);
}
Ejemplo n.º 10
0
int main(int argc, char *argv[])
{
	Event event; 
	Reader reader;

	/* Init struct */
	clear_event(&event);

	reader_init(&reader, argv[1]);

	evh_register_handler(&reader, &numEventsHandler);
	evh_register_handler(&reader, &numExceptionsHandler);
	evh_register_handler(&reader, &numExceptionsInXenHandler);
	evh_register_handler(&reader, &numInterruptsHandler);
	evh_register_handler(&reader, &numInterruptsInXenHandler);
	evh_register_handler(&reader, &numHypercallsHandler);
	evh_register_handler(&reader, &lostRecordsHandler);

	reader_loop(&reader);

	reader_exit(&reader);

	return 0;
}
Ejemplo n.º 11
0
int main (int argc, char **argv)
{
  pwr_tStatus sts = 1;
  io_tCtx io_ctx;
  io_tCtx io_ctx_swap;
  pwr_sClass_IOHandler *ihp;
  int swap_io;
  int close_io;
  int init_io;
  qcom_sQid qid = qcom_cNQid;
  int tmo;
  char mp[2000];
  qcom_sGet get;
  pwr_tTime now;
  pwr_tTime next;
  pwr_tTime after;
  pwr_tDeltaTime cycle;
  lst_sEntry *csup_lh;
  int delay_action = 0;
  pwr_sNode *nodep;
  pwr_tBoolean old_emergency_break = 0;

  if ( argc > 1) {
    if ( strcmp( argv[1], "-m") == 0) {
      io_methods_print();
      exit(0);
    }
    if ( strcmp( argv[1], "-h") == 0) {
      usage();
      exit(0);
    }
  }

  ihp = init(&qid, &csup_lh, &nodep);

  plc_UtlWaitForPlc();

  /* Prepare the swap context */
  sts = io_init_swap(io_mProcess_IoComm, pwr_cNObjid, &io_ctx_swap, 1, ihp->CycleTimeBus);

  for (close_io = swap_io = 0, init_io = 1;;) {

    if (init_io) {
      double f;
      
      sts = io_init(io_mProcess_IoComm, pwr_cNObjid, &io_ctx, 1, ihp->CycleTimeBus);
      if ( ODD(sts)) 
	errh_SetStatus( PWR__SRUN);
#if defined(OS_ELN)
      ker$clear_event( &sts, io_comm_terminate);
      io_dioc_init();
      io_dioc_start();
#endif
      init_io = 0;
      tmo = ihp->CycleTimeBus * 1000.;
      f = floor(ihp->CycleTimeBus);
      cycle.tv_sec = f;
      cycle.tv_nsec = (ihp->CycleTimeBus - f) * 1.0e9;
      cycle.tv_nsec++;
      time_GetTimeMonotonic(&next);
      time_Aadd(NULL, &next, &cycle);
    }

    get.maxSize = sizeof(mp);
    get.data = mp;
    qcom_Get(&sts,&qid, &get, tmo);
    if (sts == QCOM__TMO || sts == QCOM__QEMPTY) {

      if ( nodep->EmergBreakTrue && !old_emergency_break)
        sts = io_swap(io_ctx_swap, io_eEvent_IoCommEmergencyBreak);

      sts = io_read(io_ctx);
      if (EVEN(sts)) {
	ihp->IOReadWriteFlag = FALSE;
	errh_Error("IO read, %m", sts);
      }
      sts = io_write(io_ctx);
      if (EVEN(sts)) {
	ihp->IOReadWriteFlag = FALSE;
	errh_Error("IO write, %m", sts);
      }

      if ( nodep->EmergBreakTrue && !old_emergency_break)
        sts = io_swap(io_ctx, io_eEvent_EmergencyBreak);
      old_emergency_break = nodep->EmergBreakTrue;

      if (swap_io) 
      {
        sts = io_swap(io_ctx_swap, io_eEvent_IoCommSwap);
      }
      io_ScanSupLst( io_ctx->SupCtx);

      time_GetTime(&now);
      time_GetTimeMonotonic(&after);
      next = after;
      time_Aadd(NULL, &next, &cycle);
      delay_action = csup_Exec(&sts, csup_lh, (pwr_tDeltaTime *) &next,
                            (pwr_tDeltaTime *) &after, &now);
      if (delay_action == 2)
	ihp->IOReadWriteFlag = FALSE;

      aproc_TimeStamp(ihp->CycleTimeBus, 5);
    } else {
      ini_mEvent  new_event;
      qcom_sEvent *ep = (qcom_sEvent*) get.data;

      new_event.m  = ep->mask;
      if (new_event.b.oldPlcStop && !swap_io) {
        swap_io = 1;
	close_io = 1;
	errh_SetStatus(PWR__SRVRESTART);
      } else if (new_event.b.swapDone && swap_io) {
        swap_io = 0;
	init_io = 1;
      } else if (new_event.b.terminate) {
        exit(0);
      }
      if (close_io) {    
	io_close(io_ctx);
#if defined(OS_ELN)
	ker$signal( &sts, io_comm_terminate);
#endif
	close_io = 0;
      }
    }
  }
}
Ejemplo n.º 12
0
/* This function is called (via check_events()) from the top level sieve
   loops (prime_sieve() etc.). It can assume that it is safe to tighten any
   sieving parameters other than p_min and p_max.
*/
void process_events(uint64_t current_prime)
{
  /* event_happened was set last in notify_event(), so clear it first which
     ensures that if some signal arrives while we are in process_events()
     it might have to wait until the next sieve iteration to get processed,
     but it won't be lost.
  */
  event_happened = 0;

  if (clear_event(initialise_events))
  {
    init_signals();
    init_progress_report(current_prime);
  }

  if (clear_event(sieve_parameters_changed))
    init_progress_report(current_prime);

  if (clear_event(received_sigterm))
  {
    finish_srsieve("SIGTERM was received",current_prime);
    signal(SIGTERM,SIG_DFL);
    raise(SIGTERM);
  }

  if (clear_event(received_sigint))
  {
    finish_srsieve("SIGINT was received",current_prime);
    signal(SIGINT,SIG_DFL);
    raise(SIGINT);
  }

#ifdef SIGHUP
  if (clear_event(received_sighup))
  {
    finish_srsieve("SIGHUP was received",current_prime);
    signal(SIGHUP,SIG_DFL);
    raise(SIGHUP);
  }
#endif

#if HAVE_FORK
  if (clear_event(received_sigpipe))
  {
    finish_srsieve("SIGPIPE was received",current_prime);
    signal(SIGPIPE,SIG_DFL);
    raise(SIGPIPE);
  }

  if (clear_event(received_sigchld))
  {
    finish_srsieve("SIGCHLD was received",current_prime);
    signal(SIGCHLD,SIG_DFL);
    raise(SIGCHLD);
    exit(EXIT_FAILURE);
  }
#endif

  if (clear_event(factor_found))
    next_report_due = time(NULL);

  if (clear_event(report_due))
    progress_report(current_prime);

  if (clear_event(save_due))
  {
#if SOBISTRATOR_OPT
    if (sobistrator_opt)
      sob_write_checkpoint(current_prime);
#endif
    write_checkpoint(current_prime);
  }
}
Ejemplo n.º 13
0
zPacketThread::~zPacketThread()
{
 clear_event();
 clear();
 sock=-1;
};
Ejemplo n.º 14
0
//! close file
void base_reader::close() {
  brw::close();
  clear_event();
}
Ejemplo n.º 15
0
zPacket::~zPacket() { clear_ext(); clear_event(); clear_socket(); };
Ejemplo n.º 16
0
pwr_tUInt32 bck_WaitBackup (
		void *context,
		pwr_tBoolean timeout)
{
  pwr_tUInt32 sts;
  pwr_tObjid objid;
  pwr_tInt32 c;
  pwr_tTime t;
  pwr_tVaxTime tmo;
  pwr_tVaxTime tmptime;
  pwr_sClass_Backup_Conf *backup_confp;	/* Backup_Conf object pointer */
  $DESCRIPTOR (timeunitdsc, "0 0:0:0.1");	/* 0.1 second units */
  int cycletime;

#ifdef OS_ELN
  pwr_tInt32 res;
  pwr_tVaxTime *tmop;
#endif

#ifdef OS_VMS
  $DESCRIPTOR (efcname, BCK_EFC_NAME);
#endif

/*
 * Initialize
 */

#ifdef OS_ELN
  if (!areas_mapped) {
    BCK_MAP_AREAS;
    areas_mapped = TRUE;
  }
#endif

/*
 * Find the local Backup_Conf object
 */

  sts = gdh_GetClassList (pwr_cClass_Backup_Conf, &objid);
  while (ODD (sts)) {
    sts = gdh_ObjidToPointer (objid, (pwr_tAddress *)&backup_confp);
    if (ODD (sts)) break;
    sts = gdh_GetNextObject (objid, &objid);
  }
  if (EVEN (sts)) return sts;		/* Something wrong, quit */

/*
 * Pick up argument information
 */

  if (context == NULL) time_GetTime(&t);
  else {
    t = *(pwr_tTime *)context;
    free (context);
  }

#ifdef OS_ELN
  tmop = NULL;
#else
  timed_out = FALSE;  
  sts = sys$ascefc (BCK_EFC, &efcname, 0, 0);
  if (EVEN (sts)) lib$signal (sts);			/* BUG */
#endif

  if (timeout) {
    cycletime = backup_confp->CycleSlow * 2;
    if (cycletime == 0) cycletime = BCK_DEFAULT_SLOW * 2;

#ifdef OS_ELN
    tmo = eln$time_value (&timeunitdsc);
#else
    sts = sys$bintim (&timeunitdsc, &tmo);
    if (EVEN (sts)) lib$signal (sts);		/* BUG, should not happen */
#endif

    lib$mult_delta_time (
		&cycletime,		/* multiplier */
		&tmo);			/* delta_time (modified) */
    sys$gettim (&tmptime);
    lib$add_times (&tmo, &tmptime, &tmo); /* Make absolute time */

#ifdef OS_ELN
    tmop = &tmo;
#else
    sts = sys$setimr (BCK_WRITE_DONE, &tmo, &astrtn, 4711, 0);
    if (EVEN (sts)) lib$signal (sts);			/* BUG */
#endif
  }

/*
 * Loop, and wait for things to happen
 */

  while (TRUE) {
#ifdef OS_ELN
    ker$clear_event (NULL, bck_write_done);
    ker$wait_any (NULL, &res, tmop, bck_write_done);

    /* Check for timeout */

    if (res == 0) return SS$_TIMEOUT;
#else

    sts = sys$clref (BCK_WRITE_DONE);
    if (EVEN (sts)) lib$signal (sts);			/* BUG */
    sts = sys$waitfr (BCK_WRITE_DONE);
    if (EVEN (sts)) lib$signal (sts);			/* BUG */

    /* Check for timeout */

    if (timed_out) return SS$_TIMEOUT;

#endif

    /* Check if both cycles done */

    if (time_Acomp(&backup_confp->ObjTimeSlow, &t) < 0) 
        continue;
    if (time_Acomp(&backup_confp->ObjTimeFast, &t) < 0) 
        continue;

    break;

  } /* Loop */

#ifdef OS_VMS
  sys$cantim (4711, 0);
#endif

  return 1;	/* Done. */

} /* bck_WaitBackup */
Ejemplo n.º 17
0
// entry point
int
main (int argc, char **argv)
{

  int rc = 0;
  uint64_t seqnum = 0;
  int opt_index = 0;
  int c = 0;
  int fd = 0;
  char *tmp = NULL;
  char event_buf[8192];
  char event_buf_tmp[8292];	// has to hold event_buf plus an 8-byte sequence number
  char event_path[PATH_MAX + 1];

  bool have_seqnum = false;
  ssize_t nr = 0;
  char const *required_fields[] = {
    "\nSUBSYSTEM=",
    "\nDEVPATH=",
    NULL
  };

  char target_queues[PATH_MAX + 1];

  // default event queue
  memset (g_dev_events, 0, PATH_MAX + 1);
  memset (target_queues, 0, PATH_MAX + 1);
  memset (event_path, 0, PATH_MAX + 1);

  strcpy (g_dev_events, DEFAULT_DEV_EVENTS);

  static struct option opts[] = {
    {"source-queue", required_argument, 0, 's'},
    {"seqnum", required_argument, 0, 'n'},
    {"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
  };

  char const *optstr = "n:s:h";

  while (rc == 0 && c != -1)
    {

      c = getopt_long (argc, argv, optstr, opts, &opt_index);
      if (c == -1)
	{

	  break;
	}

      switch (c)
	{

	case 's':
	  {

	    memset (g_dev_events, 0, PATH_MAX);
	    strncpy (g_dev_events, optarg, PATH_MAX);
	    break;
	  }

	case 'n':
	  {

	    seqnum = (uint64_t) strtoull (optarg, &tmp, 10);
	    if (seqnum == 0 && (tmp == optarg || *tmp != '\0'))
	      {

		usage (argv[0]);
		exit (1);
	      }

	    have_seqnum = true;
	    break;
	  }

	case 'h':
	  {

	    help (argv[0]);
	    exit (0);
	  }

	default:
	  {

	    fprintf (stderr,
		     "[ERROR] %s: Unrecognized option '%c'\n", argv[0], c);
	    usage (argv[0]);
	    exit (1);
	  }
	}
    }

  // get the event 
  memset (event_buf, 0, 8192);
  nr = read_uninterrupted (STDIN_FILENO, event_buf, 8192);

  if (nr <= 0)
    {

      rc = -errno;
      fprintf (stderr,
	       "[ERROR] %s: Failed to read event from stdin: %s\n",
	       argv[0], strerror (-rc));
      exit (1);
    }
  // simple sanity check for requirements 
  for (int i = 0; required_fields[i] != NULL; i++)
    {

      if (strstr (event_buf, required_fields[i]) == NULL)
	{

	  // head of line? with no leading '\n'?
	  if (strncmp
	      (event_buf, required_fields[i] + 1,
	       strlen (required_fields[i]) - 1) != 0)
	    {

	      fprintf (stderr,
		       "[ERROR] %s: Missing required field '%s'\n",
		       argv[0], required_fields[i] + 1);
	      fprintf (stderr,
		       "[ERROR] %s: Pass -h for a list of required fields\n",
		       argv[0]);
	      exit (1);
	    }
	}
    }

  // do we have a seqnum?
  if (!have_seqnum)
    {

      char *seqnum_str = strstr (event_buf, "SEQNUM=");

      // go find it in the device event
      if (seqnum_str == NULL)
	{

	  fprintf (stderr,
		   "[ERROR] %s: Missing SEQNUM.  Pass -n or include SEQNUM= in the input.\n",
		   argv[0]);
	  exit (1);
	}
      // is it a valid seqnum?
      seqnum =
	(uint64_t) strtoull (seqnum_str + strlen ("SEQNUM="), &tmp, 10);
      if (seqnum == 0
	  && (tmp == seqnum_str + strlen ("SEQNUM=") || *tmp != '\n'))
	{

	  // invalid seqnum 
	  fprintf (stderr,
		   "[ERROR] %s: Invalid SEQNUM.  Pass -n or include a valid SEQNUM in the input.\n",
		   argv[0]);
	  exit (1);
	}
    }
  // send it off!
  make_event_path (seqnum, event_path);

  fd = open_event (event_path);
  if (fd < 0)
    {

      fprintf (stderr, "[ERROR] %s: Failed to open '%s': %s\n",
	       argv[0], event_path, strerror (-fd));
      exit (1);
    }

  rc = write_uninterrupted (fd, event_buf, nr);
  if (rc < 0)
    {

      fprintf (stderr, "[ERROR] %s: Failed to write '%s': %s\n",
	       argv[0], event_path, strerror (-fd));

      clear_event (event_buf);
      close (fd);
      exit (1);
    }
  // propagate....
  rc = multicast_event (seqnum, event_path);
  if (rc < 0)
    {

      fprintf (stderr, "[ERROR] %s: Failed to multicast '%s': %s\n",
	       argv[0], event_path, strerror (-rc));

      clear_event (event_buf);
      close (fd);
      exit (1);
    }
  // done!
  clear_event (event_path);
  close (fd);

  return 0;
}
Ejemplo n.º 18
0
int main(int argc, char **argv) {
	SDL_bool ok;
	char const *root = getenv(ROOTVAR);
	if (!root || !*root) {
		fprintf(stderr, "error: environment undefined\n");
		fprintf(stderr, "set %s to the installation directory of Fridge Filler\n", ROOTVAR);
		return 1;
	}

	FILE *rp = 0;
	SDL_bool rp_play = SDL_FALSE;
	SDL_bool rp_save = SDL_FALSE;
	if (argc > 1) {
		if (streq(argv[1], "--save-replay") || streq(argv[1], "-s")) {
			char const *fname = "replay.txt";
			if (argc == 3) { fname = argv[2]; }
			printf("saving replay to `%s'\n", fname);
			rp = fopen(fname, "w");
			rp_save = SDL_TRUE;
		}

		if (streq(argv[1], "--replay") || streq(argv[1], "-r")) {
			char const *fname = "replay.txt";
			if (argc == 3) { fname = argv[2]; }
			printf("loading replay `%s'\n", fname);
			rp = fopen(fname, "r");
			rp_play = SDL_TRUE;
		}
	}

	session s;
	game_state gs;
	ok = init_game(&s, &gs, root);
	if (!ok) { return 1; }

	game_event ge;
	clear_event(&ge);

	unsigned ticks;
	unsigned old_ticks = SDL_GetTicks();

	int have_ev;
	SDL_Event event;
	while (gs.run != MODE_EXIT) {
		if (!rp_play) {
			have_ev = SDL_PollEvent(&event);
			if (have_ev) {
				process_event(&event, &ge);
			}

			unsigned char const *keystate = SDL_GetKeyboardState(0);
			keystate_to_movement(keystate, &ge.player);
		} else {
			have_ev = SDL_PollEvent(&event);
			if (have_ev) {
				process_event(&event, &ge);
				if (ge.exit) { break; }
				clear_event(&ge);
			}
		}

		ticks = SDL_GetTicks();
		if (ticks - old_ticks >= TICK) {
			if (rp_save) { print_event(rp, &ge); }
			else if (rp_play) { read_event(rp, &ge); }
			update_gamestate(&s, &gs, &ge);
			clear_event(&ge);
			/*
			printf("%d\n", ticks - old_ticks);
			*/
			old_ticks = ticks;
		}

		render(&s, &gs);
		SDL_Delay(TICK / 4);
	}

	int i;
	for (i = 0; i < NGROUPS; i++) {
		free(gs.entities[i].e);
	}

	destroy_level(&s.level);
	SDL_DestroyTexture(s.level.background);

	if (gs.debug.font) {
		TTF_CloseFont(gs.debug.font);
	};

	if (rp) { fclose(rp); }
	free(s.msg.msgs);

	SDL_DestroyRenderer(s.r);
	SDL_DestroyWindow(s.w);
	SDL_Quit();

	return 0;
}