foxygit / doom Log in
commit 01b69307e00ee6c0a1366542b843f1495c79ea15
Author:     Thomas A. Birkel <capnclever@gmail.com>
AuthorDate: Sat Oct 15 00:29:21 2016 -0400
Commit:     Thomas A. Birkel <capnclever@gmail.com>
CommitDate: Sat Oct 15 00:29:21 2016 -0400

    Add longtics and lowres_turn feature to Heretic/Hexen

    Allow demos to be recorded and played back assuming 16-bit resolution
    in player turns, similar to Doom's 1.91 hack. Unlike Doom, -longtics must
    also be specified using -playdemo and -timedemo.

    Also fixes a network consistency bug caused by some but not all players
    recording a demo.

    Partial implementation of #432
---
 src/heretic/d_main.c  |  8 ++++++++
 src/heretic/d_net.c   | 16 ++++++++++++++--
 src/heretic/doomdef.h |  3 +++
 src/heretic/g_game.c  | 51 +++++++++++++++++++++++++++++++++++++++++++++++---
 src/hexen/d_net.c     | 17 +++++++++++++++--
 src/hexen/g_game.c    | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/hexen/h2_main.c   |  8 ++++++++
 src/hexen/h2def.h     |  3 +++
 8 files changed, 148 insertions(+), 10 deletions(-)

diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c
index 3c88de2c..71dc626c 100644
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -1031,6 +1031,14 @@ void D_DoomMain(void)
         printf("Playing demo %s.\n", file);
     }

+    //!
+    // @category demo
+    //
+    // Record a high turning resolution demo.
+    //
+
+    longtics = M_CheckParm("-longtics") != 0;
+
     if (W_CheckNumForName(DEH_String("E2M1")) == -1)
     {
         gamemode = shareware;
diff --git a/src/heretic/d_net.c b/src/heretic/d_net.c
index 517df0cd..28e7afaf 100644
--- a/src/heretic/d_net.c
+++ b/src/heretic/d_net.c
@@ -115,10 +115,17 @@ static void LoadGameSettings(net_gamesettings_t *settings)
     startmap = settings->map;
     startskill = settings->skill;
     // TODO startloadgame = settings->loadgame;
+    lowres_turn = settings->lowres_turn;
     nomonsters = settings->nomonsters;
     respawnparm = settings->respawn_monsters;
     consoleplayer = settings->consoleplayer;

+    if (lowres_turn)
+    {
+        printf("NOTE: Turning resolution is reduced; this is probably "
+            "because there is a client recording a Vanilla demo.\n");
+    }
+
     for (i = 0; i < MAXPLAYERS; ++i)
     {
         playeringame[i] = i < settings->num_players;
@@ -142,7 +149,9 @@ static void SaveGameSettings(net_gamesettings_t *settings)
     settings->nomonsters = nomonsters;
     settings->respawn_monsters = respawnparm;
     settings->timelimit = 0;
-    settings->lowres_turn = false;
+
+    settings->lowres_turn = M_CheckParm("-record") > 0
+                         && M_CheckParm("-longtics") == 0;
 }

 static void InitConnectData(net_connect_data_t *connect_data)
@@ -159,7 +168,10 @@ static void InitConnectData(net_connect_data_t *connect_data)
     connect_data->gamemode = gamemode;
     connect_data->gamemission = heretic;

-    connect_data->lowres_turn = false;
+    // Are we recording a demo? Possibly set lowres turn mode
+
+    connect_data->lowres_turn = M_CheckParm("-record") > 0
+                             && M_CheckParm("-longtics") == 0;

     // Read checksums of our WAD directory and dehacked information

diff --git a/src/heretic/doomdef.h b/src/heretic/doomdef.h
index afb11b69..eeb91c21 100644
--- a/src/heretic/doomdef.h
+++ b/src/heretic/doomdef.h
@@ -527,6 +527,9 @@ extern boolean DebugSound;      // debug flag for displaying sound info
 extern int GetWeaponAmmo[NUMWEAPONS];

 extern boolean demorecording;
+extern boolean lowres_turn; // Truncate angleturn in ticcmds to nearest 256.
+                            // Used when recording Vanilla demos in netgames.
+extern boolean longtics;    // specifies 16-bit angleturn resolution in demos
 extern boolean demoplayback;
 extern int skytexture;

diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c
index 1b6a951a..ab10460f 100644
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -110,6 +110,8 @@ int mouseSensitivity;

 char demoname[32];
 boolean demorecording;
+boolean longtics;
+boolean lowres_turn;
 boolean demoplayback;
 byte *demobuffer, *demo_p, *demoend;
 boolean singledemo;             // quit after playing a demo from cmdline
@@ -622,6 +624,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
             BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT);
     }

