+0     WORD    Number of messages
 +2 n*6 BYTEs   Records of 6 bytes each
                 +0     DWORD   Address of message in file + 1
                 +4     WORD    Length of message in bytes
 +x   y BYTEs   undefined, or the messages

The messages texts are encrypted: each ASCII code is increased by 13dec. A single carriage return (ASCII 0Dh, encrypted 1Ah) is a line break. Empty lines are stored as a line break only (no spaces). Messages do not need to be all of the same length. Messages from Winplan clients may have additional encrypted linefeeds (ASCII 0Ah, encrypted 17h) after the CRs.

Characters with an ASCII code above 242 can't be encrypted in messages. The encryption does not have a "wraparound" (then, 250 + 13 would be 7). Attention: Planets doesn't check this and exits with an "Illegal Function Call" message. Host knows about this problem and replaces the characters with ASCII 13h (encrypted 20h = " ").

Expect messages of at most about one kilobyte each: see under MESSx.DAT for host-side size limits. Of course, real programs don't have arbitrary limits.

Message Type Codes

From Host 3.20 and PHost 2.6c onwards, received messages normally start with a header like this (PHost does this consistently since 3.3c): (-xy000)<<< Headline >>> The headers were introduced to allow sorting the messages in Winplan.

The hyphen identifies this message as a message from the current turn. If there is an "o" instead, it's an older message because the player has missed some turns.

"x" specifies the type of the message. "y" is a race number, and "000" a planet or ship id. The following list shows the existing message types (in the following list, capital letters are variable, the rest is fixed):

    (-90XXX)    Race-specific mission (Hiss, Dark Sense), XXX is a planet
                Id.
    (-a0XXX)    Message from 3rd-party add-on, see below.
    (-afile)    TKF File transfer. See below.
    (-c0XXX)    Tim Continuum attacking planet #XXX. XXX is zero for ship
                attacks and priority points.
    (-d0XXX)    Ship or starbase built at planet #XXX.
    (-dRXXX)    Ship of race R (1..9, a, b) surrendered at base #XXX.
    (-e0XXX)    Emergency call from ship #XXX.
    (-f0XXX)    Ship or planet #XXX has been destroyed or captured.
    (-g0000)    HConfig.
    (-h0000)    External message (see MESS.EXT), usually from the host
                (SENDMESS); may also read `(-h000)'.
    (-i0XXX)    Ion storm #XXX.
    (-l0XXX)    Minefield #XXX laid.
    (-m0XXX)    Minefield #XXX scanned/swept.
    (-n0XXX)    Intercepted enemy messages: ship #XXX ran on a mine, or
                planet #XXX being pillaged/RGAed.
    (-p0XXX)    Message from planet #XXX.
    (-pRXXX)    New native life, overtaxed, or bad climate at planet #XXX.
                R is a native race (0..9) or "c" for colonists.
    (-r000)     Anonymous message.
    (-rX000)    Message from race X (0..9, a, b).
    (-s0XXX)    Message from ship #XXX. #XXX is zero if the ship no longer
                exists (glory device).
    (-t0XXX)    Terraform status from planet #XXX.
    (-uXXXX)    Message about Ufo #XXXX (this type is not generated by
                host. Currently, only PCC evaluates it, but other authors
                are encouraged to use this, too, as it allows a nice and
                consistent interface for messages associated with an Ufo.
                PHost uses it for wormhole messages since 4.0e/3.4h).
    (-w0XXX)    Ship #XXX ran on a web mine.
    (-x0XXX)    Explosion on long range sensors (#XXX = sequential number
                of explosion).
    (-y0XXX)    Meteor on planet #XXX.
    (-z0XXX)    (Bio-)scanner report from planet #XXX.

Some Ids can be longer than 3 characters: (-l) and (-m) on PHost 3.3 with CPNumMinefields>=1000, (-u), possibly (-a) and (-x).

Note that some message types allow both planet and ship Ids in the "000" field (codes `f' and `s' are known to do this). I suggest trying to link the message to a ship first, and if this fails, to the planet.

Generally there are exactly as many (-f) messages as there are VCRs. Knowing this may make it easier assigning these messages to objects.

Add-on Messages (-a0XXX)

