rnd-19980930-1
[rocksndiamonds.git] / src / misc.c
index 14007b7e3d20868f510911e8a4150e93060c864f..1ab116d6b771458990b295f4d676b32f36707142 100644 (file)
@@ -1,13 +1,12 @@
 /***********************************************************
 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
 *----------------------------------------------------------*
-*  ©1995 Artsoft Development                               *
-*        Holger Schemel                                    *
-*        33659 Bielefeld-Senne                             *
-*        Telefon: (0521) 493245                            *
-*        eMail: aeglos@valinor.owl.de                      *
-*               aeglos@uni-paderborn.de                    *
-*               q99492@pbhrzx.uni-paderborn.de             *
+*  (c) 1995-98 Artsoft Entertainment                       *
+*              Holger Schemel                              *
+*              Oststrasse 11a                              *
+*              33604 Bielefeld                             *
+*              phone: ++49 +521 290471                     *
+*              email: aeglos@valinor.owl.de                *
 *----------------------------------------------------------*
 *  misc.c                                                  *
 ***********************************************************/
 #include <sys/param.h>
 #include <sys/types.h>
 
-void microsleep(unsigned long usec)
-{
-  struct timeval delay;
-
-  delay.tv_sec  = usec / 1000000;
-  delay.tv_usec = usec % 1000000;
-
-  if (select(0,NULL,NULL,NULL,&delay)!=0)
-    fprintf(stderr,"%s: in function microsleep: select failed!\n",
-           progname);
-}
-
-long mainCounter(int mode)
+static unsigned long mainCounter(int mode)
 {
   static struct timeval base_time = { 0, 0 };
   struct timeval current_time;
-  long counter_ms;
+  unsigned long counter_ms;
+
+  gettimeofday(&current_time, NULL);
 
-  gettimeofday(&current_time,NULL);
   if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
     base_time = current_time;
 
-  counter_ms = (current_time.tv_sec - base_time.tv_sec)*1000
-             + (current_time.tv_usec - base_time.tv_usec)/1000;
+  counter_ms = (current_time.tv_sec  - base_time.tv_sec)  * 1000
+             + (current_time.tv_usec - base_time.tv_usec) / 1000;
 
-  if (mode == READ_COUNTER_100)
-    return(counter_ms/10);     /* return 1/100 secs since last init */
-  else /*    READ_COUNTER_1000 */
-    return(counter_ms);                /* return 1/1000 secs since last init */
+  return counter_ms;           /* return milliseconds since last init */
 }
 
-void InitCounter() /* set counter back to zero */
+void InitCounter()             /* set counter back to zero */
 {
   mainCounter(INIT_COUNTER);
 }
 
-long Counter() /* returns 1/100 secs since last call of InitCounter() */
+unsigned long Counter()        /* get milliseconds since last call of InitCounter() */
 {
-  return(mainCounter(READ_COUNTER_100));
+  return(mainCounter(READ_COUNTER));
 }
 
-long Counter2()        /* returns 1/1000 secs since last call of InitCounter() */
+static void sleep_milliseconds(unsigned long milliseconds_delay)
 {
-  return(mainCounter(READ_COUNTER_1000));
-}
+  if (milliseconds_delay < 5)
+  {
+    /* we want to wait only a few ms -- if we assume that we have a
+       kernel timer resolution of 10 ms, we would wait far to long;
+       therefore it's better to do a short interval of busy waiting
+       to get our sleeping time more accurate */
 
-void WaitCounter(long value)   /* wait for counter to reach value */
-{
-  long wait;
+    unsigned long base_counter = Counter(), actual_counter = Counter();
+
+    while (actual_counter < base_counter + milliseconds_delay &&
+          actual_counter >= base_counter)
+      actual_counter = Counter();
+  }
+  else
+  {
+    struct timeval delay;
 
-  while((wait=value-Counter())>0)
-    microsleep(wait*10000);
+    delay.tv_sec  = milliseconds_delay / 1000;
+    delay.tv_usec = 1000 * (milliseconds_delay % 1000);
+
+    if (select(0, NULL, NULL, NULL, &delay) != 0)
+      fprintf(stderr,"%s: in function sleep_milliseconds: select() failed!\n",
+             progname);
+  }
 }
 
-void WaitCounter2(long value)  /* wait for counter to reach value */
+void Delay(unsigned long delay)        /* Sleep specified number of milliseconds */
 {
-  long wait;
-
-  while((wait=value-Counter2())>0)
-    microsleep(wait*1000);
+  sleep_milliseconds(delay);
 }
 
-void Delay(long value)
+BOOL FrameReached(unsigned long *frame_counter_var, unsigned long frame_delay)
 {
-  microsleep(value);
+  unsigned long actual_frame_counter = FrameCounter;
+
+  if (actual_frame_counter < *frame_counter_var+frame_delay &&
+      actual_frame_counter >= *frame_counter_var)
+    return(FALSE);
+
+  *frame_counter_var = actual_frame_counter;
+  return(TRUE);
 }
 
-BOOL DelayReached(long *counter_var, int delay)
+BOOL DelayReached(unsigned long *counter_var, unsigned long delay)
 {
-  long actual_counter = Counter();
+  unsigned long actual_counter = Counter();
 
-  if (actual_counter >= *counter_var+delay || actual_counter < *counter_var)
-  {
-    *counter_var = actual_counter;
-    return(TRUE);
-  }
-  else
+  if (actual_counter < *counter_var + delay &&
+      actual_counter >= *counter_var)
     return(FALSE);
+
+  *counter_var = actual_counter;
+  return(TRUE);
 }
 
-BOOL FrameReached(long *frame_counter_var, int frame_delay)
+void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
 {
-  long actual_frame_counter = FrameCounter;
+  unsigned long actual_counter;
 
-  if (actual_frame_counter >= *frame_counter_var+frame_delay
-      || actual_frame_counter < *frame_counter_var)
+  while(1)
   {
-    *frame_counter_var = actual_frame_counter;
-    return(TRUE);
+    actual_counter = Counter();
+
+    if (actual_counter < *counter_var + delay &&
+       actual_counter >= *counter_var)
+      sleep_milliseconds((*counter_var + delay - actual_counter) / 2);
+    else
+      break;
   }
-  else
-    return(FALSE);
+
+  *counter_var = actual_counter;
 }
 
 char *int2str(int ct, int nr)