+    // low-res turning
+
+    if (lowres_turn)
+    {
+        // truncate angleturn to the nearest 256 boundary
+        // for recording demos with single byte values for turn
+        cmd->angleturn &= 0xff00;
+    }
 }


@@ -1630,7 +1640,19 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
     }
     cmd->forwardmove = ((signed char) *demo_p++);
     cmd->sidemove = ((signed char) *demo_p++);
-    cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+
+    // If this is a longtics demo, read back in higher resolution
+
+    if (longtics)
+    {
+        cmd->angleturn = *demo_p++;
+        cmd->angleturn |= (*demo_p++) << 8;
+    }
+    else
+    {
+        cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+    }
+
     cmd->buttons = (unsigned char) *demo_p++;
     cmd->lookfly = (unsigned char) *demo_p++;
     cmd->arti = (unsigned char) *demo_p++;
@@ -1638,15 +1660,34 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)

 void G_WriteDemoTiccmd(ticcmd_t * cmd)
 {
+    byte *demo_start;
+
     if (gamekeydown[key_demo_quit]) // press to end demo recording
         G_CheckDemoStatus();
+
+    demo_start = demo_p;
+
     *demo_p++ = cmd->forwardmove;
     *demo_p++ = cmd->sidemove;
-    *demo_p++ = cmd->angleturn >> 8;
+
+    // If this is a longtics demo, record in higher resolution
+
+    if (longtics)
+    {
+        *demo_p++ = (cmd->angleturn & 0xff);
+        *demo_p++ = (cmd->angleturn >> 8) & 0xff;
+    }
+    else
+    {
+        *demo_p++ = cmd->angleturn >> 8;
+    }
+
     *demo_p++ = cmd->buttons;
     *demo_p++ = cmd->lookfly;
     *demo_p++ = cmd->arti;
-    demo_p -= 6;
+
+    // reset demo pointer back
+    demo_p = demo_start;

     if (demo_p > demoend - 16)
     {
@@ -1674,6 +1715,10 @@ void G_RecordDemo(skill_t skill, int numplayers, int episode, int map,
     int i;
     int maxsize;

+    // If not recording a longtics demo, record in low res
+
+    lowres_turn = !longtics;
+
     G_InitNew(skill, episode, map);
     usergame = false;
     M_StringCopy(demoname, name, sizeof(demoname));
diff --git a/src/hexen/d_net.c b/src/hexen/d_net.c
index bd0e8b21..0c292cc8 100644
--- a/src/hexen/d_net.c
+++ b/src/hexen/d_net.c
@@ -116,10 +116,17 @@ static void LoadGameSettings(net_gamesettings_t *settings)
     startmap = settings->map;
     startskill = settings->skill;
     // TODO startloadgame = settings->loadgame;
+    lowres_turn = settings->lowres_turn;
     nomonsters = settings->nomonsters;
     respawnparm = settings->respawn_monsters;
     consoleplayer = settings->consoleplayer;

+    if (lowres_turn)
+    {
+        printf("NOTE: Turning resolution is reduced; this is probably "
+            "because there is a client recording a Vanilla demo.\n");
+    }
+
     for (i=0; i<maxplayers; ++i)
     {
         playeringame[i] = i < settings->num_players;
@@ -154,7 +161,9 @@ static void SaveGameSettings(net_gamesettings_t *settings)
     settings->nomonsters = nomonsters;
     settings->respawn_monsters = respawnparm;
     settings->timelimit = 0;
-    settings->lowres_turn = false;
+
+    settings->lowres_turn = M_CheckParm("-record") > 0
+                         && M_CheckParm("-longtics") == 0;
 }

 static void InitConnectData(net_connect_data_t *connect_data)
@@ -170,7 +179,11 @@ static void InitConnectData(net_connect_data_t *connect_data)
     connect_data->gamemode = gamemode;
     connect_data->gamemission = hexen;

-    connect_data->lowres_turn = false;
+    // Are we recording a demo? Possibly set lowres turn mode
+
+    connect_data->lowres_turn = M_CheckParm("-record") > 0
+                             && M_CheckParm("-longtics") == 0;
+
     connect_data->drone = false;
     connect_data->max_players = maxplayers;

diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c
index bda707d1..c01776c6 100644
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -93,6 +93,8 @@ int levelstarttic;              // gametic at level start

 char demoname[32];
 boolean demorecording;
+boolean longtics;
+boolean lowres_turn;
 boolean demoplayback;
 byte *demobuffer, *demo_p, *demoend;
 boolean singledemo;             // quit after playing a demo from cmdline
@@ -622,6 +624,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
         cmd->buttons =
             BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT);
     }
+
+    // low-res turning
+
+    if (lowres_turn)
+    {
+        // truncate angleturn to the nearest 256 boundary
+        // for recording demos with single byte values for turn
+        cmd->angleturn &= 0xff00;
+    }
 }


