about summary refs log tree commit diff
path: root/src/engine/shared/demo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/shared/demo.cpp')
-rw-r--r--src/engine/shared/demo.cpp79
1 files changed, 69 insertions, 10 deletions
diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp
index e48c2f1e..37c82cce 100644
--- a/src/engine/shared/demo.cpp
+++ b/src/engine/shared/demo.cpp
@@ -1,17 +1,21 @@
 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
 /* If you are missing that file, acquire a complete release at teeworlds.com.                */
+#include <base/math.h>
 #include <base/system.h>
+
 #include <engine/console.h>
 #include <engine/storage.h>
+
+#include "compression.h"
 #include "demo.h"
 #include "memheap.h"
-#include "snapshot.h"
-#include "compression.h"
 #include "network.h"
+#include "snapshot.h"
 
 static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0};
-static const unsigned char gs_ActVersion = 3;
+static const unsigned char gs_ActVersion = 4;
 static const int gs_LengthOffset = 152;
+static const int gs_NumMarkersOffset = 176;
 
 
 CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta)
@@ -86,6 +90,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
 	str_copy(Header.m_aType, pType, sizeof(Header.m_aType));
 	// Header.m_Length - add this on stop
 	str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp));
+	// Header.m_aNumTimelineMarkers - add this on stop
+	// Header.m_aTimelineMarkers - add this on stop
 	io_write(DemoFile, &Header, sizeof(Header));
 
 	// write map data
@@ -102,6 +108,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
 	m_LastKeyFrame = -1;
 	m_LastTickMarker = -1;
 	m_FirstTick = -1;
+	m_NumTimelineMarkers = 0;
 
 	char aBuf[256];
 	str_format(aBuf, sizeof(aBuf), "Recording to '%s'", pFilename);
@@ -263,6 +270,25 @@ int CDemoRecorder::Stop()
 	aLength[3] = (DemoLength)&0xff;
 	io_write(m_File, aLength, sizeof(aLength));
 
+	// add the timeline markers to the header
+	io_seek(m_File, gs_NumMarkersOffset, IOSEEK_START);
+	char aNumMarkers[4];
+	aNumMarkers[0] = (m_NumTimelineMarkers>>24)&0xff;
+	aNumMarkers[1] = (m_NumTimelineMarkers>>16)&0xff;
+	aNumMarkers[2] = (m_NumTimelineMarkers>>8)&0xff;
+	aNumMarkers[3] = (m_NumTimelineMarkers)&0xff;
+	io_write(m_File, aNumMarkers, sizeof(aNumMarkers));
+	for(int i = 0; i < m_NumTimelineMarkers; i++)
+	{
+		int Marker = m_aTimelineMarkers[i];
+		char aMarker[4];
+		aMarker[0] = (Marker>>24)&0xff;
+		aMarker[1] = (Marker>>16)&0xff;
+		aMarker[2] = (Marker>>8)&0xff;
+		aMarker[3] = (Marker)&0xff;
+		io_write(m_File, aMarker, sizeof(aMarker));
+	}
+
 	io_close(m_File);
 	m_File = 0;
 	m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Stopped recording");
@@ -270,6 +296,24 @@ int CDemoRecorder::Stop()
 	return 0;
 }
 
+void CDemoRecorder::AddDemoMarker()
+{
+	if(m_LastTickMarker < 0 || m_NumTimelineMarkers >= MAX_TIMELINE_MARKERS)
+		return;
+
+	// not more than 1 marker in a second
+	if(m_NumTimelineMarkers > 0)
+	{
+		int Diff = m_LastTickMarker - m_aTimelineMarkers[m_NumTimelineMarkers-1];
+		if(Diff < SERVER_TICK_SPEED*1.0f)
+			return;
+	}
+
+	m_aTimelineMarkers[m_NumTimelineMarkers++] = m_LastTickMarker;
+
+	m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Added timeline marker");
+}
+
 
 
 CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta)
@@ -619,6 +663,16 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
 		mem_free(pMapData);
 	}
 
+	// get timeline markers
+	int Num = ((m_Info.m_Header.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_Header.m_aNumTimelineMarkers[1]<<16)&0xFF0000) |
+				((m_Info.m_Header.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_Header.m_aNumTimelineMarkers[3]&0xFF);
+	m_Info.m_Info.m_NumTimelineMarkers = Num;
+	for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++)
+	{
+		char *pTimelineMarker = m_Info.m_Header.m_aTimelineMarkers[i];
+		m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) |
+												((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF);
+	}
 
 	// scan the file for interessting points
 	ScanFile();
@@ -760,16 +814,21 @@ int CDemoPlayer::Stop()
 	return 0;
 }
 
-char *CDemoPlayer::GetDemoName()
+void CDemoPlayer::GetDemoName(char *pBuffer, int BufferSize) const
 {
-	// get the name of the demo without its path
-	char *pDemoShortName = &m_aFilename[0];
-	for(int i = 0; i < str_length(m_aFilename)-1; i++)
+	const char *pFileName = m_aFilename;
+	const char *pExtractedName = pFileName;
+	const char *pEnd = 0;
+	for(; *pFileName; ++pFileName)
 	{
-		if(m_aFilename[i] == '/' || m_aFilename[i] == '\\')
-			pDemoShortName = &m_aFilename[i+1];
+		if(*pFileName == '/' || *pFileName == '\\')
+			pExtractedName = pFileName+1;
+		else if(*pFileName == '.')
+			pEnd = pFileName;
 	}
-	return pDemoShortName;
+
+	int Length = pEnd > pExtractedName ? min(BufferSize, (int)(pEnd-pExtractedName+1)) : BufferSize;
+	str_copy(pBuffer, pExtractedName, Length);
 }
 
 bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const