Jump to content


Nautilus

Member Since 19 Nov 2004
Offline Last Active Jun 12 2013 03:37 PM
-----

Posts I've Made

In Topic: Unknown HRESULT (0x8006FC24) from DirectInput

12 June 2013 - 01:12 PM

No luck :(

DXGetErrorString (0x8006FC24); returned "Unknown"
DXGetErrorDescription (0x8006FC24); returned "n/a"

But it was worth to try.
I have also tried many an error lookup utility, starting with the one that comes with VS. All negative.
Why there's no reference of this error anywhere? I can't be the first to get it. My direct input setup leaves no room for creativity. Maybe the HWND I was feeding to IDirectInputDevice7::SetCooperativeLevel() wasn't good. So I changed that: to NULL, to the Foreground window, to any of the windows belonging to the process... it's always 8006FC24.
I want to believe: gremlins do exist!

If I repeat the test with DirectInput8 it all works as per the documentation. I'll switch to DI8 and move on.

In Topic: Unknown HRESULT (0x8006FC24) from DirectInput

11 June 2013 - 01:03 AM

No, I disagree.
This is from <winerror.h>
//
//  Values are 32 bit values layed out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---+-+-+-----------------------+-------------------------------+
//  |Sev|C|R|	 Facility		  |			   Code			|
//  +---+-+-+-----------------------+-------------------------------+
//
//  where
//
//	  Sev - is the severity code
//
//		  00 - Success
//		  01 - Informational
//		  10 - Warning
//		  11 - Error
//
//	  C - is the Customer code flag
//
//	  R - is a reserved bit
//
//	  Facility - is the facility code
//
//	  Code - is the facility's status code
//
//
// Define the facility codes
//
#define FACILITY_WINDOWSUPDATE		   36
#define FACILITY_WINDOWS_CE			  24
#define FACILITY_WINDOWS				 8
#define FACILITY_URT					 19
#define FACILITY_UMI					 22
#define FACILITY_SXS					 23
#define FACILITY_STORAGE				 3
#define FACILITY_STATE_MANAGEMENT		34
#define FACILITY_SSPI					9
#define FACILITY_SCARD				   16
#define FACILITY_SETUPAPI				15
#define FACILITY_SECURITY				9
#define FACILITY_RPC					 1
#define FACILITY_WIN32				   7
#define FACILITY_CONTROL				 10
#define FACILITY_NULL					0
#define FACILITY_METADIRECTORY		   35
#define FACILITY_MSMQ					14
#define FACILITY_MEDIASERVER			 13
#define FACILITY_INTERNET				12
#define FACILITY_ITF					 4
#define FACILITY_HTTP					25
#define FACILITY_DPLAY				   21
#define FACILITY_DISPATCH				2
#define FACILITY_DIRECTORYSERVICE		37
#define FACILITY_CONFIGURATION		   33
#define FACILITY_COMPLUS				 17
#define FACILITY_CERT					11
#define FACILITY_BACKGROUNDCOPY		  32
#define FACILITY_ACS					 20
#define FACILITY_AAF					 18
(while at it, notice the absence of Facility 6)

And this is from the 1st paragraph of the 2.1 HRESULT webpage I linked:

Quote

The HRESULT numbering space is vendor-extensible. Vendors can supply their own values for this field, as long as the C bit (0x20000000) is set, indicating it is a customer code.
Clearly, the C bit is bit_29 (or the 30th bit from the right -- little endian).

Let's make a practical example with the #definition of DIERR_INPUTLOST from <dinput.h>:
/*
* Access to the device has been lost.  It must be re-acquired.
*/
#define DIERR_INPUTLOST				 \
	MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)

The MAKE_HRESULT macro from <winerror.h>:
//
// Create an HRESULT value from component pieces
//

