Here's a patch that seems to cure the problem with midnight rollovers.  This
shows up by the time appearing normal, but the date incrementing by one
every time the system clock is read - which some programs do many times
per second.

The problem appears to be in INT1A:00.  I'm going to make a couple assumptions
here that may be completely off base, so someone with a clue please correct
me (and this patch) if I'm full of it.

The main problem is that when an overflow occurs, INT1A:00 adjusts the time for
the current return value, but fails to adjust the time base delta (usr_delta_ticks).
Next time it's called, the value is still over the 24 hour tick threshold, so it
adjusts the current time and resets the overflow flag, which increases the date
again... this can happen many times per second in some programs, making the date
appear "random".

I think there's a basic problem with how INT1A:00 is written - and here's where
I'm treading on thin ice, since I've only speant a couple hours looking at this,
and my asm is very rust.

It looks like the tick overflow flag is supposed to be set by int8, not INT1A:00.
INT1A should read the flag, adjust the tick value appropriatly, return the
value of the flag in AL, and then clear it.

I also feel that the comments at the top of AH:00 are irrelevant, because int8
just sets the flag, not increments it, so there's no way it could be more than
one anyway.

The patch simply offsets one day from the time base delta before it does
anything else if the flag is set, and ignores it after that - it is cleared in
set_ticks().

I really appreciate all the work that has gone into dosemu... it's great to be
able to run two historic BBSes on one Linux machine, and have plenty of time
left over.  Thanks!

--- 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    Thu Dec 17 02:33:36 1998
@@ -791,25 +791,29 @@
        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;
-    }
     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