gzdoom/code/D_proto.c
1998-12-22 00:00:00 +00:00

319 lines
No EOL
6.1 KiB
C

#include "m_alloc.h"
#include "i_system.h"
#include "d_proto.h"
#include "d_ticcmd.h"
#include "d_net.h"
#include "doomdef.h"
#include "doomstat.h"
#include "cmdlib.h"
#include "z_zone.h"
demoqueue_t DemoQueue[MAXPLAYERS];
char *ReadString (byte **stream)
{
char *string = *stream;
*stream += strlen (string) + 1;
return copystring (string);
}
int ReadByte (byte **stream)
{
byte v = **stream;
*stream += 1;
return v;
}
int ReadWord (byte **stream)
{
short v = (((*stream)[0]) << 8) | (((*stream)[1]));
*stream += 2;
return v;
}
int ReadLong (byte **stream)
{
int v = (((*stream)[0]) << 24) | (((*stream)[1]) << 16) | (((*stream)[2]) << 8) | (((*stream)[3]));
*stream += 4;
return v;
}
void WriteString (const char *string, byte **stream)
{
char *p = *stream;
while (*string) {
*p++ = *string++;
}
*p++ = 0;
*stream = p;
}
void WriteByte (byte v, byte **stream)
{
**stream = v;
*stream += 1;
}
void WriteWord (short v, byte **stream)
{
(*stream)[0] = v >> 8;
(*stream)[1] = v & 255;
*stream += 2;
}
void WriteLong (int v, byte **stream)
{
(*stream)[0] = v >> 24;
(*stream)[1] = (v >> 16) & 255;
(*stream)[2] = (v >> 8) & 255;
(*stream)[3] = v & 255;
*stream += 4;
}
// Returns the number of bytes read
int UnpackUserCmd (usercmd_t *ucmd, byte **stream)
{
byte *start = *stream;
byte flags;
byte flags2;
// make sure the ucmd is empty
memset (ucmd, 0, sizeof(usercmd_t));
flags = ReadByte (stream);
if (flags & UCMDF_MORE)
flags2 = ReadByte (stream);
else
flags2 = 0;
if (flags) {
if (flags & UCMDF_BUTTONS)
ucmd->buttons = ReadByte (stream);
if (flags & UCMDF_PITCH)
ucmd->pitch = ReadWord (stream);
if (flags & UCMDF_YAW)
ucmd->yaw = ReadWord (stream);
if (flags & UCMDF_FORWARDMOVE)
ucmd->forwardmove = ReadWord (stream);
if (flags & UCMDF_SIDEMOVE)
ucmd->sidemove = ReadWord (stream);
if (flags & UCMDF_UPMOVE)
ucmd->upmove = ReadWord (stream);
if (flags & UCMDF_IMPULSE)
ucmd->impulse = ReadByte (stream);
if (flags2) {
if (flags2 & UCMDF_ROLL)
ucmd->roll = ReadWord (stream);
if (flags2 & UCMDF_USE)
ucmd->use = ReadByte (stream);
}
}
return *stream - start;
}
// Returns the number of bytes written
int PackUserCmd (usercmd_t *ucmd, byte **stream)
{
byte flags = 0;
byte flags2 = 0;
byte *temp = *stream;
byte *start = *stream;
WriteByte (0, stream); // Make room for the packing bits
if (ucmd->roll || ucmd->use) {
flags |= UCMDF_MORE;
WriteByte (0, stream); // Make room for more packing bits
}
if (ucmd->buttons) {
flags |= UCMDF_BUTTONS;
WriteByte (ucmd->buttons, stream);
}
if (ucmd->pitch) {
flags |= UCMDF_PITCH;
WriteWord (ucmd->pitch, stream);
}
if (ucmd->yaw) {
flags |= UCMDF_YAW;
WriteWord (ucmd->yaw, stream);
}
if (ucmd->forwardmove) {
flags |= UCMDF_FORWARDMOVE;
WriteWord (ucmd->forwardmove, stream);
}
if (ucmd->sidemove) {
flags |= UCMDF_SIDEMOVE;
WriteWord (ucmd->sidemove, stream);
}
if (ucmd->upmove) {
flags |= UCMDF_UPMOVE;
WriteWord (ucmd->upmove, stream);
}
if (ucmd->impulse) {
flags |= UCMDF_IMPULSE;
WriteByte (ucmd->impulse, stream);
}
if (ucmd->roll) {
flags2 |= UCMDF_ROLL;
WriteWord (ucmd->roll, stream);
}
if (ucmd->use) {
flags2 |= UCMDF_USE;
WriteByte (ucmd->use, stream);
}
// Write the packing bits
WriteByte (flags, &temp);
if (flags2)
WriteByte (flags2, &temp);
return *stream - start;
}
int WriteUserCmdMessage (usercmd_t *ucmd, byte **stream)
{
WriteByte (DEM_USERCMD, stream);
return PackUserCmd (ucmd, stream) + 1;
}
int SkipTicCmd (byte **stream, int count)
{
int i;
byte *flow = *stream;
int skip;
int type;
BOOL moreticdata;
for (i = count; i > 0; i--) {
flow += 2; // Skip consistancy marker
moreticdata = true;
while (moreticdata) {
type = *flow++;
switch (type) {
case DEM_MUSICCHANGE:
case DEM_PRINT:
case DEM_CENTERPRINT:
case DEM_UINFCHANGED:
case DEM_SINFCHANGED:
case DEM_GIVECHEAT:
case DEM_CHANGEMAP:
skip = strlen (flow) + 1;
break;
case DEM_GENERICCHEAT:
case DEM_DROPPLAYER:
skip = 1;
break;
case DEM_SAY:
skip = 2 + strlen (flow + 1);
break;
case DEM_USERCMD:
moreticdata = false;
skip = 1;
if (*flow & UCMDF_BUTTONS) skip += 1;
if (*flow & UCMDF_PITCH) skip += 2;
if (*flow & UCMDF_YAW) skip += 2;
if (*flow & UCMDF_FORWARDMOVE) skip += 2;
if (*flow & UCMDF_SIDEMOVE) skip += 2;
if (*flow & UCMDF_UPMOVE) skip += 2;
if (*flow & UCMDF_IMPULSE) skip += 1;
if (*flow & UCMDF_MORE) {
flow++;
if (*flow & UCMDF_ROLL) skip += 2;
if (*flow & UCMDF_USE) skip += 1;
}
break;
default:
// All other commands are assumed to have zero parameters
skip = 0;
break;
}
flow += skip;
}
}
skip = flow - *stream;
*stream = flow;
return skip;
}
void ReadTicCmd (ticcmd_t *tcmd, byte **stream, int player)
{
int type, queuelen;
byte *start;
tcmd->consistancy = ReadWord (stream);
start = *stream;
while ((type = ReadByte (stream)) != DEM_USERCMD)
Net_DoCommand (type, stream, player);
// Save special "ticcmds" for later saving to a demo
if (demorecording && ((queuelen = *stream - start - 1) > 0)) {
if (DemoQueue[player].queue)
Z_Free (DemoQueue[player].queue);
DemoQueue[player].queue = Z_Malloc (queuelen, PU_STATIC, NULL);
memcpy (DemoQueue[player].queue, start, queuelen);
DemoQueue[player].size = queuelen;
}
UnpackUserCmd (&tcmd->ucmd, stream);
}
byte *lenspot;
// Write the header of an IFF chunk and leave space
// for the length field.
void StartChunk (int id, byte **stream)
{
WriteLong (id, stream);
lenspot = *stream;
*stream += 4;
}
// Write the length field for the chunk and insert
// pad byte if the chunk is odd-sized.
void FinishChunk (byte **stream)
{
int len;
if (!lenspot)
return;
len = *stream - lenspot - 4;
WriteLong (len, &lenspot);
if (len & 1)
WriteByte (0, stream);
lenspot = NULL;
}
// Skip past an unknown chunk. *stream should be
// pointing to the chunk's length field.
void SkipChunk (byte **stream)
{
int len;
len = ReadLong (stream);
stream += len + (len & 1);
}