#define MAKE_HRESULT(sev,fac,code) \
	((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )

With the macros SEVERITY_ERROR, FACILITY_WIN32, and ERROR_READ_FAULT expanding to 1, 7 and 30L respectively (all from <winerror.h>), we have that:
DIERR_INPUTLOST = (1 << 31) | (7 << 16) | (30L)
DIERR_INPUTLOST = 0x8007001E
DIERR_INPUTLOST = 2147942430
In this case Facility is 7, which is "FACILITY_WIN32" according to the 2.1 HRESULT page as well.
Therefore the Facility field within the HRESULT I'm getting from DirectInput is a genuine 6 -- unless the error code is longer than 16 bits (which is out of the rules, even though the macro won't see to clamp it) so making the true Facility either 0, 2 or 4. In any case this HRESULT value is undocumented.

In Topic: Simple Moving Average fps display, and framerate limiters...

25 May 2013 - 04:04 PM

Hello.

Your contribute is appreciated. As always. And I understand what you're saying. But...
Here is my code for the SMA I described in the opening post:
	QueryPerformanceCounter ((LARGE_INTEGER*) &this->Tick.Now);

	// Make a reference to the table element to modify this time.
	double& Entry = this->Frame.Avg.pHist [this->Frame.Avg.Index++ % this->Frame.Avg.Count];

	// Subtract the oldest frame time, save the current frame time in the history,
	// then add it to the sum.
	this->Frame.Avg.Sum -= Entry;
			  Entry = this->Frame.Avg.dFreq / double (this->Tick.Now - this->Frame.Avg.Before);
	this->Frame.Avg.Sum += Entry;

	// Calculate the average.
	this->Frame.Avg.Fps = this->Frame.Avg.Sum * this->Frame.Avg.InvCount;

	// Save this frame tick, for the next iteration.
	this->Frame.Avg.Before = this->Tick.Now;

It runs immediately after returning from a call to Present().
With .dFreq being the PerformanceCounter frequency, converted from DWORD64 to double datatype.
And with .InvCount being the inverse of .Count. Tiny optimizations.

And believe it, here is the previous version of it, still lingering in a comment past the above snippet:
/*
	QueryPerformanceCounter ((LARGE_INTEGER*) &this->Tick.Now);

	// Make a reference to the table element to modify this time.
	double& Entry = this->Frame.Avg.pHist [this->Frame.Avg.Index++ % this->Frame.Avg.Count];

	// Subtract the oldest frame time, save the current frame time in the history,
	// then add it to the sum.
	this->Frame.Avg.Sum -= Entry;
			 Entry = double (this->Tick.Now - this->Frame.Avg.Before);
	this->Frame.Avg.Sum += Entry;

	// Calculate the average.
	this->Frame.Avg.Fps = this->Frame.Avg.dFreq / (this->this->Frame.Avg.Sum * this->Frame.Avg.InvCount);

	// Save this frame tick, for the next iteration.
	this->Frame.Avg.Before = this->Tick.Now;
*/

This last one is the 1/average(30,60,40) you suggested.
It too ends up exceeding the true frame count in presence of jumpy performance.
It also has another problem: I have to explicit the loop to build the .Sum from 0 at every frame, else it develops an offset that permanently embeds in the .Sum (until I wipe the .Sum, but the offset just reforms with a different magnitude). For example, when running at 75.0 fps it'll say I'm at 75.3. Alt-Tab out and back In, now it says that I'm at 74.9 fps. It gets worse when at 60.0 fps, going as low as 55.6 fps.
These offsets do not form when rebuilding the .Sum on a per frame basis:
	QueryPerformanceCounter ((LARGE_INTEGER*) &this->Tick.Now);

	// Overwrite the oldest value with the newest one.
	this->Frame.Avg.pHist [this->Frame.Avg.Index++ % this->Frame.Avg.Count] = double (this->Tick.Now - this->Frame.Avg.Before);

	// Calculate the sum ex-novo.
	this->Frame.Avg.Sum = 0.0;
	for (DWORD i = 0; i < this->Frame.Avg.Count; ++i)
	{
		this->Frame.Avg.Sum += this->Frame.Avg.pHist [i];
	}

	// Calculate the average.
	this->Frame.Avg.Fps = this->Frame.Avg.dFreq * (double (this->Frame.Avg.Count) / this->Frame.Avg.Sum);

	// Save this frame tick, for the next iteration.
	this->Frame.Avg.Before = this->Tick.Now;

