From 49e11a611aa0aaac2f3584324604c0c9da471550 Mon Sep 17 00:00:00 2001 From: mszulecki Date: Wed, 7 Mar 2007 00:08:36 +0000 Subject: Add rough prototype of specifications and license info for the library/tools. git-svn-id: http://svn.sukimashita.com/repos/hldemo/trunk@3 e98d5eb1-5f28-0410-b569-d5a1ad2e6e54 --- doc/hl1-demofile-spec.txt | 299 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) (limited to 'doc') diff --git a/doc/hl1-demofile-spec.txt b/doc/hl1-demofile-spec.txt index e69de29..930b20b 100644 --- a/doc/hl1-demofile-spec.txt +++ b/doc/hl1-demofile-spec.txt @@ -0,0 +1,299 @@ +Half-Life 1 Demofile Specifications +-------------------------------------------------------------------------------- + +The Half-Life Demofile format has it's roots in the Quake 1 Demo format and is +basically just an extension to it. Thus it contains only basic descriptors which +rapidly points into raw recorded network data. + +It requires a lot of game engine related logic to be used for parsing such a +file in a non-game client application. This explains the lack of any +documentation or examples in the SDK as it would require to heavily open up +game engine sources. + + +General Fileformat Data Hiarchy: + +DemoFile { + DemoHeader + + DemoSegment { + DemoMacroBlock { + DemoMacroHeader + DemoMacroData { + + } + } + ... + } + ... + + DemoDirectoryEntry + ... +} + + +Demofile Header +-------------------------------------------------------------------------------- +The header starting at the beginning of the file contains the magic and further +global game related information. + +DemoHeader->directory_offset points to a table of DemoDirectoryEntry structs +prefixed by a count and suffixed by a file offset to the end of table. + +The location of the entries is usually somewhere at the end of the demo file, +which is often a cause for "corrupt" demofiles if the data inbetween got +altered/wrongly written by the game itself (raw network stream insanity or +crash) thus resulting in a wrong offset. + +This can be fixed by parsing the end of the file for directory entries and +fixing the proper offset value which allows playback in the game again. + +Known network_version -> Half-Life version mappings: + + 40 = '1.0.1.6' + 42 = '1.1.0.1' + 43 = '1.1.0.4/6' + 45 = '1.1.0.8' + 46 = '1.1.1.x' + 47 = '1.1.1.x' + +struct DemoHeader +{ + char[8] magic; + uint32 demo_version; + uint32 network_version; + char[260] map_name; + char[260] game_dll; + uint32 map_crc; + uint32 directory_offset { + uint32 dir_count; // 1 to 1024 + DemoDirectoryEntry* entries; + uint32 dir_end; + } +} + + +Demofile Directory Entries +-------------------------------------------------------------------------------- + +A directory entry is used to define a series of data segments of the recording +which contain the game data. Usually this is used to split data of the +"Loading..." part and the actual game recording part. + +DemoDirectoryEntry->offset points to the start of a data segment within the +demofile. + +struct DemoDirectoryEntry +{ + uint32 number; + char[64] title; + uint32 flags; + int32 play; + float32 time; + uint32 frames; + uint32 offset; // points to a DemoSegment + uint32 length; // length of the DemoSegment at offset +} + + +Demofile Data Segments +-------------------------------------------------------------------------------- + +Each segment is of variable size and contains a sequence of numbered macro +blocks. We use it here purely as a virtual container. + +struct DemoSegment +{ + DemoMacro* macros; +} + + +Demofile Macro Blocks +-------------------------------------------------------------------------------- + +Each macro block is "stamped" with time and frame information from the +recording and is followed by the individual macro type data which has to be +parsed individually. This relates to the game engine's status information at +a specific time. + +The game uses 10 macro types: + + 0 = 'Game Data' + 1 = 'Game Data' + 2 = 'N/A' // unused, skip + 3 = 'Client Command' // string + 4 = 'N/A' // string + 5 = 'Last in segment' + 6 = 'N/A' + 7 = 'N/A'-------------------------------------------------------------------------------- + 8 = 'Play Sound' + 9 = 'N/A' // delta data + +struct DemoMacroHeader +{ + uint32 file_offset; + uint8 type; + float32 time; + uiint32 frame; + ... +} + +Demofile Macro Types +-------------------------------------------------------------------------------- + +Each macro type has it's own structure closely related to the game engine and +it's parsing differs among the demo's network version. + +# 0 and 1 / Game Data: + +struct DemoMacro_GameData +{ + if(network_version = 42) + { + uint8[560] extinfo; + } + else + if(network_version >= 45) + { + uint8[220] extinfo; + uint16 recorded_resolution_width; + uint16 recorded_resolution_height; + uint16 recorded_resolution_depth; + uint8[238] extinfo; + } + + int32 chunklength; // size of following DemoServerMessage + ... +} + +A server message follows the game data information and is parsed dynamically. + +struct DemoServerMessage +{ + uint8 id; + ... +} + +List of Server Message IDs: + +{0} 'bad', +{1} 'nop', +{2} 'disconnect', +{3} 'event', +{4} 'version', +{5} 'setview', +{6} 'sound', +{7} 'time', +{8} 'print', +{9} 'stufftext', +{10} 'setangle', +{11} 'serverinfo', +{12} 'lightstyle', +{13} 'updateuserinfo', +{14} 'deltadescription', +{15} '', +{16} 'stopsound', +{17} '', +{18} '', +{19} '', +{20} '', +{21} '', +{22} '', +{23} 'temp_entity', +{24} 'setpause', +{25} '', +{26} '', +{27} '', +{28} '', +{29} 'spawnstaticsound', +{30} 'intermission', +{31} '', +{32} 'cdtrack', +{33} '', +{34} '', +{35} 'weaponanim', +{36} '', +{37} 'roomtype', +{38} 'addangle', +{39} 'newusermsg', +{40} '', +{41} '', +{42} '', +{43} '', +{44} '', +{45} 'classinfo', +{46} '', +{47} '', +{48} '', +{49} '', +{50} 'hltv', +{51} 'director', +{52} '', +{53} '', +{54} 'sendextrainfo', +{55} '', +{56} '', +{57} '', +{58} '', +{59} '', +{60} '', +{61} '', +{62} '', +{63} '', +{64} '', +{65} '', +{66} '', +{67} '', +{68} '', +{69} '', +{70} '', +{71} '', +{72} '', +{73} '', +{74} '', +{75} '', +{76} '', +{77} '', +{78} '', +{79} '', +{80} '', +{81} '', +{82} '', +{83} '', +{84} '', +{85} '', +{86} '', +{87} '', +{88} '', +{89} '', +{90} '', +{91} '', +{92} '', +{93} '', +{94} '', +{95} '', +{96} '', +{97} '', +{98} '', +{99} '', +{100} '' + +# 2 / Unknown + +This is an unused macro type in Half-Life and should never be encountered. + +# 3 / Client Command + +A null-terminated string corresponding to a client command such as "+weapon". + +# 4 / Unknown + +A null-terminated string. + +# 5 / Last in segment + +This macro type marks the end of this segment for verification and switch to the +next one. + +# 6 / Unknown + -- cgit v1.1-32-gdbae