@@ -1782,7 +1793,19 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)
     }
     cmd->forwardmove = ((signed char) *demo_p++);
     cmd->sidemove = ((signed char) *demo_p++);
-    cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+
+    // If this is a longtics demo, read back in higher resolution
+
+    if (longtics)
+    {
+        cmd->angleturn = *demo_p++;
+        cmd->angleturn |= (*demo_p++) << 8;
+    }
+    else
+    {
+        cmd->angleturn = ((unsigned char) *demo_p++) << 8;
+    }
+
     cmd->buttons = (unsigned char) *demo_p++;
     cmd->lookfly = (unsigned char) *demo_p++;
     cmd->arti = (unsigned char) *demo_p++;
@@ -1790,15 +1813,34 @@ void G_ReadDemoTiccmd(ticcmd_t * cmd)

 void G_WriteDemoTiccmd(ticcmd_t * cmd)
 {
+    byte *demo_start;
+
     if (gamekeydown[key_demo_quit]) // press to end demo recording
         G_CheckDemoStatus();
+
+    demo_start = demo_p;
+
     *demo_p++ = cmd->forwardmove;
     *demo_p++ = cmd->sidemove;
-    *demo_p++ = cmd->angleturn >> 8;
+
+    // If this is a longtics demo, record in higher resolution
+
+    if (longtics)
+    {
+        *demo_p++ = (cmd->angleturn & 0xff);
+        *demo_p++ = (cmd->angleturn >> 8) & 0xff;
+    }
+    else
+    {
+        *demo_p++ = cmd->angleturn >> 8;
+    }
+
     *demo_p++ = cmd->buttons;
     *demo_p++ = cmd->lookfly;
     *demo_p++ = cmd->arti;
-    demo_p -= 6;
+
+    // reset demo pointer back
+    demo_p = demo_start;

     if (demo_p > demoend - 16)
     {
@@ -1826,6 +1868,10 @@ void G_RecordDemo(skill_t skill, int numplayers, int episode, int map,
     int i;
     int maxsize;

+    // If not recording a longtics demo, record in low res
+
+    lowres_turn = !longtics;
+
     G_InitNew(skill, episode, map);
     usergame = false;
     M_StringCopy(demoname, name, sizeof(demoname));
diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c
index 3fa16a34..1e2c0af6 100644
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -676,6 +676,14 @@ static void HandleArgs(void)
         ST_Message("Playing demo %s.\n", myargv[p+1]);
     }

+    //!
+    // @category demo
+    //
+    // Record a high turning resolution demo.
+    //
+
+    longtics = M_CheckParm("-longtics") != 0;
+
     if (M_ParmExists("-testcontrols"))
     {
         autostart = true;
diff --git a/src/hexen/h2def.h b/src/hexen/h2def.h
index 9c1e76bc..aa84e430 100644
--- a/src/hexen/h2def.h
+++ b/src/hexen/h2def.h
@@ -632,6 +632,9 @@ extern player_t players[MAXPLAYERS];

 extern boolean DebugSound;      // debug flag for displaying sound info

+extern boolean lowres_turn; // Truncate angleturn in ticcmds to nearest 256.
+                            // Used when recording Vanilla demos in netgames.
+extern boolean longtics;    // specifies 16-bit angleturn resolution in demos
 extern boolean demoplayback;
 extern int maxzone;             // Maximum chunk allocated for zone heap