Specifications

From Aleph One Wiki

Jump to: navigation, search

Marathon File Specifications

Return to History

Bernie Freiden

Contents

[edit] Unofficial MARATHON Specs

release version v0.0 - January 19, 1995

brought to you by:

freidin@phoenix.princeton.edu (Bernie Freidin)

Special thanks to:

pjcreath@phoenix.princeton.edu (Peter Creath) omv@cool-toys.mit.edu (Danimal) bhines@sdcc13.ucsd.edu (Clef) MORBID@resnova.com jon3@quads.uchicago.edu (Jason Jones)

[edit] General Information

Marathon consists of the following files:

File Type Content
Marathon application
Shapes graphics
Sounds sounds
Map level information
Music music information but not the notes
Physics Model optional - contains physics information
Saved Games mostly levels information


The following information is contained in each file:

[edit] Marathon

(type 'APPL', creator '26.2')

Program code, and the usual assortment of resources found in most Mac applications. The only interesting things here are the resources of type 'term', which contain the text displayed on the computer terminals in the game.

[edit] Shapes

(type 'shps')

All graphic data for textures, sprites, and interfaces, stored as resources of type '.256'. There are also 'clut' resources (color tables), and 'PICT' resources that contain the pictures displayed between levels. I'm not sure whether the color tables here are used, or the color tables stored in the main application. See below for more information on the format of '.256' resources.

[edit] Sounds

(type 'sndz')

All game sounds. These are stored as ordinary Mac 'snd ' resources, of format

[edit] Map

(type 'scen')

Map information for all levels, stored in the data fork. See below for more information.

[edit] Music

(type 'msik')

Music sequencing information, stored in the data fork. Exact format unknown, but is supposedly it is some form of MIDI .

[edit] Physics Model

(type 'phys')

Physical infomation, stored in the data fork. There is also a 'text' resource put in by Jason giving a short description of some of the format for this file. See below for more information.

[edit] Saved games

(type 'sgam')

Same information as "Map" files, stored in the data fork. There should be only one level, however, and the 'EPNT' chunk is replaced by a 'PNTS' chunk (see below). Also contained in these files is a 'PICT' resource of a portion of the level map (as seen in the preview box), and a 'STR ' resource containing the level name.

[edit] Films

(type 'film')

Contains keystroke information necessary to replay a game. Exact format unknown.

#define NONE -1

typedef long fixed;
typedef unsigned short angle;
typedef struct shape_descriptor
{
char set;
char frame;
};
typedef short world_distance;
typedef struct world_point2d
{
world_distance x, y;
};

[edit] Shapes Information

Header format:

Each '.256' resource starts with a 544 byte header:

enum /* shapes classes */
{
_shapeUnused,
_shapeTexture, /* RAW */
_shapeSprite, /* RLE */
_shapeInterface, /* RAW */
_shapeScenery /* RLE */
};
%_shapeUnused: not used
%_shapeTexture: usually 128x128 pixels, but not always
%_shapeSprite: all monsters, guns, objects..
%_shapeInterface: everything that doesn't go in the window
%_shapeScenery: ???

struct shapes_header /* 544 bytes */
{
short type;
short class;
unsigned short flags;

short color_count;
short palette_count;
long first_palette_address;

short high_level_shapes_count;
long high_level_shapes_table;

short low_level_shapes_count;
long low_level_shapes_table;

short image_count;
long image_table;

short scale_factor;
long size;

short unused[253];
};
%type: always equals 3
%class: see above
%flags:
%color_count: number of color entries in each palette
%palette_count: number of palettes (different palettes are used for different "variations" of monsters)
%first_palette_address: offset to first palette
%high_level_shapes_count: number of high-level shapes
%high_level_shapes_table: offset to table of addresses of high-level shape records
%low_level_shapes_count: number of low-level shapes
%low_level_shapes_table: offset to table of addresses of low-level shape records
%image_count: number of images
%image_table: offset to table of addresses of images
%size: size of entire resource

Palettes:

Each palette contain color_count entries, where each entry has the following structure:

struct color_entry /* 8 bytes */
{
short entry_number; /* ranges from 0 to color_count - 1 */
unsigned short red;
unsigned short green;
unsigned short blue;
};

The palettes are stored consecutively with no gaps between.

High-level shapes:

These describe an entire animated sequence, complete with sound effects and frame rate information. The exact format is as follows:

enum /* high-level shape flags */
{
};