I haven't debugged to see how the offsets develop (might be an initial imprecision that gets naturally discarded when you remake the .Sum at every frame), but since they do, and since to have them *not* I must run a loop, I use the first SMA version which is cheaper at least.

Anyway, none of the formulas here do what I want. I want a way to calculate an average fps that won't exceed the true fps. I see games doing this, so there has to be a way. I remain open to suggestions, as always.

In Topic: How to detect a monitor's Default refresh frequency?

23 May 2013 - 12:49 AM

So true.
All methods seem to be fallible in a way or another. Searching among the list of display modes is no safer. The very list may have frequencies of 0 - this used to be my case with my previous gfx card. I admit that now I see no zeroes in the caps viewer, still I don't feel safe. Then again the default frequency isn't necessarily the lowest of the lot. Take my case of 800x600 R5G6B5. I know my Default frequency is 60 Hz. But I see my monitor also supports 800x600 R5G6B5 56 Hz. Imagine the surprise when I saw that.

So far my idea is that the default frequency is the one common to *all* available display modes. 60 Hz for me. But if said Default is altered by the user through DxDiag, then it could be anything else. I don't suppose you know the Registry key that holds the user-specified override for the DirectDraw's default frequency? Knowing that might solve the problem (if, and I stress *IF*, the default frequency is indeed the one common to all display modes).

If at least Windows wasn't in the way of the I/O ports, one could read the settings for the PIC's second counter, and from there derive the monitor's frequency in use. Now *that* would be infallible. Naturally I'm in ring 3... and tools like WinIO are overkill.

Any and every method I find that could be used to retrieve the monitor's frequency will warn against a possible return of 0 or 1 to indicate the misty Default frequency.
The only method that doesn't say anything about Defaults is IDirectDraw7::GetMonitorFrequency(). Does it guarantee success??
Right now it sounds like my best bet, so I'll go that route.

In Topic: [DirectX / C++] Runtime Check Failure #0

30 April 2013 - 12:41 PM

Sweet : )

Problem solved. Sneaky game was getting creative with the IUnknown::QueryInterface() method. I must say, it's the first game I see making any use of that. Yet another demonstration that one can't make assumptions...

Seeing what truly happens now, I confirm that the order of operations during initialization makes no sense. It creates and releases D3D many times, obtaining several duplicate pointers from different sources in the process, then releasing only a part of them while continuing to ask for more pointers in the canonic way. I suspect it's a sort of anti-cheat measure, since most cheating softwares exploit the d3d dll to invade a game's process. Maybe I'm wrong. But it's a fact that this game ships with dedicated anti-cheat [3rd party] software on the DVD, and the user is prompted whether to install it along with the game (to make online play safer).
Be as it may, I myself know of solid ways (and their counters) to detect alien modules in a game's address space. I mean, if really this was anti-cheat, it was a weak attempt.

Anyway, in my simplification of the code (see the H_IDirect3D9 wrapper class I posted) I had stripped QueryInterface() of the instructions to sniff into the parameters passing through. That in itself wasn't causing the error, but had I left it in place I'd have spot the problem sooner.

Remains the mistery of how the speed at which I debug my dll code drives to either the Runtime Check Failure #0 error (slow) or the Access Violation first-hand exception (fast). That, and the __vfptr pointer changing name within the VS debugger (__vfptr if slow, lpVtbl if fast).
If somebody someday has the answer, post away. I'll make sure to read it.

I'm off to refine my code into a proper release build.

Ciao ciao : )