j-rod Posted February 10, 2004 Report Posted February 10, 2004 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; }
Pete Dowson Posted February 10, 2004 Report Posted February 10, 2004 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
vdkeybus Posted February 11, 2004 Report Posted February 11, 2004 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.
lueckmw Posted December 14, 2004 Report Posted December 14, 2004 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, &val.lval, pdwResult); FSUIPC_Write(0x0574, 4, &val.hval, pdwResult); FSUIPC_Process(pdwResult); FSUIPC_Read(0x0570, 4, &altLowerTemp, pdwResult); FSUIPC_Read(0x0574, 4, &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
Pete Dowson Posted December 15, 2004 Report Posted December 15, 2004 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
lueckmw Posted December 15, 2004 Report Posted December 15, 2004 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, &val, pdwResult); }
Pete Dowson Posted December 16, 2004 Report Posted December 16, 2004 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
lueckmw Posted December 16, 2004 Report Posted December 16, 2004 Ah, it finally clicked as to what's going on there. Thanks for your help. Matt
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now