enum /* high-level shape types */
{
};
struct high_level_shape /* 88 bytes */
{
short type;
unsigned short flags;

char name_length;
char name[33];

short view_count;
short frames_per_view;
short ticks_per_frame;

short key_frame; 

short transfer_mode;
short transfer_mode_period; /* in ticks */

short first_frame_sound;
short key_frame_sound;
short last_frame_sound;

short scale_factor;

short unused[15];

//frame information
};
%type: see above
%flags: see above
%name_length: length of name string (i.e. this is a Pascal string)
%name: ASCII string
%view_count: number of angles at which this animation can be viewed. This should only be 1, 2, 5, or 8.
%frames_per_view: number of frames of animation
%ticks_per_frame: speed of animation
%key_frame: frame at which "something happens"?
%transfer_mode:
%transfer_mode_period: absolutely no idea..
%first_frame_sound: 'snd ' resource to play at start of animation
%key_frame_sound: 'snd ' resource to play at key frame
%last_frame_sound: 'snd ' resource to play at end of animation
%scale_factor:

After this comes the frame information, which is a series of 2-byte words, each corresponding to a low-level shape. There will be view_count * frames_per_view entries, followed by 2 bytes of zero signifying to end of the animation. Note that if view_count equals 5, then it's really 8 * frames_per_view entries.

Low-level shapes:

These describe just one non-animated sprite, or one frame of an animated sequence. The exact format is as follows:

enum /* low-level shape flags */
{
_lowShapeXMirror = 0x8000,
_lowShapeYMirror = 0x4000,
_lowShapeKeyObscure = 0x2000
}

%_lowShapeXMirror: indicates that the sprite is to be drawn from right to left rather than left to right
%_lowShapeYMirror: similar to _lowShapeXMirror, but affects drawing vertically rather than horizontally. It doesn't seem to be implemented
%_lowShapeKeyObscure: ???

struct low_level_shape /* 36 bytes */
{
unsigned short flags;

fixed minimum_light_intensity;
short image_index;
short x_origin, y_origin;
short x_key, y_key;
short left, right, top, bottom;
short world_x_origin, world_y_origin;

short unused[4];
};

%flags: see above
%minimum_light_intensity: minimum light value that can be assigned to this image. Used for "bright" sprites, such as explosions, that are never supposed to be dark.
%image_index: indicates which image is used to draw this low-level shape
%x_origin, y_origin: center of shape? Who knows..
%x_key, y_key: no idea..
%left, top, right, bottom: defines the bounding rectangle?
%world_x_origin, world_y_origin: no idea..

Images:

These contain the actual graphic data for the images. First is a header, then follows the scan start address table, and then the pixel data. The exact format of the pixel data depends on the type of shape (RAW or RLE).

struct image_header /* 26 bytes */
{
short width;
short height;
short unknown[11]; /* ??? */
};

%width: width of image
%height: height of image

Next comes the scan start addresses. These are run-time calculated, so there is no need to provide valid information here. However, the right amount of space must be reserved for this block. The size of the block will be width * 4, plus 4 bytes at the end (unknown?).

And finally comes the actual image data. In RAW format, this is just a block of bytes, where each byte corresponds to one pixel. The pixels are stored top to bottom, then right to left. The color of a pixel can be determined by using the pixel value as an index into the palette. RLE format is a little different. It starts with a 2-byte command word. If this word is greater than zero, it signifies the start of a vertical run of pixels. The pixel data follows immediately, and the number of pixels is equal to the command word. If the command word is negative, it signifies the start of a vertical "skip" in which no pixels are drawn (a hole). The length of the skip will be equal to negative the value of the command word. If the command word is zero, it signifies the start of the next vertical column, which will start one pixel to the right of the start of the first column. The command words are repeated until the entire sprite is drawn.


[edit] Physics Model Information

The Physics Model contains information on gravity, weapon speed, monster behavior, and many other things. I'm not sure where the default physics information is stored (there doesn't appear to be any in the Marathon application, nor the Map files..).

Like the Map file, the Physics Model is made up of a number of "chunks", each of which contains a number of "entries". The following chunk types are known:


Chunk Type Content
mons monster information
effe effects information
proj projectile information
phys physics information
weap weapons information


Each chunk starts with a header, which has the following format:

struct physics_chunk_header /* 12 bytes */
{
long chunk_type;
short unused[2];
short entry_count;
short entry_size;
};

%chunk_type: 4 character ASCII string signifying chunk type
%entry_count: number of entries in chunk
%entry_size: size of each entry

