• Re: I Need a millesecond Timer under DOS ?

    From Game Corner Playthroughs@21:1/5 to Oliver Kreylos on Tue Dec 21 12:08:44 2021
    On Wednesday, October 14, 1998 at 3:00:00 AM UTC-4, Oliver Kreylos wrote:
    device wrote:

    I think there are ways to reprogram the clock to generate more higher resolution tics.

    Dave
    Yes, there are. I am using a custom timer resolution in my game, here's
    what you have to do to
    a) set the timer to 1ms resolution
    b) keep the DOS clock going correctly nonetheless
    Just reprogramming the timer chip without some book-keeping would let
    the DOS clock run 18 times as fast. We don't want that... --8<------------------------------------------------------------
    typedef void (__interrupt __far* INTFUNCPTR)(void);
    INTFUNCPTR oldTimerInterrupt; // Original interrupt handler
    volatile long int milliseconds; // Elapsed time in milliseconds
    void __interrupt __far timerHandler(void)
    {
    static unsigned long count=0; // To keep track of original timer ticks ++milliseconds;
    count+=1103;
    if(count>=65536) // It is now time to call the original handler
    {
    count-=65536;
    _chain_intr(oldTimerInterrupt);
    }
    else
    outp(0x20,0x20); // Acknowledge interrupt
    }
    void installInterrupt(void)
    {
    union REGS r;
    struct SREGS s;
    _disable();
    segread(&s);
    /* Save old interrupt vector: */
    r.h.al=0x08;
    r.h.ah=0x35;
    int386x(0x21,&r,&r,&s);
    oldTimerInterrupt=(INTFUNCPTR)MK_FP(s.es,r.x.ebx);
    /* Install new interrupt handler: */
    milliseconds=0;
    r.h.al=0x08;
    r.h.ah=0x25;
    s.ds=FP_SEG(timerHandler);
    r.x.edx=FP_OFF(timerHandler);
    int386x(0x21,&r,&r,&s);
    /* Set resolution of timer chip to 1ms: */
    outp(0x43,0x36);
    outp(0x40,(unsigned char)(1103&0xff));
    outp(0x40,(unsigned char)((1103>>8)&0xff));
    _enable();
    }
    void removeInterrupt(void)
    {
    union REGS r;
    struct SREGS s;
    _disable();
    segread(&s);
    /* Re-install original interrupt handler: */
    r.h.al=0x08;
    r.h.ah=0x25;
    s.ds=FP_SEG(oldTimerInterrupt);
    r.x.edx=FP_OFF(oldTimerInterrupt);
    int386x(0x21,&r,&r,&s);
    /* Reset timer chip resolution to 18.2...ms: */
    outp(0x43,0x36);
    outp(0x40,0x00);
    outp(0x40,0x00);
    _enable();
    }
    --8<------------------------------------------------------------
    To query the elapsed time in ms, just read the variable milliseconds.
    A note: This program is for Watcom C. For other compilers, some
    structures and functions (like _enable) might have different names.
    Refer to your compiler's manual.
    A second note: This program is for Protected Mode using DOS/4G. To
    compile it for real mode, just replace all int386 by int86, and all wide registers (like edx) with their short counterparts (like dx). The
    program should work fine then.
    I hope this helps a bit,
    Oliver

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)