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 `_'.