Why do the Physics Model chunks follow a different format from the Map chunks?

[edit] 'mons' chunk:

The Monster chunk defines every monster in the game, including non-hostiles. A couple of things to note - first, different 'colored' monsters are defined separately. Second, the monster chunk references the effects chunk for animations when they get hit, the projectile chunk for the projectiles they shoot (in the attack structure), and the shapes directly for their moving shapes.

enum /* monster flags */
{
_monsterOmniscent = 0x00000001,
_monsterFly = 0x00000002,
_monsterAlien = 0x00000004,
_monsterMajor = 0x00000008,
_monsterMinor = 0x00000010,
_monsterNoDrop = 0x00000020,
_monsterFloat = 0x00000040,
_monsterNoAttack = 0x00000080,
_monsterSnipe = 0x00000100,
_monsterInvisible = 0x00000200,
_monsterSubInvisible = 0x00000400,
_monsterKamakazi = 0x00000800,
_monsterBerserk = 0x00001000,
_monsterEnlarged = 0x00002000,
_monsterDelayedHardDeath = 0x00004000,
_monsterFiresSymmetrically = 0x00008000,
_monsterNuclearHardDeath = 0x00010000,
_monsterNoFireBackwards = 0x00020000,
_monsterFlammable = 0x00040000
};
Type Number Note
_monsterOmniscent 0x00000001  ?
_monsterFly 0x00000002 Can fly
_monsterAlien 0x00000004 moves more slowly on lower levels
_monsterMajor 0x00000008 type -1 is major?
_monsterMinor 0x00000010 type +1 is minor?
_monsterNoDrop 0x00000020 lower levels can not skip monster
_monsterFloat 0x00000040 floats
_monsterNoAttack 0x00000080 civilian, constantly runs for safety
_monsterSnipe 0x00000100 uses long range weapon to attack from ledges
_monsterInvisible 0x00000200 invisible
_monsterSubInvisible 0x00000400 partially invisible
_monsterKamakazi 0x00000800 explodes if close to player
_monsterBerserk 0x00001000 goes beserk when below 25% viability
_monsterEnlarged 0x00002000 125% size
_monsterDelayedHardDeath 0x00004000 always dies soft then switches to hard?
_monsterFiresSymmetrically 0x00008000  ?
_monsterNuclearHardDeath 0x00010000 screen briefly turns white
_monsterNoFireBackwards 0x00020000 can not turn more than 135 degrees
_monsterFlammable 0x00040000 susceptible to flamethrower


Monsters unable to open doors have door retry masks of NONE

Monsters unable to switch levels have min,max ledge deltas of 0

Monsters unstopped by bullets have hit frames of NONE

enum /* attack types */
{
};

struct attack_struct /* 16 bytes */
{
short type;

short repetitions;
angle error;

world_distance range;
short attack_shape;

world_distance dx;
world_distance dy;
world_distance dz;
};

Type Note
type see above
repetitions number of retepitions of attack
error error added to firing angle
range range of attack
attack_shape attack occurs when keyframe is displayed
dx attack vector, distance = out (x-axis)
dy attack vector, distance = right (y-axis)
dz attack vector, distance = up (z-axis)


enum /* damage flags */
{
};

enum /* damage types */
{
};

struct damage_struct /* 12 bytes */
{
short type;
unsigned short flags;

short base;
short random;
fixed scale;
};
Type Note
type see above
flags see above
base base damage
random random factor
scale  ??
struct monster_entry /* 138 bytes */
{
short collection;

short vitality;
unsigned long immunities;
unsigned long weaknesses;
unsigned long flags; 

long class;
unsigned long friends;
unsigned long enemies;

short activation_sound;
short conversation_sound;
short flaming_sound;
short random_sound;
short random_sound_mask;

short carrying_item_type;

world_distance radius;
world_distance height;
world_distance preferred_hover_height;
world_distance minimum_ledge_delta;
world_distance maximum_ledge_delta;
fixed external_velocity_scale;
short impact_effect;
short melee_impact_effect;

short half_visual_arc;
short half_vertical_visual_arc;
world_distance visual_range;
world_distance dark_visual_range;
short intelligence;
short speed;
short gravity;
short terminal_velocity;
short door_retry_mask;
short shrapnel_radius; /* no shapnel if NONE */
struct damage_struct shrapnel_damage;

shape_descriptor hit_shapes;
shape_descriptor hard_dying_shape; /* minus dead frame */
shape_descriptor soft_dying_shape; /* minus dead frame */
shape_descriptor hard_dead_shapes; /* NONE = vanishing */
shape_descriptor soft_dead_shapes; /* NONE = vanishing */
shape_descriptor stationary_shape;
shape_descriptor moving_shape;

short attack_frequency;
struct attack_struct melee_attack;
struct attack_struct ranged_attack;
};


