This file is for PCC2 what VMx.CC is for PCC 1.x. It contains the state of PCC's script interpreter for player x. Scripts which are suspended (`Stop') end up here, including auto tasks.

The file is structured in objects, where each object has a certain type and some properties.

Note that although the header structure is the same as for PCC 1.x's VMx.CC, the file cannot be called the same because PCC 1.1.18 doesn't validate the version number and would try to parse it.

Format of header (same as VMx.CC):
 +0   4 BYTEs   Signature 'CCvm'
 +4  18 BYTEs   Timestamp
+22     BYTE    Signature 26 (^Z)
+23     BYTE    Format version (currently 100)
+24     WORD    Number of bytes following in header (currently 4)
+26     WORD    Turn number
+28     WORD    Player Id
--- end of header ---
+30   n BYTEs   Objects
Format of an object:
 +0     DWORD   Object Type
                 1      Bytecode object (code snippet)
                 2      Process object (suspended script)
                 3      Stack frame (only valid within a process
                        object's stack frame property)
                 4      Array data
                 5      Hash data
                 6      Structure data
                 7      Structure type definition
 +4     DWORD   Object Id
 +8     DWORD   Object Size, covering property headers and data
+12     DWORD   "n" Number of properties
+16   n RECORDs of 8 bytes each: property headers
                 +0     DWORD   "count" Property element count
                 +4     DWORD   "size" Property total size
 +?   x BYTEs   Property data. For each property, "size" bytes. The
                interpretation depends on the property and its "count".

Bytecode object

The Id from the object header is used to refer to this bytecode object.

  • property 0: reserved
  • property 1: header
                     +0     WORD    Flags
                                     Bit 0  This is a SUB, not a FUNCTION
                                     Bit 1  Varargs routine
                     +2     WORD    Minimum number of arguments when called
                     +4     WORD    Maximum number of arguments when called
                     +6     WORD    Number of labels in code segment
  • property 2: data, data segment (literals used within the bytecode), see below.
  • property 3: names, name list (names used within the bytecode), see below.
  • property 4: code. Contains "count" 32-bit instructions. Each instruction has this format (little endian, thus "backwards"):
                     +0     WORD    Parameter
                     +2     BYTE    Minor opcode
                     +3     BYTE    Major opcode
                                      0     push
                                      1     binary operation
                                      2     unary operation
                                      3     ternary operation
                                      4     jump
                                      5     indirect call
                                      6     stack operations
                                      7     pop
                                      8     store
                                      9     member reference
                                     10     variable creation
                                     11     special
  • property 5: local names, name list (local variables).
  • property 6: name, string (name hint for loading). The property contains the raw string without a terminator or additional length field.
  • property 7: source file name, string
  • property 8: source line numbers. Contains "count" records
                     +0     DWORD   address (0-based index into code)
                     +4     DWORD   source line number

Process object

The Id from the object header is not used.

  • property 0: reserved
  • property 1: header
                     +0     BYTE    Priority
                     +1     BYTE    Process kind. This is used to find processes,
                                    it has no effect upon their operation.
                                     0      normal
                                     1      ship auto task
                                     2      planet auto task
                                     3      base auto task
                     +2     WORD    context_tos; number of contexts that were
                                    created before the process started (i.e. its
                                    initial environment)
  • Property 2: name, string
  • Property 3: frames. This property contains "count" Stack frame objects
  • Property 4: contexts, data segment
  • Property 5: exceptions. Contains "count" records of 16 bytes each
                     +0     DWORD   frame_sp
                     +4     DWORD   context_sp
                     +8     DWORD   value_sp
                    +12     DWORD   pc
  • Property 6: value stack, data segment

Stack frame object

The Id from the object header contains this frame's nesting level, i.e. frames are numbered, starting at 0.

  • property 0: reserved
  • property 1: header
                     +0     DWORD   Id of bytecode object executing here
                     +4     DWORD   pc
                     +8     DWORD   context_sp
                    +12     DWORD   exception_sp
                    +16     DWORD   flags
                                     Bit 0  Caller wants a result
  • property 2: local values, data segment
  • property 3: local names, name list

Array data object

The Id from the object header contains the array Id used to refer to the array from data segments.

  • property 0: reserved
  • property 1: dimensions. Contains "count" DWORDs with the array dimensions, in normal order.
  • property 2: values, data segment. Contains array values in "C"/"Pascal" order. Empty values at the end are omitted.

Hash data object

The Id from the object header contains the hash Id used to refer to the hash from data segments.

A hash is a pool of key/value pairs, where the keys are unique strings; new values can be added at any time. Each key slot names the corresponding value slot.

  • property 0: reserved
  • property 1: keys, name list.
  • property 2: values, data segment.

Structure data object

The Id from the object header contains the structure Id used to refer to the structure from data segments.

A structure is a list of values associated with a fixed list of names. The names are defined in the structure type and can be shared with other structures of the same type.

  • property 0: reserved
  • property 1: header
                     +0     DWORD   Id of structure type definition
  • property 2: values, data segment.

Structure type definition

The Id from the object header contains the type Id used to refer to this structure type from structure data objects. A structure type definition contains the names used for structure objects. Each name slot names the structure's corresponding value slot.

  • property 0: reserved
  • property 1: names, name list

Data segments

A data segment consists of "count" 6-byte values optionally followed by data, see CHARTx.CC, block 7/8.

Data segments used in a Process's Contexts property can only contain context references, i.e. values that have the highest bit in the Tag word set.

Reference data (arrays, hashes, structs, subroutines) is stored in separate objects, not in the data segment itself. That is, multiple values referring to the same object will still refer to the same object after loading. Forward references are permitted but should be avoided if possible. Object references are typed, that is, an array object and a hash object with the same Id can coexist, and are uniquely identified by Array or Hash reference entries in a data segment.

Name Lists

A name list is a sequence of Pascal strings (length byte + text). Other than the implied 255 limit, PCC2 has no limit on identifier length. Valid characters in identifiers are capital letters, digits, `$', `.' and `_'.

This is a testing version.
It may be incomplete, and have more bugs (or features) than the public live version at planetscentral.com.