For messages starting with "(-a0XXX)", Winplan displays a the file WINPLAN\BMP\VPAUXxxx.BMP in the message reader. Those pictures are not transferred with the RST file; players have to install them in advance. Tim assigns Id numbers.

        Range        |  Used by...
       ==============|=================================================
          010        | Wormhole by Kevin D. Foster and James W. Allan
        101..126     | Dan & Dave Add-ons (RacePlus, Starbase+, etc.)
          149        | Neutral Zone by Dan Gale
        191..192     | HugeRock 1.2 by Ryo Nakamura
          202        | Unity by Wolfgang Merkel
          401        | Trade 1.20 by Nestor Delfino & Alejandro Biondo
        403..405     | 1st Corsarian Satellite Bank by -"-
          450        | Space Dragons or Non-Aligned Worlds by Joe Thomas
          451        | Non-Aligned Worlds by Joe Thomas
        451..454     | Lurkers/Stormfront
          500        | Gryphon by Oleg Shvartsman
        503..507     | Space Dragons by Joe Thomas
          510        | Nemesis by Oleg Shvartsman
          528        | JS-Q
          601        | Margetios Bazaars
          602        | mcpEdge
        666..668     | Aliens! (default configuration)
        700..717     | RAW! by Dan & Dave
          800        | GivePlan by Ryo Nakamura
          801        | PName by Ryo Nakamura
        802..803     | HugeRock Advanced by Ryo Nakamura
        805..816     | Interstellar Pig by Chris Stucchio
        870..873     | Portal by Rene Gallati

VPA Data Transmission

VPA data transmissions are normal player-to-player messages where the message body looks like this:

    <<< VPA Data Transmission >>>

    OBJECT: Planet 555           <--- Object & Id
    DATA: 1234567890             <--- Checksum in ASCII
    aaaaaaaaaaaaaaaaaaaaaaaaa    <--- Data
    aaaaaaaaaaaaaaaaaaaaaaaaa

Two data characters form one byte. "a" stands for 0, "p" for 15: the value of the byte encoded by two characters is 16*(second char) + (first char). Line breaks are inserted after 40 columns (20 bytes).

The checksum is a 32 bit number, encoded as a signed decimal figure. The lower 16 bits are the size of the data block in bytes, the upper 16 bits are some kind of checksum:

{ let this array contain the characters of the message, i.e. the 'a' to 'p' letters, but not the headers or the linefeeds: }

    VAR bytes : ARRAY[0..nchars-1] OF BYTE;

    sum := 0;
    i := 0;
    WHILE i < nchars DO BEGIN
      X := 256*bytes[i+1] + bytes[i];
      sum := 2*sum + X
      i := i + 2;
    END

(nchars is the number of characters in the message, i.e. two times the number of bytes to encode) This checksum effectively only depends upon the last 16 bytes of the text to be encoded, that is, the last 32 characters of the message.

Note that the characters are case-insensitive for the decoder, but not for the checksummer. 'A' means the same as 'a', namely the digit 0, but has a different value for checksumming.

The decoded blocks read as follows:

--- Planet ("OBJECT: Planet 123") ---
 +0     WORD    Turn number
 +2     WORD    Turn number
 +4     WORD    Owner of planet
 +6  81 BYTEs   Contents of planet record at offset 4 (Friendly Code), see
                PDATAx.DAT for description. Unknown values are set to -1.
+87     WORD    ? ("when")
+89     WORD    Flags ("EPLN").
                 Bits 0..7      Owner
                 Bits 8..10     Industry level
                 Bit 14         1 = No starbase
                 Bit 15         1 = Starbase present

--- Mine field ("OBJECT: Mine field 29") ---
 +0     WORD    Turn number
 +2     WORD    X
 +4     WORD    Y
 +6     WORD    Owner
 +8     DWORD   Mine units
+12     WORD    Type
                 0      Normal
                 1      Web

--- Marker ("OBJECT: Marker") ---
 +0     BYTE    Type
                 1      Flag "p"
                 2      Small circle "o"
                 3      Cross "x"
                 4      Square "[]"
                 5      Diamond "<>"
                 6      Dot "."
                 7      Circle with arbitrary radius
                 8      Line
                 9      Dotted line
                --- VPA 3.60+: ---
                 10     Grave "t"
                 11     Cactus "y"
                --- VPA 3.63+: ---
                 12     Black flag "P"
                 13     White flag "P"
                 14     Flag "k"
                 15     Up arrow
                 16     Up/Right arrow
                 17     Right arrow
                 18     Down/Right arrow
                 19     Down arrow
                 20     Down/Left arrow
                 21     Left arrow
                 22     Up/Left arrow
                 23     Neutronium marker "Ne"
                 24     Tritanium marker "Tr"
                 25     Duranium marker "Du"
                 26     Molybdenum marker "Mo"
                 27     Skull
 +1     BYTE    Color (1..15, standard EGA colors, see UFO.HST)
 +2     WORD    X
 +4     WORD    Y
 +6     BYTE    horizontal text justification (0=marker is to the left of
                the text, 1=center, 2=right)
 +7     BYTE    vertical text justification (0=marker is below the text,
                1=center, 2=above)
 +8     WORD    Lines: X extent