Type Note
 %collection  ?
 %vitality How much damage the monter can sustain
immunities mask of what the monster is immune to
weaknesses mask of what the monster is susceptible to flags
class bit of which class the monster belongs to
friends mask of friend classes
enemies mask of enemy classes
activation_sound sound made when monster is generated
conversation_sound sound made in conversation (?)
flaming_sound sound made when the monster gets TOZT'ed
random_sound randomly played sound (?)
random_sound_mask mask of when to play sound (??)
carrying_item something the monster will drop (ex: alien weapon)
radius radius of monster
height height of monster
preffered_hover_height height at which the monsters 'likes' to fly
maximum_ledge_delta the maximum a monster can 'climb' up
minimum_ledge_delta the maximum a monster can 'climb' down
external_velocity_scale No idea (?!?!?)
impact effect effeect to play when monster hits person {kamikazee?}
melee_impact_effect effect to play when monster whacks person
half_visual_arc horizontal visual range {side-to-side vision}
half_vertical_visual_arc vertical visual range {up-down vision}
visual_range range at which the monster can 'see' something
dark_visual_range range at which monster can see in the 'dark' (?)
intelligence hmmm... (???)
speed how fast the monster goes
gravity acceleration on falling monster (?)
terminal_velocity maximum fall rate (?)
door_retry_mask something to do with doors - which they can open? (??)
shrapnel_radius blast radius when self destructing
shrapnel_damage damage structure for self destruction
hit_shapes shapes of monster being hit by bullets
hard/soft_dying_shape shape of monster dying
hard/soft_dead_shape shape of dead monster on floor
stationary_shape monster not moving {sitting down, etc}
moving_shape normal monster in motion
attack_frequency how many ticks between attacks - melee is twice as often as ranged
melee_attack attack structure for melee attacks
ranged_attack attack structure for ranged attacks

[edit] 'effe' chunk:

This is all guesswork I've got from playing with the effects a bit. I'm not certain what the hell the flags are, although they always seem to be either 0 or 4..?

struct effect_entry /* 138 bytes */
{
short collection;
short shape;
short flags;
}
Type Note
collection Which collection the effect is from
animation which animation it is
flags unknown (???)

[edit] 'proj' chunk:

Projectiles are the bullets that everyone fires. No rocket science here.

enum /* projectile flags */
{
_projectileGuided = 0x0001,
_projectileNoAnimation = 0x0002,
_projectilePersistent = 0x0004,
_projectileAlien = 0x0008,
_projectileGravity = 0x0010,
_projectileNoHErr = 0x0020,
_projectileNoVErr = 0x0040,
_projectileHitSwitch = 0x0080,
_projectilePositiveVErr = 0x0100,
_projectileMelee = 0x0200
};
Type Note
_projectileGuided tracks targets apparently - useless for user weapons at the moment
_projectileNoAnimation projectile stops when animation loops - ex flamethrower
_projectilePersistent  ???
_projectileAlien does less damage and moves slower on lower levels
_projectileGravity projectile is affected by gravity
_projectileNoHErr no horizontal error - spread is entirely vertical
_projectileNoVErr no vertical error - spead is entirely horizontal
_projectileHitSwitch projectile can toggle switches
_projectilePositiveVErr positive vertical error - only shoots high? (??)
_projectileMelee can use a monster's custom melee detonation (??)


struct projectile_entry /* 36 bytes */
{
short collection;
short shape_index;

short detonation_effect; 

short contrail_effect;
short ticks_between_contrails;
short maximum_contrails;

world_distance radius;
world_distance area_of_effect;

short damage_type;
short damage_flags;
short damage_base, damage_random
fixed damage_scale;

word flags;

world_distance speed;
world_distance maximum_range;

short flyby_sound;
};
Type Note
collection if -1 (NONE), then this is invisible
maximum_contrails how many contrails will be left. if -1 (NONE), then this is treated as infinite
radius proximity radius - can be zero and will still hit
area_of_effect detonation radius - one target if = 0

[edit] 'weap' chunk:

Lots of stuff to play with here. Unfortunately, it seems like a fair amount of stuff is hardcoded, like where ammo is displayed, ammo shapes on the screen, weapon names, etc.

struct weapon_entry /* 120 bytes */
{
short type;
short class;
unsigned short flags;

short ammunition_type;
short rounds_per_magazine;
short secondary_ammunition_type;
short secondary_rounds_per_magazine;

fixed firing_light_intensity;
short firing_intensity_decay_ticks;

fixed idle_height;
fixed bob_amplitude;
fixed kick_height;
fixed reload_height;
fixed idle_width;
fixed horizontal_amplitude;

short collection;
short idle_shape;
short firing_shape;
short reloading_shape;
short shell_casing_shape;
short charging_shape;
short charged_shape;

short primary_ticks_per_round;
short secondary_ticks_per_round;
short reload_ticks;
short ready_ticks;
short primary_recovery_ticks;
short secondary_recovery_ticks;
short primary_charging_ticks;
short secondary_charging_ticks;

world_distance primary_recoil_magnitude;
world_distance secondary_recoil_magnitude; 

short primary_firing_sound;
short secondary_firing_sound;
short primary_click_sound;
short secondary_click_sound;
short reload_sound;
short charging_sound;
short primary_shell_casing_sound;
short secondary_shell_casing_sound;
short primary_sound_activation_range;
short secondary_sound_activation_range;

short primary_round_projectile_type;
short secondary_round_projectile_type;

short short primary_theta_error;
short secondary_theta_error;

short primary_dx;
short primary_dz;
short secondary_dx;
short secondary_dz;

short primary_burst_count;
short secondary_burst_count;

short instant_reload_tick;
};


Type Note
type unknown (???)
class unknown (???)
ammunition_type what type of ammo gets used up
rounds_per_magazine how many rounds you get to fire before reloading
secondary_ammunition_type ammo for the secondary weapon (if any)
short secondary_rounds_per_magazine rounds/clip for the secondary weapon (if any)
fixed firing_light_intensity how much the room lights up when firing (?)
short firing_intensity_decay_ticks how long the light lasts
fixed idle_height how high the weapon appears when being held
fixed bob_amplitude how much the weapon bounces when moving
fixed kick_height recoil height
fixed reload_height how far it goes up when reloading (?)
fixed idle_width width of weapon when idle (???)
fixed horizontal_amplitude side to side sway (???)
short collection collection of shapes for the weapon
short idle_shape shape when idle
short firing_shape shape when firing
short reloading_shape shape when reloading
short shell_casing_shape the casing shape, if any.
short charging_shape Shape when a weapon is being charged
short charged_shape Shape when a weapon is charged
short primary_ticks_per_round How many ticks to fire a round (?)
short secondary_ticks_per_round How many ticks to fire a round (?)
short reload_ticks ticks to reload weapon
short ready_ticks ticks to 'draw' weapon
short primary_recovery_ticks time to recover from recoil for primary weapon
short secondary_recovery_ticks time to recover from recoil for secondary weapon
short primary_charging_ticks time to charge primary weapon
short secondary_charging_ticks time to charge secondary weapon
world_distance primary_recoil_magnitude how far the weapon recoils when firing primary
world_distance secondary_recoil_magnitude how far the weapon recoils when firing secondary
short primary_firing_sound sound when firing primary weapon
short secondary_firing_sound sound when firing secondary weapon
short primary_click_sound primary weapon is empty
short secondary_click_sound secondary weapon is empty
short reload_sound sound when reloading
short charging_sound sound when charging
short primary_shell_casing_sound sound of casing for primary hitting ground
short secondary_shell_casing_sound sound of casing for secondary hitting ground
short primary_sound_activation_range (???)
short secondary_sound_activation_range (???)
short primary_round_projectile_type type of projectile fired from primary
short secondary_round_projectile_type type of projectile fire from secondary
short primary_theta_error 'spread' of the weapon for firing primary
short secondary_theta_error 'spread' of the weapon for firing secondary
short primary_dx displacement for the primary weapon firing in the horizontal direction.
short primary_dz displacement for the primary weapon firing in the vertical direction
short secondary_dx displacement for the secondary weapon firing in the horizontal direction
short secondary_dz displacement for the primary weapon firing in the vertical direction
short primary_burst_count burst fire for primary weapon
short secondary_burst_count burst fire for secondary weapon
short instant_reload_tick no idea (?)

