about summary refs log tree commit diff
path: root/src/engine/e_demorec.cpp
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2010-05-29 07:25:38 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2010-05-29 07:25:38 +0000
commit72c06a258940696093f255fb1061beb58e1cdd0b (patch)
tree36b9a7712eec2d4f07837eab9c38ef1c5af85319 /src/engine/e_demorec.cpp
parente56feb597bc743677633432f77513b02907fd169 (diff)
downloadzcatch-72c06a258940696093f255fb1061beb58e1cdd0b.tar.gz
zcatch-72c06a258940696093f255fb1061beb58e1cdd0b.zip
copied refactor to trunk
Diffstat (limited to 'src/engine/e_demorec.cpp')
-rw-r--r--src/engine/e_demorec.cpp640
1 files changed, 0 insertions, 640 deletions
diff --git a/src/engine/e_demorec.cpp b/src/engine/e_demorec.cpp
deleted file mode 100644
index 1bab1b8d..00000000
--- a/src/engine/e_demorec.cpp
+++ /dev/null
@@ -1,640 +0,0 @@
-#include <base/system.h>
-#include "e_demorec.h"
-#include "e_memheap.h"
-#include "e_snapshot.h"
-#include "e_compression.h"
-#include "e_network.h"
-#include "e_engine.h"
-#include "e_if_other.h"
-
-static IOHANDLE record_file = 0;
-static const unsigned char header_marker[8] = {'T', 'W', 'D', 'E', 'M', 'O', 0, 1};
-
-/* Record */
-static int record_lasttickmarker = -1;
-static int record_lastkeyframe;
-static unsigned char record_lastsnapshotdata[CSnapshot::MAX_SIZE];
-
-int demorec_isrecording() { return record_file != 0; }
-
-int demorec_record_start(const char *filename, const char *netversion, const char *map, int crc, const char *type)
-{
-	DEMOREC_HEADER header;
-	if(record_file)
-		return -1;
-
-	record_file = engine_openfile(filename, IOFLAG_WRITE);
-	
-	if(!record_file)
-	{
-		dbg_msg("demorec/record", "Unable to open '%s' for recording", filename);
-		return -1;
-	}
-	
-	/* write header */
-	mem_zero(&header, sizeof(header));
-	mem_copy(header.marker, header_marker, sizeof(header.marker));
-	str_copy(header.netversion, netversion, sizeof(header.netversion));
-	str_copy(header.map, map, sizeof(header.map));
-	str_copy(header.type, type, sizeof(header.type));
-	header.crc[0] = (crc>>24)&0xff;
-	header.crc[1] = (crc>>16)&0xff;
-	header.crc[2] = (crc>>8)&0xff;
-	header.crc[3] = (crc)&0xff;
-	io_write(record_file, &header, sizeof(header));
-	
-	record_lastkeyframe = -1;
-	record_lasttickmarker = -1;
-	
-	dbg_msg("demorec/record", "Recording to '%s'", filename);
-	return 0;
-}
-
-/*
-	Tickmarker
-		7   = Always set
-		6   = Keyframe flag
-		0-5 = Delta tick
-	
-	Normal
-		7   = Not set
-		5-6 = Type
-		0-4 = Size
-*/
-
-enum
-{
-	CHUNKTYPEFLAG_TICKMARKER = 0x80,
-	CHUNKTICKFLAG_KEYFRAME = 0x40, /* only when tickmarker is set*/
-	
-	CHUNKMASK_TICK = 0x3f,
-	CHUNKMASK_TYPE = 0x60,
-	CHUNKMASK_SIZE = 0x1f,
-	
-	CHUNKTYPE_SNAPSHOT = 1,
-	CHUNKTYPE_MESSAGE = 2,
-	CHUNKTYPE_DELTA = 3,
-
-	CHUNKFLAG_BIGSIZE = 0x10
-};
-
-static void demorec_record_write_tickmarker(int tick, int keyframe)
-{
-	if(record_lasttickmarker == -1 || tick-record_lasttickmarker > 63 || keyframe)
-	{
-		unsigned char chunk[5];
-		chunk[0] = CHUNKTYPEFLAG_TICKMARKER;
-		chunk[1] = (tick>>24)&0xff;
-		chunk[2] = (tick>>16)&0xff;
-		chunk[3] = (tick>>8)&0xff;
-		chunk[4] = (tick)&0xff;
-
-		if(keyframe)
-			chunk[0] |= CHUNKTICKFLAG_KEYFRAME;
-		
-		io_write(record_file, chunk, sizeof(chunk));
-	}
-	else
-	{
-		unsigned char chunk[1];
-		chunk[0] = CHUNKTYPEFLAG_TICKMARKER | (tick-record_lasttickmarker);
-		io_write(record_file, chunk, sizeof(chunk));
-	}	
-
-	record_lasttickmarker = tick;
-}
-
-static void demorec_record_write(int type, const void *data, int size)
-{
-	char buffer[64*1024];
-	char buffer2[64*1024];
-	unsigned char chunk[3];
-	
-	if(!record_file)
-		return;
-
-	
-	/* pad the data with 0 so we get an alignment of 4,
-	else the compression won't work and miss some bytes */
-	mem_copy(buffer2, data, size);
-	while(size&3)
-		buffer2[size++] = 0;
-	size = intpack_compress(buffer2, size, buffer); /* buffer2 -> buffer */
-	size = CNetBase::Compress(buffer, size, buffer2, sizeof(buffer2)); /* buffer -> buffer2 */
-	
-	
-	chunk[0] = ((type&0x3)<<5);
-	if(size < 30)
-	{
-		chunk[0] |= size;
-		io_write(record_file, chunk, 1);
-	}
-	else
-	{
-		if(size < 256)
-		{
-			chunk[0] |= 30;
-			chunk[1] = size&0xff;
-			io_write(record_file, chunk, 2);
-		}
-		else
-		{
-			chunk[0] |= 31;
-			chunk[1] = size&0xff;
-			chunk[2] = size>>8;
-			io_write(record_file, chunk, 3);
-		}
-	}
-	
-	io_write(record_file, buffer2, size);
-}
-
-void demorec_record_snapshot(int tick, const void *data, int size)
-{
-	if(record_lastkeyframe == -1 || (tick-record_lastkeyframe) > SERVER_TICK_SPEED*5)
-	{
-		/* write full tickmarker */
-		demorec_record_write_tickmarker(tick, 1);
-		
-		/* write snapshot */
-		demorec_record_write(CHUNKTYPE_SNAPSHOT, data, size);
-			
-		record_lastkeyframe = tick;
-		mem_copy(record_lastsnapshotdata, data, size);
-	}
-	else
-	{
-		/* create delta, prepend tick */
-		char delta_data[CSnapshot::MAX_SIZE+sizeof(int)];
-		int delta_size;
-
-		/* write tickmarker */
-		demorec_record_write_tickmarker(tick, 0);
-		
-		delta_size = CSnapshot::CreateDelta((CSnapshot*)record_lastsnapshotdata, (CSnapshot*)data, &delta_data);
-		if(delta_size)
-		{
-			/* record delta */
-			demorec_record_write(CHUNKTYPE_DELTA, delta_data, delta_size);
-			mem_copy(record_lastsnapshotdata, data, size);
-		}
-	}
-}
-
-void demorec_record_message(const void *data, int size)
-{
-	demorec_record_write(CHUNKTYPE_MESSAGE, data, size);
-}
-
-int demorec_record_stop()
-{
-	if(!record_file)
-		return -1;
-		
-	dbg_msg("demorec/record", "Stopped recording");
-	io_close(record_file);
-	record_file = 0;
-	return 0;
-}
-
-/* Playback */
-typedef struct KEYFRAME
-{
-	long filepos;
-	int tick;
-} KEYFRAME;
-
-typedef struct KEYFRAME_SEARCH
-{
-	KEYFRAME frame;
-	struct KEYFRAME_SEARCH *next;
-} KEYFRAME_SEARCH;
-
-static IOHANDLE play_file = 0;
-static DEMOREC_PLAYCALLBACK play_callback_snapshot = 0;
-static DEMOREC_PLAYCALLBACK play_callback_message = 0;
-static KEYFRAME *keyframes = 0;
-
-static DEMOREC_PLAYBACKINFO playbackinfo;
-static unsigned char playback_lastsnapshotdata[CSnapshot::MAX_SIZE];
-static int playback_lastsnapshotdata_size = -1;
-
-
-const DEMOREC_PLAYBACKINFO *demorec_playback_info() { return &playbackinfo; }
-int demorec_isplaying() { return play_file != 0; }
-
-int demorec_playback_registercallbacks(DEMOREC_PLAYCALLBACK snapshot_cb, DEMOREC_PLAYCALLBACK message_cb)
-{
-	play_callback_snapshot = snapshot_cb;
-	play_callback_message = message_cb;
-	return 0;
-}
-
-static int read_chunk_header(int *type, int *size, int *tick)
-{
-	unsigned char chunk = 0;
-	
-	*size = 0;
-	*type = 0;
-	
-	if(io_read(play_file, &chunk, sizeof(chunk)) != sizeof(chunk))
-		return -1;
-		
-	if(chunk&CHUNKTYPEFLAG_TICKMARKER)
-	{
-		/* decode tick marker */
-		int tickdelta = chunk&(CHUNKMASK_TICK);
-		*type = chunk&(CHUNKTYPEFLAG_TICKMARKER|CHUNKTICKFLAG_KEYFRAME);
-		
-		if(tickdelta == 0)
-		{
-			unsigned char tickdata[4];
-			if(io_read(play_file, tickdata, sizeof(tickdata)) != sizeof(tickdata))
-				return -1;
-			*tick = (tickdata[0]<<24) | (tickdata[1]<<16) | (tickdata[2]<<8) | tickdata[3];
-		}
-		else
-		{
-			*tick += tickdelta;
-		}
-		
-	}
-	else
-	{
-		/* decode normal chunk */
-		*type = (chunk&CHUNKMASK_TYPE)>>5;
-		*size = chunk&CHUNKMASK_SIZE;
-		
-		if(*size == 30)
-		{
-			unsigned char sizedata[1];
-			if(io_read(play_file, sizedata, sizeof(sizedata)) != sizeof(sizedata))
-				return -1;
-			*size = sizedata[0];
-			
-		}
-		else if(*size == 31)
-		{
-			unsigned char sizedata[2];
-			if(io_read(play_file, sizedata, sizeof(sizedata)) != sizeof(sizedata))
-				return -1;
-			*size = (sizedata[1]<<8) | sizedata[0];
-		}
-	}
-	
-	return 0;
-}
-
-static void scan_file()
-{
-	long start_pos;
-	HEAP *heap = 0;
-	KEYFRAME_SEARCH *first_key = 0;
-	KEYFRAME_SEARCH *current_key = 0;
-	/*DEMOREC_CHUNK chunk;*/
-	int chunk_size, chunk_type, chunk_tick = 0;
-	int i;
-	
-	heap = memheap_create();
-
-	start_pos = io_tell(play_file);
-	playbackinfo.seekable_points = 0;
-
-	while(1)
-	{
-		long current_pos = io_tell(play_file);
-		
-		if(read_chunk_header(&chunk_type, &chunk_size, &chunk_tick))
-			break;
-			
-		/* read the chunk */
-		if(chunk_type&CHUNKTYPEFLAG_TICKMARKER)
-		{
-			if(chunk_type&CHUNKTICKFLAG_KEYFRAME)
-			{
-				KEYFRAME_SEARCH *key;
-				
-				/* save the position */
-				key = (KEYFRAME_SEARCH *)memheap_allocate(heap, sizeof(KEYFRAME_SEARCH));
-				key->frame.filepos = current_pos;
-				key->frame.tick = chunk_tick;
-				key->next = 0;
-				if(current_key)
-					current_key->next = key;
-				if(!first_key)
-					first_key = key;
-				current_key = key;
-				playbackinfo.seekable_points++;
-			}
-			
-			if(playbackinfo.first_tick == -1)
-				playbackinfo.first_tick = chunk_tick;
-			playbackinfo.last_tick = chunk_tick;
-		}
-		else if(chunk_size)
-			io_skip(play_file, chunk_size);
-			
-	}
-
-	/* copy all the frames to an array instead for fast access */
-	keyframes = (KEYFRAME*)mem_alloc(playbackinfo.seekable_points*sizeof(KEYFRAME), 1);
-	for(current_key = first_key, i = 0; current_key; current_key = current_key->next, i++)
-		keyframes[i] = current_key->frame;
-		
-	/* destroy the temporary heap and seek back to the start */
-	memheap_destroy(heap);
-	io_seek(play_file, start_pos, IOSEEK_START);
-}
-
-static void do_tick()
-{
-	static char compresseddata[CSnapshot::MAX_SIZE];
-	static char decompressed[CSnapshot::MAX_SIZE];
-	static char data[CSnapshot::MAX_SIZE];
-	int chunk_type, chunk_tick, chunk_size;
-	int data_size;
-	int got_snapshot = 0;
-
-	/* update ticks */
-	playbackinfo.previous_tick = playbackinfo.current_tick;
-	playbackinfo.current_tick = playbackinfo.next_tick;
-	chunk_tick = playbackinfo.current_tick;
-
-	while(1)
-	{
-		if(read_chunk_header(&chunk_type, &chunk_size, &chunk_tick))
-		{
-			/* stop on error or eof */
-			dbg_msg("demorec", "end of file");
-			demorec_playback_pause();
-			break;
-		}
-		
-		/* read the chunk */
-		if(chunk_size)
-		{
-			if(io_read(play_file, compresseddata, chunk_size) != (unsigned)chunk_size)
-			{
-				/* stop on error or eof */
-				dbg_msg("demorec", "error reading chunk");
-				demorec_playback_stop();
-				break;
-			}
-			
-			data_size = CNetBase::Decompress(compresseddata, chunk_size, decompressed, sizeof(decompressed));
-			if(data_size < 0)
-			{
-				/* stop on error or eof */
-				dbg_msg("demorec", "error during network decompression");
-				demorec_playback_stop();
-				break;
-			}
-			
-			data_size = intpack_decompress(decompressed, data_size, data);
-
-			if(data_size < 0)
-			{
-				dbg_msg("demorec", "error during intpack decompression");
-				demorec_playback_stop();
-				break;
-			}
-		}
-			
-		if(chunk_type == CHUNKTYPE_DELTA)
-		{
-			/* process delta snapshot */
-			static char newsnap[CSnapshot::MAX_SIZE];
-			
-			got_snapshot = 1;
-			
-			data_size = CSnapshot::UnpackDelta((CSnapshot*)playback_lastsnapshotdata, (CSnapshot*)newsnap, data, data_size);
-			
-			if(data_size >= 0)
-			{
-				if(play_callback_snapshot)
-					play_callback_snapshot(newsnap, data_size);
-
-				playback_lastsnapshotdata_size = data_size;
-				mem_copy(playback_lastsnapshotdata, newsnap, data_size);
-			}
-			else
-				dbg_msg("demorec", "error duing unpacking of delta, err=%d", data_size);
-		}
-		else if(chunk_type == CHUNKTYPE_SNAPSHOT)
-		{
-			/* process full snapshot */
-			got_snapshot = 1;
-			
-			playback_lastsnapshotdata_size = data_size;
-			mem_copy(playback_lastsnapshotdata, data, data_size);
-			if(play_callback_snapshot)
-				play_callback_snapshot(data, data_size);
-		}
-		else
-		{
-			/* if there were no snapshots in this tick, replay the last one */
-			if(!got_snapshot && play_callback_snapshot && playback_lastsnapshotdata_size != -1)
-			{
-				got_snapshot = 1;
-				play_callback_snapshot(playback_lastsnapshotdata, playback_lastsnapshotdata_size);
-			}
-			
-			/* check the remaining types */
-			if(chunk_type&CHUNKTYPEFLAG_TICKMARKER)
-			{
-				playbackinfo.next_tick = chunk_tick;
-				break;
-			}
-			else if(chunk_type == CHUNKTYPE_MESSAGE)
-			{
-				if(play_callback_message)
-					play_callback_message(data, data_size);
-			}
-		}
-	}
-}
-
-void demorec_playback_pause()
-{
-	playbackinfo.paused = 1;
-}
-
-void demorec_playback_unpause()
-{
-	if(playbackinfo.paused)
-	{
-		/*playbackinfo.start_tick = playbackinfo.current_tick;
-		playbackinfo.start_time = time_get();*/
-		playbackinfo.paused = 0;
-	}
-}
-
-int demorec_playback_load(const char *filename)
-{
-	play_file = engine_openfile(filename, IOFLAG_READ);
-	if(!play_file)
-	{
-		dbg_msg("demorec/playback", "could not open '%s'", filename);
-		return -1;
-	}
-	
-	/* clear the playback info */
-	mem_zero(&playbackinfo, sizeof(playbackinfo));
-	playbackinfo.first_tick = -1;
-	playbackinfo.last_tick = -1;
-	/*playbackinfo.start_tick = -1;*/
-	playbackinfo.next_tick = -1;
-	playbackinfo.current_tick = -1;
-	playbackinfo.previous_tick = -1;
-	playbackinfo.speed = 1;
-	
-	playback_lastsnapshotdata_size = -1;
-
-	/* read the header */	
-	io_read(play_file, &playbackinfo.header, sizeof(playbackinfo.header));
-	if(mem_comp(playbackinfo.header.marker, header_marker, sizeof(header_marker)) != 0)
-	{
-		dbg_msg("demorec/playback", "'%s' is not a demo file", filename);
-		io_close(play_file);
-		play_file = 0;
-		return -1;
-	}
-	
-	/* scan the file for interessting points */
-	scan_file();
-	
-	/* ready for playback */	
-	return 0;
-}
-
-int demorec_playback_nextframe()
-{
-	do_tick();
-	return demorec_isplaying();
-}
-
-int demorec_playback_play()
-{
-	/* fill in previous and next tick */
-	while(playbackinfo.previous_tick == -1 && demorec_isplaying())
-		do_tick();
-		
-	/* set start info */
-	/*playbackinfo.start_tick = playbackinfo.previous_tick;
-	playbackinfo.start_time = time_get();*/
-	playbackinfo.current_time = playbackinfo.previous_tick*time_freq()/SERVER_TICK_SPEED;
-	playbackinfo.last_update = time_get();
-	return 0;
-}
-
-int demorec_playback_set(float percent)
-{
-	int keyframe;
-	int wanted_tick;
-	if(!play_file)
-		return -1;
-	
-	/* -5 because we have to have a current tick and previous tick when we do the playback */
-	wanted_tick = playbackinfo.first_tick + (int)((playbackinfo.last_tick-playbackinfo.first_tick)*percent) - 5;
-	
-	keyframe = (int)(playbackinfo.seekable_points*percent);
-
-	if(keyframe < 0 || keyframe >= playbackinfo.seekable_points)
-		return -1;
-	
-	/* get correct key frame */
-	if(keyframes[keyframe].tick < wanted_tick)
-		while(keyframe < playbackinfo.seekable_points-1 && keyframes[keyframe].tick < wanted_tick)
-			keyframe++;
-
-	while(keyframe && keyframes[keyframe].tick > wanted_tick)
-		keyframe--;
-	
-	/* seek to the correct keyframe */
-	io_seek(play_file, keyframes[keyframe].filepos, IOSEEK_START);
-
-	/*playbackinfo.start_tick = -1;*/
-	playbackinfo.next_tick = -1;
-	playbackinfo.current_tick = -1;
-	playbackinfo.previous_tick = -1;
-
-	/* playback everything until we hit our tick */
-	while(playbackinfo.previous_tick < wanted_tick)
-		do_tick();
-	
-	demorec_playback_play();
-	
-	return 0;
-}
-
-void demorec_playback_setspeed(float speed)
-{
-	playbackinfo.speed = speed;
-}
-
-int demorec_playback_update()
-{
-	int64 now = time_get();
-	int64 deltatime = now-playbackinfo.last_update;
-	playbackinfo.last_update = now;
-	
-	if(!demorec_isplaying())
-		return 0;
-	
-	if(playbackinfo.paused)
-	{
-		
-	}
-	else
-	{
-		int64 freq = time_freq();
-		playbackinfo.current_time += (int64)(deltatime*(double)playbackinfo.speed);
-		
-		while(1)
-		{
-			int64 curtick_start = (playbackinfo.current_tick)*freq/SERVER_TICK_SPEED;
-
-			/* break if we are ready */		
-			if(curtick_start > playbackinfo.current_time)
-				break;
-			
-			/* do one more tick */
-			do_tick();
-			
-			if(playbackinfo.paused)
-				return 0;
-		}
-
-		/* update intratick */
-		{	
-			int64 curtick_start = (playbackinfo.current_tick)*freq/SERVER_TICK_SPEED;
-			int64 prevtick_start = (playbackinfo.previous_tick)*freq/SERVER_TICK_SPEED;
-			playbackinfo.intratick = (playbackinfo.current_time - prevtick_start) / (float)(curtick_start-prevtick_start);
-			playbackinfo.ticktime = (playbackinfo.current_time - prevtick_start) / (float)freq;
-		}
-		
-		if(playbackinfo.current_tick == playbackinfo.previous_tick ||
-			playbackinfo.current_tick == playbackinfo.next_tick)
-		{
-			dbg_msg("demorec/playback", "tick error prev=%d cur=%d next=%d",
-				playbackinfo.previous_tick, playbackinfo.current_tick, playbackinfo.next_tick);
-		}
-	}
-	
-	return 0;
-}
-
-int demorec_playback_stop()
-{
-	if(!play_file)
-		return -1;
-		
-	dbg_msg("demorec/playback", "Stopped playback");
-	io_close(play_file);
-	play_file = 0;
-	mem_free(keyframes);
-	keyframes = 0;
-	return 0;
-}
-
-