mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
Add demo format auto-detection.
nq now rejects anything that doesn't look like a .dem, and qw not only rejects anything that looks like neither a .qwd nor a .mvd, but even detects which one is being played by the contents rather than the file name (foo.mvd.gz would be mis-detected as a qwd!!).
This commit is contained in:
parent
dfc8f8bb20
commit
93e35d7ec0
2 changed files with 143 additions and 3 deletions
|
@ -35,6 +35,7 @@
|
|||
# include <strings.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/cvar.h"
|
||||
|
@ -374,6 +375,58 @@ CL_Record (const char *argv1, int track)
|
|||
demo_start_recording (track);
|
||||
}
|
||||
|
||||
static int
|
||||
demo_check_dem (void)
|
||||
{
|
||||
int c, ret = 0;
|
||||
uint32_t len, bytes;
|
||||
|
||||
// .dem demo files begin with an ascii integer (possibly negative)
|
||||
// representing the forced bgm track, followed by a newline
|
||||
c = Qgetc (cls.demofile);
|
||||
if (c == '-')
|
||||
c = Qgetc (cls.demofile);
|
||||
while (isdigit (c))
|
||||
c = Qgetc (cls.demofile);
|
||||
if (c != '\n')
|
||||
goto done;
|
||||
|
||||
// After the bgm track comes the packet length plus 3 floats for view
|
||||
// angles (not included in the packet length)
|
||||
Qread (cls.demofile, &len, sizeof (len));
|
||||
len = LittleLong (len);
|
||||
if (len > MAX_DEMMSG)
|
||||
goto done;
|
||||
Qseek (cls.demofile, 3 * 4, SEEK_CUR); // 3 * float (angles)
|
||||
|
||||
// Normally, svc_serverinfo is the first command in the packet, but some
|
||||
// servers (eg, fitzquake) add in an svc_print command first. Allow
|
||||
// multiple svc_print commands (but nothing else) before the svc_serverinfo
|
||||
net_message->message->cursize = len;
|
||||
bytes = Qread (cls.demofile, net_message->message->data, len);
|
||||
if (bytes != len)
|
||||
goto done;
|
||||
MSG_BeginReading (net_message);
|
||||
while (!ret) {
|
||||
if (net_message->badread)
|
||||
goto done;
|
||||
c = MSG_ReadByte (net_message);
|
||||
switch (c) {
|
||||
case svc_print:
|
||||
MSG_ReadString (net_message);
|
||||
break;
|
||||
case svc_serverinfo:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
Qseek (cls.demofile, 0, SEEK_SET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
CL_StartDemo (void)
|
||||
{
|
||||
|
@ -396,6 +449,14 @@ CL_StartDemo (void)
|
|||
dstring_delete (name);
|
||||
return;
|
||||
}
|
||||
if (!demo_check_dem ()) {
|
||||
Sys_Printf ("%s is not a valid .dem file.\n", name->str);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
dstring_delete (name);
|
||||
Qclose (cls.demofile);
|
||||
cls.demofile = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cls.demoplayback = true;
|
||||
CL_SetState (ca_connected);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/cmd.h"
|
||||
|
@ -880,10 +881,80 @@ CL_Record (const char *argv1, int track)
|
|||
demo_start_recording (track);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
get_ulong (const byte *buf)
|
||||
{
|
||||
return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
}
|
||||
|
||||
static inline float
|
||||
get_float (const byte *buf)
|
||||
{
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} uf;
|
||||
uf.u = get_ulong (buf);
|
||||
return uf.f;
|
||||
}
|
||||
|
||||
static int
|
||||
demo_check_qwd_mvd (void)
|
||||
{
|
||||
byte buf[22];
|
||||
size_t bytes;
|
||||
int c, ret = 0;
|
||||
float f;
|
||||
uint32_t u;
|
||||
|
||||
bytes = Qread (cls.demofile, buf, sizeof (buf));
|
||||
if (bytes != sizeof (buf))
|
||||
goto done;
|
||||
|
||||
if ((f = get_float (buf + 0)) >= 0 && !isinf (f) && !isnan (f)
|
||||
&& buf[4] == dem_read && get_ulong (buf + 5) <= MAX_DEMMSG
|
||||
&& get_ulong (buf + 9) == 1 && get_ulong (buf + 13) == 1
|
||||
&& buf[17] == svc_serverdata
|
||||
&& (u = get_ulong (buf + 18)) >= 26 && u <= PROTOCOL_VERSION) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
if (buf[0] != 0 || (buf[1] != dem_read && buf[1] != dem_all)
|
||||
|| (u = get_ulong (buf + 2)) > MAX_DEMMSG)
|
||||
goto done;
|
||||
Qseek (cls.demofile, 6, SEEK_SET);
|
||||
net_message->message->cursize = u;
|
||||
bytes = Qread (cls.demofile, net_message->message->data, u);
|
||||
if (bytes != u)
|
||||
goto done;
|
||||
MSG_BeginReading (net_message);
|
||||
while (!ret) {
|
||||
if (net_message->badread)
|
||||
goto done;
|
||||
c = MSG_ReadByte (net_message);
|
||||
switch (c) {
|
||||
case svc_print:
|
||||
MSG_ReadString (net_message);
|
||||
break;
|
||||
case svc_serverdata:
|
||||
if (MSG_ReadLong (net_message) != PROTOCOL_VERSION)
|
||||
goto done;
|
||||
ret = 2;
|
||||
break;
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
Qseek (cls.demofile, 0, SEEK_SET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
CL_StartDemo (void)
|
||||
{
|
||||
dstring_t *name;
|
||||
int type;
|
||||
|
||||
// open the demo file
|
||||
name = dstring_strdup (demoname);
|
||||
|
@ -897,16 +968,24 @@ CL_StartDemo (void)
|
|||
dstring_delete (name);
|
||||
return;
|
||||
}
|
||||
if (!(type = demo_check_qwd_mvd ())) {
|
||||
Sys_Printf ("%s is not a valid .qwd or .mvd file.\n", name->str);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
dstring_delete (name);
|
||||
Qclose (cls.demofile);
|
||||
cls.demofile = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cls.demoplayback = true;
|
||||
key_game_target = IMT_DEMO;
|
||||
Key_SetKeyDest (key_game);
|
||||
net_blocksend = 1;
|
||||
if (strequal (QFS_FileExtension (name->str), ".mvd")) {
|
||||
if (type == 2) {
|
||||
cls.demoplayback2 = true;
|
||||
Sys_Printf ("mvd\n");
|
||||
Sys_MaskPrintf (SYS_DEV, "mvd\n");
|
||||
} else {
|
||||
Sys_Printf ("qwd\n");
|
||||
Sys_MaskPrintf (SYS_DEV, "qwd\n");
|
||||
}
|
||||
CL_SetState (ca_demostart);
|
||||
Netchan_Setup (&cls.netchan, net_from, 0, NC_QPORT_SEND);
|
||||
|
|
Loading…
Reference in a new issue