[edit] MAP INFORMATION

The Map file is by far the most complex of all the Marathon files. It contains all information about the structure and layout of the levels. Most Marathon Map files contain multiple levels, which are stored as follows:

header (128 bytes)
level 1
level 2
level 3...
....
level n
trailer (n * 8 bytes)

Each level contains a number of chunks. Not all chunks must be present, and they may be in any order, but levels will not function properly without certain chunks.

The exact format for the header is as follows:

struct map_header /* 128 bytes */
{
short type;
unsigned short flags;
char name[64];
long unknown;
long map_size;
short level_count;
short unused[25]; //not quite..
};
Type Note
type usually zero, as far as I can see.
flags usually zero, as far as I can see.
name ASCII string, zero terminated, up to 64 characters. Usually "Merged Map Files", but for saved games this is the name of the file.
map_size total size of map file, excluding trailer but including header
level_count number of levels

The trailer contains one entry for each level:

struct map_trailer_entry /* 8 bytes */
{
long offset;
long size;
};
Type Note
offset offset from start of file to this level
size total size of all chunks in this level

Each chunk starts with a header, followed by a number of entries (exact size and number of entries depends on the type of chunk). The format for the chunk header is as follows:

struct map_chunk_header /* 12 bytes */
{
long chunk_type;
long offset;
long size;
//..rest of chunk data follows
};
Type Note
chunk_type 4 character ASCII string signifying chunk type
offset offset from start of this level (not start of file) to next chunk
size size of chunk

[edit] Chunk types:

Type Note
'iidx' exclusion zone chunk
'EPNT' vertex chunk (with extra info)
'PNTS' vertex chunk
'LINS' line chunk
'SIDS' side chunk
'POLY' polygon chunk
'NAME' name chunk (name of level)
'LITE' light source chunk
'NOTE' note chunk (text in automap)
'OBJS' object chunk
'pth'  ???
'Minf' map-info chunk (?) (physics and environment info)
'plac' placement chunk
'door'  ??? not used?
'plat' platform chunk (elevators, doors..)
'plyr' player chunk
'dwol'  ???
'mobj'  ???
'alin'  ???
'apol'  ???
'mOns' monster chunk??
'fx ' effects chunk??
'bang'  ???
'PLAT'  ???
  1. define MAXIMUM_VERTICES 1024
  2. define MAXIMUM_LINES 1024
  3. define MAXIMUM_SIDES 1024
  4. define MAXIMUM_POLYGONS 256
  5. define MAXIMUM_LIGHTSOURCES 32
  6. define MAXIMUM_OBJECTS 256


[edit] 'EPNT' / 'PNTS' chunk:

Each 'PNTS' entry is of type world_point2d.

Each 'EPNT' entry has the following structure:

enum /* vertex flags */
{
_vertexSolid = 0x0001,
_vertexMultipleHeights = 0x0002
};
Type Note
_vertexSolid  ???
_vertexMultipleHeights adjacent polygons have different heights


struct vertex_entry /* 16 bytes */
{
unsigned short flags;

world_distance highest_floor;
world_distance lowest_ceiling;

world_point2d vertex;
world_point2d transformed;

short polygon_index;
};


Type Note
flags see above
highest_adjacent_floor highest adjacent floor height
lowest_adjacent_ceiling lowest adjacent ceiling height
vertex coordinates of vertex
transformed  ???
polygon_index  ???

[edit] 'LINS' chunk:

enum /* line flags */
{
_lineSolid = 0x4000,
_lineTransparent = 0x2000,
_lineLandscaped = 0x1000,
_lineElevated = 0x0800,
_lineVariableElevation = 0x0400
};
Type Note
_lineSolid  ?
_lineTransparent  ?
_lineLandscaped  ?
_lineElevated  ?
_lineVariableElevation  ?


struct line_entry /* 32 bytes */
{
short vertex_indexes[2];
unsigned short flags;

world_distance length;
world_distance highest_floor;
world_distance lowest_ceiling;

short left_side_index;
short right_side_index;

short left_polygon_index;
short right_polygon_index;

short unused[6];
};
Type Note
vertex_indexes endpoints of line
flags see above
length length of line
highest_floor highest adjacent floor height
lowest_ceiling lowest adjacent ceiling height
left_side_index  ?
right_side_index  ?
left_polygon_index  ?
right_polygon_index  ?

[edit] 'SIDS' chunk:

