Click for more information!

THE .DEM FILE FORMAT
messy

This is the documentation provided on the .dem format that blood uses for it's demos. It came with 1.21 One Whole Unit.

messy

Blood's .DEM file format (1.10 and above)
Copyright 1997, Monolith Productions. All Rights Reserved.

08/20/97

THIS IS ALL SUBJECT TO CHANGE.

===============================================================================
WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
===============================================================================

The INPUT structure couuld change, causing the demos to be invalid. 

More often, however, AI or weapon changes cause the recorded actions to 
become 'not the intended action'. 

For example, 1.02 demos that use the Voo-Doo alt-fire were 'broken' in 1.10
when the alt-fire VooDoo action was changed. Monsters that were previously
killed were now still alive. This could cause the player to run into them
instead of proceeding safely to the next area, etc. All further actions
would then be modified as the recorded re-actions of the player are now blindly
responsding to events that don't happen. The usual result is early death.

===============================================================================

File format:

DEMOHEAHDER
INPUT[nInputCount][nNetPlayers] // set of INPUT for each of the players.

===============================================================================

DEMOHEADER Structure definition

struct DEMOHEADER
{
DWORD signature; //'DEM\0x1a'
BLOODVERSION nVersion; // version of Blood that created the demo
long nBuild; // build of Blood that created the demo
// builds are:
// SW, SWCD: 2
// Registered: 3
// Plasma Pak: 4
long nInputCount; // number of INPUT structures recorded
int nNetPlayers; // number of players recorded
short nMyConnectIndex; // the ID of the player
short nConnectHead; // index into connectPoints of Player
short connectPoints[MAXPLAYERS]; // IDs of players

GAMEOPTIONS gameOptions; // game options used for level
};


===============================================================================

GAMEOPTIONS Structure definition

struct GAMEOPTIONS
{
GAMETYPE nGameType;
DIFFICULTY nDifficulty;
int nEpisode;
int nLevel;
char zLevelName[ _MAX_PATH ];
char zLevelSong[ _MAX_PATH ];
int nTrackNumber;
char szSaveGameName[kMaxFileKeyLen];
char szUserGameName[kMaxFileKeyLen];
short nSaveGameSlot;
int picEntry;
ulong uMapCRC;
MONSTERSETTINGS nMonsterSettings;

ulong uGameFlags;

// net game options/data only
ulong uNetGameFlags;

WEAPONSETTINGS nWeaponSettings;
ITEMSETTINGS nItemSettings;
RESPAWNSETTINGS nRespawnSettings;
TEAMSETTINGS nTeamSettings; // team and cooperative

int nMonsterRespawnTime;
int nWeaponRespawnTime;
int nItemRespawnTime;
int nSpecialRespawnTime;
};


===============================================================================

INPUT Structure definition

/***********************************************************************
* BUTTONFLAGS
*
* This structure is packetized and sent to other players. These keys
* are used frequently during the game. The purpose for separating and
* keeping this structure small, is to limit the amount of transferred
* data.
*
**********************************************************************/
union BUTTONFLAGS
{
char byte;
struct
{
unsigned jump : 1; // player is jumping (once!)
unsigned crouch : 1; // player is crouching
unsigned shoot : 1; // normal attack
unsigned shoot2 : 1; // alternate attack
unsigned lookUp : 1; // > glance or aim up/down
unsigned lookDown : 1; // > if glancing then lookCenter is set
};
};

union KEYFLAGS
{
short word;
struct
{
unsigned action : 1; // open or activate
unsigned jab : 1; // quick attack
unsigned prevItem : 1; // next inventory item
unsigned nextItem : 1; // prev inventory item
unsigned useItem : 1; // use inventory item
unsigned prevWeapon : 1; // prev useable weapon
unsigned nextWeapon : 1; // next useable weapon
unsigned holsterWeapon : 1; // holster current weapon

unsigned lookCenter : 1; // used for lookUp/lookDown only
unsigned lookLeft : 1; // > glance or aim up/down
unsigned lookRight : 1; // > if glancing then lookCenter is set
unsigned spin180 : 1; // spin 180 degrees

unsigned pause : 1; // pause the game
unsigned quit : 1; // quit the game
unsigned restart : 1; // restart the level
};
};

union USEFLAGS
{
char byte;
struct
{
unsigned useBeastVision : 1;
unsigned useCrystalBall : 1;
unsigned useJumpBoots : 1;
unsigned useMedKit : 1;
};
};

union SYNCFLAGS
{
char byte;
struct
{
unsigned buttonChange : 1;
unsigned keyChange : 1;
unsigned useChange : 1;
unsigned weaponChange : 1;
unsigned mlookChange : 1;
unsigned run : 1; // player is running
};
};

struct INPUT
{
SYNCFLAGS syncFlags; // always sent: indicates optional fields
schar forward; // always sent
sshort turn; // always sent
schar strafe; // always sent

// optional fields
BUTTONFLAGS buttonFlags;
KEYFLAGS keyFlags;
USEFLAGS useFlags;
uchar newWeapon; // sent as 0 every frame unless changed
schar mlook;
};