Difference between revisions of "BGL File Format"

From FSDeveloper Wiki
Jump to: navigation, search
(minor updates)
(Undo revision 10099 by MichaelCox (talk))
Line 50: Line 50:
 
| dwLowDateTime of the FILETIME structure.<br/>Date and Time the file was created<br/>
 
| dwLowDateTime of the FILETIME structure.<br/>Date and Time the file was created<br/>
 
The FILETIME structure represents the number of 100-nanosecond intervals since January 1, 1601<br/>
 
The FILETIME structure represents the number of 100-nanosecond intervals since January 1, 1601<br/>
See [http://support.microshit.com/kb/188768 Working with the FILETIME Structure].
+
See [http://support.microsoft.com/kb/188768 Working with the FILETIME Structure].
 
|-
 
|-
 
| 0x0C
 
| 0x0C
Line 165: Line 165:
 
| 0x00
 
| 0x00
 
| 4 - DWORD
 
| 4 - DWORD
| Section type (as defined by microshit Flight Simulator): one of the following values:<br/>
+
| Section type (as defined by Microsoft Flight Simulator): one of the following values:<br/>
 
* None = 0x0
 
* None = 0x0
 
* Copyright = 0x1
 
* Copyright = 0x1
Line 199: Line 199:
 
* [[#TERRAIN SECTIONS|TerrainSeasonApr]] = 0x7B
 
* [[#TERRAIN SECTIONS|TerrainSeasonApr]] = 0x7B
 
* [[#TERRAIN SECTIONS|TerrainSeasonMay]] = 0x7C
 
* [[#TERRAIN SECTIONS|TerrainSeasonMay]] = 0x7C
* [[#TERRAIN SECTIONS|TerrainSeasonJun] ... \n
+
* [[#TERRAIN SECTIONS|TerrainSeasonJun]] = 0x7D
 +
* [[#TERRAIN SECTIONS|TerrainSeasonJul]] = 0x7E
 +
* [[#TERRAIN SECTIONS|TerrainSeasonAug]] = 0x7F
 +
* [[#TERRAIN SECTIONS|TerrainSeasonSep]] = 0x80
 +
* [[#TERRAIN SECTIONS|TerrainSeasonOct]] = 0x81
 +
* [[#TERRAIN SECTIONS|TerrainSeasonNov]] = 0x82
 +
* [[#TERRAIN SECTIONS|TerrainSeasonDec]] = 0x83
 +
* [[#TERRAIN SECTIONS|TerrainPhotoJan]] = 0x8C
 +
* [[#TERRAIN SECTIONS|TerrainPhotoFeb]] = 0x8D
 +
* [[#TERRAIN SECTIONS|TerrainPhotoMar]] = 0x8E
 +
* [[#TERRAIN SECTIONS|TerrainPhotoApr]] = 0x8F
 +
* [[#TERRAIN SECTIONS|TerrainPhotoMay]] = 0x90
 +
* [[#TERRAIN SECTIONS|TerrainPhotoJun]] = 0x91
 +
* [[#TERRAIN SECTIONS|TerrainPhotoJul]] = 0x92
 +
* [[#TERRAIN SECTIONS|TerrainPhotoAug]] = 0x93
 +
* [[#TERRAIN SECTIONS|TerrainPhotoSep]] = 0x94
 +
* [[#TERRAIN SECTIONS|TerrainPhotoOct]] = 0x95
 +
* [[#TERRAIN SECTIONS|TerrainPhotoNov]] = 0x96
 +
* [[#TERRAIN SECTIONS|TerrainPhotoDec]] = 0x97
 +
* [[#TERRAIN SECTIONS|TerrainPhotoNight]] = 0x98
 +
* FakeTypes = 0x2710
 +
* IcaoRunway = 0x2711
 +
|- valign="top"
 +
| 0x04
 +
| 4 - DWORD
 +
| Value used to compute the size of each subsection.<br/>
 +
<pre>subSection Size = ((value & 0x10000) | 0x40000) >> 0x0E</pre>
 +
Most subsections have a size of 16 bytes. However, subsections for TerrainSeasonXXXX have a size of 20 bytes.
 +
|-
 +
| 0x08
 +
| 4 - DWORD
 +
| Number of subsections in the section.
 +
|-
 +
| 0x0C
 +
| 4 - DWORD
 +
| File offset = position in the file where the first subsection starts.
 +
|-
 +
| 0x10
 +
| 4 - DWORD
 +
| Total Size (in bytes) of all the subsections. This value should be equal to : nbSubSections x (size computed at offset 0x04)
 +
|}
 +
<br/>
 +
 
 +
=== Example ===
 +
For example, in CVX2815.bgl, the only one section, at offset 0x38, has this:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Values
 +
! Description
 +
|-
 +
| 0x38
 +
| <pre>65 00 00 00</pre>
 +
| TerrainVectorDb = 101 = 0x65
 +
|-
 +
| 0x3C
 +
| <pre>01 00 00 00</pre>
 +
| 1 => subsection size = 16
 +
|-
 +
| 0x40
 +
| <pre>8D 07 00 00</pre>
 +
| 0x078D = 1933 subsections in the section
 +
|-
 +
| 0x44
 +
| <pre>01 CD 1F 00</pre>
 +
| 0x1FCD01 = File offset = position in the file where the first subsection starts.
 +
|-
 +
| 0x48
 +
| <pre>D0 78 00 00</pre>
 +
| Size (in bytes) =0x78D0 = 30928 bytes = 16 * 1933
 +
|}
 +
 
 +
== Subsections ==
 +
A subsection contains information about the geographical area it covers. If also contains the file offset of the subsection’s data. All subsections of a same section are contiguous meaning that they are following each other in the file.
 +
<br/>A subsection has a size of 16 bytes, except for the following sections that have a size of 20 bytes
 +
* TerrainElevation
 +
* TerrainLandClass
 +
* TerrainWaterClass
 +
* TerrainRegion
 +
* PopulationDensity
 +
* TerrainIndex
 +
* TerrainSeasonXXX
 +
* TerrainPhotoXXX
 +
* TerrainPhotoXXX
 +
<br/>The subsection has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| 4 - DWORD
 +
| QMID Dword A. See this [[#Getting QMID from DWORD values|algorithm]] to retrieve the QMID values.
 +
'''''Note that all subsections inside a section are sorted on this value, meaning that subsections with the lowest QMID level (bigger squares) are followed by subsections with higher QMID levels (smaller squares).'''''
 +
|- valign="top"
 +
| 0x04
 +
| 4 - DWORD
 +
| QMID Dword B - This field is present only for subsections having a size of 20 bytes)
 +
|- valign="top"
 +
|
 +
| 4 - DWORD
 +
| Number of records contained in the subsection's data.<br/>
 +
It is 0 for TerrainVectorDb.<br/>
 +
For '''NameList''', there is only one record. This value is actually the number of ICAO entries defined in the record data.
 +
|-
 +
|
 +
| 4 - DWORD
 +
| File Offset = Position in the file of the subsection’s data
 +
|-
 +
|
 +
| 4 - DWORD
 +
| Size of the subsection’s data
 +
|}
 +
<br/>
 +
The interpretation of the section data depends on the section type.
 +
=== Example ===
 +
In CVX2815.bgl:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Values
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x1FCD01
 +
| <pre>00 FA 81 00</pre>
 +
| Bounding coordinates:<br/>
 +
* MinLatitude(Deg) = 47.63671875
 +
* MaxLatitude(Deg) = 47.8125
 +
* MinLongitude(Deg) =- 75.0
 +
* MaxLongitude(Deg) = -74.765625
 +
|-
 +
| 0x1FCD05
 +
| <pre>00 00 00 00</pre>
 +
| Number of records = 0
 +
|-
 +
| 0x1FCD09
 +
| <pre>4C 00 00 00</pre>
 +
| 0x4C = File Offset = Position in the file of the subsection’s data.
 +
|-
 +
| 0x1FCD0D
 +
| <pre>DD 00 00 00</pre>
 +
| Size of the subsection’s data = 0xDD = 221 bytes.
 +
|}
 +
<br/><br/>
 +
 
 +
= AIRPORT =
 +
Each airport record consists of a fixed part with the length of 0x38 bytes, followed by a variable
 +
part with 0..n subrecords of different types. The structure of the fixed part is as follows
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x003C</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the airport record
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Number of RUNWAY subrecords
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Number of COM subrecords
 +
|-
 +
| 0x08
 +
| <center>1</center>
 +
| BYTE
 +
| Number of START subrecords
 +
|-
 +
| 0x09
 +
| <center>1</center>
 +
| BYTE
 +
| Number of APPROACH subrecords (?)
 +
|- valign="top"
 +
| 0x0A
 +
| <center>1</center>
 +
| BYTE
 +
| Bit 0-6 : Number of aprons (?)<br/>Bit 7: flag for deleteAirport record
 +
|-
 +
| 0x0B
 +
| <center>1</center>
 +
| BYTE
 +
| Number of HELIPAD subrecords
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude (in meters)
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| DWORD
 +
| Tower Longitude (if present)
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| DWORD
 +
| Tower Latitude (if present)
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| DWORD
 +
| Tower Altitude (in meters)
 +
|-
 +
| 0x24
 +
| <center>4</center>
 +
| FLOAT
 +
| Magnetic Variation (Deg)
 +
|-
 +
| 0x28
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO Ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x2C
 +
| <center>4</center>
 +
| DWORD
 +
| Region Ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x30
 +
| <center>4</center>
 +
| DWORD
 +
| Type of fuel present at the airport and its availability.
 +
Each availability is coded on 2 bits: 0 = No, 1 = Unknown, 2 = Prior Request, 3 = Yes
 +
* Bits 0-1 : Availability for 73 octane
 +
* Bits 2-3 : Availability for 87 octane
 +
* Bits 4-5 : Availability for 100 octane
 +
* Bits 6-7 : Availability for 130 octane
 +
* Bits 8-9 : Availability for 145 octane
 +
* Bits 10-11 : Availability for MOGAS
 +
* Bits 12-13 : Availability for JET
 +
* Bits 14-15 : Availability for JETA
 +
* Bits 16-17 : Availability for JETA1
 +
* Bits 18-19 : Availability for JETAP
 +
* Bits 20-21 : Availability for JETB
 +
* Bits 22-23 : Availability for JET4
 +
* Bits 24-22 : Availability for JET5
 +
* Bit 30 : Airport has avgas
 +
* Bit 31 : Airport has jet fuel
 +
|-
 +
| 0x34
 +
| <center>1</center>
 +
| BYTE
 +
| Unknown (always 0x00) - FSX only
 +
|-
 +
| 0x35
 +
| <center>1</center>
 +
| BYTE
 +
| INT(Traffic Scalar * 255) - FSX only
 +
|-
 +
| 0x36
 +
| <center>2</center>
 +
| WORD
 +
| Unknown (always 0x00) - FSX only
 +
|}
 +
The following subrecords can be present after the main airport record:
 +
== Name ==
 +
This subrecord seems to be present in every airport record, and is usually the first one immediately after the fixed part. However a DELETE subsection may precede the Name subsection.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0019 </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the Name subrecord
 +
|-
 +
| 0x06
 +
|
 +
| STRING
 +
| AirportName (padded with NUL (0x000 bytes)
 +
|}
 +
 
 +
== Included Tower Scenery Object ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0066 </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the subrecord
 +
|-
 +
| 0x06
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the included scenery object
 +
|}
 +
After this record we find an included scenery object with an internal structure identical to that of
 +
other scenery objects (see below) and including possible attachments. The BglComp compiler
 +
allows only one scenery object to be included at this point, but in some FS X scenery files we find
 +
more than one objects included here. If present, the subrecords of this type appear immediately
 +
after the Name subrecord.
 +
 
 +
== Runway ==
 +
The runway subrecord consists of a fixed part with a length of 0x34 bytes and a variable number of
 +
sub-subrecords. The fixed part has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0004 </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the runway subrecord
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Type of surface:<br/>
 +
* 0x0000 CONCRETE
 +
* 0x0001 GRASS
 +
* 0x0002 WATER
 +
* 0x0004 ASPHALT
 +
* 0x0007 CLAY
 +
* 0x0008 SNOW
 +
* 0x0009 ICE
 +
* 0x000C DIRT
 +
* 0x000D CORAL
 +
* 0x000E GRAVEL
 +
* 0x000F OIL_TREATED
 +
* 0x0010 STEEL_MATS
 +
* 0x0011 BITUMINOUS
 +
* 0x0012 BRICK
 +
* 0x0013 MACADAM
 +
* 0x0014 PLANKS
 +
* 0x0015 SAND
 +
* 0x0016 SHALE
 +
* 0x0017 TARMAC
 +
* 0x00FE UNKNOWN
 +
|-
 +
| 0x08
 +
| <center>1</center>
 +
| BYTE
 +
| Primary runway number (01 - 36)
 +
|-
 +
|- valign="top"
 +
| 0x09
 +
| <center>1</center>
 +
| BYTE
 +
| Primary runway designator:<br/>
 +
* 0 = NONE
 +
* 1 = LEFT
 +
* 2 = RIGHT
 +
* 3 = CENTER
 +
* 4 = WATER
 +
* 5 = A
 +
* 6 = B
 +
|-
 +
| 0x0A
 +
| <center>1</center>
 +
| BYTE
 +
| Secondary runway number
 +
|-
 +
| 0x0B
 +
| <center>1</center>
 +
| BYTE
 +
| Secondary runway designator
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO Ident. for primary ILS ([[#ICAO Identifiers and region codes|Special Format]]), 0x0000 if none.
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO Ident. for seconday ILS ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| FLOAT
 +
| Length (in meters)
 +
|-
 +
| 0x24
 +
| <center>4</center>
 +
| FLOAT
 +
| Width (in meters)
 +
|-
 +
| 0x28
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading (Deg)
 +
|-
 +
| 0x2C
 +
| <center>4</center>
 +
| FLOAT
 +
| Pattern Altitude (in meters)
 +
|-
 +
|- valign="top"
 +
| 0x30
 +
| <center>2</center>
 +
| WORD
 +
| Marking flags:<br/>
 +
BIT 0: edges<br/>
 +
BIT 1: threshold<br/>
 +
BIT 2: fixedDistance<br/>
 +
BIT 3: touchdown<br/>
 +
BIT 4: dashes<br/>
 +
BIT 5: ident<br/>
 +
BIT 6: precision<br/>
 +
BIT 7: edgePavement<br/>
 +
BIT 8: singleEnd<br/>
 +
BIT 9: primaryClosed<br/>
 +
BIT 10: secondaryClosed<br/>
 +
BIT 11: primaryStol<br/>
 +
BIT 12: secondaryStol<br/>
 +
BIT 13: alternate threshold<br/>
 +
BIT 14: alternate fixedDistance<br/>
 +
BIT 15: alternate touchdown<br/>
 +
BIT 21: alternate precision<br/>
 +
BIT 22: leading zero Ident<br/>
 +
BIT 23: noThresholdEndArrows
 +
 
 +
|-
 +
|- valign="top"
 +
| 0x32
 +
| <center>1</center>
 +
| BYTE
 +
| Lights flags: <br/>
 +
BIT 0-1: edge<br/>
 +
* 0 = None
 +
* 1 = Low
 +
* 2 = Medium
 +
* 3 = High
 +
BIT 2-3: center (as with edge)<br/>
 +
BIT 5: flag for centerRed<br/>
 +
BIT 5-7: unused (?)<br/>
 +
|-
 +
|- valign="top"
 +
| 0x33
 +
| <center>1</center>
 +
| BYTE
 +
| Pattern flags: <br/>
 +
BIT 0: primaryTakeoff (0 = YES)<br/>
 +
BIT 1: primaryLanding (0 = YES)<br/>
 +
BIT 2: primaryPattern (0 = LEFT)<br/>
 +
BIT 3: secondaryTakeoff<br/>
 +
BIT 4: secondaryLanding<br/>
 +
BIT 5: secondaryPattern<br/>
 +
BIT 6-7: unused (?)<br/>
 +
|}
 +
The following sub-subreports can be present within a runway subrecord:
 +
<br/><br/>
 +
=== OffsetThreshold ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Primary (<b><span style="color:#0000FF">0x0005 </span></b>)<br/>
 +
Id Secondary (<b><span style="color:#0000FF">0x0006 </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of sub-subrecord (0x10)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Surface (same as in runway)
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Length in meters
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| Width in meters
 +
|}
 +
 
 +
=== BlastPad ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Primary (<b><span style="color:#0000FF">0x0007 </span></b>)<br/>
 +
Id Secondary (<b><span style="color:#0000FF">0x0008 </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of sub-subrecord (0x10)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Surface (same as in runway)
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Length in meters
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| Width in meters
 +
|}
 +
 
 +
=== Overrun ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Primary (<b><span style="color:#0000FF">0x0009 </span></b>)<br/>
 +
Id Secondary (<b><span style="color:#0000FF">0x000A </span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of sub-subrecord (0x10)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Surface (same as in runway)
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Length in meters
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| Width in meters
 +
|}
 +
 
 +
=== Vasi ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Primary Left (<b><span style="color:#0000FF">0x000B</span></b>)
 +
Id Primary Right (<b><span style="color:#0000FF">0x000C</span></b>)
 +
 
 +
Id Secondary Left (<b><span style="color:#0000FF">0x000D</span></b>)
 +
 
 +
Id Secondary Right (<b><span style="color:#0000FF">0x000E</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of sub-subrecord (0x18)
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Type:<br/>
 +
* 0x01 = VASI21
 +
* 0x02 = VASI31
 +
* 0x03 = VASI22
 +
* 0x04 = VASI32
 +
* 0x05 = VASI23
 +
* 0x06 = VASI33
 +
* 0x07 = PAPI2
 +
* 0x08 = PAPI4
 +
* 0x09 = TRICOLOR
 +
* 0x0a = PVASI
 +
* 0x0b = TVASI
 +
* 0x0c = BALL
 +
* 0x0d = APAP/PANELS
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasX
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasZ
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| FLOAT
 +
| Spacing
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Pitch
 +
|}
 +
 
 +
=== Approach Lights ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Primary (<b><span style="color:#0000FF">0x000F</span></b>)<br/>
 +
Id Secondary (<b><span style="color:#0000FF">0x0010</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of sub-subrecord (0x08)
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Bits [0-5]: System<br/>
 +
* 0x00 = NONE
 +
* 0x01 = ODALS
 +
* 0x02 = MALSF
 +
* 0x03 = MALSR
 +
* 0x04 = SSALF
 +
* 0x05 = SSALR
 +
* 0x06 = ALSF1
 +
* 0x07 = ALSF2
 +
* 0x08 = RAIL
 +
* 0x09 = CALVERT
 +
* 0x0a = CALVERT2
 +
* 0x0b = MALS
 +
* 0x0c = SALS
 +
* 0x0e = SSALS<br/>
 +
Bit 5: Endlights (0 = false, 1 = true)<br/>
 +
Bit 6: Reil (0 = false, 1 = true)<br/>
 +
Bit 7: Touchdown (0 = false, 1 = true)<br/>
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Number of strobes
 +
|}
 +
 
 +
== Helipad ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0026</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of subrecord (0x24)
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Surface (as in Runway)
 +
|-
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| bit 0-3: Type
 +
* 0 = NONE
 +
* 1 = H
 +
* 2 = SQUARE
 +
* 3 = CIRCLE
 +
* 4 = MEDICAL
 +
bit 4: transparent<br/>
 +
bit 5: closed <br/>
 +
bit 6-7: unused<br/>
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| BYTE[4]
 +
| color (cannot be set with bglcomp because of error kin compiler)
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude x 1000 (in meters)
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Length
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| Width
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading
 +
|}
 +
 
 +
== Start ==
 +
(the keywords “Start” and “RunwayStart” produce identical subrecords)
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0011</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of subrecord (0x18)
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Runway Number
 +
|-
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| bit 0-3: Runway Designator (as with runway subrecord)<br/>
 +
bit 4-7: Start Type
 +
* 1 = RUNWAY
 +
* 2 = WATER
 +
* 2 = HELIPAD
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading
 +
|}
 +
 
 +
== Com ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0012</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of subrecord: variable
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Type. The following numbers have been identified:<br/>
 +
* 0x0001 ATIS
 +
* 0x0002 MULTICOM
 +
* 0x0003 UNICOM
 +
* 0x0004 CTAF
 +
* 0x0005 GROUND
 +
* 0x0006 TOWER
 +
* 0x0007 CLEARANCE
 +
* 0x0008 APPROACH
 +
* 0x0009 DEPARTURE
 +
* 0x000A CENTER
 +
* 0x000B FSS
 +
* 0x000C AWOS
 +
* 0x000D ASOS
 +
* 0x000E CLEARANCE_PRE_TAXI
 +
* 0x000F REMOTE_CLEARANCE_DELIVERY
 +
|- valign="top"
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| Frequency x 1000000
 +
|-
 +
| 0x0C
 +
| <center>Variable</center>
 +
| STRINGZ
 +
| Name. Maximum Length = 48 (0x30)
 +
|}
 +
 
 +
== Delete Airport ==
 +
The DeleteAirport subrecord has a fixed and a variable part. The fixed part has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0033</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size of subrecord: variable
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| delete flags
 +
* BIT 0: allApproaches
 +
* BIT 1: allApronLights
 +
: Note: in the bglcomp.xsd this keyword is written allApronlights, but the compiler accepts only allApronLights.
 +
: You have to edit bglcomp.xsd, if you want to use this feature.
 +
* BIT 2: allAprons
 +
* BIT 3: allFrequencies
 +
* BIT 4: allHelipads
 +
* BIT 5: allRunways
 +
* BIT 6: allStarts
 +
* BIT 7: allTaxiways
 +
|-
 +
| 0x08
 +
| <center>1</center>
 +
| BYTE
 +
| Number of individual runways to delete
 +
|-
 +
| 0x09
 +
| <center>1</center>
 +
| BYTE
 +
| Number of individual starts to delete
 +
|-
 +
| 0x0A
 +
| <center>1</center>
 +
| BYTE
 +
| Number of individual frequencies to delete
 +
|-
 +
| 0x0B
 +
| <center>1</center>
 +
| BYTE
 +
| Unused (?)
 +
|}
 +
according to the number of individual features to delete there are the following parts of the record added:
 +
=== for Runways ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>1</center>
 +
| BYTE
 +
| Surface (as in runway subrecord)
 +
|-
 +
| 0x01
 +
| <center>1</center>
 +
| BYTE
 +
| Runway number primary
 +
|-
 +
| 0x02
 +
| <center>1</center>
 +
| BYTE
 +
| Runway number secondary
 +
|-
 +
|- valign="top"
 +
| 0x03
 +
| <center>1</center>
 +
| BYTE
 +
| bit 0-3: Runway designator primary<br/>
 +
bit 4-7: Runway designator secondary
 +
|}
 +
=== for Starts ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>1</center>
 +
| BYTE
 +
| Runway number
 +
|-
 +
| 0x01
 +
| <center>1</center>
 +
| BYTE
 +
| Runway designator
 +
|-
 +
|- valign="top"
 +
| 0x02
 +
| <center>1</center>
 +
| BYTE
 +
| Type of start
 +
* 1 = RUNWAY,
 +
* 2 = WATER,
 +
* 3 = HELIPAD
 +
|-
 +
| 0x03
 +
| <center>1</center>
 +
| BYTE
 +
| Unused (?)
 +
|}
 +
=== for Frequencies ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
|- valign="top"
 +
| 0x00
 +
| <center>4</center>
 +
| DWORD
 +
| bit 28-31: type (as with COM records)<br/>bit 0-27: frequency * 1000000
 +
|}
 +
 
 +
== Apron ==
 +
There are 2 subrecords for each apron which follow each other. Both have variable length.
 +
<br/>First record
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0037</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| surface (as with runway subrecord)
 +
|-
 +
| 0x07
 +
| <center>2</center>
 +
| WORD
 +
| Number of vertices
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each vertex:</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then</b>
 +
|-
 +
|
 +
|
 +
|
 +
| zero-fill to next DWORD boundary
 +
|}
 +
Second record
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0030</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| surface (as with runway subrecord)
 +
|-
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| flags:
 +
* bit 0: drawSurface
 +
* bit 1: drawDetail
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| Number of vertices
 +
|-
 +
| 0x0A
 +
| <center>2</center>
 +
| WORD
 +
| Number of triangles to draw
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each vertex:</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each triangle to draw:</b>
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of first point
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of second point
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of third point
 +
|}
 +
 
 +
== Apron Edge Lights ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0031</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| Number of vertices
 +
|-
 +
| 0x0A
 +
| <center>2</center>
 +
| WORD
 +
| Number of edges
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| 0xFF0000FF: Unknown, probably color of lights
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| FLOAT
 +
| 0x3F800000: Unknown (value 1)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| 0x44480000: Unknown (value 800)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each vertex</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each edge</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| FLOAT
 +
| Unknown (value 60.96)
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of start vertex
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of end vertex
 +
|}
 +
 
 +
== Taxiway Point ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x001A</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of taxiway points present
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and for each taxipoint:</b>
 +
|- valign="top"
 +
|
 +
| <center>1</center>
 +
| BYTE
 +
| Type
 +
* 1 = NORMAL
 +
* 2 = HOLD
 +
* 4 = ILS_HOLD_SHORT
 +
|- valign="top"
 +
|
 +
| <center>1</center>
 +
| BYTE
 +
| Flag
 +
* 1 = FORWARD
 +
* 2 = REVERSE
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|}
 +
 
 +
== Taxiway Parking ==
 +
This record type has a short fixed part for all TaxiwayParking records together and a longer variable part with sections for each TaxiwayParking. The fixed part is 8 bytes long:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x003D</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of taxiway parking records present
 +
|}
 +
The record sections for each TaxiwayParking are again of variable length, depending on the number of airlineCodes present:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>4</center>
 +
| DWORD
 +
| bit 31-24: count of airlineCodes present<br/>
 +
bit 23-12: number<br/>
 +
bit 11-8: type
 +
* 0x1 = RAMP_GA
 +
* 0x2 = RAMP_GA_SMALL
 +
* 0x3 = RAMP_GA_MEDIUM
 +
* 0x4 = RAMP_GA_LARGE
 +
* 0x5 = RAMP_CARGO
 +
* 0x6 = RAMP_MIL_CARGO
 +
* 0x7 = RAMP_MIL_COMBAT
 +
* 0x8 = GATE_SMALL
 +
* 0x9 = GATE_MEDIUM
 +
* 0xa = GATE_HEAVY
 +
* 0xb = DOCK_GA
 +
* 0xc = FUEL
 +
* 0xd = VEHICLES
 +
bit 7-6: pushback
 +
* 00 = none
 +
* 01 = left
 +
* 10 = right
 +
* 11 = both
 +
bit 5-0: name
 +
* 0x00 = NONE
 +
* 0x01 = PARKING
 +
* 0x02 = N_PARKING
 +
* 0x03 = NE_PARKING
 +
* 0x04 = E_PARKING
 +
* 0x05 = SE_PARKING
 +
* 0x06 = S_PARKING
 +
* 0x07 = SW_PARKING
 +
* 0x08 = W_PARKING
 +
* 0x09 = NW_PARKING
 +
* 0x0a = GATE
 +
* 0x0b = DOCK
 +
* 0x0c = GATE_A
 +
* 0x0d = GATE_B
 +
* 0x0e = GATE_C
 +
* 0x0f = GATE_D
 +
* 0x10 = GATE_E
 +
* ..
 +
* ..
 +
* 0x25 = GATE_Z
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| FLOAT
 +
| Radius
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| teeOffset1
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| FLOAT
 +
| teeOffset1
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| teeOffset3
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| teeOffset4
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| ...
 +
| <center>4</center>
 +
| STRING
 +
| Airline Designator (0..n times repeated)
 +
|}
 +
 
 +
== Taxiway Path ==
 +
This record has a fixed length of 8 bytes and a variable part with records for each path. It has the  following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x001C</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of paths defined
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and for each path:</b>
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| index of start point.<br/>
 +
For type TAXI, the index of the start and of the end must both refer to a TaxiPoint.<br/>
 +
For type PARKING the start index must refer to a TaxiPoint, the end index must refer to a TaxiwayParking.
 +
<br/>Indexes are zero-based.
 +
|- valign="top"
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Bit 0-11: index of end point Bit 12-15: runway designator
 +
|- valign="top"
 +
| 0x04
 +
| <center>1</center>
 +
| BYTE
 +
| BIT 0-4: Type
 +
* 0x1 = TAXI
 +
* 0x2 = RUNWAY
 +
* 0x3 = PARKING
 +
* 0x4 = PATH
 +
* 0x5 = CLOSED
 +
<br> BIT 5: "drawSurface flag" (TRUE=1)
 +
<br> BIT 6: "drawDetail flag" (TRUE=1)
 +
<br> BIT 7: unused (?) 
 +
|- valign="top"
 +
| 0x05
 +
| <center>1</center>
 +
| BYTE
 +
| runway number / index into TaxiName
 +
|- valign="top"
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| bitfield
 +
BIT 0: centerline
 +
<br>BIT 1: centerLineLighted
 +
<br>BIT 2-3: leftEdge
 +
* 00 = NONE
 +
* 01 = SOLID
 +
* 10 = DASHED
 +
*  11 = SOLID_DASHED
 +
<br>BIT 4: leftEdgeLighted
 +
<br>BIT 5-6: rightEdge
 +
<br>BIT 7: rightEdgeLighted
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Surface
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Width
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| Weight Limit
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| ??
 +
|}
 +
 
 +
== TaxiName ==
 +
This record has variable length, it consist of 8 bytes as a fixed part and then 8 bytes for each Name.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x001D</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of name entries
 +
|-
 +
|
 +
|
 +
|
 +
| <b>and for each name:</b>
 +
|-
 +
|
 +
|
 +
| STRING
 +
| Taxiname
 +
|}
 +
== Taxiway Sign ==
 +
These records are coded in the [[#TaxiwaySign|section]] for scenery objects (0x25) with a separate type of entry. Apparently all Taxiway signs for one airport are coded together on one record. There seems to be no coordination of this record with the airport record to which it belongs!
 +
I guess that for historical reasons, the TaxiwaySign fixed part looks like the LibraryObject record and that is why the records are stored in the Scenery object section.
 +
 
 +
== Jetway ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x003A</span></b>)<br/>0x05 for FS9
 +
|-
 +
| 0x04
 +
| <center>2</center>
 +
| WORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Parking number (refers to an existing parking)
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| Gate Name
 +
|-
 +
| 0x0A
 +
| <center>4</center>
 +
| DWORD
 +
| Size of the scenery object data to follow (0x40)
 +
|- valign="top"
 +
| 0x0E
 +
| <center>64</center>
 +
|
 +
| [[#LibraryObject|LibraryObject]] record
 +
|}
 +
 
 +
== Approach ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0024</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Suffix
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Runway Number
 +
|- valign="top"
 +
| 0x08
 +
| <center>1</center>
 +
| BYTE
 +
| bit 0-3: Type
 +
* 0x01 = GPS
 +
* 0x02 = VOR
 +
* 0x03 = NDB
 +
* 0x04 = ILS
 +
* 0x05 = LOCALIZER
 +
* 0x06 = SDF
 +
* 0x07 = LDA
 +
* 0x08 = VORDME
 +
* 0x09 = NDBDME
 +
* 0x0a = RNAV
 +
* 0x0b = LOCALIZER_BACKCOURSE
 +
bit 4-6: Runway designator<br/>
 +
bit 7: gpsOverlay flag
 +
|-
 +
| 0x09
 +
| <center>1</center>
 +
| BYTE
 +
| Number of transitions (?)
 +
|-
 +
| 0x0A
 +
| <center>1</center>
 +
| BYTE
 +
| Number of approach legs
 +
|-
 +
| 0x0B
 +
| <center>1</center>
 +
| BYTE
 +
| Number of missedApproach legs ?
 +
|- valign="top"
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| fixIdent
 +
BIT 0-4: fixType
 +
* 02 = VOR
 +
* 03 = NDB
 +
* 04 =  TERMINAL_NDB
 +
* 05 = WAYPOINT
 +
* 06 = TERMINAL_WAYPOINT
 +
* 09 = RUNWAY
 +
BIT 5-31: fixIdent
 +
|- valign="top"
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: fixRegion<br/>
 +
bit 11-31: ICAO Id of relevant airport
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| missedAltitude
 +
|}
 +
after this the following record can occur:
 +
 
 +
=== ApproachLegs ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x002D</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of legs to follow
 +
|}
 +
each leg is a structure with a fixed length of 44 bytes
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>1</center>
 +
| BYTE
 +
| ID of the leg types found:
 +
* 0x01 = AF
 +
* 0x02 = CA
 +
* 0x03 = CD
 +
* 0x04 = CF
 +
* 0x05 = CI
 +
* 0x06 = CR
 +
* 0x07 = DF
 +
* 0x08 = FA
 +
* 0x09 = FC
 +
* 0x0a = FD
 +
* 0x0b = FM
 +
* 0x0c = HA
 +
* 0x0d = HF
 +
* 0x0e = HM
 +
* 0x0f = IF
 +
* 0x10 = PI
 +
* 0x11 = RF
 +
* 0x12 = TF
 +
* 0x13 = VA
 +
* 0x14 = VD
 +
* 0x15 = VI
 +
* 0x16 = VM
 +
* 0x17 = VR
 +
|- valign="top"
 +
| 0x01
 +
| <center>1</center>
 +
| BYTE
 +
| Altitude Descriptor
 +
* 01 = A
 +
* 02 = +
 +
* 03 = -
 +
* 04 = B
 +
|- valign="top"
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Flags
 +
* bit 0: turnDirection = L
 +
* bit 1: turnDirection = R
 +
* bit 8: magneticCourse (0)* trueCourse (1)
 +
* bit 9: distance (0) or time (1)
 +
* bit 10: flyover false (0) true (1)
 +
|- valign="top"
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| bit 5-31: fixIdent<br/>bit 0-4: fixType
 +
|- valign="top"
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: fixRegion<br/>bit 11-32: ICAO Id of relevant airport
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| bit 5-31: recommendedIdent<br/>bit 0-4: recommendedType
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Recommended region
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Theta
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Rho
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| trueCourse / magneticCourse (depending on flag)
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| FLOAT
 +
| Distance / Time
 +
|-
 +
| 0x24
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude 1
 +
|-
 +
| 0x28
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude 2
 +
|}
 +
=== MissedApproachLegs ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x002E</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of legs to follow
 +
|}
 +
=== Transition ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x002C</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| transitionType 1 = FULL, 2 = DME
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Number of TransitionLegs
 +
|- valign="top"
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-4: fixType
 +
* 2 = VOR
 +
* 3 = NDB
 +
* 4 = TERMINAL_NDB
 +
* 5 = WAYPOINT
 +
* 6 = TERMINAL_WAYPOINT
 +
bit 5-31: fixIdent ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: fixRegion
 +
bit 11-31 : airportID of relevant airport
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude
 +
|-
 +
|
 +
|
 +
|
 +
| <b>If transitionType = DME and DmeArc record exists, then the following 16 bytes are present</b>
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| dmeIndent
 +
|- valign="top"
 +
| 0x18
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: dmeRegion
 +
bit 11-31: airportID of relevant airport
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| DWORD
 +
| Radial
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| FLOAT
 +
| Distance
 +
|}
 +
 
 +
=== TransitionLegs ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x002F</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of legs to follow.
 +
|}
 +
== WayPoint ==
 +
The waypoint record can be part of the Airport group or can be entered independently. In both cases the output for the BGL is the same but for the DWORD at offset 0x18.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0022</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Type
 +
* 1 = NAMED
 +
* 2 = UNNAMED
 +
* 3 = VOR
 +
* 4 = NDB
 +
* 5 = OFF_ROUTE
 +
* 6 = IAF
 +
* 7 = FAF
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Number of Route entries to follow
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| FLOAT
 +
| Magnetic Variation
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| WayPoint Ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x18
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: waypointRegion ([[#ICAO Identifiers and region codes|Special Format]])
 +
bit 11-31: ICAO ident of the relevant airport, if it is a terminal waypoint, defined within an airport record.
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | Optional, if Route is given
 +
|- valign="top"
 +
| 0x1C
 +
| <center>1</center>
 +
| BYTE
 +
| Route type
 +
* 1 = VICTOR
 +
* 2 = JET
 +
* 3 = BOTH
 +
|-
 +
| 0x1D
 +
| <center>8</center>
 +
| char[8]
 +
| Name (zero padded), name cannot be longer than 8 characters
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>for Next:</b>
 +
|- valign="top"
 +
| 0x25
 +
| <center>4</center>
 +
| DWORD
 +
| BIT 0-2: Type
 +
* 1 = NDB
 +
* 2 = VOR
 +
* 5 = all other
 +
BIT 5-31: waypointIdent ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x29
 +
| <center>4</center>
 +
| DWORD
 +
| Bit 0-10 waypointRegion ([[#ICAO Identifiers and region codes|Special Format]])
 +
Bit 11-31 airportId if terminal waypoint
 +
|- valign="top"
 +
| 0x2D
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude Minimum
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>for Previous:</b>
 +
|- valign="top"
 +
| 0x31
 +
| <center>4</center>
 +
| DWORD
 +
| BIT 0-2: Type
 +
* 1 = NDB
 +
* 2 = VOR
 +
* 5 = all other
 +
BIT 5-31: waypointIdent ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x35
 +
| <center>4</center>
 +
| DWORD
 +
| Bit 0-10 waypointRegion ([[#ICAO Identifiers and region codes|Special Format]])
 +
Bit 11-31 airportId if terminal waypoint
 +
|- valign="top"
 +
| 0x39
 +
| <center>4</center>
 +
| FLOAT
 +
| Altitude Minimum
 +
|}
 +
Note: it is not necessary for any route to have both previous and next defined, in that case the fields for this part of the record are all zero.
 +
<br/>
 +
== Fences ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id<br/>
 +
<b><span style="color:#0000FF">0x0038</span></b> BlastFence<br/>
 +
<b><span style="color:#0000FF">0x0039</span></b> BoundaryFence
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of vertices
 +
|-
 +
| 0x08
 +
| <center>16</center>
 +
| GUID
 +
| Instance Id
 +
|-
 +
| 0x18
 +
| <center>16</center>
 +
| GUID
 +
| Profile
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each vertex:</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|}
 +
<br/>
 +
== Unknown Record 0x3B ==
 +
Every (?) airport in the FS X scenery files contains a subrecord with the ID of 0x3B. This record
 +
contains as usual a DWORD length field at offset 0x02.<br/>It cannot be reproduced with the BglComp
 +
compiler, and it has no apparent function.<br/>
 +
It concists of a long list of vertices along the perimeter of
 +
the airport and a list of indices for triangles to be drawn (similar to the second Apron record), but in
 +
fact the sim apparently does not use this list for drawing.<br/>
 +
It has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
 
 +
<br/><br/>
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id : <b><span style="color:#0000FF">0x003B</span>
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (variable)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| Number of vertices
 +
|-
 +
| 0x0A
 +
| <center>2</center>
 +
| WORD
 +
| Number of triangles
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | '''and then for each vertex:'''
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | '''and then for each triangle:'''
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of vertex #1
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of vertex #2
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Index of vertex #3
 +
|}
 +
 
 +
= AIRPORTSUMMARY =
 +
The record has a fixed size of 44 bytes.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0032</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (0x2C)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Flags
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude x 1000 (in meters)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO Ident.
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| DWORD
 +
| Region
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| Magnetic Variation
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| FLOAT
 +
| Length of the longest runway
 +
|-
 +
| 0x24
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading of the longest runway
 +
|-
 +
|- valign = "top"
 +
| 0x28
 +
| <center>4</center>
 +
| DWORD
 +
| Type of fuel present at the airport and its availability.
 +
Each availability is coded on 2 bits: 0 = No, 1 = Unknown, 2 = Prior Request, 3 = Yes
 +
* Bits 0-1 : Availability for 73 octane
 +
* Bits 2-3 : Availability for 87 octane
 +
* Bits 4-5 : Availability for 100 octane
 +
* Bits 6-7 : Availability for 130 octane
 +
* Bits 8-9 : Availability for 145 octane
 +
* Bits 10-11 : Availability for MOGAS
 +
* Bits 12-13 : Availability for JET
 +
* Bits 14-15 : Availability for JETA
 +
* Bits 16-17 : Availability for JETA1
 +
* Bits 18-19 : Availability for JETAP
 +
* Bits 20-21 : Availability for JETB
 +
* Bits 22-23 : Availability for JET4
 +
* Bits 24-22 : Availability for JET4
 +
* Bit 30 : Airport has avgas
 +
* Bit 31 : Airport has jet fuel
 +
|}
 +
<br/><br/>
 +
 
 +
= ILS/VOR =
 +
The records for ILS and VOR are in the same section and they are identical for the fixed section. ILS records can have an additional subrecords. The fixed part is 40 bytes long and has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0013</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|- valign="top"
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Type. The following numbers have been found:
 +
* 0x0001 VOR TERMINAL
 +
* 0x0002 VOR LOW
 +
* 0x0003 VOR HIGH
 +
* 0x0004 ILS
 +
* 0x0005 VOR VOT
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Flags. The following bits have been recognized:
 +
* bit 0: if 0 then DME only, otherwise 1 for ILS
 +
* bit 2: backcourse (0 = false, 1 = true)
 +
* bit 3: glideslope present
 +
* bit 4: DME present
 +
* bit 5: NAV true
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Frequency
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Range in meters
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| Magnetic Variation
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x24
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10 regionId
 +
bit 11-31 airportId (for ILS)
 +
|}
 +
The following subrecords can follow:
 +
== Localizer ==
 +
(For ILS)
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id Localizer (<b><span style="color:#0000FF">0x0014</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (0x10)
 +
|-
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Runway Number
 +
|-
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Runway Designator (0=NONE, 1=LEFT, 2=RIGHT, 3=CENTER)
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading (True,°)
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| FLOAT
 +
| Loc Beam width (°)
 +
|}
 +
 
 +
== GlideSlope ==
 +
For (ILS)
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id GlideSlope (<b><span style="color:#0000FF">0x0015</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (0x1C)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Range
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Pitch
 +
|}
 +
 
 +
== Dme ==
 +
For (ILS/VOR)
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id DME(<b><span style="color:#0000FF">0x0016</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (0x18)
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| FLOAT
 +
| Range
 +
|}
 +
After these subsections, a name subsection is added:
 +
 
 +
== Name ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0019</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
|
 +
| STRING
 +
| Name (max. 48 characters)
 +
|}
 +
If VisualModel is added in the source file, the compiler adds another section to the file with a record of type <b><span style="color:#0000FF">0x0025</span></b> (SceneryxObject) with the GUID for the object referenced.
 +
The coordinates for this objects are taken from the ILS/VOR and adjusted, if BiasXYZ is added to the VisualModel.
 +
<br/><br/>
 +
 
 +
= NDB =
 +
The NDB records are stored in a separate section. The have a 40 bytes long fixed section and a
 +
name section of variable length. The fixed section has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0017</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|- valign="top"
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Type
 +
* 0 = COMPASS_POINT
 +
* 1 = MH
 +
* 2 = H
 +
* 3 = HH
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| Frequency
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Elevation x 1000 (in meters)
 +
|-
 +
| 0x18
 +
| <center>4</center>
 +
| FLOAT
 +
| Range
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| Magnetic Variation
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x24
 +
| <center>4</center>
 +
| DWORD
 +
| bit 0-10: region
 +
bit 11-31: ICAO id of airport, if it was defined with an airport (terminal NDB)
 +
|}
 +
The name subsection has the following structure
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0019</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size
 +
|-
 +
| 0x06
 +
|
 +
| STRING
 +
| Name
 +
|}
 +
<br/><br/>
 +
 
 +
= SCENERYOBJECT =
 +
== TaxiwaySign ==
 +
These records are coded in the section for scenery objects (0x25) with a separate type of entry. Apparently all Taxiway signs for one airport are coded together on one record. There seems to be no coordination of this record with the airport record to which it belongs!
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x000E</span></b>)<br/>0x05 for FS9
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size: variable
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude (?) cannot be coded with the compiler
 +
|- valign="top"
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| Flags (cannot be coded)
 +
* Bit 0: IsAboveAGL
 +
* Bit 1: NoAutogenSuppression
 +
* Bit 2: NoCrash
 +
* Bit 3: NoFog
 +
* Bit 4: NoShadow
 +
* Bit 5: NoZWrite
 +
* Bit 6: NoZTest
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch(?)]] - Cannot be coded
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank(?)]] - Cannot be coded
 +
|- valign="top"
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading(?)]] - Cannot be coded
 +
|-
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| ImageComplexity (?) - Cannot be coded
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>2</center>
 +
| WORD
 +
| Number of taxiway signs for this airport
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each sign:</b>
 +
|- valign="top"
 +
| 0x00
 +
| <center>4</center>
 +
| FLOAT
 +
| Longitude offset from anchor value in fix part above
 +
Value = (TaxiSign Longitude - Anchor Longitude) * 40075000 * cos ((pi/180) * abs (Anchor Latitude + LatOffset /2) / 360
 +
|- valign="top"
 +
| 0x04
 +
| <center>4</center>
 +
| FLOAT
 +
| Latitude offset from anchor value in fix part above
 +
Value = (TaxiSign Latitude - Anchor Latitude) * 40007000 / 360
 +
|- valign="top"
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|- valign="top"
 +
| 0x0A
 +
| <center>1</center>
 +
| BYTE
 +
| Size
 +
* 1 = SIZE1
 +
* 2 = SIZE2
 +
* 3 = SIZE3
 +
* 4 = SIZE4
 +
* 5 = SIZE5
 +
|-
 +
| 0x0B
 +
| <center>1</center>
 +
| BYTE
 +
| Justification (1 = right, 2 = left)
 +
|-
 +
| 0x0C
 +
| <center></center>
 +
| STRINGZ
 +
| Label (zero filled to next WORD address)
 +
|}
 +
 
 +
== LibraryObject ==
 +
The record has a fixed length of 0x40 bytes with the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x000B</span></b>)
 +
(0x02 for FS9)
 +
|- valign="top"
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size (0x0040)
 +
(0x0030 for FS9)
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|- valign="top"
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| Flags
 +
* Bit 0: IsAboveAGL
 +
* Bit 1: NoAutogenSuppression
 +
* Bit 2: NoCrash
 +
* Bit 3: NoFog
 +
* Bit 4: NoShadow
 +
* Bit 5: NoZWrite
 +
* Bit 6: NoZTest
 +
 
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|- valign="top"
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| imageComplexity
 +
* 0 = VERYSPARSE
 +
* 1 = SPARSE
 +
* 2 = NORMAL
 +
* 3 = DENSE
 +
* 4 = VERYDENSE
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>16</center>
 +
| GUID
 +
| FSX only: contains an empty GUID
 +
|-
 +
| 0x2C
 +
| <center>16</center>
 +
| GUID
 +
| Name
 +
|-
 +
| 0x3C
 +
| <center>4</center>
 +
| FLOAT
 +
| Scale
 +
|}
 +
If an <b>AttachedObject</b> exists, there are 3 other records following:
 +
=== AttachedObject ===
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x1002</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size (0x0004)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then the 2nd record</b>
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| ID depending on the kind of attached object.
 +
It is possible to attach beacons, effects and other library objects
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size
 +
|-
 +
| 0x04
 +
| <center>2</center>
 +
| WORD
 +
| Offset of attach point string
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x0A
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| BiasX
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| BiasY
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| BiasZ
 +
|-
 +
| 0x18
 +
| <center>16</center>
 +
| GUID
 +
| Instance Id
 +
|-
 +
| 0x28
 +
| <center>2</center>
 +
| WORD
 +
| Probability
 +
|-
 +
| 0x30
 +
| <center>2</center>
 +
| WORD
 +
| Randomness
 +
|- valign="top"
 +
| 0x32
 +
| <center>1</center>
 +
| BYTE
 +
| Type
 +
* 0xF5 = CIVILIAN AIRPORT
 +
* 0xF6 = CIVILIAN HELIPORT
 +
* 0xF7 = CIVILIAN SEA_BASE
 +
* 0xF8 = MILITARY AIRPORT
 +
* 0xF9 = MILITARY HELIPORT
 +
* 0xFA = MILITARY SEA_BASE
 +
|-
 +
| 0x33
 +
| <center>1</center>
 +
| BYTE
 +
| Unknown, always 0x01 (?)
 +
|-
 +
| 0x34
 +
| <center>2</center>
 +
| WORD
 +
| unknown , always 0x0000
 +
|-
 +
| 0x36
 +
|
 +
| STRINGZ
 +
| Name of the attachment point
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then the 3rd record</b>
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x1001</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size (0x004)
 +
|}
 +
 
 +
== Effect ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x000D</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size: variable
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| Flag: 1 = isAboveAGL
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|- valign="top"
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| ImageComplexity
 +
* 0 = VERYSPARSE
 +
* 1 = SPARSE
 +
* 2 = NORMAL
 +
* 3 = DENSE
 +
* 4 = VERYDENSE
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>80</center>
 +
| STRINGZ
 +
| effectName
 +
|-
 +
| 0x6C
 +
| <center></center>
 +
| STRINGZ
 +
| effectParams
 +
|}
 +
 
 +
== GenericBuilding ==
 +
NB.: BuildingBias is not implemented in the compiler.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x000A</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size: variable
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| flag: 1 = isAboveAGL
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|- valign="top"
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| imageComplexity
 +
* 0 = VERYSPARSE
 +
* 1 = SPARSE
 +
* 2 = NORMAL
 +
* 3 = DENSE
 +
* 4 = VERYDENSE
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>4</center>
 +
| FLOAT
 +
| Scale
 +
|-
 +
| 0x20
 +
| <center>2</center>
 +
| WORD
 +
| type: 0x00a0 generic building
 +
|-
 +
| 0x22
 +
| <center>2</center>
 +
| WORD
 +
| Size fo record
 +
|- valign="top"
 +
| 0x24
 +
| <center>2</center>
 +
| WORD
 +
| subtype. The following numbers have been identified:
 +
* 0x0004 rectangular with roofType FLAT
 +
* 0x0006 rectangular with roofType RIDGE
 +
* 0x0007 rectangular with roofType PEAKED
 +
* 0x0008 rectangular with roofType SLANT
 +
* 0x0009 pyramidal building
 +
* 0x000a multisidedBuilding
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for all rectangular buildings:
 +
|-
 +
| 0x26
 +
| <center>2</center>
 +
| WORD
 +
| SizeX (0)
 +
|-
 +
| 0x28
 +
| <center>2</center>
 +
| WORD
 +
| SizeZ (1)
 +
|-
 +
| 0x2A
 +
| <center>2</center>
 +
| WORD
 +
| bottomTexture (2)
 +
|-
 +
| 0x2C
 +
| <center>2</center>
 +
| WORD
 +
| sizeBottomY (3)
 +
|-
 +
| 0x2E
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexBottomX (4)
 +
|-
 +
| 0x30
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexBottomZ (5)
 +
|-
 +
| 0x32
 +
| <center>2</center>
 +
| WORD
 +
| windowTexture(6)
 +
|-
 +
| 0x34
 +
| <center>2</center>
 +
| WORD
 +
| sizeWindowY(7)
 +
|-
 +
| 0x36
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowX(8)
 +
|-
 +
| 0x38
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowY(9)
 +
|-
 +
| 0x3A
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowZ(10)
 +
|-
 +
| 0x3C
 +
| <center>2</center>
 +
| WORD
 +
| topTexture (11)
 +
|-
 +
| 0x3E
 +
| <center>2</center>
 +
| WORD
 +
| sizeTopY (12)
 +
|-
 +
| 0x40
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexTopX (13)
 +
|-
 +
| 0x42
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexTopZ (14)
 +
|-
 +
| 0x44
 +
| <center>2</center>
 +
| WORD
 +
| roofTexture (15)
 +
|-
 +
| 0x46
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofX (16)
 +
|-
 +
| 0x48
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofX (17)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | end for rectangular buildings with rooftype FLAT.
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for rectangular buildings with roofType RIDGE or SLANTED:
 +
|-
 +
| 0x4A
 +
| <center>2</center>
 +
| WORD
 +
| sizeRoofY (18)
 +
|-
 +
| 0x4C
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexGableY (19)
 +
|-
 +
| 0x4E
 +
| <center>2</center>
 +
| WORD
 +
| gableTexture (20)
 +
|-
 +
| 0x50
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexGableZ (21)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for roofType SLANTED only:
 +
|-
 +
| 0x52
 +
| <center>2</center>
 +
| WORD
 +
| faceTexture (22)
 +
|-
 +
| 0x54
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexFaceX (23)
 +
|-
 +
| 0x56
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexFaceX (24)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for rectangular buildings with roofType PEAKED:
 +
|-
 +
| 0x4A
 +
| <center>2</center>
 +
| WORD
 +
| sizeRoofY(18)
 +
|-
 +
| 0x4C
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofY (19)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for multisided buildings:
 +
|- valign="top"
 +
| 0x26
 +
| <center>2</center>
 +
| WORD
 +
| buildingSides
 +
: Note: The Argument for smoothing is required by the compiler, but it has no effect on the BGL-file
 +
|-
 +
| 0x28
 +
| <center>2</center>
 +
| WORD
 +
| sizeX (1)
 +
|-
 +
| 0x2A
 +
| <center>2</center>
 +
| WORD
 +
| sizeZ (2)
 +
|-
 +
| 0x2C
 +
| <center>2</center>
 +
| WORD
 +
| bottomTexture (3)
 +
|-
 +
| 0x2E
 +
| <center>2</center>
 +
| WORD
 +
| sizeBottomY (4)
 +
|-
 +
| 0x30
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexBottomX (5)
 +
|-
 +
| 0x32
 +
| <center>2</center>
 +
| WORD
 +
| windowTexture (6)
 +
|-
 +
| 0x34
 +
| <center>2</center>
 +
| WORD
 +
| sizeWindowY (7)
 +
|-
 +
| 0x36
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowX (8)
 +
|-
 +
| 0x38
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowY (9)
 +
|-
 +
| 0x3A
 +
| <center>2</center>
 +
| WORD
 +
| topTexture (10)
 +
|-
 +
| 0x3C
 +
| <center>2</center>
 +
| WORD
 +
| sizeTopY (11)
 +
|-
 +
| 0x3E
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexTopX (12)
 +
|-
 +
| 0x40
 +
| <center>2</center>
 +
| WORD
 +
| roofTexture (13)
 +
|-
 +
| 0x42
 +
| <center>2</center>
 +
| WORD
 +
| sizeRoofY (14)
 +
|-
 +
| 0x44
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofX (15)
 +
|-
 +
| 0x46
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofY (16)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | Note: textureIndexRoofY is required by the compiler, but it has no effect on the bgl file !
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for pyramidal buildings:
 +
|-
 +
| 0x26
 +
| <center>2</center>
 +
| WORD
 +
| sizeX (0)
 +
|-
 +
| 0x28
 +
| <center>2</center>
 +
| WORD
 +
| sizeZ (1)
 +
|-
 +
| 0x2A
 +
| <center>2</center>
 +
| WORD
 +
| sizeTopX (2)
 +
|-
 +
| 0x2C
 +
| <center>2</center>
 +
| WORD
 +
| sizeTopZ (3)
 +
|-
 +
| 0x2E
 +
| <center>2</center>
 +
| WORD
 +
| bottomTexture (4)
 +
|-
 +
| 0x30
 +
| <center>2</center>
 +
| WORD
 +
| sizeBottomY (5)
 +
|-
 +
| 0x32
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexBottomX (6)
 +
|-
 +
| 0x34
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexBottomZ (7)
 +
|-
 +
| 0x36
 +
| <center>2</center>
 +
| WORD
 +
| windowTexture (8)
 +
|-
 +
| 0x38
 +
| <center>2</center>
 +
| WORD
 +
| sizeWindowY (9)
 +
|-
 +
| 0x3A
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowX (10)
 +
|-
 +
| 0x3C
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowY (11)
 +
|-
 +
| 0x3E
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexWindowZ (12)
 +
|-
 +
| 0x40
 +
| <center>2</center>
 +
| WORD
 +
| topTexture (13)
 +
|-
 +
| 0x42
 +
| <center>2</center>
 +
| WORD
 +
| sizeTopY (14)
 +
|-
 +
| 0x44
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexTopX (15)
 +
|-
 +
| 0x46
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexTopZ (16)
 +
|-
 +
| 0x48
 +
| <center>2</center>
 +
| WORD
 +
| roofTexture (17)
 +
|-
 +
| 0x4A
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofX (18)
 +
|-
 +
| 0x4C
 +
| <center>2</center>
 +
| WORD
 +
| textureIndexRoofZ (19)
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | for all
 +
|-
 +
|
 +
| <center>2</center>
 +
| WORD
 +
| Unknown : 0x22 0x00
 +
|}
 +
 
 +
== Windsock ==
 +
Record with fixed length of 46 bytes.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0C</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size (0x2E)
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| flags (unused)
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|-
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| imageComplexity
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>16</center>
 +
| GUID
 +
| Instance Id
 +
|-
 +
| 0x2C
 +
| <center>4</center>
 +
| FLOAT
 +
| poleheight
 +
|-
 +
| 0x30
 +
| <center>4</center>
 +
| FLOAT
 +
| sockLength
 +
|-
 +
| 0x34
 +
| <center>1</center>
 +
| BYTE
 +
| PoleColor: blue
 +
|-
 +
| 0x35
 +
| <center>1</center>
 +
| BYTE
 +
| PoleColor: green
 +
|-
 +
| 0x36
 +
| <center>1</center>
 +
| BYTE
 +
| PoleColor: red
 +
|-
 +
| 0x37
 +
| <center>1</center>
 +
| BYTE
 +
| PoleColor ? (0xFF)
 +
|-
 +
| 0x38
 +
| <center>4</center>
 +
| BYTE[4]
 +
| SockColor
 +
|-
 +
| 0x3C
 +
| <center>2</center>
 +
| WORD
 +
| flag: lighted (TRUE = 0x0001)
 +
|}
 +
 
 +
== Extrusion Bridge ==
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x12</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| LONG
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| Flags
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|-
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| imageComplexity
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>16</center>
 +
| GUID
 +
| Instance Id
 +
|-
 +
| 0x2C
 +
| <center>16</center>
 +
| GUID
 +
| Profile
 +
|-
 +
| 0x3C
 +
| <center>16</center>
 +
| GUID
 +
| Material Set
 +
|-
 +
| 0x4C
 +
| <center>12</center>
 +
| DWORD[3]
 +
| altitude sample location 1
 +
|-
 +
| 0x58
 +
| <center>12</center>
 +
| DWORD[3]
 +
| altitude sample location 2
 +
|-
 +
| 0x64
 +
| <center>4</center>
 +
| FLOAT
 +
| road width
 +
|-
 +
| 0x68
 +
| <center>4</center>
 +
| FLOAT
 +
| Probability
 +
|-
 +
| 0x6C
 +
| <center>1</center>
 +
| BYTE
 +
| Suppress
 +
|-
 +
| 0x6D
 +
| <center>1</center>
 +
| BYTE
 +
| Placement Count
 +
|-
 +
| 0x6E
 +
| <center>2</center>
 +
| WORD
 +
| Point count
 +
|-
 +
|
 +
|
 +
|
 +
| <b>and then for each polyline object placement</b>
 +
|-
 +
|
 +
| <center>16</center>
 +
| GUID
 +
| placement id
 +
|-
 +
|
 +
|
 +
|
 +
| <b>and then for each polyline point</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
|
 +
| <center>4</center>
 +
| LONG
 +
| Elevation
 +
|}
 +
== Trigger ==
 +
The record consists of a fixed part and a variable part. The fixed part is 34 bytes long and has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x10</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size: variable
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| AltitudeIsAGL (0x0001 = TRUE)
 +
|-
 +
| 0x12
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Pitch]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Bank]]
 +
|-
 +
| 0x16
 +
| <center>2</center>
 +
| WORD
 +
| [[#Pitch, bank and heading|Heading]]
 +
|-
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| imageComplexity
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown
 +
|-
 +
| 0x1C
 +
| <center>16</center>
 +
| GUID
 +
| Instance Id
 +
|- valign="top"
 +
| 0x2C
 +
| <center>2</center>
 +
| WORD
 +
| Type
 +
* 0x0000 = REFUEL_REPAIR
 +
* 0x0001 = WEATHER
 +
|-
 +
| 0x2E
 +
| <center>4</center>
 +
| FLOAT
 +
| triggerHeight
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | In case of '''WEATHER''' the variable part has the following structure:
 +
|- valign="top"
 +
| 0x32
 +
| <center>2</center>
 +
| WORD
 +
| Type
 +
* 0x0001 = RIDGE_LIFT
 +
* 0x0002 = UNIDIRECTIONAL_TURBULENCE
 +
: note: in bglcomp.xsd this keyword is spelled NONDIRECTIONAL_TURBULENCE, but the compiles does not understand it. If you change the keyword in bglcomp.xsd compilation is ok.
 +
* 0x0003 = DIRECTIONAL_TURBULENCE
 +
* 0x0004 = THERMAL
 +
|-
 +
| 0x34
 +
| <center>4</center>
 +
| FLOAT
 +
| Heading
 +
|-
 +
| 0x38
 +
| <center>4</center>
 +
| FLOAT
 +
| Scalar
 +
|-
 +
| 0x3C
 +
| <center>4</center>
 +
| DWORD
 +
| Number of vertices
 +
|-
 +
|
 +
|
 +
|
 +
| <b>and then for each vertex:</b>
 +
|-
 +
|
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasX
 +
|-
 +
|
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasY
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | In case of '''FUEL_REPAIR''' the variable part has the following structure:
 +
|- valign="top"
 +
| 0x32
 +
| <center>4</center>
 +
| DWORD
 +
| Fuel type and availability
 +
* bit 0-1: type 73
 +
* bit 2-3: type 87
 +
* bit 4-5: type 100
 +
* bit 6-7: type 130
 +
* bit 8-9: type 145
 +
* bit 10-11: type MOGAS
 +
* bit 12-13: type JET
 +
* bit 14-15: type JETA
 +
* bit 16-17: type JETA1
 +
* bit 18-19: type JETAP
 +
* bit 20-21: type JETB
 +
* bit 22-23: type JET4
 +
* bit 24-25: type JET5
 +
* bit 26-29 : unused
 +
* bit 30 : piston type
 +
* bit 31 : jet type
 +
for all except last two :
 +
* 0 = NO
 +
* 1 = UNKNOWN
 +
* 2 = PRIOR_REQUEST
 +
* 3 = YES
 +
when type=UNKNOWN and availability = YES then type=100 and type = JETA both are set to availability=YES
 +
|-
 +
| 0x036
 +
| <center>4</center>
 +
| DWORD
 +
| Number of vertices
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>and then for each vertex</b>
 +
|-
 +
| 0x036
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasX
 +
|-
 +
| 0x036
 +
| <center>4</center>
 +
| FLOAT
 +
| BiasZ
 +
|}
 +
<br/><br/>
 +
 
 +
= MARKER =
 +
The Marker record has a fixed length of 28 bytes with the following structure:<br/>
 +
NOTE:  The structure given by Winfried appears to be wrong in the first three fields
 +
* ID 2 bytes WORD
 +
* Size 4 bytes DWORD
 +
* Heading 1 byte BYTE
 +
 
 +
The structure below is taken from the source code of BGLXMl.
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x18</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| WORD
 +
| Size (0x0000001C)
 +
|-
 +
| 0x04
 +
| <center>1</center>
 +
| BYTE
 +
| Unknown
 +
|-
 +
| 0x05
 +
| <center>2</center>
 +
| WORD
 +
| Heading
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| Type
 +
* 0 = INNER
 +
* 1 = MIDDLE
 +
* 2 = OUTER
 +
* 3 = BACKCOURSE
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Altitude
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x18
 +
| <center>2</center>
 +
| WORD
 +
| Region ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x1A
 +
| <center>2</center>
 +
| WORD
 +
| Unknown (0x0000)
 +
|}
 +
<br/><br/>
 +
 
 +
= BOUNDARY =
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x20</span></b>)
 +
|-
 +
| 0x00
 +
| <center>4</center>
 +
| DWORD
 +
| Size: variable
 +
|- valign="top"
 +
| 0x06
 +
| <center>1</center>
 +
| BYTE
 +
| Type
 +
* 00 = NONE
 +
* 01 = CENTER
 +
* 02 = CLASS_A
 +
* 03 = CLASS_B
 +
* 04 = CLASS_C
 +
* 05 = CLASS_D
 +
* 06 = CLASS_E
 +
* 07 = CLASS_F
 +
* 08 = CLASS_G
 +
* 09 = TOWER
 +
* 0a = CLEARANCE
 +
* 0b = GROUND
 +
* 0c = DEPARTURE
 +
* 0d = APPROACH
 +
* 0e = MOA
 +
* 0f = RESTRICTED
 +
* 10 = PROHIBITED
 +
* 11 = WARNING
 +
* 12 = ALERT
 +
* 13 = DANGER
 +
* 14 = NATIONAL_PARK
 +
* 15 = MODEC
 +
* 16 = RADAR
 +
* 17 = TRAINING
 +
|- valign="top"
 +
| 0x07
 +
| <center>1</center>
 +
| BYTE
 +
| BIT 0-3: maximumAltitudeType
 +
BIT 4-7: minimumAltitudeType
 +
* 1 = MEAN_SEA_LEVEL (= UNKNOWN)
 +
* 2 = ABOVE_GROUND_LEVEL
 +
* 3 = UNLIMITED
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| Minimum [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of area covered
 +
|-
 +
| 0x12
 +
| <center>4</center>
 +
| DWORD
 +
| Minimum [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of area covered
 +
|-
 +
| 0x16
 +
| <center>4</center>
 +
| DWORD
 +
| Minimum Altitude * 1000
 +
|-
 +
| 0x20
 +
| <center>4</center>
 +
| DWORD
 +
| Maximum [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of area covered
 +
|-
 +
| 0x24
 +
| <center>4</center>
 +
| DWORD
 +
| Maximum [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of area covered
 +
|-
 +
| 0x28
 +
| <center>4</center>
 +
| DWORD
 +
| Maximum Altitude
 +
|-
 +
| 0x32
 +
| <center>2</center>
 +
| WORD
 +
| Type field of name record (0x19)
 +
|-
 +
| 0x34
 +
| <center>4</center>
 +
| DWORD
 +
| Size of name record
 +
|-
 +
| 0x36
 +
| <center>size-6</center>
 +
| STRING
 +
| Name
 +
|}
 +
on this follows a record describing the drawing of the lines
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x21</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| size: variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of points to follow
 +
|-
 +
|
 +
|
 +
|
 +
| <b>for each point 10 bytes</b>
 +
|- valign="top
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Type of point
 +
* 1 = START
 +
* 2 = LINE
 +
* 3 = ORIGIN
 +
* 4 = ARC clockwise
 +
* 5 = arc counter-clockwise
 +
* 6 = circle
 +
NB: in case of circle, the entries for minimumAltitude and maximumAltitude override
 +
the values in start if both are given.<br/>
 +
the start entry is in case of circle not needed at all<br/>
 +
Note: there is a bug in the new version of bglcomp.xsd: the word BoundaryStart in grpBoundaryChildren has to be replaced by Start, otherwise the compiler does not accept it!
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of point (in case of circle: unknown, = 0x0000)
 +
|-
 +
| 0x06
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of point (in case of circle: FLOAT: radius)
 +
|}
 +
<br/><br/>
 +
 
 +
= GEOPOL =
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x23</span></b>)
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| DWORD
 +
| Size: Variable
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Bit 0-13: Number of vertices number of vertices
 +
Bit 14-15: Type
 +
:0x40 = BOUNDARY
 +
:0x80 = COASTLINE)
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| DWORD
 +
| Minimum [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x0C
 +
| <center>2</center>
 +
| DWORD
 +
| Minimum [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| DWORD
 +
| Maximum [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x14
 +
| <center>2</center>
 +
| DWORD
 +
| Maximum [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|-
 +
| colspan="4" style="background: #F5F6CE; text-align: center;" | <b>variable part: for each vertex</b>
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]]
 +
|-
 +
| 0x04
 +
| <center>2</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]]
 +
|}
 +
<br/><br/>
 +
 
 +
= MODEL DATA =
 +
The model data structure has a fixed length of 24 bytes.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>16</center>
 +
| GUID
 +
| Name
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| Mdl File offset from the start of this subsection
 +
|-
 +
| 0x14
 +
| <center>4</center>
 +
| DWORD
 +
| Mdl File Length
 +
|}
 +
<br/><br/>
 +
 
 +
= EXCLUSIONRECTANGLE =
 +
This record has a fixed length record of 20 bytes.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| exclusion type
 +
: 0x0008 = exclude All
 +
Otherwise:
 +
* bit 4 = Beacon Objects
 +
* bit 5 = Effect Objects
 +
* bit 6 = GenericBuilding Objects
 +
* bit 7 = Library Objects
 +
* bit 8 = TaxiwaySign Objects
 +
* bit 9 = Trigger Objects
 +
* bit 10 = Windsock Objects
 +
* bit 11 = ExclusionBridge Objects
 +
|-
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| Size (unused - always 0)
 +
|-
 +
| 0x04
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of NW corner
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of NW corner
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of SE corner
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| DWORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of SE corner
 +
|}
 +
<br/><br/>
 +
 
 +
= NAMELIST =
 +
The namelist contains only one record of variable length. It consists of a fixed part and a variable part. The fixed part is 42 bytes long and has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|-
 +
| 0x00
 +
| <center>2</center>
 +
| WORD
 +
| Id (<b><span style="color:#0000FF">0x0027</span></b>)
 +
|-
 +
| 0x02
 +
| <center>4</center>
 +
| DWORD
 +
| Size (?) seems always to be 0x00000000
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Number of region names
 +
|-
 +
| 0x08
 +
| <center>2</center>
 +
| WORD
 +
| Number of country names
 +
|-
 +
| 0x0A
 +
| <center>2</center>
 +
| WORD
 +
| Number of state names
 +
|-
 +
| 0x0C
 +
| <center>2</center>
 +
| WORD
 +
| Number of city names
 +
|-
 +
| 0x0E
 +
| <center>2</center>
 +
| WORD
 +
| Number of airport names
 +
|-
 +
| 0x10
 +
| <center>2</center>
 +
| WORD
 +
| Number of ICAO Ident
 +
|-
 +
| 0x12
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of region list (from start of record)
 +
|-
 +
| 0x16
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of country list (from start of record)
 +
|-
 +
| 0x1A
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of state list (from start of record)
 +
|-
 +
| 0x1E
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of city list (from start of record)
 +
|-
 +
| 0x22
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of airport list (from start of record)
 +
|-
 +
| 0x26
 +
| <center>4</center>
 +
| DWORD
 +
| Offset of ICAO Ident list (from start of record)
 +
|}
 +
The lists for region, country, state, city and airport names have all the same structure:
 +
an index with 1 DWORD for each entry in the list. The DWORD is an offset in the buffer of names that follows the DWORDs. Each name in that buffer is null-char terminated. Note that the offset values may not be in ascending order (see example).<br/> The ICAO list has a different structure. It contains n entries (one for each ICAO name), each of them 20 bytes long, with the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Number<br/>of bytes
 +
! Format
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| <center>1</center>
 +
| BYTE
 +
| Region name index (all indexes start with 0 for the first name in the relevant list)
 +
|-
 +
| 0x01
 +
| <center>1</center>
 +
| BYTE
 +
| Country Name index
 +
|- valign="top"
 +
| 0x02
 +
| <center>2</center>
 +
| WORD
 +
| bit 0-3 : unknown
 +
bit 4-15 : state name index
 +
|-
 +
| 0x04
 +
| <center>2</center>
 +
| WORD
 +
| City Name index
 +
|-
 +
| 0x06
 +
| <center>2</center>
 +
| WORD
 +
| Airport Name index
 +
|-
 +
| 0x08
 +
| <center>4</center>
 +
| DWORD
 +
| ICAO Identifier ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x0C
 +
| <center>4</center>
 +
| DWORD
 +
| Region Ident ([[#ICAO Identifiers and region codes|Special Format]])
 +
|-
 +
| 0x10
 +
| <center>4</center>
 +
| WORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Longitude]] of the upper left corner of the corresponding QMID Level 9 Square.<br/>The value stored here is the same (2nd value in the triplet) that you see in the status bar of the [http://msdn.microsoft.com/en-us/library/cc707102.aspx#TheTmfViewerTool TmfViewer] application when the QMID grid Level 9 is selected.<br/>[[File:Qmid9.png]]<br/>. The 1st value of the triplet is the level.
 +
|-
 +
| 0x12
 +
| <center>4</center>
 +
| WORD
 +
| [[#Computing Longitude and Latitude from a DWORD value|Latitude]] of the upper left corner of the corresponding QMID Level 9 Square<br/>The value stored here is the same (3rd value in the triplet) that you see in the status bar of the [http://msdn.microsoft.com/en-us/library/cc707102.aspx#TheTmfViewerTool TmfViewer] application when the QMID grid Level 9 is selected.
 +
|}
 +
== Example ==
 +
Let's look at the file APX25230.bgl located in the (...)\Microsoft Flight Simulator X\Scenery\0302\scenery folder.<br/>
 +
The NameList record starts at offset 0x77B4.
 +
{| class="wikitable"
 +
|-
 +
| Offset
 +
| Field
 +
| Value
 +
|-
 +
| 77B4
 +
| Id
 +
| 0x0027
 +
|-
 +
| 77B6
 +
| Size
 +
| 0
 +
|-
 +
| 77BA
 +
| NbRegionNames
 +
| 1
 +
|-
 +
| 77BC
 +
| NbCountryNames
 +
| 1
 +
|-
 +
| 77BE
 +
| NbStateNames
 +
| 1
 +
|-
 +
|77C0
 +
|NbCityNames
 +
|3
 +
|-
 +
|77C2
 +
|NbAirportNames
 +
|3
 +
|-
 +
|77C4
 +
|NbICAOIdents
 +
|3
 +
|-
 +
|77C6
 +
|RegionListOffset
 +
|0x002A
 +
|-
 +
|77CA
 +
|CountryListOffset
 +
|0x002F
 +
|-
 +
|77CE
 +
|StateListOffset
 +
|0x0038
 +
|-
 +
|77D2
 +
|CityListOffset
 +
|0x003D
 +
|-
 +
|77D6
 +
|AirportListOffset
 +
|0x0070
 +
|-
 +
|77DA
 +
|ICAOListOffset
 +
|0x00AA
 +
|}
 +
 
 +
Let's focus on the '''cities'''. There are 3 cities defined (at per offset 0x77C0). So the cities list start at offset 0x77B4 + 0x3D = 0x77F1.<br/>
 +
At offset 0x77F1, we find 3 DWORDs (one for each city).
 +
{| class="wikitable"
 +
|-
 +
| Offset
 +
| Field
 +
| Value
 +
|-
 +
| 77F1
 +
| Offset #0
 +
| 7: the first name if at offset 7 in the buffer that follow at offset 0x77FD
 +
|-
 +
| 77F5
 +
| Offset #1
 +
| 0: the second name if at offset 0 in the buffer that follow at offset 0x77FD
 +
|-
 +
| 77F9
 +
| Offset #2
 +
| 14: the second third if at offset 14 in the buffer that follow at offset 0x77FD
 +
|}
 +
 
 +
Then follows a buffer of 38 (0x26) bytes containing the names of the cities (since the AirportList starts at 0x77B4 + 0x70 = 0x7824, we know the the buffer of cities names stops at 0x7823 so it has size of 0x26).
 +
<pre>
 +
4D 61 72 69 65 6C 00 48 61 76 61 6E 61 00 53 61
 +
6E 20 41 6E 74 6F 6E 69 6F 20 44 65 20 4C 6F 73
 +
20 42 61 6E 6F 73
 +
</pre>
 +
The first name starts at offset 7: <pre>48 61 76 61 6E 61 00 : Havana</pre>
 +
The second name starts at offset 0: <pre>4D 61 72 69 65 6C 00 : Mariel</pre>
 +
The third name starts at offset 14: <pre>53 61 6E 20 41 6E 74 6F 6E 69 6F 20 44 65 20 4C 6F 73 20 42 61 6E 6F 73 : San Antonio De Los Banos</pre>
 +
 
 +
Now the '''ICAO'''.<br/>
 +
The ICAO list starts at offset 0x77B4 + 0xAA = 0x785E. There are 3 ICA identifiers, so 3 consecutive records of 20 bytes. Let's look at the first ICAO record:
 +
{| class="wikitable"
 +
|-
 +
| Offset
 +
| Field
 +
| Value
 +
|-
 +
|785E
 +
|RegionNameIndex
 +
|0
 +
|-
 +
|785F
 +
|CountryNameIndex
 +
|0
 +
|-
 +
|7860
 +
|StateNameIndex
 +
|0
 +
|-
 +
|7862
 +
|CityNameIndex
 +
|1 : Index = 1 so that is the 2nd name in the cities names list = Mariel
 +
|-
 +
|7864
 +
|AirportNameIndex
 +
|0
 +
|-
 +
|7866
 +
|ICAOIdent
 +
|E1 0C 9A 02 => MUML
 +
|-
 +
|786A
 +
|Unknown
 +
|???
 +
|-
 +
| 786E
 +
| UpperLeft Longitude of the QMID
 +
| 67 00 => -83.4375
 +
|-
 +
|7870
 +
|UpperLeft Latitude of the QMID
 +
|5F 00 => 23.203125
 +
|}
 +
<br/><br/>
 +
 
 +
= TERRAIN_VECTOR_DB =
 +
This type of subsection contains values to retrieve geographical coordinates and types of vector data, organized as segments.
 +
<br/><br/>
 +
The section does not contain geographical coordinates per se but '''offsets''' to the lower left corner (minimum latitude / longitude) of the covered area (QMID Square). The covered area is also defined in the subsection.<br/>
 +
Not that a vector that stretches over several QMID squares is split in as many sub-vectors.
 +
<br/><br/>
 +
The data is organized in lists of pair values (One pair per geographical coordinate). Each pair can then be used to compute the final geographical coordinates. There are 3 ways to retrieve these lists of pairs.
 +
<br/><br/>
 +
The first value in a pair is longitude-related. The second value is latitude-related.
 +
<br/><br/>
 +
The algorithm to compute the geographical coordinates from a pair is:
 +
<pre>
 +
 
 +
void convertToCoordinates (double longitude_related_Value, double latitude_related_Value)
 +
{
 +
    var deltaLongFactor = (MaxLongitudeDeg - MinLongitudeDeg) / 0x8000;
 +
    var deltaLatFactor = (MaxLatitudeDeg - MinLatitudeDeg) / 0x8000;
 +
 
 +
    var LongitudeDeg = MinLongitudeDeg + (longitude_related_Value * deltaLongFactor);
 +
    var LatitudeDeg = MinLongitudeDeg + (latitude_related_Value * deltaLatFactor);
 +
}
 +
 
 +
</pre>
 +
 
 +
== Subsection Header ==
 +
Each subsection starts with the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|-
 +
| 0x00
 +
| 4 - DWORD
 +
| 6<br/>This is the identifier for a vector subsection.
 +
|-
 +
| 0x04
 +
| 4 - DWORD
 +
| Defines the QMID square related to this subsection (all vectors are within the square). See [[#Getting QMID from DWORD values| Getting QMID from DWORD values]].
 +
|- valign="top"
 +
| 0x08
 +
| 4 - DWORD
 +
| ADDTOCELLS
 +
When the -ADDTOCELLS flag is used with the Shp2Vec tool, this value is 1, otherwise 0
 +
|- valign="top"
 +
| 0x0C
 +
| 4 - DWORD
 +
| Number of entities.<br/>An entity is a list of segments. (a segment is a list of points).
 +
|-
 +
|- valign="top"
 +
| 0x10
 +
| 4 - DWORD
 +
| Number of bytes in the attributes buffer.<br/>The attributes buffer contains some GUIDs identifying the segments of this subsection.
 +
Some GUID values (like the Texture) are not used by the TmfViewer application.
 +
It also contains some extra bytes needed by some attributes (for example, 2 FLOAT32 values - SlopeX and SlopeY - are needed for WaterPolys).<br/>The GUID values are defined at [http://msdn.microsoft.com/en-us/library/cc707102.aspx#TheShp2VecTool Terrain And Scenery]
 +
<br/>(See Vector Attributes for the Shp2Vec Tool)
 +
<br/>The usable primary GUID values are:
 +
<pre>
 +
{359C73E8-06BE-4FB2-ABCB-EC942F7761D0} Airport Bounds
 +
{91CB4A9B-9398-48E6-81DA-70AEA3295914} Parks
 +
{EA0C44F7-01DE-4D10-97EB-FB5510EB7B72} Water Polygons (GPS)
 +
{956A42AD-EC8A-41BE-B7CB-C68B5FF1727E} Water Polygons
 +
{AC39CDCB-DB78-4628-9A7C-051DA7AC864A} Exclusions
 +
{0CBC8FAD-DF73-40A1-AD2B-FE62F8004F6F} Shorelines
 +
{714BF912-F9DF-467E-80AE-28EB27374DBD} Streams
 +
{C7ACE4AE-871D-4938-8BDC-BB29C4BBF4E3} Utilities
 +
{33239EB4-D2B8-46F5-98AB-47B3D0922E2A} Railways
 +
{560FA8E6-723D-407D-B730-AE08039102A5} Roads
 +
{54B91ED8-BC02-41B7-8C3B-2B8449FF85EC} Freeway Traffic Roads
 +
{1B6A15BB-05FB-4401-A8D1-BB520E84904C} Water Polygons Slope
 +
</pre>
 +
|-
 +
| 0x14
 +
| 4 - DWORD
 +
| Number of attribute offsets used in that subsection.
 +
|-
 +
| 0x18
 +
| 4 - DWORD
 +
| Number of points used in that subsection.
 +
|-
 +
| 0x1C
 +
| 4 - DWORD
 +
| Number of points, in that subsection, that have a different altitude value than the altitude of their siblings in the same segment.
 +
|- valign="top"
 +
| 0x20
 +
| N
 +
| Attributes buffer containing <N> bytes, where N is defined at relative offset 0x10.
 +
The attributes buffer contains the primary GUIDs identifying the type of vectors (Roads, RailWays, Streams,...) used in the QMID square related to this subsection, as well as secondary GUIDS (Type of park for example).<br/>
 +
The GUIDs are those defined in the XML file used by the [http://msdn.microsoft.com/en-us/library/cc707102.aspx#TheShp2VecTool Shp2Vec tool].
 +
The buffer is organized as this:
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Description
 +
! Number of bytes
 +
|-
 +
| Vector Type 1 GUID
 +
| 16 - GUID
 +
|-
 +
| Nb Additional bytes (ADD) for Type 1
 +
| 4 - DWORD
 +
|-
 +
| colspan="2" style="background: #F5F6CE; text-align: center;" |'' if additional bytes > 0''
 +
|- valign="top"
 +
| style="background: #F5F6CE" | Additional Data<br/>
 +
For Type Texture, the additional data is usually a GUID (ADD=16) and is one of the values defined at [http://msdn.microsoft.com/en-us/library/cc526968.aspx Vector Shape Properties GUIDs]
 +
| style="background: #F5F6CE" | ADD
 +
|-
 +
| Vector Type 2 GUID
 +
| 16 - GUID
 +
|-
 +
| Nb Additional bytes (ADD) for Type 2
 +
| 4 - DWORD
 +
|-
 +
| ...
 +
 
 +
|}
 +
 
 +
|}
 +
 
 +
=== Attributes Buffer Example ===
 +
This example is taken from the file (...)\Microsoft Flight Simulator X\Scenery\0301\scenery\cvx2815.bgl
 +
At offset 0x565, we have 160 bytes:
 +
<pre>
 +
86 7D B0 CE 05 36 BE 44 B4 8A 97 F8 D0 1B 74 DE 
 +
08 00 00 00 00 00 00 00 00 00 00 00 AD 8F BC 0C 
 +
73 DF A1 40 AD 2B FE 62 F8 00 4F 6F 00 00 00 00 
 +
AD 42 6A 95 8A EC BE 41 B7 CB C6 8B 5F F1 72 7E 
 +
00 00 00 00 F7 44 0C EA DE 01 10 4D 97 EB FB 55 
 +
10 EB 7B 72 00 00 00 00 BB 15 6A 1B FB 05 01 44 
 +
A8 D1 BB 52 0E 84 90 4C 10 00 00 00 82 C1 D5 BC 
 +
8B 9C 57 4C 97 BD 27 2C F4 92 CB FF BB 15 6A 1B 
 +
FB 05 01 44 A8 D1 BB 52 0E 84 90 4C 10 00 00 00 
 +
D8 29 32 7B ED 18 4D 4F AE 22 12 66 08 62 AB A1 
 +
</pre>
 +
that can be interpreted as :<br/>
 +
At offset 0<br/>
 +
86 7D B0 CE 05 36 BE 44 B4 8A 97 F8 D0 1B 74 DE : GUID for Water Polygons Slope {CEB07D86-3605-44BE-B48A-97F8D01B74DE}<br/>
 +
08 00 00 00 : 8 bytes of additionnal data (for slopeX and slopeY)<br/>
 +
00 00 00 00 : slopeX = 0 <br/>
 +
00 00 00 00 : slopeY = 0 <br/>
 +
At offset 0x1C:<br/>
 +
AD 8F BC 0C 73 DF A1 40 AD 2B FE 62 F8 00 4F 6F : GUID for Shorelines {0CBC8FAD-DF73-40A1-AD2B-FE62F8004F6F}<br/>
 +
00 00 00 00 : No additional data<br/>
 +
At offset 0x30:<br/>
 +
AD 42 6A 95 8A EC BE 41 B7 CB C6 8B 5F F1 72 7E : GUID for Water Polygons {956A42AD-EC8A-41BE-B7CB-C68B5FF1727E}<br/>
 +
00 00 00 00 : No additional data<br/>
 +
At offset 0x44:<br/>
 +
F7 44 0C EA DE 01 10 4D 97 EB FB 55 10 EB 7B 72 : GUID for Water Polygons - GPS {EA0C44F7-01DE-4D10-97EB-FB5510EB7B72}<br/>
 +
00 00 00 00 : No additional data<br/>
 +
At offset 0x58:<br/>
 +
BB 15 6A 1B FB 05 01 44 A8 D1 BB 52 0E 84 90 4C : GUID Texture {1B6A15BB-05FB-4401-A8D1-BB520E84904C}<br/>
 +
10 00 00 00 : 16 bytes of additional data <br/>
 +
82 C1 D5 BC 8B 9C 57 4C 97 BD 27 2C F4 92 CB FF : GUID for Hydro_Polygons_Generic_Lake_Perennial {BCD5C182-9C8B-4C57-97BD-272CF492CBFF}<br/>
 +
At offset 0x7C:<br/>
 +
BB 15 6A 1B FB 05 01 44 A8 D1 BB 52 0E 84 90 4C : GUID Texture {1B6A15BB-05FB-4401-A8D1-BB520E84904C}<br/>
 +
10 00 00 00 : 16 bytes of additional data <br/>
 +
D8 29 32 7B ED 18 4D 4F AE 22 12 66 08 62 AB A1 : GUID for Shorelines_Generic_Lake {7B3229D8-18ED-4F4D-AE22-12660862ABA1}<br/>
 +
<br/><br/>
 +
 
 +
== Entity Structure ==
 +
Then for each entity (the number of entities is defined at relative offset 0x0C of the subsection header (see [[#Subsection Header|Subsection Header]] above), we have the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|-
 +
| 0x00
 +
| 4 - DWORD
 +
| Number of segments in the entity.
 +
|-
 +
| 0x04
 +
| 4 - DWORD
 +
| Segment type:
 +
* 1 – Points only
 +
* 2 – Lines
 +
* 3 - Polygons
 +
|-
 +
| 0x08
 +
| 2 - WORD
 +
| Number of signatures offsets (Must be < 0x64).
 +
|- valign="top"
 +
| 0x0A
 +
| 4 * N - DWORD[N]
 +
| N = Number of signatures offsets (see above).<br/>Will contain the offsets into the signature buffer.
 +
For example, 2 signatures offsets may be defined here: one for a park and the second for the texture used for this park.
 +
|}
  
== private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm ==
+
== Segment Structure ==
 +
Then for each segment (the number of segments is defined at relative offset 0x00 of the entity structure (see [[#Entity Structure|Entity Structure]] above), we have the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|-
 +
| 0x00
 +
| 4 - DWORD
 +
| Number of points (geographical coordinates) in this segment.
 +
|- valign="top"
 +
| 0x04
 +
| 1 - BYTE
 +
| Altitude Information Flag
 +
* 0 – No altitude information
 +
* 1 – The points have different altitudes
 +
* 2 – All points have the same altitude
 +
If 1 or 2 there will be additional bytes after the data buffer.
 +
|-
 +
|- valign="top"
 +
| 0x05
 +
| 1 - BYTE
 +
| Method used to build the pairs list from the data buffer.<br/>Possible values are 1,2 or 3
 +
* 1 – Method1
 +
* 2 – Method2
 +
* 3 – Method3 
 +
<br/>Note: I did not find a cvx file with a value of 3 but it looks like Method3 read the pairs list directly from the data buffer without any extra processing.
 +
<br/>Methods 1 and 2 need some extra processing. See below.
 +
|-
 +
|- valign="top"
 +
| 0x06
 +
|
 +
| Data buffer – Size may vary depending on the method used. See below.
 +
|-
 +
|- valign="top"
 +
| -
 +
| 4 x N - FLOAT[N]
 +
| N depends on the Altitude Information Flag defined at relative offset 0x04.
 +
* If 0 then N = 0 (no bytes)
 +
* If 1 then N = NumberOfPoints (as defined at relative offset 0x00). Each FLOAT is the altitude (in meters) of the corresponding point.
 +
* If 2 then N = 1 then this is the altitude (in meters) common to all points.
  
Offers private label cosmetics with custom design. We produce lip balms, serum, creams and more. Easy to buy with eshop. Private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm
+
|}
 +
[[File:Cvx_SectionStructure.png]]
 +
=== Method 1 ===
 +
By far the most complex method. I have some code for it. But I still have to figure out the big picture.
 +
<br/><br/>The data buffer for this method has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative offset
 +
! Number of bytes
 +
! Description
 +
|-
 +
| 0x00
 +
| 4 - DWORD
 +
| First Longitude Data - First value in the list of pairs.
 +
|-
 +
| 0x04
 +
| 4 - DWORD
 +
| First Latitude Data - First value in the list of pairs.
 +
|-
 +
| 0x08
 +
| 4 - DWORD
 +
| LongitudeData Increment
 +
|-
 +
| 0x0C
 +
| 4 - DWORD
 +
| LatitudeData Increment
 +
|-
 +
| 0x10
 +
| 4 - DWORD
 +
| Number of bytes
 +
|-
 +
| 0x14
 +
| N
 +
| N is the number of bytes defined above at relative offset 0x10.<br/>These N bytes are the raw data used to build the final list of pairs.
 +
|}
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
=== Method 2 ===
 +
The data buffer for this method has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative offset
 +
! Number of bytes
 +
! Description
 +
|-
 +
| 0x00
 +
| 1 - BYTE
 +
| Root Mask
 +
|-
 +
|- valign="top"
 +
| 0x01
 +
| N
 +
| N is computed using the value of the Root Mask.<br/>N = (RootMask * NbPoints * 2 + 7) >> 3<br/>where
 +
* ''RootMask'' is defined at relative offset 0x00 of this structure.
 +
* ''NbPoints'' is the number of points as defined at relative offset 0x00 of the Segment Structure.
 +
<br/>These N bytes are the raw data used to build the final list of pairs.
 +
|}
 +
==== Algorithm ====
 +
The algorithm used by Method2 to build the list of pairs is:
 +
<pre>
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
/*
 +
Fills an array listOfValues of DWORD
 +
*/
  
== private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm ==
+
PositionInPair = 0;  /* 0 = first value in pair, 1 = second value in pair */
 +
PairIndex = 0 ;
 +
ShiftValue = 0 ;
 +
NbBytesLeftToRead = ((rootMask * nbPoints) * 2 + 7) >> 3;
 +
Mask = 1 << rootMask ;    /* 2 ^ rootMask */
  
Offers private label cosmetics with custom design. We produce lip balms, serum, creams and more. Easy to buy with eshop. Private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm
+
/* Read first value */
 +
if (NbBytesLeftToRead > 3)
 +
{
 +
    valueFromFile = read (4 bytes)
 +
    NbBytesLeftToRead -= 4 ;
 +
}
 +
else
 +
{
 +
    valueFromFile = read (NbBytesLeftToRead bytes)
 +
    NbBytesLeftToRead = 0 ;
 +
}
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
while (PairIndex < nbPoints)
 +
{
 +
    if (ShiftValue < 0)
 +
    {
 +
        /* Shift Left */
 +
        result = (uint)((valueFromFile << (-ShiftValue)) & Mask);
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
        /* Add to existing pair value */
 +
        result += listOfValues[PairIndex * 2 + PositionInPair];       
  
== private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm ==
+
        listOfValues[PairIndex * 2 + PositionInPair] = result;
 +
    }
 +
    else
 +
    {
 +
        /* Shift Right */
 +
        result = (uint)((valueFromFile >> ShiftValue) & Mask);
 +
        listOfValues[PairIndex * 2 + PositionInPair] = result;
 +
    }
  
Offers private label cosmetics with custom design. We produce lip balms, serum, creams and more. Easy to buy with eshop. Private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm
+
    if (rootMask + ShiftValue >= 32)
 +
    {
 +
        if (NbBytesLeftToRead > 3)
 +
        {
 +
            valueFromFile = read (4 bytes)
 +
            NbBytesLeftToRead -= 4 ;
 +
        }
 +
        else
 +
        {
 +
            valueFromFile = read (NbBytesLeftToRead bytes)
 +
            NbBytesLeftToRead = 0 ;
 +
        }
 +
        ShiftValue -= 32;    /* now negative */
 +
    }
 +
    else
 +
    {
 +
        /* continue processing value from file */
 +
        ShiftValue += rootMask;
 +
        PositionInPair++;
 +
    }
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
    if (PositionInPair == 2)
 +
    {
 +
        PairIndex++;    /* Next entry in the list of pair values */
 +
        PositionInPair = 0;
 +
    }
 +
}
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
</pre>
  
== private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm ==
+
=== Example ===
 +
Still with the same example as in Subsections, we know that the first subsection data starts at offset 0x4C (as described in the first subsection starting  at offset 0x1FCD01) . So at this file offset, we have the subsection header of the first subsection data.
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Value
 +
! Description
 +
|-
 +
| 0x4C
 +
| <pre>06 00 00 00</pre>
 +
| 6
 +
|-
 +
| 0x50
 +
| <pre>00 FA 81 00</pre>
 +
| Bounding coordinates:
 +
* MinLatitude(Deg) = 47.63671875
 +
* MaxLatitude(Deg) = 47.8125
 +
* MinLongitude(Deg) =- 75.0
 +
* MaxLongitude(Deg) = -74.765625
 +
QMID (u=448, v=240, l=11) , using 0x0081FA00 as A and 0 as B in [[#Getting QMID from DWORD values| this algorithm]].
 +
|-
 +
| 0x54
 +
| <pre>00 00 00 00</pre>
 +
| 0 => AddToCells = False
 +
|-
 +
| 0x58
 +
| <pre>03 00 00 00</pre>
 +
| Number of entities = 3
 +
|-
 +
| 0x5C
 +
| <pre>14 00 00 00</pre>
 +
| Number of bytes in the signatures buffer = 20
 +
|-
 +
| 0x60
 +
| <pre>03 00 00 00</pre>
 +
| Number of attribute offsets used in that subsection = 3
 +
|-
 +
| 0x64
 +
| <pre>1C 00 00 00</pre>
 +
| Number of pair values in that subsection = 28
 +
|-
 +
| 0x68
 +
| <pre>00 00 00 00</pre>
 +
| 0
 +
|-
 +
| 0x6C
 +
|
 +
| Signatures buffer containing 20 bytes.<pre>F7 44 0C EA DE 01 10 4D 97 EB FB 55 10 EB 7B 72 00 00 00 00</pre>
 +
That is GUID {EA0C44F7-01DE-4D10-97EB-FB5510EB7B72} = Water Polygons (GPS), followed by 4 zeroes.
 +
|}
 +
Then follows 3 entities.<br/>The first entity (at offset 0x80 of the file) is
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Value
 +
! Description
 +
|-
 +
| 0x80
 +
| <pre>01 00 00 00</pre>
 +
| Number of segments in the entity = 1
 +
|-
 +
| 0x84
 +
| <pre>03 00 00 00</pre>
 +
| Segment type = 3  - Polygons
 +
|-
 +
| 0x88
 +
| <pre>01 00</pre>
 +
| Number of signatures offsets = 1
 +
|-
 +
| 0x8A
 +
| <pre>00 00 00 00</pre>
 +
| Signatures offset = 0: points to the only one GUID
 +
|}
 +
This entity is followed by only one segment, at offset 0x8E of the file
 +
{| class="wikitable"
 +
|-
 +
! Offset
 +
! Value
 +
! Description
 +
|-
 +
| 0x8E
 +
| <pre>0E 00 00 00</pre>
 +
| Number of points = 14
 +
|-
 +
| 0x92
 +
| <pre>00</pre>
 +
| 0 => No Altitude information
 +
|-
 +
| 0x93
 +
| <pre>02</pre>
 +
| 2 – Method2
 +
|-
 +
| 0x94
 +
| <pre>0F</pre>
 +
| Root Mask = 0x0F<br/>So N = (15 * 14* 2 + 7) >> 3 = 53<br/>53 bytes to follow.
 +
|-
 +
| 0x95
 +
|
 +
| 53 bytes:<pre>
 +
84 3E 56 37
 +
65 10 74 1D
 +
3C 44 5B 9F
 +
11 C5 D0 05
 +
C9 2C F3 D5
 +
B2 3A 8D 8A
 +
8D 9D 9B 67
 +
8B ED 52 59
 +
B3 BC 0B 36
 +
35 5F 54 25
 +
B5 33 30 6D
 +
E2 64 4B EB
 +
36 A1 8F D5
 +
0D</pre>
 +
|}
 +
 
 +
The next entity starts at file offset 0xCA.
 +
<br/><br/>So the algorithm for method 2 goes like this:
 +
<pre>
 +
Mask = 0x7FFF ;
 +
 
 +
NbBytesLeftToRead = 53 ; shiftValue = 0; PairIndex = 0 ; PositionInPair = 0
 +
  valueFromFile = read (4 bytes) = 0x37563E84
 +
  result = (valueFromFile >> shiftValue) & mask = 0x3E84
 +
  listOfValues[0] = 0x3E84
 +
 
 +
NbBytesLeftToRead = 49 ; shiftValue = 0x0F; PairIndex = 0 ; PositionInPair = 1
 +
  result = (valueFromFile >> shiftValue) & mask = 0x6EAC
 +
  listOfValues[1] = 0x6EAC
  
Offers private label cosmetics with custom design. We produce lip balms, serum, creams and more. Easy to buy with eshop. Private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm
+
NbBytesLeftToRead = 49 ; shiftValue = 0x1E; PairIndex = 1 ; PositionInPair = 0
 +
  result = (valueFromFile >> shiftValue) & mask = 0x000
 +
  listOfValues[2] = 0x0000
 +
  rootMask + shiftValue = 0x2D > 0x20 so
 +
valueFromFile = read (4 bytes) = 0x1D741065
 +
shiftValue = 0xFFFFFFFE
 +
 +
NbBytesLeftToRead = 45 ; shiftValue = 0xFFFFFFFE; PairIndex = 1 ; PositionInPair = 0
 +
  result = (valueFromFile << (-shiftValue)) & mask = 0x4194
 +
  result += listOfValues[2] = 0x4194 + 0x0000 = 0x4194
 +
  listOfValues[2] = 0x4194
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
NbBytesLeftToRead = 45 ; shiftValue = 0x0D; PairIndex = 1 ; PositionInPair = 1
 +
  result = (valueFromFile >> shiftValue) & mask = 0x6BA0
 +
  listOfValues[3] = 0x6BA0
  
[[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
NbBytesLeftToRead = 45 ; shiftValue = 0x1C; PairIndex = 2 ; PositionInPair = 0
 +
  result = (valueFromFile >> shiftValue) & mask = 0x0001
 +
  listOfValues[4] = 0x0001
 +
  rootMask + shiftValue = 0x2BD > 0x20 so
 +
valueFromFile = read (4 bytes) = 0x9F5B443C
 +
shiftValue = 0xFFFFFFFC
  
== private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm ==
+
NbBytesLeftToRead = 41 ; shiftValue = 0xFFFFFFFC; PairIndex = 2 ; PositionInPair = 0
 +
  result = (valueFromFile << (-shiftValue)) & mask = 0x43C0
 +
  result += listOfValues[4] = 0x0x43C0 + 0x0001 = 0x43C1
 +
  listOfValues[4] = 0x43C1
  
Offers private label cosmetics with custom design. We produce lip balms, serum, creams and more. Easy to buy with eshop. Private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm
+
etc
 +
</pre>
 +
Once the 53 bytes have been processed, the list contains the following 28 values, making up a list of 14 pairs.
 +
<pre>
 +
3E84
 +
6EAC
 +
4194
 +
6BA0
 +
43C1
 +
6B68
 +
4467
 +
6862
 +
4905
 +
6659
 +
4B57
 +
69D5
 +
58A8
 +
73B1
 +
59E6
 +
76C5
 +
5952
 +
7966
 +
582E
 +
79A9
 +
5545
 +
76A4
 +
4C0C
 +
7136
 +
4B64
 +
6DD6
 +
3E84
 +
6EAC
 +
</pre>
 +
To get the coordinates of the first point, we take the first pair {0x3E84, 0x6EAC} and use the convertToCoordinates method described at [[#TERRAIN_VECTOR_DB|Terrain_Vector_DB]].
 +
<br/>The first value in the pair is longitude-related. The second value in the pair is latitude-related.
 +
<pre>
  
  [[http://ultra-high-end.com/custom-made.html private label cosmetics, custom made cosmetic, custom made cream, custom lip stick lip balm]]
+
double deltaLongFactor = ((-74.765625) - (- 75.0)) / 0x8000; // = 0.000007152557373046875
 +
double deltaLatFactor  = (47.8125 - 47.63671875) / 0x8000;    // = 0.0000053644180297851563
 +
 
 +
double LongitudeDeg = (- 75.0) + (0x3E84 * deltaLongFactor);    // = -74.885530471801758
 +
double LatitudeDeg = 47.63671875 + (0x6EAC * deltaLatFactor);  // = 47.788703441619873
 +
 
 +
</pre>
 +
 
 +
= TERRAIN SECTIONS =
 +
 
 +
The following sections share the same structure:
 +
* TerrainElevation
 +
* TerrainLandClass
 +
* TerrainWaterClass
 +
* TerrainRegion
 +
* PopulationDensity
 +
* TerrainIndex
 +
* TerrainSeasonXXX
 +
* TerrainPhotoXXX
 +
* TerrainPhotoXXX
 +
 
 +
 
 +
 
 +
The number of subsections depends on the size of the scenery area. For higher levels of details, chances are that the area will overlap across multiple QMID squares. However, there will be at least a level for which the entire scenery area is contained inside the QMID square.<br/>
 +
So there will be a subsection for each level for which the entire scenery area is contained inside the corresponding QMID square.<br/>
 +
<br/>
 +
For example, let's say that your photo scenery has the following coordinates:<br/>
 +
North-West corner : Longitude = -73.388000, Latitude = 45.511400<br/>
 +
Sout-East corner : Longitude = -73.373019, Latitude = 45.498672<br/>
 +
<br/>
 +
At QMID level 14, the image overlaps across QMID (luv) = (14, 3639, 2024) and QMID(luv) = (14,3629, 2025). <br/>
 +
However, at level 13, the image is entirely contained within QMID(luv) = (13,1819, 1012)<br/>
 +
So there will be 14 subsections, the first one defining the level 0 and the last one defining the level 13.<br/>
 +
 
 +
<span style="color:red">
 +
'''While the relation between the QMID Level and the rank of the subsection may be true for BGL files generated by the resample tool, it appears that this is wrong with other native BGL files such as the worldlc.bgl or other files located in the BASE folder.'''</span>
 +
 
 +
== SubSection with TRQ1 Records ==
 +
<br/>The number of subsections for a Terrain section is defined in the parent section.<br/>
 +
A subsection has a size of 16 (0x10) bytes and has the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| 8 - DWORD[2]
 +
| These 2 values are derived from the u,v,l values of the QMID containing the whole scenery for this specific level.
 +
To retrieve the corresponding QMID values, see the [[#Getting QMID from DWORD values|algorithm]] in Annexe.
 +
|-
 +
| 0x08
 +
| 4 - DWORD
 +
| File Offset = Position in the file of the subsection’s data
 +
|-
 +
| 0x0C
 +
| 4 - DWORD
 +
| Size of the subsection’s data
 +
|}
 +
=== TRQ1 Record ===
 +
The TRQ1 Record is a fixed-size header that contains information about each RasterDataLayer "Chunk" in a BGL file. Raster chunks are 2-Dimensional bitmaps of rasterized data containing 16-bit unsigned integer (32-bit for MS Flight) data points broken down into 256X256 pixel squares. The data can represent many different terrain elements including landclass, elevation, and raw aerial imagery data.
 +
 
 +
At the file offset specified at relative offset 0x08 of the subsection above, we find a TRQ1 record, followed by 1 or 2 other records.
 +
 
 +
The TRQ1 record has a size of 40 (0x28) bytes for the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| 4 - DWORD
 +
| Signature = 0x31515254 = 'TRQ1'
 +
|- valign="top"
 +
| 0x04
 +
| 4 - DWORD
 +
| Size of this record = 0x28
 +
|- valign="top"
 +
| 0x08
 +
| 2 - WORD
 +
| Identifier of the parent section
 +
*1: TERRAIN_PHOTO_XXX
 +
*2: TERRAIN ELEVATION
 +
*3: TERRAIN_LAND_CLASS
 +
*4: TERRAIN_WATER_CLASS
 +
*5: TERRAIN_REGION
 +
*6: TERRAIN_SEASON_XXX
 +
*7: POPULATION_DENSITY
 +
*8: N/A
 +
*9: TERRAIN_INDEX
 +
|- valign="top"
 +
| 0x0A
 +
| 1 - BYTE
 +
| Compression Type of 1st Section following this record
 +
(Note that only a subset of these appear to be used by the resampler)
 +
*0x0: Not_Compressed
 +
*0x1: LZ1_Compressed
 +
*0x2: Delta_Compressed
 +
*0x3: Delta_And_LZ1_Compressed
 +
*0x4: LZ2_Compressed
 +
*0x5: Delta_And_LZ2_Compressed
 +
*0x6: BitPack_Compressed
 +
*0x7: BitPack_And_LZ1
 +
*0x8: Solid_Block
 +
*0x9: BitPack_And_LZ2
 +
*0xA: PTC
 +
*0xB: DXT1
 +
*0xC: DXT3
 +
*0xD: DXT5
 +
|- valign="top"
 +
| 0x0B
 +
| 1 - BYTE
 +
| Compression Type of 2nd Section following this record (same as above)
 +
|- valign="top"
 +
| 0x0C
 +
| 4 - DWORD[2]
 +
| Same 2 DWORDS as the ones defined at offset 0 of the subsection above.
 +
|- valign="top"
 +
| 0x14
 +
| 4 - DWORD
 +
| Month Mask for TERRAIN_PHOTO and TERRAIN_SEASON (0x0000 otherwise)
 +
*JAN: 0x0001
 +
*FEB: 0x0002
 +
*MAR: 0x0004
 +
*APR: 0x0008
 +
*MAY: 0x0010
 +
*JUN: 0x0020
 +
*JUL: 0x0040
 +
*AUG: 0x0080
 +
*SEP: 0x0100
 +
*OCT: 0x0200
 +
*NOV: 0x0400
 +
*DEC: 0x0800
 +
|- valign="top"
 +
| 0x18
 +
| 4 - DWORD
 +
| NROWS - Number of raster rows present in chunk (including whitespace)
 +
|- valign="top"
 +
| 0x1C
 +
| 4 - DWORD
 +
| NCOLS - Number of raster columns present in chunk (including whitespace)
 +
|- valign="top"
 +
| 0x20
 +
| 4 - DWORD
 +
| Size of 1st data chunk that follows this record
 +
|- valign="top"
 +
| 0x24
 +
| 4 - DWORD
 +
| Size of 2nd data chunk following this record (that follows the 1st record if size > 0)
 +
Not Present for TERRAIN_INDEX sections
 +
Note: this section is automatically added by resample after relevant raster sections,
 +
does not count toward total block count displayed in the resample statistics, and seems
 +
to always be relatively short such as TERRAIN_INDEX sections. It appears to always
 +
be compressed with BitPack + LZ1.
 +
|}
 +
 
 +
 
 +
The content of the 2 records that follows is still to be determined based off of each applicable compression scheme. Work is underway to decompress each type.
 +
<br/><br/>
 +
 
 +
=== RCS1 Record ===
 +
The RCS1 Record is a fixed-size header that contains information about terrain scaling for any section of type TERRAIN_ELEVATION.
 +
 
 +
Terrain scaling is used to convert the integer terrain values in the BGL data to the floating point values used in the terrain triangulation engine. These values correspond directly to the Fraction Bits settings in the resampler, and is always present with default values if these settings are not specified.
 +
 
 +
It is not a true subsection in that it does not have a child section, it is merely a data section that is prepended to the compressed chunk.
 +
 
 +
The RCS1 record has a size of 12 (0xC) bytes for the following structure:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| 4 - DWORD
 +
| Signature = 0x31435352= 'RCS1'
 +
|-
 +
| 0x04
 +
| 4 - FLOAT
 +
| Scale Value = The scaling multiplier for the integer terrain value (Default: 1.0f)
 +
This number is halved for each fractional bit required (FractionBits=1: Scale = 0.5f, FractionBits=2: Scale=0.25)
 +
|-
 +
| 0x08
 +
| 4 - DWORD
 +
| Base Value = The base offset to be added to the scaled value (Default: 0)
 +
|}
 +
 
 +
Thus, the actual terrain value = (Decompressed integer value * Scale) + Base. When default values are used,
 +
the input is simply converted to a floating point number and not modified.
 +
 
 +
For more information on Fractional Values please see the Scaled Elevation Values section in the Terrain and Scenery SDK document.
 +
 
 +
=== Delta Compressed Segment ===
 +
Adaptive delta compression is the simplest of the decompression techniques. It simply looks for one of several sentinel values, and the following bytes are read as deltas from the last value, until another sentinel value is seen.
 +
 
 +
An implementation of this algorithm is given below:
 +
 
 +
<nowiki>
 +
    int DecompressDelta(byte destination[], unsigned int destinationLength, byte source[])
 +
    {
 +
          short previous;
 +
          byte *destPointer;
 +
          int count;
 +
         
 +
          if (destinationLength & 1)
 +
          {
 +
              *((char *)destination) = *((char *)source);
 +
              source += 1;
 +
              destination += 1;
 +
              destinationLength -= 1;
 +
          }
 +
          if (destinationLength != 1)
 +
          {
 +
              previous = *(short *)source;
 +
              *(short *)destination = *(short *)source;
 +
              source += 2;
 +
              destPointer = destination + 2;
 +
              count = (destinationLength >> 1) - 1;
 +
 
 +
              if (count)
 +
              {
 +
                    while (1)
 +
                    {
 +
                        if (*(byte *)source == 0x80)
 +
                        {
 +
                              *(short *)destPointer = *(short *)(source + 1);
 +
                              source += 3;
 +
                        }
 +
                        else if (*(byte *)source == 0x81)
 +
                        {
 +
                              *(short *)destPointer = previous - *(byte *)(source + 1) - 126;
 +
                              source += 2;
 +
                        }
 +
                        else if (*(byte *)source == 0x82)
 +
                        {
 +
                              *(short *)destPointer = previous + *(byte *)(source + 1) + 128;
 +
                              source += 2;
 +
                        }
 +
                        else
 +
                        {
 +
                              *(short *)destPointer = previous + *(char*)source;
 +
                              source += 1;
 +
                        }
 +
                        previous = *(short *)destPointer;
 +
                        destPointer += 2;
 +
                        --count;
 +
                        if (!count)
 +
                              return 1;
 +
                    }
 +
              }
 +
          }
 +
          return 1;
 +
    }
 +
</nowiki>
 +
 
 +
= INDEXES =
 +
The section VorIlsIcaoIndex (0x28), NdbIcaoIndex (0x29) and WayPointIcaoindex (0x2A) all share the same structure of 12 bytes:
 +
{| class="wikitable"
 +
|-
 +
! Relative Offset
 +
! Number of bytes
 +
! Description
 +
|- valign="top"
 +
| 0x00
 +
| 4 - DWORD
 +
| ICAO Identification ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x04
 +
| 4 - DWORD
 +
| Region and Airport Identification
 +
Bits 0-10 : Region ([[#ICAO Identifiers and region codes|Special Format]])<br/>
 +
Bits 11-31 : Airport ICA ([[#ICAO Identifiers and region codes|Special Format]])
 +
|- valign="top"
 +
| 0x08
 +
| 2 - WORD
 +
| QMID U Value (Level 9)
 +
|- valign="top"
 +
| 0x0C
 +
| 2 - WORD
 +
| QMID V value (Level 9)
 +
|}
 +
 
 +
= Annexe A =
 +
== Computing the bounding coordinates from a DWORD value ==
 +
 
 +
<pre>
 +
 
 +
public static List<double> GetBoundingCoordinates(uint boundingValue)
 +
{
 +
    var list = new List<double>();
 +
    var shiftValue = 15;
 +
    var work = boundingValue;
 +
    var latitudeData = (uint)0;
 +
    var longitudeData = (uint)0;
 +
 
 +
    while (work < 0x80000000 && shiftValue >= 0)
 +
    {
 +
        shiftValue--;
 +
        work *= 4;
 +
    }
 +
    work &= 0x7FFFFFFF;    // Remove negative flag, if any
 +
    var powerOfTwo = shiftValue;
 +
 
 +
    while (shiftValue >= 0)
 +
    {
 +
        if (work >= 0x80000000)
 +
        {
 +
            latitudeData += (uint)(1 << shiftValue);
 +
        }
 +
 
 +
        if ((work & 0x40000000) != 0)
 +
        {
 +
            longitudeData += (uint)(1 << shiftValue);
 +
        }
 +
        work *= 4;
 +
        shiftValue--;
 +
    }
 +
 
 +
    // factor = 1.0 / (2^i)
 +
    var factor = 1.0 / (1 << powerOfTwo);
 +
 
 +
    // Calc bounding coordinates
 +
    var minLatitudeDeg = 90.0 - ((latitudeData + 1.0) * factor * 360.0);
 +
    var maxLatitudeDeg = 90.0 - (latitudeData * factor * 360.0);
 +
    var minLongitude = (longitudeData * factor * 480.0) - 180.0;
 +
    var maxLongitude = ((longitudeData + 1.0) * factor * 480.0) - 180.0;
 +
   
 +
    list.Add(minLatitudeDeg);
 +
    list.Add(maxLatitudeDeg);
 +
    list.Add(minLongitude);
 +
    list.Add(maxLongitude);
 +
    return list;
 +
}
 +
 
 +
</pre>
 +
 
 +
== Computing Longitude and Latitude from a DWORD value ==
 +
Latitude and longitude are no longer represented as before. Each location on the earth is fixed in
 +
the LOD grid. Longitude and latitude are each represented by a 4 byte value (DWORD). The formula
 +
for obtaining the decimal values is as follows:
 +
<pre>
 +
(double) Lon = ((DWORD) Lon * (360.0 / (3 * 0x10000000))) – 180.0
 +
(double) Lat = 90.0 - (DWORD) Lat * (180.0 / (2 * 0x10000000))
 +
</pre>
 +
 
 +
== Pitch, bank and heading ==
 +
Pitch, bank and heading are given as ANGLE16 in form of a DWORD. The formula for obtaining
 +
the decimal value is as follows:
 +
(double) Pitch = (DWORD) Pitch * 360.0 / 0x10000
 +
<br/>
 +
 
 +
== ICAO Identifiers and region codes ==
 +
ICAO Identifiers and region codes are coded in a special format. Each number and letter has a
 +
value from 0 .. 37:
 +
{| class="wikitable"
 +
|-
 +
| blank
 +
| 00
 +
|-
 +
| Digits 0-9
 +
| 02-11
 +
|-
 +
| Letters A-Z
 +
| 12-37
 +
|}
 +
 
 +
'''Encoding'''
 +
 
 +
The code is calculated by starting from left: the value of the first digit/letter is multiplied by 38 (0x26), then
 +
the value of the next digit/letter to the right is added, the sum s multiplied by 38 (0x26), and as long as
 +
there are more digits/letters this process is repeated.
 +
The region codes have only 2 digits/letters and the result is used as such; for the ICAO identifiers
 +
for airports, ILS, VOR, NDB and waypoints there are up to 5 digits/letters, and the result is shifted
 +
left by 5 positions, i.e. multiplied by 0x20. Bits 0 .. 4 of the resulting DWORD are frequently used
 +
for other purposes.
 +
The ICAO identifiers for primary and secondary ILS in a runway record are not shifted.
 +
 
 +
'''Decoding'''
 +
So you have a DWORD value to be translated in a ICAO string.
 +
If the value comes from an airport identifier, it first has to be shifted 5 bits to the right.
 +
The pseudo-algorithm looks like this
 +
 
 +
<pre>
 +
if (values from airport data)
 +
{
 +
  shift value 5 bits to the right
 +
}
 +
 
 +
while (value > 37)
 +
{
 +
  oneCodedChar = value % 38
 +
  prepend OneCodedChar to the list
 +
  value = (value - oneCodedChar) / 38
 +
  if (value < 38)
 +
  {
 +
      oneCodedChar = value
 +
  }
 +
}
 +
 
 +
// The first coded char in the list is the last one computed in the while loop
 +
 
 +
foreach (oneCodedChar in list)
 +
{
 +
  if (oneCodedChar == 0)
 +
  {
 +
      output space char
 +
  }
 +
  else if (oneCodedChar > 1 && oneCodedChar < 12)
 +
  {
 +
      // digit 0-9
 +
      output '0' + (oneCodedChar - 2)
 +
  }
 +
  else
 +
  {
 +
      // letter
 +
      output 'A' + (oneCodedChar - 12)
 +
  }
 +
}
 +
</pre>
 +
 
 +
Example:<br/>
 +
The value 0x0257C221 comes from an airport record.<br/>
 +
0x0257C221 is first shifted 5 bits to the right , which gives 0x0012BE11 = 1228305<br/>
 +
- 1228305 is >= 38 so 1228305 % 38 = '''31''' and (1228305 - 31)/ 38 = 32323<br/>
 +
- 32323 is >= 38 so 32323 % 38 = '''23''' and (32323 - 23) / 38 = 850<br/>
 +
- 850 >= 38 so 850 % 38 = '''14''' and (850 - 14) / 38 = 22<br/>
 +
- '''22''' is < 38 so that is the last value.<br/>
 +
So we got 31,23,14 and 22<br/>
 +
- 22 is in the range [12 - 37] so letter = 'A' + (22-12) = 'K'<br/>
 +
- 14 is in the range [12 - 37] so letter = 'A' + (14-12) = 'C'<br/>
 +
- 23 is in the range [12 - 37] so letter = 'A' + (14-23) = 'L'<br/>
 +
- 31 is in the range [12 - 37] so letter = 'A' + (31-12) = 'T'<br/>
 +
So the ICAO code is KCLT
 +
 
 +
== Computing QMID u and v based on level and coordinates ==
 +
 
 +
Whenever you move your mouse in the TmfViewer application, the u and v values of the QMID (Quad Mesh IDentifier) are updated in the status bar at the bottom of the screen.
 +
All coordinates (longitude , latitude) inside the same QMID (or square) have the same u and v values for a specific level. The greater the level, the smaller the square.
 +
See [http://msdn.microsoft.com/en-ca/library/cc707102.aspx#QMIDandLODValues Microsoft: Terrain and Scenery].
 +
 
 +
The algorithm to compute the u and v values is the following:
 +
 
 +
<pre>
 +
Input:
 +
- Longitude in degrees
 +
- Latitude in degrees
 +
- Level (QMID Level = LOD + 2) in the range [2..29]
 +
 
 +
LongitudeData = INT(0.5 + (180 + LongitudeDeg) * (0x2000000 / 15))
 +
LatitudeData = INT(0.5 + (90 - LatitudeDeg) * (0x8000000 / 45))
 +
 
 +
If LongitudeData > 0x30000000
 +
LongitudeData -= 0x30000000
 +
If LongitudeData < 0
 +
LongitudeData += 0x30000000
 +
 
 +
If LatitudeData > 0x20000000
 +
LatitudeData -= 0x20000000
 +
If LatitudeData < 0
 +
LatitudeData += 0x20000000
 +
 
 +
n = 30 - QMIDLevel
 +
QMID.u = LongitudeData >> n
 +
QMID.v = LatitudeData >> n
 +
QMID.l = level
 +
 
 +
</pre><br/>
 +
 
 +
== Getting DWORD values from QMID ==
 +
 
 +
 
 +
The algorithm takes the QMID data (u, v and l) as input and produces 2 DWORD values as output.
 +
 
 +
 
 +
The '''u''' (longitude-related), '''v''' (latitude-related) and '''l''' (level) values are handled as DWORD (4 bytes).
 +
 
 +
 
 +
The DWORD value '''u''' is made of 4 bytes: U<sub>3</sub>, U<sub>2</sub>, U<sub>1</sub> and U<sub>0</sub> where U<sub>3</sub> is the most significant byte and U<sub>0</sub> the least significant.<br/>
 +
The DWORD value '''v''' is made of 4 bytes: V<sub>3</sub>, V<sub>2</sub>, V<sub>1</sub> and V<sub>0</sub> where V<sub>3</sub> is the most significant byte and V<sub>0</sub> the least significant.
 +
 
 +
Let's compute U'<sub>3</sub>, U'<sub>2</sub>, U'<sub>1</sub>, U'<sub>0</sub>, V'<sub>3</sub>, V'<sub>2</sub>, V'<sub>1</sub>, V'<sub>0</sub> where:<br/>
 +
* U'<sub>i</sub> = f (U<sub>i</sub>)
 +
* V'<sub>i</sub> = f (V<sub>i</sub>)
 +
 
 +
The fonction f(x) decomposes the input value x (a byte) in base-4:<br/>
 +
x = a<sub>3</sub>.4<sup>3</sup> + a<sub>2</sub>.4<sup>2</sup> + a<sub>1</sub>.4<sup>1</sup> + a<sub>0</sub>.4<sup>0</sup> = a<sub>3</sub>.64 + a<sub>2</sub>.16 + a<sub>1</sub>.4 + a<sub>0</sub>
 +
 
 +
Then for each a<sub>i</sub>, we compute the corresponding b<sub>i</sub>:
 +
* a<sub>i</sub> = 0 &rArr; b<sub>i</sub> = 0
 +
* a<sub>i</sub> = 1 &rArr; b<sub>i</sub> = 1
 +
* a<sub>i</sub> = 2 &rArr; b<sub>i</sub> = 4
 +
* a<sub>i</sub> = 3 &rArr; b<sub>i</sub> = 5
 +
where b<sub>i</sub> are the coefficients of the output value in base-16.
 +
 
 +
The output value y = f(x) is computed as follows:<br/>
 +
y = b<sub>3</sub>.4096 + b<sub>2</sub>.256 + b<sub>1</sub>.16 + b<sub>0</sub>
 +
 
 +
For example, f(0x4B) gives:<br/>
 +
a<sub>3</sub> = 1, a<sub>2</sub> = 0, a<sub>1</sub> = 2, a<sub>0</sub> = 3  (0x4B = 75 = 1 x 64 + 0 x 16 + 2 x 4 + 3)<br/>
 +
So we have b<sub>3</sub> = 1, b<sub>2</sub> = 0, b<sub>1</sub> = 4, b<sub>0</sub> = 5<br/>
 +
and the output value is: 1 x 4096 + 0 x 256 + 4 x 16 + 5  = 4165 = 0x1045
 +
 
 +
We now know how to compute U'<sub>i</sub> and V'<sub>i</sub>.
 +
 
 +
Let's have:<br/>
 +
'''A''' = (2 << (2 * Level)) + 2 * (V'<sub>1</sub> * 65536 + V'<sub>0</sub>) + (U'<sub>1</sub> * 65536 + U'<sub>0</sub>)<br/>
 +
'''B''' = 2 * (V'<sub>3</sub> * 65536 + V'<sub>2</sub>) + (U'<sub>3</sub> * 65536 + U'<sub>2</sub>)
 +
 
 +
where '''A''' and '''B''' are the 2 output DWORD values.<br/>
 +
The value '''A''' goes at offset 0 of the subsection.<br/>
 +
The value '''B''' goes at offset 4 of the subsection.<br/>
 +
 
 +
Note: Because of the <code>(2 << (2 * Level))</code> part and because the A is a DWORD, the maximum QMID level is 15.
 +
 
 +
'''Example'''<br/>
 +
Lets' take our previous example with QMID (13,1819,1012).
 +
 
 +
 
 +
1819 = 0x71B and 1012 = 0x3F4.<br/>
 +
so U<sub>0</sub> = 0x1B, U<sub>1</sub> = 0x07, V<sub>0</sub> = 0xF4 and V<sub>1</sub> = 0x03. Other values are 0x00.<br/>
 +
The conversion gives:<br/>
 +
U'<sub>0</sub> = 0x145, U'<sub>1</sub> = 0x15, V'<sub>0</sub> = 0x5510 and V'<sub>1</sub> = 0x05. Other values are 0x00.<br/>
 +
2 << (2 * Level) = 2 << 26 = 0x8000000.
 +
 
 +
So '''A''' = 0x8000000 + 2 *(0x00055510) + 0x00150145 = '''0x81FAB65'''<br/>
 +
and '''B''' = '''0x00'''
 +
<br/><br/>
 +
 
 +
== Getting QMID from DWORD values ==
 +
 
 +
The algorithm takes 2 DWORD values (A and B) as input and produces the QMID data (u, v and l) as output.<br/>
 +
For the header and some subsections, the 2nd DWORD value (B) is zero.
 +
 
 +
 
 +
The '''level''' value can be deduced from the A value since for each level there is a maximum value of u and v and hence a maximum value of A. (The minimum value is 0)<br/>
 +
U<sub>max</sub> = 3 * 2<sup>Level-2</sup> - 1<br/>
 +
V<sub>max</sub> = 2<sup>Level-1</sup> - 1<br/>
 +
{| border="1" cellspacing="0" cellpadding="5"
 +
| Level
 +
| U<sub>max</sub>
 +
| V<sub>max</sub>
 +
| A<sub>min</sub>
 +
| A<sub>max</sub>
 +
|-
 +
| 0
 +
| 0
 +
| 0
 +
| 0x02
 +
| 0x02
 +
|-
 +
| 1
 +
| 0
 +
| 0
 +
| 0x08
 +
| 0x08
 +
|-
 +
| 2
 +
| 2
 +
| 1
 +
| 0x20
 +
| 0x26
 +
|-
 +
| 3
 +
| 5
 +
| 3
 +
| 0x80
 +
| 0x9B
 +
|-
 +
| 4
 +
| 11
 +
| 7
 +
| 0x200
 +
| 0x26F
 +
|-
 +
| 5
 +
| 23
 +
| 15
 +
| 0x800
 +
| 0x9BF
 +
|-
 +
| 6
 +
| 47
 +
| 31
 +
| 0x2000
 +
| 0x26FF
 +
|-
 +
| 7
 +
| 95
 +
| 63
 +
| 0x8000
 +
| 0x9BFF
 +
|-
 +
| 8
 +
| 191
 +
| 127
 +
| 0x20000
 +
| 0x26FFF
 +
|-
 +
| 9
 +
| 383
 +
| 255
 +
| 0x80000
 +
| 0x9BFFF
 +
|-
 +
| 10
 +
| 767
 +
| 511
 +
| 0x200000
 +
| 0x26FFFF
 +
|-
 +
| 11
 +
| 1535
 +
| 1023
 +
| 0x800000
 +
| 0x9BFFFF
 +
|-
 +
| 12
 +
| 3071
 +
| 2047
 +
| 0x2000000
 +
| 0x26FFFFF
 +
|-
 +
| 13
 +
| 6143
 +
| 4095
 +
| 0x8000000
 +
| 0x9BFFFFF
 +
|-
 +
| 14
 +
| 12287
 +
| 8191
 +
| 0x20000000