enum /* side flags */
{
_sideControlPanelStatus = 0x0001,
_sideControlPanel = 0x0002,
_sideRepairSwitch = 0x0004
};
Type Note
_sideControlPanelStatus  ?
_sideControlPanel  ?
_sideRepairSwitch  ?


enum /* side types */
{
_sideFull,
_sideHigh,
_sideLow,
_sideComposite,
_sideSplit
};
Type Note
_sideFull primary texture is mapped from ceiling down to floor
_sideHigh primary texture is mapped from ceiling downwards
_sideLow primary texture is mapped from floor upwards
_sideComposite primary texture is mapped from ceiling down to floor, secondary texture is mapped ???
_sideSplit primary texture is mapped from ceiling downards, and secondary texture is mapped from floor upwards


enum /* control panel side types */
{
_panelOxygen,
_panelShield,
_panelDoubleShield,
_panelTripleShield,
_panelLightSwitch
_panelPlatformSwitch,
_panelPatternBuffer,
_panelUnused,
_panelCommTerminal
_panelSwitch,
_alienPanelDoubleShield
_alienPanelTripleShield,
_alienPanelPlatformSwitch,
_alienPanelPatternBuffer
};

enum             /* transfer modes (for sides and polygons) */
{
tNormal,
tFadeToBlack,
tInvisible,
tSubInvisible,
tPulsate,        /* polygons only */
tWobble,         /* polygons only */
tFastWobble,     /* polygons only */
tStatic,
tSubStatic,
tLandscape,
tSmear,          /* flat shading */
tFadeOutStatic,
tPulsateStatic,
tFoldIn,
tFoldOut,
tHorizSlide,
tFastHorizSlide,
tVertSlide,
tFastVertSlide,
tWander,
tFastWander
};


Type Note
tNormal normal texture mapping
tFadeToBlack
tInvisible
tSubInvisible
tPulsate
tWobble
tFastWobble
tStatic
tSubStatic
tLandscape direct copy (no texture mapping). This is typically used to draw the view outside of windows.
tSmear fill polygon with pixel (0,0)
tFadeOutStatic
tPulsateStatic
tFoldIn
tFoldOut
tHorizSlide
tFastHorizSlide
tVertSlide
tFastVertSlide
tWander
tFastWander


struct side_texture_struct /* 6 bytes */
{
world_distance x0, y0;
shape_descriptor texture;
};


Type Note
x0,y0 texture offsets
texture specifies texture set (first byte) and texture (second byte)


struct side_exclusion_zone /* 16 bytes */
{
world_point2d e0, e1, e2, e3;
}; 

%e0,e1,e2,e3:

struct side_entry /* 64 bytes */
{
short type;
unsigned short flags;

struct side_texture_struct primary_texture;
struct side_texture_struct secondary_texture;
struct side_texture_struct transparent_texture;

struct side_exclusion_zone exclusion_zone;

short control_panel_type;
short control_panel_permutation;

short primary_transfer_mode;
short secondary_transfer_mode;
short transparent_transfer_mode;

angle direction;
short line_index;

short unused[6];
};

[edit] 'POLY' chunk:

enum /* polygon flags */
{
_polygonDetached = 0x4000,
_polygonPlatformInitiallyOff = 0x2000,
_polygonPlatformInitiallyExtended = 0x1000
};


Type Note
_polygonDetached  ???
_polygonPlatformInitiallyOff platform is initially off
_polygonPlatformInitiallyExtended platform is initially extended


enum /* polygon types */
{
_polygonNormal,
_polygonItemImpassable,
_polygonMonsterImpassable,
_polygonMinorDamage,
_polygonMajorDamage,
_polygonPlatform,
_polygonLightOnTrigger,
_polygonPlatformOnTrigger,
_polygonLightOffTrigger,
_polygonPlatformOffTrigger,
_polygonTeleporter,
_polygonGlueTrigger,
_polygonSuperglue,
_polygonMustExplore,
_polygonExit
};

struct polygon_entry /* 128 bytes */
{
short type;
unsigned short flags;
short permutation;

short vertex_count;
short vertex_index[8];
short line_index[8];

shape_descriptor floor_texture;
shape_descriptor ceiling_texture;
world_distance floor_height;
world_distance ceiling_height;
short floor_lightsource_index;
short ceiling_lightsource_index;

long area;

short first_object;

short first_exclusion_zone_index;
short line_exclusion_zone_count;
short point_exclusion_zone_count;

short floor_transfer_mode;
short ceiling_transfer_mode;

short adjacent_polygon_index[8];

short first_neighbor_index;
short neighbor_count;

world_point2d center;

short side_index[8];

short unused[10];
};

