aboutsummaryrefslogtreecommitdiff
path: root/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'api.c')
-rw-r--r--api.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/api.c b/api.c
index 5dba38a..0562bba 100644
--- a/api.c
+++ b/api.c
@@ -74,7 +74,9 @@ bool api_init(void) {
// find videomode
// CEngineAPI::SetEngineWindow calls videomode->SetGameWindow after
// detaching the current window with another vcall. Look for the second one.
- // This, like the demoplayer, is a pointer. Mind the double dereference.
+ // This, like the demoplayer, is a pointer. We need to keep the double
+ // pointer because when we get this, it is null. It is set by the engine
+ // later.
instr = (const u8 *)engineapi->vt->set_engine_window;
int mov_ecx_counter = 0;
for (const u8 *p = instr; p - instr < 64;) {
@@ -89,6 +91,34 @@ bool api_init(void) {
p += l;
}
debug("videomode = %p", (void *)videomode);
+
+ // find cl_movieinfo
+ {
+ // step 1: find CL_IsRecordingMovie() in
+ // CEngineTools::StartMovieRecording
+ instr = (const u8 *)enginetools->vt->start_movie_recording;
+ void *cl_isrecordingmovie = NULL;
+ for (const u8 *p = instr; p - instr < 64;) {
+ // this is the first call in the function
+ if (*p == X86_CALL) {
+ cl_isrecordingmovie = (void *)(p + 5 + *(i32 *)(p + 1));
+ }
+ int l = x86_len(p);
+ if (l == -1)
+ bail("invalid instruction looking for CL_IsRecordingMovie");
+ p += l;
+ }
+ if (!cl_isrecordingmovie)
+ bail("couldn't find cbuf_addtext CL_IsRecordingMovie");
+
+ // step 2: get the pointer to cl_movieinfo
+ // should be in the first instruction
+ instr = (const u8 *)cl_isrecordingmovie;
+ if (instr[0] != X86_ALUMI8 || instr[1] != X86_MODRM(0, 7, 5))
+ bail("couldn't get movieinfo");
+ movieinfo = *(struct movieinfo **)(instr + 2);
+ debug("movieinfo = %p", (void *)movieinfo);
+ }
return true;
}