Metropoli BBS
VIEWER: timer.c MODE: TEXT (ASCII)
#include <dos.h>
#include <dpmi.h>
#include <go32.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/nearptr.h>

_go32_dpmi_seginfo info;
_go32_dpmi_seginfo original;

volatile long long OldTimerHandler;
volatile int TicksPerCall, OriginalTicks, Counter;

static volatile void TimerStart() {}

void TimerHandler() {
    Counter++;
    OriginalTicks+=TicksPerCall;
    if(OriginalTicks>=65536) {
        OriginalTicks-=65536;
        __asm__ __volatile__ ("
            pushfl
            lcall %0
        "
        :
        : "g" (OldTimerHandler));
    } else {
        outportb(0x20, 0x20);
    }
}

static volatile void TimerEnd() {}

void SetTimerRate(unsigned short ticks) {
  outportb(0x43, 0x34);
  outportb(0x40, ( ticks & 0x00FF ) );
  outportb(0x40, ( ( ticks >> 8 ) & 0x00FF ) );
}

void InitTimer(int tickspersecond) {
    __dpmi_meminfo lock;

    lock.address = __djgpp_base_address + (unsigned) &TimerStart;
    lock.size = ((unsigned)&TimerEnd - (unsigned)&TimerStart);
    __dpmi_lock_linear_region(&lock);

    Counter=0;
    OriginalTicks=0;
    TicksPerCall=1193181/((unsigned short)tickspersecond);
  
    disable();

    _go32_dpmi_get_protected_mode_interrupt_vector(0x0008, &original);

    OldTimerHandler=((unsigned long long)original.pm_offset) +
                    (((unsigned long long)original.pm_selector)<<32);

    info.pm_offset=(unsigned long int)TimerHandler;
    info.pm_selector=_my_cs();
    _go32_dpmi_allocate_iret_wrapper(&info);

    SetTimerRate(TicksPerCall);
    _go32_dpmi_set_protected_mode_interrupt_vector(0x0008, &info);
    enable();
}

void DeinitTimer() {
    disable();
    SetTimerRate(0);
    _go32_dpmi_set_protected_mode_interrupt_vector(0x0008, &original);
    enable();  
}
[ RETURN TO DIRECTORY ]