VOGONS

Common searches


First post, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I already asked this question at https://www.vbforums.com/editpost.php?p=5531200&do=editpost but I get the feeling I may have more success here. (Given this relates to MS-DOS programming and older hardware.)

Whenever I needed a delay in my QBasic/QB45 program I would use a simple delay based on the TIMER function:

DEFINT A-Z
CLS
Delay! = .25
DO
StartTime! = TIMER
DO WHILE TIMER < StartTime! + Delay! OR TIMER < StartTime!
'Put code that doesn't need to be timed here.
LOOP
'Put code that needs to be timed here.
PRINT "*";
LOOP

However sometimes I would want to use more precise timing but could never figure out a decent way of implementing it. After some searching online I found it was very hard to find anything about this subject for QBasic. What I found usually was in some other language using some internal high-precision Delay method (Turbo Basic and Turbo C++ for example.) or some highly technical info about the 8253/8253 PIT chip. The closest I have found to what I need is at https://www.franksteinberg.de/pbeisp.htm in a file called "Timing.zip". Unfortunately most of the commenting and documentation is in German and what I have found in English are long-winded technical documents.

My question is: could someone help me narrow down all this information to something straightforward that does pretty much the same thing as in my TIMER example, but with greater precision?

Yes, I know QBasic/QB45 might be too slow to go into the millisecond range unless the CPU is fast enough without resorting to assembly code, but I would prefer to avoid assembly language if possible. While I do understand assembly language somewhat, any attempt at using it in combination with QBasic/QB45 by me resulted in just freezing the system. There is something about CALL ABSOLUTE I never quite got.

If it's not possible in QBasic, then how is it done in asm or C?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 1 of 10, by Kalle

User metadata
Rank Newbie
Rank
Newbie

I don't know about QBasic, but the BIOS offers a function to wait a specific time (int 15h, function 86h, time to wait in microseconds has to be in cx:dx). Maybe you could implement that into QBasic somehow?

Reply 2 of 10, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I will look into that. I could use CALL ABSOLUTE or QB45 library function INTERRUPT.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 4 of 10, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

If you need to be able to execute BASIC statements *during* the overall delay interval as implied in your example, keep in mind that the BIOS function will only return after the specified amount of time, so you will probably have to call it multiple times in a loop.

Reply 5 of 10, by Ringding

User metadata
Rank Member
Rank
Member

Usually what you do is: raise the frequency of the timer interrupt (by writing a lower counter value into the PIT); install an IRQ 0 handler that calls the original one at the original frequency (approx. 18.2 times per second) and does the actual custom time keeping that you need. I don’t want to touch QB these days, but I’m certain that there exist a few tutorials on how to hook an interrupt handler in it.

Reply 6 of 10, by Peter Swinkels

User metadata
Rank Member
Rank
Member

@Kalle: I will look at the file. Thanks.
@ripsaw8080: It depends on what exactly I would need.
@Ringding : I could do that, but won't that mess up the time/date?

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 7 of 10, by Peter Swinkels

User metadata
Rank Member
Rank
Member

I found something that might work using INT 0x15, 0x86. Thank you Kalle!

https://www.vbforums.com/showthread.php?89292 … l=1#post5531376

Once I modify a game I wrote or write new one I can really test this solution.

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels

Reply 8 of 10, by Kalle

User metadata
Rank Newbie
Rank
Newbie

"I could do that, but won't that mess up the time/date?"

If you call the original handler at the original frequency, then no, otherwise yes. Let's say you let the timer run at twice the speed, then your int 8 handler has to call the original int 8 handler every second time that your handler is called, then the time/date will be fine.

Reply 10 of 10, by Peter Swinkels

User metadata
Rank Member
Rank
Member

Using interrupt 15h works well enough for me. Example:

https://github.com/PeterSwinkels/Balls/blob/main/BALLS.BAS

Do not read if you don't like attention seeking self-advertisements!

Did you read it anyway? Well, you can find all sorts of stuff I made using various programming languages over here:
https://github.com/peterswinkels