256 lines
6.9 KiB
C
256 lines
6.9 KiB
C
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#ifndef __DEMO_H__
|
||
|
#define __DEMO_H__
|
||
|
|
||
|
//#include "../../sys/sys_local.h"
|
||
|
#include "../UsercmdGen.h"
|
||
|
|
||
|
//===============================================================
|
||
|
//
|
||
|
// sdDemo
|
||
|
//
|
||
|
//===============================================================
|
||
|
|
||
|
#define DEMO_IDENT (('O'<<24)+('M'<<16)+('D'<<8)+'N')
|
||
|
#define DEMO_VERSION 3
|
||
|
#define JUMPSTART_IDENT (('O'<<24)+('D'<<16)+('S'<<8)+'J')
|
||
|
#define JUMPSTART_VERSION 1
|
||
|
#define KEYFRAMEFILE_IDENT (('F'<<24)+('F'<<16)+('K'<<8)+'D')
|
||
|
#define KEYFRAMEFILE_VERSION 1
|
||
|
|
||
|
class sdFrameBuffer;
|
||
|
|
||
|
class sdDemo {
|
||
|
public:
|
||
|
typedef enum demoState_e {
|
||
|
DS_IDLE,
|
||
|
DS_RECORDING,
|
||
|
DS_PLAYING
|
||
|
} demoState_t;
|
||
|
|
||
|
static const int TIMEDEMO_FRAME_MSEC;
|
||
|
static const int KEYFRAME_INTERVAL;
|
||
|
|
||
|
sdDemo();
|
||
|
|
||
|
void Record( const char* fileName );
|
||
|
void Stop();
|
||
|
void Play( const char* fileName, bool timeDemo = false );
|
||
|
void PlayJumpStart( const char* fileName );
|
||
|
|
||
|
static bool CheckVersion( const char* fileName );
|
||
|
|
||
|
demoState_t GetState() const { return state; }
|
||
|
|
||
|
bool IsRecording() const;
|
||
|
bool IsPlaying() const;
|
||
|
bool IsPaused() const;
|
||
|
bool IsTimeDemo() const;
|
||
|
bool IsRenderDemo() const;
|
||
|
bool IsGeneratingKeyFrames() const;
|
||
|
bool IsCuttingDemo() const;
|
||
|
|
||
|
void RecordMessage( const int time, const idBitMsg& msg, int clientPrediction );
|
||
|
bool PlayMessage( const int clientTime, void* data, int& size, const int maxSize, const int timeOut, int& clientPrediction );
|
||
|
|
||
|
void RecordUsercmd( const usercmd_t& usercmd );
|
||
|
void ReadUsercmd( int gameFrame );
|
||
|
|
||
|
void WriteUsercmd( idFile* file, const usercmd_t& usercmd );
|
||
|
bool ReadUsercmd( idFile* file, usercmd_t& usercmd );
|
||
|
|
||
|
void WriteKeyFrame( const int clientTime );
|
||
|
|
||
|
void RunFrame();
|
||
|
|
||
|
// silent stop called from idSessionLocal::Stop, not the same as the Stop() command
|
||
|
void SessionStop();
|
||
|
void Shutdown();
|
||
|
|
||
|
void IncrementDemoFrame() { numDemoFrames++; }
|
||
|
void CaptureRenderDemoFrame( const int gameTime );
|
||
|
|
||
|
const char* GetName() const { return fileName.c_str(); }
|
||
|
int GetRenderDemoFPS() const { return renderDemoFPS; }
|
||
|
|
||
|
int GetStartGameTime() const;
|
||
|
int GetPosition() const;
|
||
|
int GetLength() const;
|
||
|
int GetStartPosition() const;
|
||
|
int GetEndPosition() const;
|
||
|
int GetCutStartMarker() const;
|
||
|
int GetCutEndMarker() const;
|
||
|
usercmd_t GetCachedUsercmd( void ) const { return usercmd; }
|
||
|
|
||
|
void ForceMega();
|
||
|
|
||
|
static void DemoFileName( const char* base, idStr& fileName );
|
||
|
|
||
|
static void Toggle_f( const idCmdArgs& args );
|
||
|
static void Record_f( const idCmdArgs& args );
|
||
|
static void Stop_f( const idCmdArgs& args );
|
||
|
static void Play_f( const idCmdArgs& args );
|
||
|
static void PlayJumpStartDemo_f( const idCmdArgs& args );
|
||
|
static void Time_f( const idCmdArgs& args );
|
||
|
static void Render_f( const idCmdArgs& args );
|
||
|
static void GenerateKeyFrames_f( const idCmdArgs& args );
|
||
|
static void NextKeyFrame_f( const idCmdArgs& args );
|
||
|
static void PrevKeyFrame_f( const idCmdArgs& args );
|
||
|
static void Pause_f( const idCmdArgs& args );
|
||
|
static void CutPlaceStartMarker_f( const idCmdArgs& args );
|
||
|
static void CutPlaceEndMarker_f( const idCmdArgs& args );
|
||
|
static void Cut_f( const idCmdArgs& args );
|
||
|
static void WriteJumpStartDemo_f( const idCmdArgs& args );
|
||
|
|
||
|
public:
|
||
|
static idCVar debug;
|
||
|
static idCVar scale;
|
||
|
static idCVar snapshotDelay;
|
||
|
static idCVar prediction;
|
||
|
static idCVar forceMega;
|
||
|
|
||
|
private:
|
||
|
void Clear();
|
||
|
|
||
|
void DoRenderDemo( const int fps, const int startTime, const int endTime );
|
||
|
void TogglePause();
|
||
|
void WriteJumpStartDemo( const char* jumpStartFileName );
|
||
|
|
||
|
void WriteKeyFrameFile();
|
||
|
void ReadKeyFrames();
|
||
|
void PlayFromKeyFrame( const int keyFrame );
|
||
|
void StepKeyFrame( bool reverse );
|
||
|
|
||
|
void Cut( const char* fileName, const char* cutFileName );
|
||
|
void WriteCut();
|
||
|
void SetCutStartMarker();
|
||
|
void SetCutEndMarker();
|
||
|
|
||
|
void WriteHeader( idFile* file );
|
||
|
int ReadHeader( idFile* file, const idStr& headerFileName );
|
||
|
|
||
|
void WriteNetworkHeader( idFile* file );
|
||
|
void ReadNetworkHeader( idFile* file, bool keyFrame = false );
|
||
|
|
||
|
void WriteDict( idFile* file, const idDict* dict );
|
||
|
void ReadDict( idFile* file, idDict* dict );
|
||
|
|
||
|
void WriteByte( idFile* file, const byte value );
|
||
|
void WriteSignedChar( idFile* file, const signed char value );
|
||
|
|
||
|
void ReadByte( idFile* file, byte& value );
|
||
|
void ReadSignedChar( idFile* file, signed char& value );
|
||
|
|
||
|
static bool CheckVersion( idFile* file, const char* headerFileName, bool verbose );
|
||
|
|
||
|
private:
|
||
|
demoState_t state;
|
||
|
|
||
|
idStr fileName;
|
||
|
idFile* file;
|
||
|
|
||
|
int networkStreamOffset;
|
||
|
|
||
|
int usercmdOffset; // position in file for the ucmd start position record
|
||
|
int usercmdStart; // position in file of the ucmd stream, written at ucmd_offset in file
|
||
|
idFile* usercmdFile;
|
||
|
usercmd_t usercmd;
|
||
|
|
||
|
int startTime;
|
||
|
int startGameTime;
|
||
|
int nextMessageTime;
|
||
|
bool paused;
|
||
|
|
||
|
int numDemoFrames;
|
||
|
|
||
|
bool timeDemo;
|
||
|
bool renderDemo;
|
||
|
bool generatingKeyFrames;
|
||
|
bool cuttingDemo;
|
||
|
|
||
|
idDict userinfo; // backup userinfo to set it to what it was after demo replay
|
||
|
|
||
|
// demo rendering
|
||
|
sdFrameBuffer* renderDemoFrameBuffer;
|
||
|
int renderDemoFPS;
|
||
|
int renderStartTime;
|
||
|
int renderStopTime;
|
||
|
int renderStartFrame;
|
||
|
int renderEndFrame;
|
||
|
|
||
|
// key frames
|
||
|
struct keyFrame_t {
|
||
|
int offset;
|
||
|
int clientTime;
|
||
|
};
|
||
|
|
||
|
idFile* keyFrameFile;
|
||
|
int lastKeyFrameTime;
|
||
|
idList< keyFrame_t> keyFrames;
|
||
|
|
||
|
// demo cutting
|
||
|
idStr cutFileName;
|
||
|
int cutStartMarker;
|
||
|
int cutEndMarker;
|
||
|
};
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsRecording() const {
|
||
|
return state == DS_RECORDING;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsPlaying() const {
|
||
|
return state == DS_PLAYING;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsPaused() const {
|
||
|
return paused;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsTimeDemo() const {
|
||
|
return timeDemo;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsRenderDemo() const {
|
||
|
return renderDemo;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsGeneratingKeyFrames() const {
|
||
|
return generatingKeyFrames;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool sdDemo::IsCuttingDemo() const {
|
||
|
return cuttingDemo;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetStartGameTime() const {
|
||
|
return startGameTime;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetPosition() const {
|
||
|
return ( file != NULL ? file->Tell() : -1 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetLength() const {
|
||
|
return ( file != NULL ? file->Length() : -1 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetStartPosition() const {
|
||
|
return networkStreamOffset;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetEndPosition() const {
|
||
|
return ( file != NULL ? file->Length() - usercmdStart : -1 ) + networkStreamOffset;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetCutStartMarker() const {
|
||
|
return cutStartMarker;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int sdDemo::GetCutEndMarker() const {
|
||
|
return cutEndMarker;
|
||
|
}
|
||
|
|
||
|
#endif /* !__DEMO_H__ */
|