[edit] 'NAME' chunk:

[edit] 'LITE' chunk:

enum /* light flags */
{
_lightAutotriggered = 0x4000;
};

enum /* light types */
{
_lightNormal,
_lightRheostat,
_lightFlourescent,
_lightStrobe,
_lightFlicker,
_lightPulsate,
_lightAnnoying,
_lightEnergyEfficient
};

enum /* light modes */
{
_lightTurningOn,
_lightOn,
_lightTurningOff,
_lightOff,
_lightToggle
};

struct lightsource_entry /* 32 bytes */
{
unsigned short flags;

short type;
short mode;
short phase;

fixed minimum_intensity;
fixed maximum_intensity;
short period;

fixed intensity;

short unused[5];
};

[edit] 'NOTE' chunk:

[edit] 'OBJS' chunk:

enum /* map object types */
{
_savedMonster,
_savedObject,
_savedItem,
_savedPlayer,
_savedGoal
};

struct map_object_entry /* 16 bytes */
{
short type;
short index;
short facing;
short polygon_index;
world_point2d location;
short unused[2];
};

[edit] 'pth' chunk:

[edit] 'Minf' chunk:

enum /* mission flags */
{
_missionNone = 0x0000,
_missionExtermination = 0x0001,
_missionExploration = 0x0002,
_missionRetrieval = 0x0004,
_missionRepair = 0x0008,
_missionRescue = 0x0010
};

enum /* environment flags */
{
_environmentNormal = 0x0000,
_environmentVacuum = 0x0001,
_environmentMagnetic = 0x0002,
_environmentRebellion = 0x0004,
_environmentLowGravity = 0x0008
};

struct static_entry /* 86 bytes */
{
short environment_code;

short physics_model;

short song_index;
unsigned short mission_flags;
unsigned short environment_flags;

short unused[4];

char level_name[64];
long entry_point_flags;
};

[edit] 'plat' chunk:

enum /* platform types */
{
_platformInitiallyActive = 0x00000001,
_platformInitiallyExtended = 0x00000002,
_platformStopsAtEachLevel = 0x00000004,
_platformStopsAtInitialLevel = 0x00000008,
_platformActivatesAdjacentUponDeactivating = 0x00000010,
_platformExtendsFloorToCeiling = 0x00000020,
_platformExtendsFloor = 0x00000040,
_platformExtendsCeiling = 0x00000080,
_platformCausesDamage = 0x00000100,
_platformNoActivateParent = 0x00000200,
_platformOneShot = 0x00000400,
_platformActivatesLight = 0x00000800,
_platformDeactivatesLight = 0x00001000,
_platformPlayerControllable = 0x00002000,
_platformMonsterControllable = 0x00004000,
_platformSafety = 0x00008000,
_platformNoExternalActivate = 0x00010000,
_platformUsesNativeHeights = 0x00020000,
_platformDelaysBeforeActivate = 0x00040000,
_platformActivatesAdjacentUponActivating = 0x00080000,
_platformDeactivatesAdjacentUponActivating = 0x00100000,
_platformDeactivatesAdjacentUponDeactivating = 0x00200000,
_platformContractsSlow = 0x00400000,
_platformActivatesAdjacentOnEachLevel = 0x00800000,
_platformFloods = 0x01000000
};


struct platform_entry /* 16 bytes */
{
short type;

short speed;
short delay;

short maximum_height;
short minimum_height;

unsigned long flags;

short owner_polygon_index;

short unused[8];
};

[edit]  ?

enum /* game options */
{
_gameMultiplayer = 0x0001,
_gameReplenishAmmo = 0x0002,
_gameReplenishWeapons = 0x0004,
_gameReplenishSpecials = 0x0008,
_gameReplenishMonsters = 0x0010,
_gameNoMotionSensor = 0x0020,
_gameOmniscientMap = 0x0040,
_gameLoseItemsOnDeath = 0x0080,
_gameDebugMap = 0x0100,
_gameKillLimit = 0x0200,
_gameNoTeams = 0x0400,
_gamePenalizeDying = 0x0800,
_gamePenalizeSuicide = 0x1000,
_gameMapShowsItems = 0x2000,
_gameMapShowsMonsters = 0x4000,
_gameMapShowsProjectiles = 0x8000
};
Personal tools