Jump to content
The simFlight Network Forums

Writing Altitude to FS2002 over widefs


Recommended Posts

I need help witing altitude to FS2002 over WideFS. I Start with an altitude in feet then convert to meters, of course. I then break up the units and the fractional parts. Using a union (uAlt) I individually determine their hex values and write them to a temporary buffer. That temporary buffer then gets sent to FS. When it does its thing it sends the plane to 10000 feet and locks up. Any ideas? (see code below)

//***************bAltWrite2FS***************

//will eventually have a void parameter and grab info from shared

//memory

bool fs02if::bAltWrite2FS( double dAlt )

{

DWORD dwResult;

int i, j, tmpVal;

char chTmpBuffer[8] = {'0', '0', '0', '0', '0', '0', '0', '0' };

bool bTmp;

//TODO: get shared memory data

//Note: dAlt is in meters

uAlt.iVal = (int)floor( dAlt ); //get the units

for( i=0; i <= 4 ; i++ )

{

chTmpBuffer[i+4] = uAlt.chVal; //copy units to temp buffer

}

tmpVal = (int)floor( ( dAlt - uAlt.iVal ) * 100 ); //get dec (precision 2)

uAlt.iVal = tmpVal; //assign to union

for( j = 0; j <= 4 ; j++ )

{

chTmpBuffer = uAlt.chVal; //copy decimal to temp buffer

}

//8 byte swap

b8ByteSwap( chTmpBuffer );

// Write the true heading to MSFS

bTmp = FSUIPC_Write(0x0570, 8, chTmpBuffer, &dwResult) &&

FSUIPC_Process(&dwResult); // Process the request(s)

return bTmp;

}

Link to comment
Share on other sites

I need help witing altitude to FS2002 over WideFS. I Start with an altitude in feet then convert to meters, of course. I then break up the units and the fractional parts. Using a union (uAlt) I individually determine their hex values and write them to a temporary buffer. That temporary buffer then gets sent to FS.

I don't understand why you are doing all that. Just write the whole number of metres to the normal 32-bit signed integer in the 4 bytes at offset 0x0574 and the fraction (if any) to the unsigned integer in the 4 bytes at offset 0x570. There's no need for any other complexity.

The fraction would be in 1/65536ths, for example 0.5 metres is 32768 in the lower word.

When in doubt over anything like this, please look at FSInterrogate and see what that does. You can experiment writing and reading almost anything with that program. Also please use the FSUIPC logging for IPC reads/writes. I'd rather see a log extract and tell you what is wrong with that than plough through code, expecially code which is doing things I don't understand. :?

Regards,

Pete

Link to comment
Share on other sites

for( i=0; i <= 4 ; i++ )

{

chTmpBuffer[i+4] = uAlt.chVal; //copy units to temp buffer

}

Given the definition of chTmpBuffer (8 uchars), this piece of code will overwrite the byte following chTmpBuffer. Change 'i<=4' to 'i<4', or you will get exceptions someday.

Rather, you could get the job done like this (I avoid the use of 64 bit integers. Some older compilers/libraries do not support them. Hence the

more elaborate number conversion.):

#include

#include

bool fs02if::bAltWrite2FS(double dAlt)

{

static struct {

unsigned lval;

int hval;

} val; // Make static, so the FSUIPC pointers point to

// something meaningful when we return from

// this function. (The struct will get allocated to

// the .bss section during linking.)

DWORD dwResult;

bool bTmp;

val.hval=floor(dAlt);

val.lval=(unsigned)((dAlt-val.hval)*2*MAXINT);

bTmp=FSUIPC_Write(0x0570,8,&val,&dwResult) &&

FSUIPC_Process(&dwResult);

// Due to the static allocation of 'val', you can now postpone the

// FSUIPC_Process call (not done in this example).

return(bTmp);

}

J.

Link to comment
Share on other sites

  • 10 months later...

I'm trying to write a function to set altitude and I came across this thread. I've pretty much using vdkeybus's function, but I can't get it to work. After I write the two words, I read them back and print them out. It reads back the correct value for the upper word, but the fractional portion is zero. When I checked the log, it appears to be writing the correct value, but it reads back all zeros. Here's a section of the log file:

    24703 WRITE0  0570,   4 bytes: 8F 02 00 00 
    24703 WRITE0  0574,   4 bytes: D3 00 00 00 
    24703  READ0  0570,   4 bytes: 00 00 00 00 
    24703  READ0  0574,   4 bytes: D3 00 00 00 

Here's my function:

void setAltitude(DWORD *pdwResult, double Altitude)
{
	unsigned int altLowerTemp;
	int altUpperTemp;

	static struct 
	{ 
		unsigned lval; 
		int hval; 
	} val; 

	val.hval=(int)floor(Altitude); 
	val.lval=(unsigned)((Altitude-val.hval)*65536); 
	printf("decimal value = %f\n", Altitude-val.hval);
	printf("alt lower wrote = %d\n", val.lval);
	printf("alt upper wrote = %d\n", val.hval);

	FSUIPC_Write(0x0570, 4, &amp;val.lval, pdwResult);
	FSUIPC_Write(0x0574, 4, &amp;val.hval, pdwResult);
	FSUIPC_Process(pdwResult); 

	FSUIPC_Read(0x0570, 4, &amp;altLowerTemp, pdwResult);
	FSUIPC_Read(0x0574, 4, &amp;altUpperTemp, pdwResult);
	FSUIPC_Process(pdwResult);

	printf("alt lower read = %d\n", altLowerTemp);
	printf("alt upper read = %d\n\n", altUpperTemp);

}

Am I missing something simple here? Thanks for your help.

Matt

Link to comment
Share on other sites

I'm trying to write a function to set altitude and I came across this thread. I've pretty much using vdkeybus's function, but I can't get it to work. After I write the two words, I read them back and print them out. It reads back the correct value for the upper word, but the fractional portion is zero. When I checked the log, it appears to be writing the correct value, but it reads back all zeros.

If FS2002 and before, FS itself read and actioned these offsets, albeit only in Pause or Slew modes. In FS2004 it never reads them. FSUIPC has to see you writing to them and call a routine in FS's SIM1.DLL to get them activated.

I don't know precisely what is happening, but by writing the low part and the high part separately you are invoking two independent calls to that routine in FS, and odd results may well occur.

Try either using a single 64-bit value (long long or __int64 depending on your compiler), or a structure with the two values in (unsigned int for the fraction and int for the integer part, respectively). Write using one write of 8 bytes.

Let me know please. This is something I've not previously been aware of.

In general it is always better to structure single entities like this in your own program and write them as one unit to FS. In fact the Altitude is one one of 6 values, and all 6 have to be written together even when you only change the altitude. These are offsets 0560 to 0583, encompassing Latitude, Longitude, altitude, Pitch, Bank and Heading (LLAPBH). There's no separate way I can change one part.

Regards,

Pete

Link to comment
Share on other sites

Writing it all at once as an 8 byte chunck didn't seem to make any difference, but I did notice that if I multiply by (65536 * 65536) it works properly. After looking back at vdkeybus's code, I noticed he multiplied by that (MAXINT) rather than just 65536. I guess this basically moves the important part of the number to the upper 2 bytes of the 4 byte chunk. I don't really understand why that works, but it does, so I'm not complaining. According to the log it still reads back 00 00 for the lower 2 bytes, which it claimed that it wrote during the previous write. At any rate, it seems to work. Here's the function I ended up with (I call FSUIPC_Process after the function returns):

void setAltitude(DWORD *pdwResult, double Altitude)
{
	static struct 
	{ 
		unsigned int lval; 
		int hval; 
	} val; 

	val.hval=(int)floor(Altitude); 
	val.lval=(unsigned int)((Altitude-val.hval)*65536*65536); 

	FSUIPC_Write(0x0570, 8, &amp;val, pdwResult);
}

Link to comment
Share on other sites

I don't really understand why that works, but it does, so I'm not complaining.

Ahvery sorry. I didn't examine your original code segment closely enough.

Yes, you had:

val.lval=(unsigned)((Altitude-val.hval)*65536);

which of course isn't right. Think about it, with an example. half a metre (0.5) would be represented in binary by a 1 bit just below the "binary point". In this 64-bit bumber the "binary point" is between the two 32-bit values -- the first, or lower 32 bits, represent the fraction.

So, 0.5 metres is, in hexadecimal:

0x80000000

in that 32-bit word.

By only multiplying your fraction by 65536 you were only shifting the value to the top of the first 16 bits (65536 = 0x10000), so getting only

0x00008000.

I expect this was coming back as zero because FS doesn't work to any greater accuracy than 1/65536th of a metre (0.15 mm). In fact it probably doesn't even use all of the top 16 bits.

If your compiler supports long long or _int64 (as I think the current MS C/C++ compilers do) then all you needed to do was

_int64 llAlt = (_int64) (Altitude*65536*65536);

then write llAlt as an 8 byte value.

Regards,

Pete

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.