FSDECODE DECODER FOR MICROSOFT FLIGHT SIMULATOR DATA FILES Version Beta 2; Release date: 4 February 1993 Updates: ù Link table increased to 240 entries ù Added the scale factor in register 'S' ù Added ASCII text to dump fields ù Added quotes (") to dump and string fields ù Added the undefined record procedure ù Added the absolute and relative link directives (#@, #$) ù Added the "mark routine" and the "call marked" directives (#M, #N) ù Updated SD-DEF.DES ù Added SCN.DES ù Documented the #S directive and the ERRORLEVEL return codes. Version Beta 1; Release date: 8 December 1992 ----------- FSDECODE REFERENCE ----------- WHAT FSDECODE DOES FSDECODE reads a Flight Simulator data file (.SC1, .SCN, .DY1, .DYN, .DEM, .MOD...), chops it in fields each containing a single value and outputs a field contents description to an ASCII text file. To do that, FSDECODE, which has almost no specific knowlegde about FS data file structures, uses a description file (thereafter called ".DES file") which tells the program how long each data field is, what it contains and how it has to be formatted in the output. By default, FSDECODE selects a description file according to the input file exten- sion, but a specific description file can be indicated. HOW INSTALL FSDECODE Copy the program file (FSDECODE.EXE) and all the .DES files to the same directory. This directory can be the Flight Simulator directory or a different one. HOW TO RUN FSDECODE The syntax for FSDECODE command line is: FSDECODE InputFileName OutpuFileName [/FfromOffset] [/TtoOffset] [/DdescrFileName] [/WoutputWidth] [/U] [/X[o][x][t]] where: is the name of the data file to be read is the name of the ASCII file to be created. These 2 arguments are required. is the input file offset from where to start (either a decimal or an hex number; the latter in the format 0x.... es.: 1024 = 0x400) is the input file offset at where to stop (either a decimal or an hex number) is the name of the description file to use is the maximum line width for the output file /U forces the program to unconditionally scan the input file from and not from the beginning /Xo or /Xx or /Xt exclude one of the three output columns (offset, hex and text, see below); they can be combined up to /Xoxt These 6 arguments are optional, and can appear in any order but AFTER the two file names. Defaults: defaults to 0 defaults to the file end defaults to a file name equal to the input file extension, and a .DES extension defaults to 132, legal values are in the range 80-197; values lower than 80 are converted to 80 and values greater than 197 are converted to 197. If a fromOffset parameter greater than 0 is given, the input file is scanned from the beginning to set possible link points and to follow the record struc- ture (see below), however no output is generated until the point is reached; when the point is reached, the program ends. If, however, the /U option is used, scanning begins directly from ; this can exclude some of the cross-check possibilities and has to be used only when the user is sure that is exactly the initial point of a record. If is equal to or lower than , the program ends with an error message. All file names can include a full drive:\path\ indication. The description file (both default or given by the user) is looked for in the current directory; if it is not found, it is looked for in the directory where FSDECODE itself resides. This permits to automatically use, for each input file kind, specialized .DES files for data files in different directories, resorting to a generic .DES file for that type if none is found. If no suitable .DES file is found, the program aborts with an error message. During the run, FSDECODE displays the current input file offset and, at the end, the offset of the last accessed field and record; these are not neces- sarily the last DECODED field or record, if they fall beyond the limit. By pressing the ESC key while the program is running, the user can interrupt the program at any moment. ERRORLEVEL RETURN CODE If run in a batch file, FSDECODE returns the following ERRORLEVEL codes: 0 success 1 invalid or missing parameter(s) 2 I/O error 3 other errors (out of memory, description file syntax...) MEMORY CONSIDERATION The input file is read a field at a time, and then input file size is not an issue. The description file, however, is kept in memory in its entirety and cannot be longer than ca. 53 kB. If there is not enough memory to hold the des- cription file, the program aborts with an error message. Given that FSDECODE uses the small memory model, the program can run in about 100 kB of memory, but there is nothing you can do if you hit the small memory limit other than trying to simplify the description file, no matter how many MB of extended/expanded memory you have. Each description file line takes 7+strlen(caption) bytes of memory. OUTPUT FILE LAYOUT Output files are organized in three columns: 1) at the left margin, the current file offset as a 6-digit hex number 2) at position 8, hex dump of the field values (hex column) 3) at position 62, field descriptions and values (text column) If any column is excluded with /X option, the column at its right takes over its width. Many fields can fit in a line and is the description file which tells FSDECODE when to start a new output line. One blank space is automatically inserted before any hex dump and field description. If the hex dump or the field description do not fit in the remaining portion of their columns, a new output line is generated; if they are longer than the corresponding column width, they are truncated. Hex dumps are always in hex, but all the digits of a field are given in the 'right' order (MSB first) and not in the Intel format (LSB first) actually used in the files. Some kinds of field (primarily geographic coordinates) generate a formatted hex dump (see below for details). Field description format is almost entirely dictated by the description file. When the decoding is over, a record count list is appended, detailing the occurrences of each record found at least once in the input file and the total occurrences of undefined records. NOTE: please be aware that output files generated by FSDECODE can be HUGE, a reasonable guess being about 20 times the length of the input file. ------------ LINK POINTS AND REGISTERS ------------ LINK POINTS The program maintains a table of up to 64 link points. Link points are set by specific instructions in .DES files. If the program is unable to correctly parse a point of the input file, it dumps an unformatted hex listing up to next link point. If the next link point is more than 2 kB after the current point, FSDECODE assumes to have lost syncronism with the input file, dumps 1024 bytes in hex and aborts. The link table is updated (and elapsed link points are removed) every time a link is inserted and at each new record. REGISTERS The program maintains a set of 27 registers. Registers can be set and checked with appropriate directives; checks can trigger jump to other descrip- tion lines. All registers are signed long values (32 bits) and all register assignments are casted to (signed long). Registers are addressed with a single character name from '@' to 'Z'. The following registers are somewhat special: '@': this is actually a sort of pseudo-register; when read, it yields the next link value, when set it inserts the given value into the link table; as the link table is kept in ascending order, a new value can occupy any position and is not necessarily the value returned when the register is read back. 'Q': holds the file offset of the record being decoded and is internally used to compute relative offset addresses (see below); it can be read and writ- ten, but it is overwritten every time the program enters a new record. 'R': holds the code of the current record; it can be read and written, but it is overwritten every time the program enters a new record. 'S': holds the current scale factor for FS delta coordinates and is internally used to convert delta coordinates to actual FS coordinates. It is not set by the program, but it is left to the user to be sure that the .DES file sets it when required. 'V': holds the current field value; it can be read and written, but it is over- written every time a new field is read. If the current field is shorter than 32 bits, the value is 0-extended for unsigned fields and sign-extended for signed fields. Strings and hex dump fields do not affect this register. 'W': holds the file offset of the current field; it can be read and written, but it is overwritten at each .DES line execution. Registers X, Y, Z are not reserved by the program, but are consistently used in the supplied .DES files to store the current East, North, Alt. coordinates of the current object or plane position. It is recommended that this practice will be observed. Other registers can be freely read and set with .DES instructions. ------------ DESCRIPTION FILE REFERENCE ------------ GENERAL STRUCTURE Description files are ASCII text files which tell FSDECODE how to interpret the input file and how to format the output. .DES files are made of lines, each describing a field (i.e. a single value). .DES lines are made of three columns: 1) a number: the length in bytes of the field 2) one or two characters: field value type and optional command 3) caption (a text string, optional): what to print before and/or after the field value output. Columns can be separed by any combination of blanks (spaces and/or tabs) and do not need to be actually drawn up in column. However, the first column MUST begin at the first line character and the caption column CANNOT contain blanks (but see below). Line length is limited to a maximum of 197 characters. For example, the follwing .DES line: 2 I file_length:_ tells FSDECODE that the next field is 2 bytes long, its value has to be printed as an I(nteger) number and the string "file length: " has to be prepended at the field value (underscore characters will be replaced by spaces). Given that many FS data files (as, for instance, .SC1, .DY1, .DEM) are made of records, each characterized by an initial byte code and each with its own structure and meaning, FSDECODE description files are also built around the record concept: a record line states for which record code the following description is intended, and subsequent lines describes the various record fields. Lines pertaining to the many fields of a record have to appear in the same order in which the fields appear in the record, one for each field, but des- criptions for the different record codes can appear in any order within the description file; however it is recommended to keep them sorted by record code. If some lines appear in the description file before the first record line, they are intended to describe a file header and are executed to decode the input file initial portion, until the first record line is met. See also section "NOTES" for details on record selection. COMMENTS Lines starting with a semicolon (;) are considered comment lines and are entirely disregarded. Any text after the caption, separated by at least one blank, is considered a comment and is entirely disregarded. Comments do not occupy memory. FIELD CAPTIONS The caption contains a descriptive text which is output with the field value. Within captions, 3 characters have a special meaning: '#': if a caption starts with a pound sign, a new output line is generated; otherwise output for the current field will follow output for the previous field in the same line, if it fits. If the symbol occurs in other positions it is printed normally (but see below the note about the 'E' field type). '|': if a pipe symbol appears anywhere in the caption, the field value is inserted at this point of the caption; if no pipe symbol occur, the caption is output entirely before the field value. '_': all undescore symbols are replaced by space characters. Always remember to add to captions the required leading or trailing underscores to separate caption text from field value. Captions stop at the first space or tab character they contain. FIELD VALUE TYPES Field value type tells FSDECODE how to interpret the field and how to print its value in the text column. As a general rule, upper case types are unsigned, lower case types are signed; if this distinction does not apply (as for non-numeric fields, like strings), case makes no difference. The following table lists the field types supported by FSDECODE Beta 2. For each type, the supported field lengths, a pattern of hex output and of text output as well as a description are given. ÚÄÄÄÄÄÄÂÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ type ³len³ hex dump ³ value output ³ description ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ B/b ³ 1 ³ hh ³ bbbbbbbb ³ binary number ³ ³ ³ 2 ³ hhhh ³ 2x bbbbbbbb ³ ³ ³ ³ 3 ³ hhhhhh ³ 3x bbbbbbbb ³ ³ ³ ³ 4 ³ hhhhhhhh ³ 4x bbbbbbbb ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ C ³ 2 ³ hhhh ³ ddddd ³ int. FS coord (-0xC000) ³ ³ ³ 4 ³ hhhh.hhhh ³ ddddd.dddd ³ fract. FS coord (-0xC000) ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ c ³ 2 ³ hhhh ³ +dddddd ³ delta FS co., scale factor 8 ³ ³ ³ ³ ³ +dddd.d ³ " , scale factor 6-7 ³ ³ ³ ³ ³ +ddd.dd ³ " , scale factor 2-5 ³ ³ ³ ³ ³ +d.dddd ³ " , scale factor 0-1 ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ D/d ³any³ hh hh hh..³ "ASCII text" ³ hex dump ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ E/e ³1-4³as for b/B ³ see below ³ enumeration (see below) ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ G ³ 1 ³ hh ³ ddd.ddø ³ degrees (0 - 360) ³ ³ ³ 2 ³ hhhh ³ ddd.ddø ³ " ³ ³ g ³ 1 ³ hh ³ +ddd.ddø ³ signed degrees (-180 - +180) ³ ³ ³ 2 ³ hhhh ³ +ddd.ddø ³ " ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ I ³ 1 ³ hh ³ *** ³ decimal integer ³ ³ ³ 2 ³ hhhh ³ *** ³ " ³ ³ ³ 4 ³ hhhhhhhh ³ *** ³ " ³ ³ i ³ 1 ³ hh ³ +*** ³ signed decimal integer ³ ³ ³ 2 ³ hhhh ³ +*** ³ " ³ ³ ³ 4 ³ hhhhhhhh ³ +*** ³ " ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ J ³ 2 ³ hh.hh ³ ddd.dd ³ decimal with 1 fract. byte ³ ³ ³ 4 ³ hhhhhh.hh ³ ddddd.dd ³ ³ ³ j ³ 2 ³ hh.hh ³ +ddd.dd ³sign. dec. with 1 fract. byte ³ ³ ³ 4 ³ hhhhhh.hh ³ +ddddd.dd ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ K ³ 4 ³ hhhh.hhhh ³ ddddd.dddd ³ decimal with 2 fract. bytes ³ ³ k ³ 4 ³ hhhh.hhhh ³ +ddddd.dddd ³sign. dec. with 2 fract. bytes³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ O/o ³1-4³as for b/B ³ "off"/"on" ³ on / off switch: ³ ³ ³ ³ ³ ³ "off" printed if LSB == 0 ³ ³ ³ ³ ³ ³ "on" otherwise ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ S/s ³any³hh hh hh.. ³ "ASCII text" ³ textual string ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ X/x ³ 1 ³ hh ³ hh ³ hex number ³ ³ ³ 2 ³ hhhh ³ hhhh ³ ³ ³ ³ 3 ³ hhhhhh ³ hhhhhh ³ ³ ³ ³ 4 ³ hhhhhhhh ³ hhhhhhhh ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Y/y ³ 2 ³ hh.hh ³ hh.hh ³ hex number with 1 fract. byte³ ³ ³ 4 ³ hhhhhh.hh ³ hhhhhh.hh ³ ³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ X/x ³ 4 ³ hhhh.hhhh ³ hhhh.hhhh ³hex number with 2 fract. bytes³ ÃÄÄÄÄÄÄÅÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ '-' ³1-4³as for b/B ³ none ³ empty value ³ ÃÄÄÄÄÄÄÅÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ # ³ Command directive; see next section ³ ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Symbols: 'b', 'd', 'h' stand for one binary, decimal or hex digit resp. '+' stands for a sign character (either '+' or '-') '***' stands for the amount of decimal digits necessary for expressing the number (output is left justified; other field outputs are right justified). Notes: 'C': the field value is corrected by the -0xC000 base shift after hex output. 2-byte 'C' fields are aligned with int FSu decimal point (<< 16) after value output. These modifications show up in the 'V' register also. 'c': the field value is corrected by the current value of register 'S' (scale factor) after hex output, so that the field is aligned with int FSu decimal point and is ready to be added to current reference coordinate to calculate resulting point. These modifications show up in the 'V' register also. Text output has a variable number of decimal digits to make it to fit in 7 characters. 'E': enumerations provide a way to convert coded values to text labels. They are intended for fields that can assume a small number of consecutive values. For enumerations, the caption column must have a precise structure: "[pre_label]|text_for_value_0#text_for_value_1#....[|post_label]" the program prints in the text column the text corresponding to the field value, with the optional pre_ and post_labels before and after. Note that the final '|' is required only if the post_label is present, but the first '|' is ALWAYS required. If the field value is greater than the number of supplied texts, a 2-digit hex number is printed. Only the LSB of the field is tested and printed, whatever the declared length of the field. 'G': for degree fields, value output is converted in degrees, calculating 10000h (for 2-byte fields) or 100h (for 1-byte fields) = 360ø. This calcula- tion does not affect the V register which keeps its value. For 1-byte fields, however, after value output, V is shifted 1 byte to the left to keep the value aligned with 2-byte fields. Value outputs have a final 'ø'. 'D': strings are output in text chunks up to 16 bytes long, each surrounded by a pair of quotes ("); control characters are replaced by the '^' symbol; new output lines are generated until the field length is exhausted. If the field length is not known in advance, a length of -1 can be declared and the file will be hex-dumped up to next link point. 'S': strings are output in text chunks up to 16 bytes long, each surrounded by a pair of quotes ("); control characters are replaced by the '^' symbol; new output lines are generated until the field length is exhausted. If the field length is not known in advance, a length of -1 can be declared and text will be output up to the next NULL character included. '-': no value output. Hex dump is generated, but value output is not. Used to read a field while deferring value output if it requires special manipula- tions or avoiding it when caption text is enough. String and hex dump fields can have any length between 1 and 32677. Other fields can be only 1 to 4 bytes long; if the declared field length is greater, the program stops with an error during description file check. If a field length unsupported for that field type is declared, hex output will be usually correct, but no text output will be generated. No messages are issued by the program. FIELD COMMANDS To the field type character, another character can be added addressing one of the internal registers. If the character is upper case ('@' or 'A'-'Z') the corresponding register is set to the current field value; if it is lower case ('$' or 'a'-'z') the current value is added to the register (algebraically added, if the field was declared as signed). Any other command will be simply ignored. Commands do not affect hex or text output in any way. The following commands require some comments: Link points: '@': the field value is declared as an absolute link point; the field value is considered an absolute file offset and inserted into the link point table as it is. '$': the field value is declared as a relative link point; the field value is added to the current record offset and inserted into the link point table. Record line 'R': declares the line as a record line; for record lines, field length column does not indicate the length of the field, but the code of the record; a record code field is always considered 1 byte long. The R register is set to the field value and the value is output according to the field type. NOTE: Record codes lesser than -1 or greater than 255 are ignored. See also ".DES execution flow" in section "NOTES" below. Undefined record procedure A record line with a code of -1 marks a special record procedure wich will be invoked to process undefined records, overriding the default procedure (dump to next link point) built in the program. No field loading '-': outputs the current field value (V register) without loading it from the file; it is used to output a field value (usually previously read with a '- ' field type) that has been manipulated through directives (see below). Value is formatted according to field type. No hex output is generated. COMMAND DIRECTIVES A line with a '#' field type is not considered a field description but a directive for the program. Directives tell FSDECODE to perform certain actions. They permit a rudimentary form of programmed file parsing. Directives are recognized by the command character. As a general rule, directive case is irrelevant. Within directives, field length column and caption column have special mean- ing. The following table lists directive supported by FSDECODE Beta 2. For each, the meanings of various columns and a description are given. ÚÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ dir ³ field length ³ caption ³ description ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #D ³ line offset ³ arithmetic ³ count Down on reg: ³ ³ ³ ³ expression ³ decrement reg and jump to ³ ³ ³ ³ ³ [line offset] if reg > value ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #U ³ line offset ³ arithmetic ³ count Up on reg: ³ ³ ³ ³ expression ³ increment reg and jump to ³ ³ ³ ³ ³ [line offset] if reg < value ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #I ³ line offset ³ boolean ³ jump If: ³ ³ ³ ³ expression ³ jump to [line offset] if ³ ³ ³ ³ ³ [expression] is true ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #J ³ line offset ³ (standard) ³ Jump: ³ ³ ³ ³ ³ jump to [line offset] ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #C ³ line offset ³ (standard) ³ Call subroutine: ³ ³ ³ ³ ³ store current description line ³ ³ ³ ³ ³ and jump to [line offset] ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #E ³ (ignored) ³ (standard) ³ End subroutine: ³ ³ ³ ³ ³ go back to the calling point ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #M ³ line offset ³ (standard) ³ mark a subroutine for later ³ ³ ³ ³ ³ execution ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #N ³ (ignored) ³ (standard) ³ call marked subroutine ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #S ³ bytes ³ (standard) ³ skip the given amount of bytes ³ ³ ³ ³ ³ in the input file ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #R ³ (ignored) ³ arithmetic ³ Register operation ³ ³ ³ ³ expression ³ ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #F ³ (ignored) ³ description ³ execute description File: ³ ³ ³ ³ file name ³ load and execute [filename] ³ ³ ³ ³ ³ (must include path and .ext) ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #H ³ (ignored) ³ heading ³ Heading: ³ ³ ³ ³ ³ output [heading] at hex column ³ ³ ³ ³ ³ in a line of its own ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #T ³ (ignored) ³ text ³ Text: ³ ³ ³ ³ ³ output [text] at value column ³ ³ ³ ³ ³ (same spec. char. as captions) ³ ÆÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵ ³ #@ ³ line offset ³ (ignored) ³ link procedure to current value ³ ³ ³ ³ ³ intended a file offset ³ ÃÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ #$ ³ line offset ³ (ignored) ³ link procedure to current value ³ ³ ³ ³ ³ intended as an offset from the ³ ³ ³ ³ ³ current file offset ³ ÀÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Notes: [line offset] is a signed short integer which gives the target line offset relatively to the current line; comment lines are not counted. Even when the field is ignored, it MUST contain a number. Line offsets can be substituted with label references (see below). [arithmetic expression] is in the form "R?VALUE", where: ù 'R' can be any register name ('@'-'Z') ù '?' can be any of the following operators: + - * / % & | = which are equi- valent to the following C operators: + += - -= * *= / /= (integral division) % %= (modulus) & &= (bitwise AND) | |= (bitwise OR) = = The operator is not checked for #D and #U directives, but it MUST be there. ù 'VALUE' can be a signed long integer (decimal or "0x...." hex) or a register name ('@'-'Z'). [boolean expression] is in the form "R?VALUE", where: ù 'R' can be any register name ('@'-'Z') ù '?' can be any of the following operators: > < = ! (greater than, lesser than, equal, not equal). Other operators are considered as '!'. ù 'VALUE' can be a signed long integer (decimal or "0x...." hex) or a register name ('@'-'Z'). '#D', '#U': implement a sort of "do...while" counted loop. They are intended to be used at the end ("while") of repeating part to conditionally branch to the initial point ("do"). The lines between "do" and "while" are always executed at least 1 time. '#C': execution continues with the called subroutine; FSDECODE returns to the calling point only when an '#E' directive is executed. There is no limit, memory availability excepted, to multiple subroutine nesting. '#E': returns execution to the calling point, either from a subroutine or from a nested .DES file. Upon returning from a nested .DES, memory occupied by the called .DES is freed and its record definitions are lost. If executed when no subroutine and no nested .DES is being called, it stops the program. 'M': marks the routine targeted by the line offset (or label reference) for later execution through the 'N' directive. 'N': calls a routine previously marked by the last 'M' directive. It is a normal subroutine call, with returns only when an 'E' directive is found. If no routine has been 'M'arked, the directive is ignored. The directive pair 'M' - 'N' is used to select among several specific routines according to contingent conditions and to call the selected routine at a later point without the need to repeat the tests or keep memory of the previous conditions. '#F': execution continues with the given .DES file. The file is looked for in the current directory and then in the FSDECODE directory, as for any .DES file; if it is not found, the program aborts with an error. File name cannot include an underscore character ('_') because it would be replaced by a space. FSDECODE returns to the calling point and frees the memory occupied by the called file only when an '#E' directive is executed. Record definitions and labels are local to the called file and do not inter- fere with the records and labels defined in the caller. Registers, undefined record procedure, marked procedure and link point proce- dures, however, are global and the called file shares the register with the caller or inherits the procedures if they have been set by the caller. There is no limit, memory availability excepted, to multiple file nesting. '#H': generates an output line containing only the given text aligned with output hex column. Text cannot contain spaces, which can be indicated by the '_' special character. New line text prefix ('#') and field value place holder ('|') are printed as regular characters. This directive is ignored if text output has been suppressed with the /Xt option. This directive is used to insert titles or separators in the output. '#T': outputs the given text at the current output value position. Text can- not contain spaces, which can be indicated by the '_' special character. New line text prefix ('#') is observed and field value place holder ('|') is printed as a regular characters. This directive is ignored if text output has been suppressed with the /Xt option. This directive is used to insert a caption that cannot be easily inserted in the caption column. '#@': links the procedure targeted by the line offset (or the label reference) to the current field value, intended as a file offset; when decoding arrives at this file offset the procedure is executed. The procedure has to be closed by an #E directive, as for any subroutine call. This directive is useful for inserting headings at given file offsets or for derouting execution during file sections with a particular structure. '#$': it similar to the previous directive, but the current field value is considered a delta from the current record offset, i.e.: the current field value is added to the current record offset, the result is considered a file offset and is linked to the targeted procedure. Any other directive will be simply ignored. Note that directives #C, #E, #J, #M, #N, #S can have a standard caption which will be output into the text column in the usual way. Refer to the supplied .DES files and to the "NOTES" section below for exam- ples and tips of using directives. LABELS Lines starting with a colon (':') are considered labels definitions and mark the following line. Only the first 8 characters (':' excluded) are sig- nificant; labels are case-sensitive and may contain any caracter from '!' (ASCII 33) to 'þ' ('ASCII' 254). Each .DES file can contain up to ca 3,000 different labels. A label can be referenced in directives, substituting the line offset with the label preceded by a '>'. Again, see the supplied .DES for examples. Labels do not count as lines and do not occupy .DES memory. ------------ NOTES ------------ .DES EXECUTION FLOW and RECORD SELECTON MECHANISM If a .DES file does not contain record lines (like, for instance, MOD.DES), it is executed linearly from the first line onward, of course taking into account possible flow control directives like #J, #C, etc, until: a) the input file is finished OR b) the .DES file is finished OR c) a #E directive is met which is not within a subroutine or #F call. If however it does contain record definitions, its execution is linear until the first record line is met. At this point, FSDECODE assumes to have entered an input file section made of records, and the .DES file is no more executed sequentially but somewhat asynchronously: a record code is read from the input file and the routine associated with this code is retrieved and executed. If the code has no associated routine, the undefined record mechanism is trig- gered. When the routine is finished (i.e. when FSDECODE arrives at another record line), another record code is read from the input file and the selection process is repeated. In 'C' terms, the record definition block of a .DES file can be described as a big "switch" within which each record line is a "case" (and at the same time it "break"s the previous "case") and the undefined record proc (either built-in or DES-defined) is the "default"; the entire "switch" is enclosed in a "while(TRUE)" block. Thee is no way to stop this process and revert to plain sequential execution; if an input file portion is known to have a non-record structure, its address (either hard-coded in the .DES or derived from the file contents) can be inserted in the link point table and associated with an appropriate decoding subroutine through the #@ or #$ directives: when the decoding arrives at that file address, the associated routine will be triggered and the special section properly decoded. After that, upon returning from the subroutine, the asyn- chronous record selection process resumes. Note that a .DES containing record definitions will never stop or, if called from antother .DES, will never return to the caller, until one the following condition is satisfied: a) the input file is finished c) one of record definition, thought to mark the end of the file, purposely contains an '#E', in which case execution of the .DES will stop after the first occurrence of this record in the input file. Condition b) (end of .DES) is no more possible, because record selection is repeated until there are records to decode. NOTE ON THE '#E' DIRECTIVE AND CALLS .DES files that do not contain record definitions can, or even should, safely end with an '#E' directive. If the file is called from another .DES with the '#F' directive, execution will return to the caller when the '#E' directive is reached; if there is no '#E', FSDECODE cannot anymore tell how to parse the file and usually aborts with an error. .DES files that contain record definitions, however, cannot simply end with an '#E', because it will necessarily appear at the end of record definition and will cause FSDECODE to stop whenever a record of that kind is parsed. The same apply to the code of a subroutine: if it follows a record definition, it will be executed whenever a record of that kind is parsed. The solution is to group all subroutines, each terminated by its own '#E', at the beginning of the file and to add before them a #J directive jumping over all of them. '-' NULL FIELD TYPE AND '-' NULL FIELD COMMAND It is important to distinguish between these two instructions: '-c' (where 'c' can be any field command, even empty) reads a field (of given length) and outputs its hex value but does not perform any text output. The field value is stored in the 'V' register, as with any field read-in. It prac- tically tells FSDECODE that there is no need for a value output because the caption is enough or that there is no simple way to output the field value and that the next .DES instructions will take care of it. It can be associated with any field command. 't-' (where 't' can be any field type) does not read anything from the input file nor output any hex value, but outputs in the text column whatever value happens to be in the 'V' register, formatted according to the accompanying field length and type. Practically, it tells FSDECODE that a suitable field value has been built in the 'V' register and that it can output this value in a standard format. It can be associated with any field type but there has to be one, because the field command is always the second character. It is also important to properly pair, when required, the null field type and the null field command, each in its .DES line, avoiding having two read-in for a single field (which would put the .DES out of synchronism with the input file) or no read-in at all. Even more care has to be put when one of the two instructions is a sub-routine; for example: a) when an instruction reads a field with the null field type and then calls a sub-routine, practically 'passing' to it the value in the 'V' register, the called sub-routine must not read the field again; b) when a sub-routine is supposed to read the fields it works on, the caller must not read them in advance. The most delicate points are sub-routines which can be executed asynchron- ously, like the undefined record procedure, procedures associated with link points and any 'marked' procedure: the .DES programmer has to be sure that these sub-routines will be executed with the right alignment with the input file. ------------ FILE LIST ------------ The package contains the following files: FSDECODE.EXE the program FSDECODE.TXT this documentation file Sample .DES files: DEM.DES for .DEM files DY1.DES for .DY1 files MOD.DES for .MOD files SC1.DES for .SC1 files SC-DEF.DES for the default scenery F1 or other sceneries with the same structure (as Mallard's *.SCN) SCN.DES tentative .DES file for alternate sceneries (subLogic's *.SCN) STATRECS.DES .DES containing static scenery record definitions, used by SC1.DES, SC-DEF.DES and SCN.DES and callable by any .DES dealing with static scenery. Notes on supplied .DES: SCN.DEF: scenery sections of *.SCN files are not contiguous but, when a sec- tion ends, the file is padded to the next kilobyte boundary, where the next section begins; also, at sector 116 (offset 59,392) there is a special section containing some of the items found in the header of F1. While the supplied SCN.DES makes no attempt to deal properly with this special section, it tries to reduce the problems posed by the padding garbage with a custom undefined record procedure, which outputs an hex dump up to the next kB boundary and then resume record decoding. This way, assuming that all real record types are properly defined, no significant portion is lost, but the initial part of each pad can be misleadingly decoded as scenery records, if it happens to follow the structure of some of the known records; therefore, records before the message "Undefined record, dumping to next kB boundary" back to the last END (79h) or RET (19h) record have to be discarded, potentially. STATRECS.DES: this .DES includes all records of which I know at least the length. Some records (like the runway record, 50h) have a simplified descrip- tion and no attempt as been made to analyze building records (code 53h); only some FS variables are converted to plain labels. Detailed description of all known records can be found in the file FSSTRUCT.TXT, available on request. ------------ COPYRIGHT NOTICE AND DISCLAIMER ------------ FSDECODE is distributed to encourage research and knowledge acquisition on the Flight Simulator environment. It is intended as KnowledgeWare: it is free, but anyone is invited to let me know discoveries obtained with it. I explicitly renounce to any copyright I may have on it. The FS4/ASD community as a whole has spent way too much time decoding this information in order to generate useful utilities. It would be nice if the original authors chose to publish an "official" documentation of FS data files. However, FSDECODE is not distributed with an eye towards enabling anyone to rob the original authors of any rightful profits and should be used only for the common good of the FS4 community and to encourage availability and sales of FS4 and related products and utilities. Flight Simulator is a registered trademark of SubLOGIC Corp. Microsoft Flight Simulator is copyright of Microsoft Corp. and Bruce A. Artwick. Aircraft and Scenery Designer is copyright of Microsoft Corp. and The Bruce Artwick Organization. FSDECODE has been realized by: Maurizio M. Gavioli - BoGaRT sas. via Mino 1 50122 FIRENZE ITALY CompuServe: 100021,2335 InterNet: "Maurizio M. Gavioli" Last, but not least: I want to thank Dan Samuel, Andrew Tuline and Steve Tur- ley for their suggestions and friendly support.