C: C++ timers: Difference between revisions

From FSDeveloper Wiki
Jump to navigationJump to search
(New page: {{Infobox-Applicable-FSVersion | FSXI = false | FSXA = false | FSX = false | FS2004 = false | FS2002 = false | XP10 = false | XP9 = false }} Most of you may be familiar with the TICK18...)
 
m (Rollout FS versions)
 
(16 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{Infobox-Applicable-FSVersion
{{Infobox-Applicable-FSVersion
| FSXI = false
| FS2020 = unknown
| FSXA = false
| FSXI = unknown
| FSX = false
| P3D4 = true
| P3D3 = true
| P3D2 = true
| P3D = true
| FSW = unknown
| FSXSE = true
| FSXA = true
| FSX = true
| FS2004 = false
| FS2004 = false
| FS2002 = false
| FS2002 = false
| XP10 = false  
| XP11 = false
| XP9 = false  
| XP10 = false
| XP9 = false
 
}}
}}
Most of you may be familiar with the TICK18 token variable which is incremented at 18Hz. Another option to make use of the 18Hz increment system (like making 0.5 second timers and such) is to call a function from the PANEL_SERVICE_PRE_UPDATE case of your callback function which increments your timing variable which you simply reset to 0 when it is equal to 9 (for a 0.5 second timer).
The following however is an undocumented function in the simulator which returns total time elapsed in seconds with sub-18Hz accuracy.


In your choice of your project's header files, do the following function prototype:


Most of you may be familiar with the TICK18 token variable which is incremented at 18Hz. Another option to make use of the 18Hz increment system (like making 0.5 second timers and such) is to call a function from the PANEL_SERVICE_PRE_UPDATE case of your callback function which increments your timing variable which you simply reset to 0 when it is equal to 9 (for a 0.5 second timer). However there is another option that allows for timers that range from several minutes down to 1 millisecond.
typedef double (__stdcall *fGetSimTime)();


  #include windows.h
Then in your module_init function:
  #ifdef _M_X64
#define PWORDX unsigned __int64
#else
#define PWORDX DWORD
#end
HMODULE hsimsched = NULL;
fGetSimTime GetSimTime6 = NULL;
void FSAPI module_init(void)
{
  GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"simscheduler.dll", &hsimsched);
  if(hsimsched)
  GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));//Note, for FSX SP2 use 4 instead of 6. Also since neither Acceleration nor SP 2 are likely to be updated,
//one can assume the offsets (0x14D0 for SP2 and 0x1530 for acceleration) will remain constant, thus leaving only P3D and FSX SE with offsets that vary.
//P3D can be retrieved with the function name thus elliminating confusion of function ordinals. }


void CALLBACK My_Timer();
Now wherever you wish to call this function, include the header where the prototype is contained and add:
UINT_PTR IDT_TIMER1;


The above code creates the function prototype for the callback function which will be executed at the desired interval. It also creates the timer ID variable.
extern fGetSimTime GetSimTime6;


To create the timer in your gauge callback function:
To call it and find out how much time has passed:


  case PANEL_SERVICE_PRE_INITIALIZE:
  double time = GetSimTime6();
SetTimer(NULL, IDT_TIMER1, 1000, (TIMERPROC)My_Timer);
//1st parameter is optional and not required in this
//case, second parameter is timer ID, third parameter is timer interval in milliseconds, 4th parameter is callback
//function
break;


Once you are finished with the timer, remove it as shown below:
UPDATE:


case PANEL_SERVICE_DISCONNECT:
The ordinal used by P3D v2.5 is different to that of FSXA. Also, the format is such that the decorated function name is available from the dll. So for P3D v2.5, use the following:
  KillTimer(NULL, IDT_TIMER1);
  GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YGNXZ");
break;


