JMF Format Specification

J.A.C.K Map Format. Similar to the RMF format but supports objects being part of multiple VisGroups. All data types uses little endian byte order.

Table of contents
  1. Overall Structure
  2. Common Structures
    1. Length-prefixed string
    2. Color
    3. Vector
    4. KeyValue
  3. Group
  4. VisGroup
  5. Camera
  6. Path
    1. Node
  7. Entity
  8. Brush
  9. Face
    1. Vertex
  10. Sources

Overall Structure

typedef struct {
    char[4] magic;                      // File format magic number
    char[4] unknown;                    // I'm unsure what this is. In all tests it came up as 0x79000000
    int ep_count;                       // Number of recent export paths
    p_char[ep_count] export_paths;      // Recent export paths
    int group_count;                    // Number of groups in the map
    Group[group_count] groups;          // Group objects
    int visgroup_count;                 // Number of VisGroups
    VisGroup[visgroup_count] visgroups; // VisGroups objects
    Vector cordon_min;                  // Minimum corner of the Cordon box
    Vector cordon_max;                  // Maximum corner of the Cordon box
    int camera_count;                   // Number of Camera objects
    Camera[camera_count] cameras;       // Camera objects
    int path_count;                     // Number of path objects
    Path[path_count] paths;             // Path objects (created with the Path tool)
    Entity[] entities;                  // All entities including worldspawn
} Jmf;

The magic number is 4 bytes represented by the string JHMF in ascii. This likely reflects J.A.C.K’s old name which was Jackhammer.

All world brushes are stored within the worldspawn entity. The entities array is read until the end of file.

Common Structures

Length-prefixed string

typedef struct {
    int length;             // The length of the string
    char[length] string;    // The ascii-encoded string
} p_char;

Color

typedef struct {
    char[4] color;      // One byte each for red, green, blue and alpha channel
} Color;

Vector

typedef struct {
    float[3] vector;    // One float each for x, y and z component
} Vector;

KeyValue

typedef struct {
    p_char key;    // Key of the property
    p_char value;  // Value of the property
} KeyValue;

Group

typedef struct {
    int group_id;           // The ID number of this group
    int group_parent_id;    // ID of the group this group is nested within
    int flags;              // Editor flags
    int count;              // Number of objects in the group
    Color color;            // Editor color of the object
} Group;

VisGroup

typedef struct {
    p_char name;        // VisGroup name
    int visgroup_id;    // VisGroup's ID number
    Color color;        // Editor color of the VisGroup
    _Bool visible;      // Whether the VisGroup is visible or not
} VisGroup;

Camera

typedef struct {
    Vector eye_position;        // The position of the camera in world coordinates
    Vector lookat_position;     // The target position in world coordinates the camera will look at
    int flags;                  // Editor flags (bit 0x02 flags whether it's selected)
    Color color;                // Editor color of the Camera
} Camera;

Path

Paths are placed using the Path tool in J.A.C.K and offer an alternative to placing path_ entities manually. It works similar to the Path tool in Hammer although can offer a “preview” in the 3D viewport of a camera travelling along the path with the speed specified by each node. One can read more about this in the J.A.C.K VDKManual.

typedef struct {
    p_char classname;           // Typically path_corner or path_track
    p_char path_name;           // The base name for this path
    int path_type;              // The direction of the path
    int unknown;
    Color color;                // Editor color of the Path
    int node_count;             // Number of nodes in the path
    Node[node_count] nodes;     // The nodes that make up the path
} Path;

The path_name will be used as the base name for the nodes belonging to this path, i.e. for a path named my_path each node will be named my_path, my_path_1, etc.

The path’s direction or path_type can have one of three different values:
0: One way (from first to last node and stops there).
1: Circular (from first to last and back to first again, as an endless loop).
2: Ping pong (from first to last and reverse direction back to first, in an endless loop).

Node

typedef struct {
    p_char name_override;           // Name to use instead of auto-generated one
    p_char fire_on_pass;            // Trigger this target when this node has been reached
    Vector position;                // The node's position in world coordinates
    Vector angles;                  // The node's angles
    int flags;                      // Editor flags
    int kv_count;                   // Number of node's key-value pairs
    KeyValue[kv_count] keyvalues;   // Node's key-value pairs (properties)
} Node;

Entity

typedef struct {
    p_char classname;                   // The entity's classname
    Vector origin;                      // The origin if it's a point entity
    int flags;                          // Editor flags
    int group_id;                       // ID of the group this entity belongs to
    int root_group_id;                  // The top-most group this entity is nested within
    Color color;                        // Editor color of the Path
    p_char[13] special_keys;            // The names of various special attributes used by J.A.C.K
    int sp_spawnflags;
    Vector sp_angles;
    int sp_rendering;
    Color sp_fx_color;
    int sp_rendermode;
    int sp_render_fx;
    short sp_body;
    short sp_skin;
    int sp_sequence;
    float sp_framerate;
    float sp_scale;
    float sp_radius;
    char[28] unknown;
    int kv_count;                       // Number of node's key-value pairs
    KeyValue[kv_count] keyvalues;       // Node's key-value pairs (properties)
    int vg_count;                       // Number of VisGroups
    KeyValue[vg_count] visgroup_ids;    // The ID numbers of the VisGroups the entity belongs to
    int brush_count;                    // Number of brushes
    Brush[brush_count] brushes;         // The brushes making up this entity (empty if point entity)
} Entity;

I am still unsure about the J.A.C.K special attributes section. The fields and their data types here just reflect how they’re described in MESS and should not be taken as a definite guide for parsing this part of the file. During my own testing I noticed the special attribute keys change depending on the type of entity and it’s possible different data types are used according to the key.

Brush

typedef struct {
    int curve_count;                    // Unused in GoldSrc, possibly related to Quake III/Volatile curve surfaces
    int flags;                          // Editor flags
    int group_id;                       // ID of the group this entity belongs to
    int root_group_id;                  // The top-most group this entity is nested within
    Color color;                        // Editor color of the Path
    int vg_count;                       // Number of VisGroups
    KeyValue[vg_count] visgroup_ids;    // The ID numbers of the VisGroups the entity belongs to
    int face_count;                     // Number of faces (polygons) making up the brush
    Face[face_count] faces;             // The brush's faces
} Brush;

It’s possible there’s an array of curve surfaces following curve_count. I do not know the structure of these but at least for game profiles with Map Type set to Half-Life / TFC there is nothing here.

Face

typedef struct {
    int render_flags;               // I'm unsure what this does. Editor flags perhaps?
    int vertex_count;               // Number of vertices in the face
    Vector right_axis;              // The texture's projected right axis
    float shift_x;                  // Horizontal shift of the texture
    Vector down_axis;               // The texture's projected down axis
    float shift_y;                  // Vertical shift of the texture
    float scale_x;                  // Horizontal scale multiplier
    float scale_y;                  // Vertical scale multiplier
    float angle;                    // The angle of the applied rotation
    char[20] unknown1;
    nt_char[64] texture_name;       // Name of the texture applied to the face
    char[20] unknown2;
    Vertex[vertex_count] vertices;  // The vertices that make up the face
} Face;

Vertex

typedef struct {
    Vector coordinates;     // Vertex coordinates
    Vector normal;          // MESS speculates this is the normal vector for the vertex
} Vertex;

Sources