Does anyone have an example of a "complete" message loop for a GUI application (game)? and one that doesn't rely on WM_TIMER
I want to make sure I'm doing it right and I'm not sure is a message loop should be special if it is for a GUI game (for example PeekMessage -- we use that for directx and opengl... should it be used to a gui application?
Sliver
I want to make sure I'm doing it right and I'm not sure is a message loop should be special if it is for a GUI game (for example PeekMessage -- we use that for directx and opengl... should it be used to a gui application?
Sliver
Below is the main loop I used for a Tetris game. It uses GetTickCount to simulate a timer. The method is to use PeekMessage and to call GetTickCount to obtain the number of ms elapsed since the last update of the game. If the number is greater than 30 ms for example, the game is updated.
here is the Hostileencounter Message loop (the single thread version faster version)
this will update the screen as fast as it can, you an allways place a Sleep(20) at the end of your game loop to let OS breathe and limit your fps to 50.
I guess QuerryPerformanceCounter could be used to fine tune this Sleep for better fixed FPS.
this will update the screen as fast as it can, you an allways place a Sleep(20) at the end of your game loop to let OS breathe and limit your fps to 50.
I guess QuerryPerformanceCounter could be used to fine tune this Sleep for better fixed FPS.
;************************************
; WinMain MESSAGE LOOP STARTS HERE
;************************************
msg_loop:
;==========================================
; we use PeekMessage in order to detect idle (no messages)
; time we can use
;==========================================
push PM_NOREMOVE
;push PM_REMOVE
push 0
push 0
push 0
push offset msg
call PeekMessageA
;===============================
; test: do we have messages?
;==============================
cmp eax, 0
je nu_sunt_msg ; happy jump if we dont
; ===============================
; but no so happy..
; if we have to handle them
; ===============================
call GetMessageA,offset msg,0,0,0
;===================================
; test: is this message WM_QUIT ?
; =================================
cmp eax,0 ; GetMessageA will return zero if it is...?
je end_loop ; EXIT PROGRAM IF TRUE!!!!
;=========================================
; default action (let windows do it's dirty job)
; for all other messages
;=========================================
call TranslateMessage,offset msg
call DispatchMessageA,offset msg
;=========================================
; and jump back to do it all over again
;======================================
jmp msg_loop
;=================================
; Here ENDS Our Program (normaly)
;==================================
end_loop:
push [msg.msWPARAM]
call ExitProcess ;exit to windows
;===================================
; we should never reach this point
;===================================
ret
;=========================================
; so...there are no win messages....
; HERE we do our GAME MAIN LOOP
;=========================================
nu_sunt_msg:
pushad
;=======================================
; test: is game loop on?
; so that in future we dont make useless/dummy/dangerouse
; paint to screen/direct draw even on pause....
;=======================================
Call Game_Main
;==================================
; just return to WIN message loop
;=================================
popad
;====================================
; return to main Message Loop
;====================================
cmp [flag_no_messages],1
jz nu_sunt_msg
;------------------------------------------------------------------
; ignore above 2 instructions if you want to play nice
;------------------------------------------------------------------
jmp msg_loop
;******************************
; END OF PROGRAM TEXT
;******************************
I guess QuerryPerformanceCounter could be used to fine tune this Sleep for better fixed FPS.
All timings in general should be derived from RDTSC (given the precise Hz information), rather than QueryPerformance or GetTickCount.. which are much worse and suffer from considerable overhead.
Maverick, I have read that there is some problems with RDTSC on some motherboards - count 'jumping'? Maybe, motherboard manufactures trying to rig performance tests? Curious is anyone else has heard anything of this?
It's simply impossible. The counter is inside the CPU. Perhaps the CPU is being frozen by a ill NMI, or by the bus.. giving this illusion.
It's simply impossible.
But I have to testimony about a badly-flashed motherboard that had short but fastidious interruptions. I noticed it because I wrote a realtime Dsp program (just for own and betatesters use, so far not publicly released) which doing direct I/O (0 latency) relied on critical timings with IRQ's disabled. Well, on that motherboard every exactly 1 second there was an audio glitch. I thought about an NMI problem, but then I re-flashed the BIOS and the problem disappeared.. so I never tracked down the exact problem. However, on a IRQs-disabled continuous loop, that would have looked just like what you mentioned: i.e. every 1 second the TSC jumping ahead of a certain quantity. But it would have been illusory though.. and perhaps (if not probably) would not have happened anyway, since in my Dsp program case what was locked was probably the PCI bus after all. The TSC is inside the CPU, so if it executes its code from the caches, nothing happening on the motherboard can affect it. Not even if the motherboard stops to give the clock to the CPU, since if this happens, also the TSC will stop anyway, and there will be no illusory "TSC skip aheads".
The TSC is truly an invaluable resource.. no overhead, extremely precise, etc.. a must to use, really. All one needs is a very precise and reliable CPU Hz-detection routine.. I wish I had some free time to convert mine (it's in my programming language) to assembly. I will do it when I have some time, and post it here.
The TSC is truly an invaluable resource.. no overhead, extremely precise, etc.. a must to use, really. All one needs is a very precise and reliable CPU Hz-detection routine.. I wish I had some free time to convert mine (it's in my programming language) to assembly. I will do it when I have some time, and post it here.
What will happen with RDTSC if processor change the frequency (mobile processors) ?? I think that RDTSC in that case won't be usefull...
minimoog, on my Transmeta Crusoe, it counts the same frequency in power saver mode or not. I don't know about Intel and AMD chips, though.
What will happen with RDTSC if processor change the frequency (mobile processors) ?? I think that RDTSC in that case won't be usefull...
Thank you Maverick for good will ...
HE uses RDTSC form a long time now, but for a beginer i thought that QuerryperformanceCounter API will be much easy to use at first sight ;)
I was expecting QPC API to be more hardware independent as compared to RDTSC instruction but hellas on a HP kayak OS reports no QPF available but RDTSC works ok ;) LOL
Bogdan
HE uses RDTSC form a long time now, but for a beginer i thought that QuerryperformanceCounter API will be much easy to use at first sight ;)
I was expecting QPC API to be more hardware independent as compared to RDTSC instruction but hellas on a HP kayak OS reports no QPF available but RDTSC works ok ;) LOL
Bogdan
Hi Bog :)
QPC not supported on a HP? Very interesting.. and deserves deep investigation.
I hope you don't mind if I ask you some questions. :)
1) Did you run your tests on Win9x or WinNT?
2) What did QPF return, exactly?
3) Do you have ~easy access to this PC for possible further tests?
I'm quite convinced that QPx must run on that PC too.. maybe the problem was due (NT case) to a non-DWORD-aligned pointer to your QWORD var, or who knows what else. Worth investigating, though.
QPC not supported on a HP? Very interesting.. and deserves deep investigation.
I hope you don't mind if I ask you some questions. :)
1) Did you run your tests on Win9x or WinNT?
2) What did QPF return, exactly?
3) Do you have ~easy access to this PC for possible further tests?
I'm quite convinced that QPx must run on that PC too.. maybe the problem was due (NT case) to a non-DWORD-aligned pointer to your QWORD var, or who knows what else. Worth investigating, though.
Yes i have acces to that machine it's "right behind" me ;)
We tested it on Win2K/NT indeed but the API returns No Performance Counters Available standard error (ie FALSE)
From API help:
So from the API help it looks like there is quite normal for a PC not to have Performance counters :)
Now the RDTSC works because of the P2 CPU inside PC but i suspect that the CTC IC is used for QPC API and maybe HP decided to reduce "production costs" and removed the "obsolete" timer IC ...
its weird indeed and it was one of the problems that made HE crash on that machine...
We tested it on Win2K/NT indeed but the API returns No Performance Counters Available standard error (ie FALSE)
From API help:
Return Value
If the installed hardware supports a high-resolution
performance counter, the return value is TRUE.
If the installed hardware does not support a high-resolution performance counter,
the return value is FALSE.
So from the API help it looks like there is quite normal for a PC not to have Performance counters :)
Now the RDTSC works because of the P2 CPU inside PC but i suspect that the CTC IC is used for QPC API and maybe HP decided to reduce "production costs" and removed the "obsolete" timer IC ...
its weird indeed and it was one of the problems that made HE crash on that machine...
Hmmm.. please, could you run this little proggy and tell me if it works? (i.e. if it shows <edit>in HEX.. argh</edit> the right (not with the precision and stability of the routine I'm gonna post, though) speed of your CPU).
Hey Maverick, I tested your CpuSpeed app and it shows 2FCB31E0 == 801845728 on my 800mhz Intel P3. This is also the speed given by other benchmarkers (801mhz). So I think, it's working fine.
Hey Maverick, I tested your CpuSpeed app and it shows 2FCB31E0 == 801845728 on my 800mhz Intel P3. This is also the speed given by other benchmarkers (801mhz). So I think, it's working fine.
Message HEX U64
---------------------------
00000000500FDF9D
---------------------------
K7-1.334Ghz
This matches with other measurements to four places.
Using QueryPerformanceFrequency, huh. :)
---------------------------
00000000500FDF9D
---------------------------
K7-1.334Ghz
This matches with other measurements to four places.
Using QueryPerformanceFrequency, huh. :)
Hi Maverick,
cpu = p3-667
try1- 0286d89d8h
try2- 0286d7d87h
try3- 0286d868eh
have nice days,
cpu = p3-667
try1- 0286d89d8h
try2- 0286d7d87h
try3- 0286d868eh
have nice days,
Frist and second try I get *000000000BE1C2D4* on my NEC 9716, p200, with 96kb ram installed ((( but 64mb maybe all that is really running because of the old 95))) running Win95. I'm on my way to beings seriously into the numbers now so that i can see what make it Tick.
Thanks Maverick
3rd try 000000000BE1BFI4
maybe i mis read the first try but it looking the same at my eye site.
Thanks Maverick
3rd try 000000000BE1BFI4
maybe i mis read the first try but it looking the same at my eye site.