Valhalla Legends Forums Archive | Visual Basic Programming | Help with never ending loop

AuthorMessageTime
Atom
Maybe someone can help me, I am making a utilitie for CS and it requires a main loop that will run over and over kinda like a game loop. I get the problem where the process runs up 100% cpu usage and pretty much fails. How can I help this?

You guys dont really need this but this is the code i have right now thats going to go in the loop.
[code]
Dim hwnd As Long
hwnd = FindWindow(vbNullString, "Counter-Strike")
If hwnd > 0 Then
Call DrawText(hwnd, 100, 500, "Counter-Strike Detected", &HFF&)
Call DrawText(hwnd, 100, 515, ".:CST00LZ vZero by Atom:.", &HF48020)
[/code]
May 15, 2004, 2:29 PM
Adron
[quote author=Atom link=board=31;threadid=6813;start=0#msg60224 date=1084631371]
Maybe someone can help me, I am making a utilitie for CS and it requires a main loop that will run over and over kinda like a game loop. I get the problem where the process runs up 100% cpu usage and pretty much fails. How can I help this?

You guys dont really need this but this is the code i have right now thats going to go in the loop.
[code]
Dim hwnd As Long
hwnd = FindWindow(vbNullString, "Counter-Strike")
If hwnd > 0 Then
Call DrawText(hwnd, 100, 500, "Counter-Strike Detected", &HFF&)
Call DrawText(hwnd, 100, 515, ".:CST00LZ vZero by Atom:.", &HF48020)
[/code]
[/quote]

Having 100% CPU usage from a simple game loop is normal. If you only need to check every X seconds or milliseconds, you should insert a delay statement into the loop. Something as simple as "Sleep 100" would probably do.
May 15, 2004, 2:52 PM
Atom
Well i might as well use a timer then i guess, thanks for your help!
Only problem with a timer is that i draw text onto the cs window, and it of course flickers with the 1ms delay.
May 16, 2004, 3:48 AM
Lenny
IIRC, the Visual Basic timer control is only accurate to the nearest 55 ms.

You would be better off using sleep as Adron said, or a high resolution timer.....
May 16, 2004, 3:58 AM
Skywing
[quote author=Lenny link=board=31;threadid=6813;start=0#msg60349 date=1084679919]
IIRC, the Visual Basic timer control is only accurate to the nearest 55 ms.

You would be better off using sleep as Adron said, or a high resolution timer.....
[/quote]
Sleep is only accurate to at best 10ms or so. No delay execution function will provide you with better than 10ms minimum scheduling granularity on a typical x86 system (excluding busy-waits) because that is as low as the system clock interrupt goes.

You should probably write to CS's backbuffer to avoid the flicker.
May 18, 2004, 3:22 AM
Grok
[quote author=Skywing link=board=31;threadid=6813;start=0#msg60606 date=1084850547]Sleep is only accurate to at best 10ms or so. No delay execution function will provide you with better than 10ms minimum scheduling granularity on a typical x86 system (excluding busy-waits) because that is as low as the system clock interrupt goes.[/quote]

Configurable? Did you find this in the IX86 programmer's guides? I'll read about it when I get home.
May 18, 2004, 2:59 PM
Skywing
[quote author=Grok link=board=31;threadid=6813;start=0#msg60652 date=1084892389]
[quote author=Skywing link=board=31;threadid=6813;start=0#msg60606 date=1084850547]Sleep is only accurate to at best 10ms or so. No delay execution function will provide you with better than 10ms minimum scheduling granularity on a typical x86 system (excluding busy-waits) because that is as low as the system clock interrupt goes.[/quote]

Configurable? Did you find this in the IX86 programmer's guides? I'll read about it when I get home.
[/quote]
None of the standard x86 HALs for NT will let you go below 10ms. I don't think you'll be able to go below 10ms with typical x86-based system hardware either (even if you convinced the HAL to try).

This isn't something that you would find in the Intel CPU manuals because it's a limitation of the timer chip and not the CPU.
May 19, 2004, 6:37 AM
Adron
I think you can go below 10 ms. IIRC it's just the standard timing. In DOS days, you could reprogram the timer to fit your application, but to keep the clock running and stuff updating, you had to call the original handler every 10 ms. Increase timer frequency by X times, then call original handler every X ticks.
May 19, 2004, 10:54 AM
Skywing
[quote author=Adron link=board=31;threadid=6813;start=0#msg60801 date=1084964040]
I think you can go below 10 ms. IIRC it's just the standard timing. In DOS days, you could reprogram the timer to fit your application, but to keep the clock running and stuff updating, you had to call the original handler every 10 ms. Increase timer frequency by X times, then call original handler every X ticks.
[/quote]
Are you guaranteed hardware support for <10ms resolution, though? Or is that just a nice feature that some computer systems may have?
May 19, 2004, 2:22 PM
Adron
[quote author=Skywing link=board=31;threadid=6813;start=0#msg60810 date=1084976543]
[quote author=Adron link=board=31;threadid=6813;start=0#msg60801 date=1084964040]
I think you can go below 10 ms. IIRC it's just the standard timing. In DOS days, you could reprogram the timer to fit your application, but to keep the clock running and stuff updating, you had to call the original handler every 10 ms. Increase timer frequency by X times, then call original handler every X ticks.
[/quote]
Are you guaranteed hardware support for <10ms resolution, though? Or is that just a nice feature that some computer systems may have?
[/quote]

There are never guarantees with computers, but:
[code]
PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254)
Notes:   XT & AT use ports 40h-43h; PS/2 uses ports 40h, 42h-44h, and 47h
   the counter chip is driven with a 1.193 MHz clock (1/4 of the
   original PC's 4.77 MHz CPU clock)

0040 RW PIT counter 0, counter divisor    (XT, AT, PS/2)
   Used to keep the system time; the default divisor of (1)0000h
   produces the 18.2Hz clock tick.
[/code]
That's the default DOS timer, having a frequency of 18.2 Hz with a divisor of 10000. If you set the divisor to 1, you should get a frequency of 1192755 Hz. And then perhaps you'll be stuck in the interrupt forever, but.... :P

edit: Interesting thing to try: Make a driver that outputs a lower value to that port and see what happens? Port 42h is the speaker frequency, so you can obviously program the timer chip to generate higher frequencies than 100 Hz.
May 24, 2004, 9:40 PM
Atom
My posts always spark the most interesting questions.
June 1, 2004, 5:02 AM
Myndfyr
[quote author=Adron link=board=31;threadid=6813;start=0#msg61612 date=1085434838]
[code]
PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254)
Notes:   XT & AT use ports 40h-43h; PS/2 uses ports 40h, 42h-44h, and 47h
   the counter chip is driven with a 1.193 MHz clock (1/4 of the
   original PC's 4.77 MHz CPU clock)

0040 RW PIT counter 0, counter divisor    (XT, AT, PS/2)
   Used to keep the system time; the default divisor of (1)0000h
   produces the 18.2Hz clock tick.
[/code]
That's the default DOS timer, having a frequency of 18.2 Hz with a divisor of 10000. If you set the divisor to 1, you should get a frequency of 1192755 Hz. And then perhaps you'll be stuck in the interrupt forever, but.... :P
[/quote]

Hrm.... I think "perhaps" is giving it too much credit; based on my (admittedly-limited) knowledge of the timer mechanism, if there is an interrupt on every cycle -- wouldn't you be stuck forever on the interrupt, no "perhaps" about it? You could also overload the interrupt registers....

Hrm, sounds like a fun project. :)
June 2, 2004, 12:59 AM
Stwong
If it lags CS, just add a DoEvents somewhere. Works like a charm, usually.
June 2, 2004, 1:08 AM
Adron
[quote author=Myndfyre link=board=31;threadid=6813;start=0#msg63162 date=1086137966]
[quote author=Adron link=board=31;threadid=6813;start=0#msg61612 date=1085434838]
   the counter chip is driven with a 1.193 MHz clock (1/4 of the
   original PC's 4.77 MHz CPU clock)
[/quote]

Hrm.... I think "perhaps" is giving it too much credit; based on my (admittedly-limited) knowledge of the timer mechanism, if there is an interrupt on every cycle -- wouldn't you be stuck forever on the interrupt, no "perhaps" about it? You could also overload the interrupt registers....

Hrm, sounds like a fun project. :)
[/quote]

Well, the frequency isn't equal to the cpu frequency. So I'm not sure whether the interrupt handling time will be enough to keep you occupied all the time or if you'll be able to execute a few regular instructions once in a while.

But it shouldn't be too hard to test. Just write a simple driver to output those values to the port and see what happens.
June 2, 2004, 9:29 AM
Lycaon
Try throwing in a DoEvents at the very end of your Loop if you haven't done so already. This allows other processes their chance at grabbing proccessor time, otherwise, the system devotes most of it's CPU resources to the VB Loop (I don't know if this is a screwup on M$'s part or if it's there intentionally).

Only downside to this is that it might be excessive. A Do / Loop with a DoEvents in it can loop a few thousand times per second. If that's an issue you could throw in another small Do / Loop to limit your code to looping, say, every 5 ms.

[code]

Private Declare Function GetTickCount Lib "kernel32" () As Long

Dim oTime As Single

Do

' My Big Loop (tm)

oTime = GetTickCount

Do
DoEvents
Loop Until oTime + 5 < GetTickCount ' Loop for 5 ms

Loop ' End of my big loop
[/code]

Alternatively, you could use the Sleep API if you don't mind >10 ms precision.

[code]
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Do

' My Big Loop (tm)

Sleep 10 ' Pause for 10ms

Loop ' End of my big loop

[/code]

If you REALLY need better precision you might be able to do something with QueryPerformanceCounter... But if you need that much precision, why are you programming in VB? :P

Edit: Argh, I really need to read the posts right above mine, hehe.
June 8, 2004, 9:50 PM

Search