MacAPRS / WinAPRS Map File Format
Thanks to Mike Musick, N0QBF for writing this documentation
Only on composing this doc did I really digest the fact that the Mac/WinAPRS map file format is an incredibily complex and powerful system, one that is not for the faint-of-heart, or "shade-tree" programmers. There are many seemingly trivial rules and conditions that have a big impact on map display behavior, much less a successful reading by the GUI APRS products. While it is possible to generate acceptable maps by using a limited subset of the available code structure, by the time "all the ducks are in their rows" and you've achieved a successful file read, you've conquered 95% of the really tough issues.
Be forewarned that most of the information contained in this file description was derived through a "reverse engineering" process, with spot assistance from Keith and Mark Sproul, the MacAPRS authors. There certainly will be things overlooked, but that is primarily because examples were not seen in the files that were dismantled for analysis. However, the information contained here has been used to create many maps from scratch, and so far there have been no serious crashes.
Something else to be aware of is that there is a possible file format revision on the drawing board, a revision which might solve some sticky display problems. This documentation only applies to map files labelled for version "1.00"; subsequent map system versions will have critical changes in the data format.
No code examples have been included due to the wide availability of map files in the public domain which may be examined using this guideline as, well... a map! Simply open a map file in the bit twiddler of your choice and examine the byte sequences.
Thanks to Keith and Mark for their generosity in allowing this doc to exist, as well as their help in filling-in the holes in my data.
The Mac/WinAPRS map file is a binary file consisting of three primary sections: header, vector descriptors, and label descriptors. The header section occupies the first bytes 0 to 255, followed by the vector descriptors which start on byte 256. Label descriptors start immediately following the vector data, with the starting point determined by the point offset (count) value from the header data.
All map files must end ".MAP" for WinAPRS to reconize them. For MacAPRS, the file type should be 'BINA' and the creator should be 'APRS'. The Mac will also recongize any file type if the file ends in ".MAP".
For Macintosh map files, this document describes the contents of the data fork. There is nothing stored in the resource fork.
The processors in the Macintosh are all "big endian", Intel processors are "little endian", this refers to the order in which the CPU stores a number. For example, the number 1000 is represented as 0x000003E8, on the Mac, this is stored in memory as follows.
Internal coordinates in the Mac/Win APRS products are based on a system where 0,0 is located at 180°W x 90°N. In Version 1.00 files, the coordinate values are long integers (4 bytes) representing tenths of seconds of distance (00°00'00.1") from this shifted datum.
Version 2 maps will PROBABLY be in hundredths of a second (00°00'00.01") increments. DO NOT GENERATE MAPS IN THIS FORM, MacAPRS and WinAPRS DO NOT CURRENTLY SUPPORT THIS. This information is provided so that you know what to expect in the future when you write your code.
ASCII fields are null (00h) fill unless otherwise noted. Each field description is followed by notes detailing or clarifying its use.
|0-3||4||Map Type||ASCII||Known valid data is "APRS", "WU2Z", "100K", and "DCW " [space (20h) fill].|
|4-7||4||Map Version||ASCII||Valid data is "Beta" and "1.00". However, current maps must be "1.00".|
|8-39||32||File Name||ASCII||Remember that ":" is not a valid Macintosh file name character, and that Windows files have to conform to the 8.3 naming convention and the limited DOS file name character set.|
|40-71||32||Map Title||ASCII||This is the map name which appears at the top of the map window and in the map menus. Commas and opening parentheses ("," and "(") are known to be not valid.|
|80-83||4||Creation Date||Long Integer||Macintosh-style date in integer seconds since midnight, Jan. 1, 1904.|
|84-87||4||Left Boundary||Long Integer||Coordinate Format. This and the following three values give the basic map rectangle data.|
|88-91||4||Right Boundary||Long Integer||Coordinate Format.|
|92-95||4||Top Boundary||Long Integer||Coordinate Format.|
|96-99||4||Bottom Boundary||Long Integer||Coordinate Format.|
|108-111||4||Total Vector Points||Long Integer||Very important! This is the number of points in the map (not the number of vectors). It is also used to compute the offset to the start of the label data.|
|112-115||4||Number of Labels||Long Integer||Number of labels in the file.|
Vectors (lines) are formatted as series of ten-byte sequences, where each ten-byte group represents a single point. The vector byte groups are in a concatenated stream of data which is read sequentially by the APRS programs. There is no filler or other gaps between point groups or finished vectors. The sequential reading of the map file vectors means that the last vector (or object) described is the last one drawn on the screen, and is therefore topmost. When layering of objects is significant, it is necessary to manage the drawing order by ordering the vector data in the stream with objects to be covered or otherwise drawn "over" occuring first.
|Point Descriptor:||Byte 0||Vector start/line color||(see notes below)|
|Byte 1||Object behavior||(see notes below)|
|Coordinate Data:||Bytes 2-5||Longitude (x-coordinate), in long integer coordinate format||(See "Mac/WinAPRS Coordinate System" above)|
|Bytes 6-9||Latitude (y-coordinate)||As above|
The first byte of the point descriptor is the primary determinator of how the line or object is going to appear when drawn. There are currently two main uses for this first byte: the first is to note that the following coordinates represent the starting location of the vector, and the second use is to select the display color. The vector start code precedes only the first coordinate pair of a contiguous line, and all subsequent coordinate pairs in the line will have a color value in this byte. Currently, the color value is attached to all subsequent coordinate pairs, but for lines only the first color code seen (which is on the second point descriptor) is applied to the vector.
Known valid Byte 0 codes are:
|FF - Vector Start|
and color codes:
|01 - Purple||08 - Black||0F - White||16 - Light Purple|
|02 - Dark Green||09 - Blue||10 - Black||17 - Light Blue|
|03 - Cyan||0A - Light Green||11 - Black||18 - Purple|
|04 - Brown||0B - Light Purple||12 - Black||19 - Light Orange|
|05 - Light Magenta||0C - Red||13 - Black||20 - White|
|06 - Orange||0D - Magenta||14 - Light Gray|
|07 - Dark Gray||OE - Yellow||15 - Magenta|
Limited testing determined that color codes not on this chart will yield a black line, though this was not verfied for all possible values through FEh. Notice that 01 through 0F parallel the DOS APRS color value system. Some of the color codes are redundant; it is not known if the values for 10h through 13h are actual color discriptors or are invalid codes which defaulted to black.
[Additional shading colors were added in WinAPRS 1.19 and MacAPRS 2.7.0., and function in some relationship to high-order bits. Due to backwards-compatibility problems and some inconsistencies found in testing, I haven't included these values in the table.]
Filled Objects and Line Width Control. In the instance of a filled object (see DCW maps for examples of maps containing filled objects), the line color code represents the color of the border line. Byte 1 of the line/object descriptor appears to have some level of bit sensitivity, or at least half-byte or nibble values; the high-order bit (MSB or sign bit) seems to be a flag for filled objects.
The following values have been found to correspond to the listed features:
|First point descriptor (line start, FFh in Byte 0):||00h||1-pixel line|
|80h||Filled object, 1-pixel border|
|81h||Filled object, 2-pixel border|
|In subsequent points:||00h||Normal line|
|81h||Red filled object|
|82h||Yellow filled object|
|83h||Light Green filled object|
|84h||Dark Blue filled object|
|85h||(Red filled object - red appears to be a default for unassigned values.)|
|86h||Cyan filled object|
It is important to note that, currently, the last object descriptor in a vector description for a filled object is the one which determines the fill color. It does not hurt to put color values in all point descriptors, but - again, currently - the line color is controlled by the Byte 0 of the second point descriptor, and the fill color is controlled by Byte 1 of the last point descriptor of the line. Clear as mud, right?
Label records (or, rather, byte sequences) immediately follow the vector data, with the point count long integer in the header the sole determinate of the label data start location. To arrive at the label section offset, multiply the vector point count by 10, then add 256, the header takes up the first 256 bytes of the file.
Each label is either text or an APRS symbol with text. The label "record" is 44 bytes in length, with records following sequentially in the same way vector groups are processed.
|0||Text Color||See line color table above|
|0 sign bit (MSB)||Text Quad||If this bit is off (0), the text sets to the left of the coordinates. If this bit is on (1, or OR'ed 80h with the color), the text sets to the right of the coordinates.|
|2-5||Longitude (x-coordinate)||Long integer coordinate format|
|6-9||Latitude (y-coordinate)||Long integer coordinate format|
|10-11||Maginifcation View Level||See notes below.|
|12-43||Label Text||Any ASCII seems to be valid, except do not begin with "$"|
|2-11||[Same as text label]|
|12||Symbol Delimiter||ASCII "$"|
|13||APRS Symbol Character||ASCII, from standard APRS set|
|14||Text Color||This is an ASCII number. Limited to 1-9; invalid codes default to black.|
Text labels print to right or left of coordinates, depending on setting of color sign bit. Symbol labels will center symbol icon on coordinates, with text centered beneath.
This is a nice feature which permits coding detailed labels while preventing label clutter at large area views. This long integer value (positive values only) determines the amount of magnfication needed before the label becomes displayable. There appears to be a correspondence to display radius in miles, i.e., a value of "10" means that the label will come into view if the area being viewed is a ten-mile radius or less. 0000h means viewable at all magnifications.