|
||
|
GP Mailing List
ATXGPSIG List
|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Oops! Re: Timer procedures in C++ DOS
Oops. This is the one with the good que code. Can't seem to find that
one.
Bob Pendleton wrote:
>
> > Luis Mendoza wrote:
> >
> > Hello fellow programmers,
> > Yeah, you read right. With DirectX 7 out I'm still programming in
> > DOS. There's just something about it that makes me want to keep
> > coming back to it. Besides, I'm still ticked that my download of DX7
> > broke after about 25MB and hours of waiting so I have to start all
> > over again. Even using GetRight doesn't always guarantee you'll get
> > what you want. Anyway, does anybody have a c++ dos procedure of a
> > "timer" that can count in milliseconds. I mean to use it as an all
> > purpose counter to regulate the speed of my frame rate etc. I have PC
> > GAME Programming Explorer and I've been fiddling around with
> > synchronizing the system clock but that still doesn't do it for me.
> > Also does anybody have any info on upgrades to WATCOM C++ 10.0a that I
> > can download free. The latest version at $150.00 is too pricey for
> > me.
> > Hope somebody cam shed some light on my queries.
> > Sincerely Yours,
> > Luis
> >
> ------------------------------------------------------
> Here you go. Not well documented but it is written
> using Watcom C++.
>
> Implements a DOS interrupt driven timer with very high
> resolution. Uses a binary heap to implement the que
> so that insertions/deletion are O(log N)
> 2
> ------------------------------------------------------
> //
> // Written by: Bob Pendleton
> //
>
> #include <dos.h>
> #include <stddef.h>
> #include "runque.h"
> #include "timerque.h"
> #include "pipe.h"
> #include "bl.h"
>
> //---------------------------------------------------
> //
> // pointer to the timer queue element free list
> //
>
> timerQueElem *timerQueElem::freeList = NULL;
>
> //---------------------------------------------------
> //
> // create a new timer queue element
> //
>
> void*
> timerQueElem::operator new(size_t size)
> {
> static timerQueElem *result;
>
> if (freeList == NULL)
> {
> result = (timerQueElem *) new char[size];
> result->link = NULL;
> }
> else
> {
> result = freeList;
> result->link = NULL;
> freeList = freeList->link;
> }
>
> return result;
> }
>
> //---------------------------------------------------
> //
> // delete a timer que element and put it on the free list
> //
> //
>
> void
> timerQueElem::operator delete(void *t)
> {
> ((timerQueElem *)t)->link = freeList;
> freeList = ((timerQueElem *)t);
> }
>
> //---------------------------------------------------
> //
> // initialize a timer queue
> //
>
> timerQue::timerQue()
> {
> head = NULL;
> tail = NULL;
> }
>
> //---------------------------------------------------
> //
> // add an event to the timer que.
> //
>
> void
> timerQue::add(long c, item f)
> {
> timerQueElem *elem;
> timerQueElem *next;
> timerQueElem *prev;
> long count;
> long prevCount;
>
> lockClock();
>
> elem = new timerQueElem;
> if (elem == NULL)
> {
> success = FALSE;
> return;
> }
> elem->func = f;
> elem->link = NULL;
>
> if (head == NULL) // nothing in the queue
> {
> elem->clicks = c;
> head = elem;
> tail = elem;
> }
> else
> {
> next = head;
> prev = NULL;
> count = 0;
> prevCount = 0;
> while (TRUE)
> {
> if (next == NULL)
> {
> // we've searched the whole queue
> // tack it on the end
>
> elem->clicks = c - count;
> tail->link = elem;
> tail = elem;
>
> break;
> }
> else
> {
> prevCount = count;
> count += next->clicks;
> if (c < count)
> {
> if (prev == NULL)
> {
> // before the first item on the list
>
> elem->clicks = c;
> next->clicks -= c;
>
> elem->link = head;
> head = elem;
> }
> else
> {
> // between two items
>
> elem->clicks = c - prevCount;
> next->clicks -= elem->clicks;
>
> elem->link = next;
> prev->link = elem;
> }
> break;
> }
> }
> prev = next;
> next = next->link;
> }
> }
> unlockClock();
> }
>
> //---------------------------------------------------
> //
> // empty the timer que. dump the requests on the floor
> //
>
> void
> timerQue::emptyQue()
> {
> timerQueElem *old;
> timerQueElem *next;
>
> lockClock();
>
> next = head;
>
> head = NULL;
> tail = NULL;
>
> while (next != NULL)
> {
> old = next;
> next = next->link;
> delete old;
> }
>
> unlockClock();
> }
>
> //---------------------------------------------------
> //
> // Count down the next event on the on the queue.
> // If it is time, put it on the run queue.
> //
> // NOTE: this procedure can only be called from an interrupt
> // service routine.
> //
>
> void
> timerQue::countTime()
> {
> static timerQueElem *thing;
>
> if (head != NULL)
> {
> head->clicks--;
> if (head->clicks <= 0)
> {
> thing = head;
> head = head->link;
> run.addFromTimer(thing);
> }
> }
> }
>
> //---------------------------------------------------
> //
> // Global data used by our timer interrupt handler
> //
>
> //
> // The number of times the interrupt function
> // has been called.
> //
>
> volatile long clicks = 0;
> static volatile int next = 0;
>
> //
> // The address of the old interrupt handler
> //
>
> static void interrupt (*oldclock)(...) = NULL;
>
> //
> // How much faster than the normal clock.
> // 1 = 18.2
> // 2 = 36.4
> // 4 = 72.8
> // 8 = 145.6
> // 16 = 291.2
> //
>
> static const int clockMultiplier = 8;
>
> //
> // clicks per second
> //
>
> const float clicksPerSecond = (18.2 * clockMultiplier);
> const float secondsPerClick = (1.0 / clicksPerSecond);
>
> //
> // Yes, we really want to grab the hardware interrupt
> //
>
> static const clockInt = 0x08;
>
> //---------------------------------------------------
> //
> // lock to control the action of the clock interrupt handler
> //
>
> static volatile int clockLock = 0;
>
> void lockClock()
> {
> disable();
> clockLock++;
> enable();
> }
>
> void unlockClock()
> {
> disable();
> if (clockLock > 0)
> {
> clockLock--;
> }
> else
> {
> clockLock = 0;
> }
> enable();
> }
>
> //---------------------------------------------------
> //
> // Our clock interrupt handler;
> //
>
> void interrupt
> clock(...)
> {
> next++;
> clicks++;
>
> if (next >= clockMultiplier)
> {
> next = 0;
> (*oldclock)();
> }
>
> if (clockLock == 0)
> {
> timer.countTime();
> tones.countTime();
> }
>
> outp(0x20, 0x20);
> }
>
> //---------------------------------------------------
> //
> // install our timer function and speed up the clock
> //
>
> void
> install_timer()
> {
> union
> {
> long divisor;
> unsigned char c[sizeof(long)];
> } count;
>
> clicks = 0;
> next = 0;
>
> oldclock = getvect(clockInt);
> setvect(clockInt, clock);
>
> count.divisor = 65536l / clockMultiplier;
> outp(0x43, 0x36);
> outp(0x40, count.c[0]);
> outp(0x40, count.c[1]);
> }
>
> //---------------------------------------------------
> //
> // restore the clock speed and remove the timer function
> //
>
> void
> remove_timer()
> {
> setvect(clockInt, oldclock);
> oldclock = NULL;
>
> //
> // slow down the clock
> //
> outp(0x43, 0x36);
> outp(0x40, (char) 0);
> outp(0x40, (char) 0);
> }
> =================================================================
> The GameProgrammer.Com mailing list is for the open discussion
> of any topic related to the art, science, and business of
> programming games. This list is especially tolerant of beginners.
> We were all beginners once
>
> To SUBSCRIBE or UNSUBSCRIBE please visit:
> http://gameprogrammer.com/mailinglist.html
=================================================================
The GameProgrammer.Com mailing list is for the open discussion
of any topic related to the art, science, and business of
programming games. This list is especially tolerant of beginners.
We were all beginners once
To SUBSCRIBE or UNSUBSCRIBE please visit:
http://gameprogrammer.com/mailinglist.html
|
|