+10     WORD    Lines: Y extent
                Circles: radius
+12     BYTE    Length of comment text
+13   n BYTEs   Comment text

For lines, relative lengths are given. The line goes from (X,Y) to (X+dx,Y+dy).

--- RST Password ("OBJECT: Password 3") [V] ---
 +0     WORD    Turn for which this password is valid
 +2     BYTE    Password length
 +3  10 BYTEs   Password (unused places are filled with garbage)
+13     BYTE    Sender (number of player who sent this message; the number
                which is also in the OBJECT: line)
+14     BYTE    Receiver (who may use this password)
+15     WORD    Permission flags (currently unused, set to 0)

This record can currently only be used with PCC. The password is not encrypted: the hex encoding can be broken with a calculator, as can the password in the GENx.DAT file, so there would be no point in protecting the password more.

This record enables the specified receiver to open the sender's RST without having to know the password. Such a transmission is only valid for one turn. The transmitted password must match the sender's current password.

Informer Alliance Information

Informer (and other tools, such as EchoView) can transfer information about a player's planets and starbases to allied players. These messages contain in the body:

    Allied Planets                       <-- Signature
    Passcode : 17                        <-- Passcode (optional)
    506 69 105 770 809 350 390           <-- Id List
    405 908

The Id List contains Ids of all the player's planets, each of which is increased by 500 if the planet has a starbase. The above information thus says, `the sender has a starbase on planet 6, he owns planets 69 and 105, he has a starbase on #270, etc.'.

Note that such messages are easy to fake, so use them with care and do not blindly accept them from anyone. Since the message text does not contain the originator race, you shouldn't forward such a message to anyone: it is of no use for them. The `Passcode' line may be missing. If present, it specifies a passcode both allies must have agreed to (a number between 1 and 9999).

VPHost Binary Data Transfer

VPHost's data transfer messages contain in the body

    <<  VPHOST Binary Data Transfer  >>
    80E300000010004586560235F6C6162702645646
    5627164796F6E602020202020202020202458656
    0264564637020202020202020202020202645646
    020202020202020202

When you read this, run either VPUNPACK v2.20 or higher, or VPUTIL v2.50 or higher to process this message.

Each line is up to 40 characters long and encodes 20 bytes. A message contains up to 13 lines with binary data. Two characters encode one byte, using normal hex digits. The only non-standard thing is that the less-significant nibble comes first (!), so the above example starts with the bytes 08h, 3Eh, 00h, 00h.

The decoded data block reads as follows:
 +0     BYTE    Type of block
 +1     WORD    "num" Number of bytes in this message, 1 to 253.
 +3     WORD    Offset into target file. If one block was split into
                multiple messages, the first message contains the first
                253 bytes (offset=0), the second one contains the next
                253 bytes (offset=253, because we already have 253), and
                so on.
 +5     WORD    Index. Zero unless otherwise stated.
 +7   n BYTEs   actual data ("num" bytes)
  • Type 6 Block: HConfig (see HCONFIG.HST);
  • Type 7 Block: VPConfig (VPHost's configuration file);
  • Type 8 Block: Race name. Index is the race number, data contains the 3 race names (30 bytes long, 20 bytes short, 12 bytes adjective = 62 bytes total).

TKF File Transfer

  A TKF file transfer message looks like this:
    (-afile)< FILE: kfvcr5.dat  [1/1] >
    1'Z+!p!K"!]RJ5!"ga&!fh;H&*=/%!!!!!!7T^oQ
    [!!!!1\)-&*=/%!!!!!!h"81&H!!!!1\)-&*=/%!
    !$!!!h"81&H$<rr1\)-&*=/%!!!!!!h"81&H!!!!
    1\)-&*=/%!!!!!!h"81&H!!!!1\)-&*=/%!iX/cn
    ...
  The header line tells you what file it is, and whether it was split;
  the body of the message contains the file in radix-85 encoding.

In radix-85 encoding, five characters encode four bytes; therefore, each line encodes 32 bytes. The encoding works as follows: { let code[1] to code[5] be five characters from the message. L is an (unsigned) 32 bit variable. }

    L := 0
    FOR i:=5 DOWNTO 1 DO
     L := 85*L + (Ord(code[i]) - 33);
    { now, L contains four bytes }
    data[1] := L AND 255;
    data[2] := (L SHR 8) AND 255;
    data[3] := (L SHR 16) AND 255;
    data[4] := (L SHR 24) AND 255;
  Note that this method will always generate files whose size is divisible
  by four; there is no way to encode "odd" sizes.

These messages are used to transmit "KFVCRx.DAT" files to players.