#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();
}