summaryrefslogtreecommitdiffhomepage
path: root/src/demorec.c
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-07-20 18:12:00 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-07-23 19:07:03 +0100
commit4721f53cb21dfa18dc787581fac0d2a25f0a9690 (patch)
tree1a79f1c5da25be0832ca986c97fb6455299ffffd /src/demorec.c
parentb53b780e1b14e174204457765b4a0a72b6d2924f (diff)
Split custom demo data into its own file/feature
Copyright note: the stuff Bill wrote is all still in the other file.
Diffstat (limited to 'src/demorec.c')
-rw-r--r--src/demorec.c114
1 files changed, 1 insertions, 113 deletions
diff --git a/src/demorec.c b/src/demorec.c
index b4a674d..1fb5e8e 100644
--- a/src/demorec.c
+++ b/src/demorec.c
@@ -18,9 +18,7 @@
#include <stdbool.h>
#include <string.h>
-#include "bitbuf.h"
#include "con_.h"
-#include "demorec.h"
#include "engineapi.h"
#include "errmsg.h"
#include "gamedata.h"
@@ -37,7 +35,7 @@
DEF_CVAR(sst_autorecord, "Continuously record demos even after reconnecting", 1,
CON_ARCHIVE | CON_HIDDEN)
-static void *demorecorder;
+void *demorecorder;
static int *demonum;
static bool *recording;
static bool wantstop = false;
@@ -252,114 +250,4 @@ void demorec_end(void) {
cmd_stop->cb = orig_stop_cb;
}
-// custom data writing stuff is a separate feature, defined below. it we can't
-// find WriteMessage, we can still probably do the auto recording stuff above
-
-static int nbits_msgtype, nbits_datalen;
-
-// The engine allows usermessages up to 255 bytes, we add 2 bytes of overhead,
-// and then there's the leading bits before that too (see create_message)
-static char bb_buf[DEMOREC_CUSTOM_MSG_MAX + 4];
-static struct bitbuf bb = {
- bb_buf, sizeof(bb_buf), sizeof(bb_buf) * 8, 0, false, false, "SST"
-};
-
-static void create_message(struct bitbuf *msg, const void *buf, int len) {
- // The way we pack our custom demo data is via a user message packet with
- // type "HudText" - this causes the client to do a text lookup which will
- // simply silently fail on invalid keys. By making the first byte null
- // (creating an empty string), we get the rest of the packet to stick in
- // whatever other data we want.
- //
- // Notes from Uncrafted:
- // > But yeah the data you want to append is as follows:
- // > - 6 bits (5 bits in older versions) for the message type - should be 23
- // > for user message
- bitbuf_appendbits(msg, 23, nbits_msgtype);
- // > - 1 byte for the user message type - should be 2 for HudText
- bitbuf_appendbyte(msg, 2);
- // > - ~~an int~~ 11 or 12 bits for the length of your data in bits,
- bitbuf_appendbits(msg, len * 8, nbits_datalen); // NOTE: assuming len <= 254
- // > - your data
- // [first the aforementioned null byte, plus an arbitrary marker byte to
- // avoid confusion when parsing the demo later...
- bitbuf_appendbyte(msg, 0);
- bitbuf_appendbyte(msg, 0xAC);
- // ... and then just the data itself]
- bitbuf_appendbuf(msg, buf, len);
- // Thanks Uncrafted, very cool!
-}
-
-typedef void (*VCALLCONV WriteMessages_func)(void *this, struct bitbuf *msg);
-static WriteMessages_func WriteMessages = 0;
-
-void demorec_writecustom(void *buf, int len) {
- create_message(&bb, buf, len);
- WriteMessages(demorecorder, &bb);
- bitbuf_reset(&bb);
-}
-
-// This finds the CDemoRecorder::WriteMessages() function, which takes a raw
-// network packet, wraps it up in the appropriate demo framing format and writes
-// it out to the demo file being recorded.
-static bool find_WriteMessages(void) {
- // TODO(compat): probably rewrite this to just scan for a call instruction!
- const uchar *insns = (*(uchar ***)demorecorder)[vtidx_RecordPacket];
- // RecordPacket calls WriteMessages pretty much right away:
- // 56 push esi
- // 57 push edi
- // 8B F1 mov esi,ecx
- // 8D BE lea edi,[esi + 0x68c]
- // 8C 06 00 00
- // 57 push edi
- // E8 call CDemoRecorder_WriteMessages
- // B0 EF FF FF
- // So we just double check the byte pattern...
- static const uchar bytes[] =
-#ifdef _WIN32
- HEXBYTES(56, 57, 8B, F1, 8D, BE, 8C, 06, 00, 00, 57, E8);
-#else
-#warning This is possibly different on Linux too, have a look!
- {-1, -1, -1, -1, -1, -1};
-#endif
- if (!memcmp(insns, bytes, sizeof(bytes))) {
- ssize off = mem_loadoffset(insns + sizeof(bytes));
- // ... and then offset is relative to the address of whatever is _after_
- // the call instruction... because x86.
- WriteMessages = (WriteMessages_func)(insns + sizeof(bytes) + 4 + off);
- return true;
- }
- return false;
-}
-
-DECL_VFUNC_DYN(int, GetEngineBuildNumber)
-
-bool demorec_custom_init(void) {
- if (!has_vtidx_GetEngineBuildNumber || !has_vtidx_RecordPacket) {
- errmsg_errorx("custom: missing gamedata entries for this engine");
- return false;
- }
-
- // More UncraftedkNowledge:
- // > yeah okay so [the usermessage length is] 11 bits if the demo protocol
- // > is 11 or if the game is l4d2 and the network protocol is 2042.
- // > otherwise it's 12 bits
- // > there might be some other l4d2 versions where it's 11 but idk
- // So here we have to figure out the network protocol version!
- // NOTE: assuming engclient != null as GEBN index relies on client version
- int buildnum = VCALL(engclient, GetEngineBuildNumber);
- // condition is redundant until other GetEngineBuildNumber offsets are added
- // if (GAMETYPE_MATCHES(L4D2)) {
- nbits_msgtype = 6;
- // based on Some Code I Read, buildnum *should* be the protocol version,
- // however L4D2 returns the actual game version instead, because sure
- // why not. The only practical difference though is that the network
- // protocol froze after 2042, so we just have to do a >=. No big deal
- // really.
- if (buildnum >= 2042) nbits_datalen = 11; else nbits_datalen = 12;
- // }
-
- return find_WriteMessages();
-}
-
// vi: sw=4 ts=4 noet tw=80 cc=80