PDA

View Full Version : Unpacking ICAO Codes etc from BGL File


scruffyduck
22 Nov 2006, 08:16
My head hurts :)

I am trying to understand how the packing of ICAO codes works in the bgl file format.

Reading Winfried's documentation each letter or number has a value between 0...37 With:
blank 00
digits 0 .. 9 02 .. 11
letters A .. Z 12 .. 37

I am to take the leftmost letter/number coded as above and multiply it by 38. I then add the next letter/number code to the result and multiply that by 38. Keep going until all the letters/numbers have been consumed. Multiply the result by 0x20 to left shift it by 5 bytes and hey presto that is the packed number!

Well not here it ain't!! So I must be doing something wrong - consistently.

Take MXA3 - M=24, X=35, A=12 and 3=5. The result in the bgl file for this is 43773729 but if I use the above calculation (WITHOUT the shift) I get 51981302. Compare the two numbers and mine is 1.187499973 times the number stored in the bgl.

I tried 6 other ICAOs and in each case got a value 1.18749973 times the value in the BGL file. Clearly I don't understand how this works so any help would be much appreciated.

Manuel Ambulo
22 Nov 2006, 22:40
Hi, scruffyduck,

In my FS2004's program, for get an airport's ICAO_ID, i use the structure (below) for airport, where i get the "dwICAO_ID" member, and pass it to the "Get_ICAO_ID" subroutine (and also, i pass an empty string which will be filled with the decoded ICAO_ID of the airport). Note, that i just get the lastest 27 bits of the DWORD containing the ICAO_ID....the first 5 bits is unused for me.

// FS2004's Airport
struct FS2004_Airport
{
unsigned short wType; // (0x0003 = Airport)
unsigned long dwSize;
unsigned char Total_runways;
unsigned char Total_com_freqs;
unsigned char Total_startlocations;
unsigned char unknown1;
unsigned char unknown2;
unsigned char Total_helipads;
unsigned long Lon;
unsigned long Lat;
unsigned long Alt;
unsigned long Tower_Lon;
unsigned long Tower_Lat;
unsigned long Tower_Alt;
float mag_var;
unsigned long dw1 :5; // (5 bits)--> Unknown
unsigned long dwICAO_ID :27; // (27 bits)--> Airport's ICAO_ID
unsigned long unknown3;
unsigned long unknown4;
};

void Get_ICAO_ID(char szId[6], unsigned long dwId)
{
static char szIdChar[] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
szId[0] = '\0';

for (int nIndex = 0; nIndex < 5 && dwId > 0; nIndex++)
{
memmove(szId + 1, szId, 5);
szId[0] = szIdChar[dwId % 38];
dwId /= 38;
}
}


Take MXA3 - M=24, X=35, A=12 and 3=5. The result in the bgl file for this is 43773729 but if I use the above calculation (WITHOUT the shift) I get 51981302. Compare the two numbers and mine is 1.187499973 times the number stored in the bgl.

24 * 38 = 912
912 + 35 * 38 = 35986
35986 + 12 * 38 = 1367924
1367924 + 5 * 38 = 51981302 <--- Here is the value you get, BUT!..the problem is...

The lastest multiplied "38"...see...if i dont multiply the last digit by "38", you will get -->
1367924 + 5 = **1367929**.........instead of 51981302.

If i convert the result "1367929" from decimal to binary i will get:

101001101111101111001

And if i get the value in the *.bgl file, "43773729", and convert it to binary:

10100110111110111100100001

Compare both values and you will see they are the SAME, except for the first 5 bits in the "43773729" value, See:

101001101111101111001-------------> 1367929
101001101111101111001---00001----> 43773729
--------------------------(5 bits)----

In others words, to the result you get from your calculations will be "1367929", if you do a Left shift (<<) of 5 bits:

1367929 << 5 = 43773728; // For add the 5 bits to your value...

You will get ---> 43773728 (pretty much closer to the value you get in the *.bgl file).

101001101111101111001----00000----> 43773728 (calculations results..)
101001101111101111001----00001----> 43773729 (value from *.bgl file.)
---------------------------(5 bits)-----------

Hope this help you :)

Best Regards,

Manuel Ambulo

scruffyduck
23 Nov 2006, 02:19
Hi Manuel and many many thanks - that is the conclusion I came to at 2am this morning when I could not sleep! I was multiplying the last letter/number by 38 when I should not. 38/32 is 1.1875 and that is the error I found :)


Update: Ok that is working fine now - thanks again!

VADS
08 Jan 2007, 09:02
I need to query when they say shift to the left 5 bytes - how does one convert the result to get what you're looking for?

as i had the idea somehow that if i have 51981302 that i'd convert
the last three by multiplying by 0.20

302 x 0.20 = 60.4 is this calculation correct or have i misunderstood something along the way?

Gareth - Vads
Virtual Aerospace Design South Africa

berendt
03 Mar 2007, 05:18
Hi,

presumably, your question is completely answered by now; however, if you feel so, you might have a look at my tool <Find_ICAO.zip> which I uploaded to the Avsim Library last week.

Regards, Gerhard.

scruffyduck
03 Mar 2007, 05:27
Thanks Gerhard

Yes SDE can now pack and unpack ICAO codes, both those that are shifted and those that are not. :)