Okay, here's the second attempt at a patch for the midnight rollover problem.
See my previous post for details on what it does.

The problem was that if a program read the time at exactly midnight, as a
BBS might as part of it's busy loop, it could return a negative tick value,
crashing the program or the entire emulator.

It now checks to make sure the return value is valid, in case the clock has
slipped a tick or two, and there are less than 1573040 ticks per day.

Both BBSes I run under dosemu survived the midnight rollover with this patch
tonight, so I think it works.

If someone actually tries this, please let me know if it works for them.

This is against 0.98.4... I imagine it should work on the 0.99 series, unless
the software interrupts have been completely rewritten.

diff -urN dosemu-0.98.4/src/base/async/int.c local-dosemu-0.98.4/src/base/async/int.c 
--- dosemu-0.98.4/src/base/async/int.c  Mon Nov  9 14:06:14 1998
+++ local-dosemu-0.98.4/src/base/async/int.c    Sat Jan  2 18:40:28 1999
@@ -791,25 +791,31 @@
        IBM and many clone BIOSes set the flag for AL rather than incrementing
          it, leading to loss of a day if two consecutive midnights pass
          without a request for the time (e.g. if the system is on but idle)
+        This appears to be irrelevant, because int8 sets the overflow flag,
+         so it can never be more than one here.
 ->     since the midnight flag is cleared, if an application calls this
 ->       function after midnight before DOS does, DOS will not receive the
 ->       midnight flag and will fail to advance the date
 */
   case 0:                      /* read time counter */
+
+    /* has the midnight passed?  Check and adjust offset.  TICK_OVERFLOW_ADDR is set 
+in int8. */
+    if (*(u_char *) TICK_OVERFLOW_ADDR) {
+      g_printf("TIMER: midnight overflow - adjusting offset.\n");
+      usr_delta_ticks -= 1573040;      /* Adjust time base delta by a day. */
+    }
+
+    last_ticks = sys_base_ticks + usr_delta_ticks + (pic_sys_time >> 16);
     /* it works because pic_sys_time has a zero reference. It doesn't
      * account for timer speedups, but any decent DOS program should
      * call back the original int8 at the 18.2 Hz rate... */
-    last_ticks = sys_base_ticks + usr_delta_ticks + (pic_sys_time >> 16);
 
-    /* has the midnight passed? */
-    if (last_ticks > 1573040) {
-      *(u_char *) (TICK_OVERFLOW_ADDR) += 0x1;
-      last_ticks -= 1573040;
-    }
+    if(last_ticks < 0) last_ticks = 0; /* Make sure return value is valid */
+
     LO(ax) = *(u_char *) (TICK_OVERFLOW_ADDR);
     LWORD(ecx) = (last_ticks >> 16) & 0xffff;
     LWORD(edx) = last_ticks & 0xffff;
-    g_printf("TIMER: read timer = %lu\n", last_ticks);
+    g_printf("TIMER: read timer = %lu overflow = %d\n", last_ticks, *(u_char 
+*)TICK_OVERFLOW_ADDR);
     set_ticks(last_ticks);     /* set_ticks is in rtc.c */
     break;
 
-- 
     /// Stefan Hudson <[EMAIL PROTECTED]>  
__  /// Senior Network Administrator - Monterey Bay Internet
\\\/// http://www.mbay.net/  -  Email: [EMAIL PROTECTED]
 \XX/ Voice: 831-642-6100  Fax: 831-642-6101  Modem: 831-642-6102

Reply via email to