To increment your timer variable:
Complete example for automatic function selection:


  int timer_1sec = 0;
  GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"simscheduler.dll", &hsimsched);
  void CALLBACK My_Timer()
  if(hsimsched)
  {
  {
timer ++;
PWORDX fsxa = (PWORDX)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));
PWORDX p3dv2 = (PWORDX)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YGNXZ");
PWORDX p3dv4 = (PWORDX)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YANXZ");
if (p3dv4)
p3dv2 = p3dv4, fsxa = 0;
if(fsxa-(PWORDX)hsimsched == 0x1530)
GetSimTime6 = (fGetSimTime)fsxa;//FSX Acceleration version
else
{
if(p3dv2)
GetSimTime6 = (fGetSimTime)p3dv2;
else
{
GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(4));//FSX SP2.
//Since neither Acceleration nor SP 2 are likely to be updated,
//one can assume the offsets (0x14D0 for SP2 and 0x1530 for acceleration) will remain constant, thus leaving only P3D and FSX SE with offsets that vary.
//P3D can be retrieved with the function name thus elliminating confusion of function ordinals.
if(PWORDX(GetSimTime6)-PWORDX(hsimsched) != 0x14D0)
GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));
}
}
  }
  }
[[Category:Aircraft Design]]
[[Category:Aircraft Design]]
[[Category:Panel and Gauge Design]]
[[Category:Panel and Gauge Design]]

Latest revision as of 09:24, 28 March 2020

Most of you may be familiar with the TICK18 token variable which is incremented at 18Hz. Another option to make use of the 18Hz increment system (like making 0.5 second timers and such) is to call a function from the PANEL_SERVICE_PRE_UPDATE case of your callback function which increments your timing variable which you simply reset to 0 when it is equal to 9 (for a 0.5 second timer).

The following however is an undocumented function in the simulator which returns total time elapsed in seconds with sub-18Hz accuracy.

In your choice of your project's header files, do the following function prototype:

typedef double (__stdcall *fGetSimTime)();

Then in your module_init function:

#ifdef _M_X64
#define PWORDX unsigned __int64
#else
#define PWORDX DWORD
#end
HMODULE hsimsched = NULL;
fGetSimTime GetSimTime6 = NULL;
void FSAPI module_init(void)
{
 GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"simscheduler.dll", &hsimsched);
 if(hsimsched)
  GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));//Note, for FSX SP2 use 4 instead of 6. Also since neither Acceleration nor SP 2 are likely to be updated,
			//one can assume the offsets (0x14D0 for SP2 and 0x1530 for acceleration) will remain constant, thus leaving only P3D and FSX SE with offsets that vary.
			//P3D can be retrieved with the function name thus elliminating confusion of function ordinals.  }

Now wherever you wish to call this function, include the header where the prototype is contained and add:

extern fGetSimTime GetSimTime6;

To call it and find out how much time has passed:

double time = GetSimTime6();

UPDATE:

The ordinal used by P3D v2.5 is different to that of FSXA. Also, the format is such that the decorated function name is available from the dll. So for P3D v2.5, use the following:

GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YGNXZ");

Complete example for automatic function selection:

GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"simscheduler.dll", &hsimsched);
if(hsimsched)
{
	PWORDX fsxa = (PWORDX)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));
	PWORDX p3dv2 = (PWORDX)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YGNXZ");
	PWORDX p3dv4 = (PWORDX)GetProcAddress(hsimsched, "?GetElapsedSimTimeSec@@YANXZ");
	if (p3dv4)
		p3dv2 = p3dv4, fsxa = 0;
	if(fsxa-(PWORDX)hsimsched == 0x1530)
		GetSimTime6 = (fGetSimTime)fsxa;//FSX Acceleration version
	else
	{
		if(p3dv2)
			GetSimTime6 = (fGetSimTime)p3dv2;
		else
		{
			GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(4));//FSX SP2. 
			//Since neither Acceleration nor SP 2 are likely to be updated,
			//one can assume the offsets (0x14D0 for SP2 and 0x1530 for acceleration) will remain constant, thus leaving only P3D and FSX SE with offsets that vary.
			//P3D can be retrieved with the function name thus elliminating confusion of function ordinals. 
			if(PWORDX(GetSimTime6)-PWORDX(hsimsched) != 0x14D0)
				GetSimTime6 = (fGetSimTime)GetProcAddress(hsimsched, MAKEINTRESOURCEA(6));
		}
	}
}