From d00096fe2ea3dd64cff9878879c077f23a783e4a Mon Sep 17 00:00:00 2001 From: Matthew Wozniak Date: Sun, 3 Nov 2024 00:16:00 -0400 Subject: find videomode --- api.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'api.c') diff --git a/api.c b/api.c index 8001f8f..b24514e 100644 --- a/api.c +++ b/api.c @@ -10,18 +10,28 @@ struct engserver *engserver = NULL; struct engclient *engclient = NULL; +struct engineapi *engineapi = NULL; +struct enginetools *enginetools = NULL; struct demoplayer *demoplayer = NULL; +struct videomode **videomode = NULL; +struct movieinfo *movieinfo = NULL; void (*cbuf_addtext)(char *) = NULL; +// TODO: should this be split up? + bool api_init(void) { void *engine_dll = os_dlhandle("engine"); createinterface_func engine_factory = (createinterface_func)os_dlsym(engine_dll, "CreateInterface"); if (!engine_factory) bail("couldn't get engine factory"); - engserver = engine_factory(INTERFACEVERSION_VENGINESERVER, NULL); + engserver = engine_factory(VENGINE_SERVER_INTERFACE_VERSION, NULL); if (!engserver) bail("couldn't get IVEngineServer from engine"); engclient = engine_factory(VENGINE_CLIENT_INTERFACE_VERSION, NULL); if (!engclient) bail("couldn't get IVEngineClient from engine"); + engineapi = engine_factory(VENGINE_LAUNCHER_INTERFACE_VERSION, NULL); + if (!engineapi) bail("couldn't get IEngineAPI from engine"); + enginetools = engine_factory(VENGINE_TOOL_INTERFACE_VERSION, NULL); + if (!engineapi) bail("couldn't get IEngineTools from engine"); // find cbuf_addtext const u8 *instr = (const u8 *)engserver->vt->server_command; @@ -41,13 +51,31 @@ bool api_init(void) { // find demoplayer instr = (const u8 *)engclient->vt->is_playing_demo; - debug("is_playing_demo = %p", (void *)instr); // CEngineClient::IsPlayingDemo is a wrapper around a demoplayer call - // The first thing it does should be load demoplayer into ECX + // The first thing it does should be load a ptr to demoplayer into ECX if (instr[0] != X86_MOVRMW || instr[1] != X86_MODRM(0, 1, 5)) bail("couldn't get demoplayer"); demoplayer = **(struct demoplayer ***)(instr + 2); debug("demoplayer = %p", (void *)demoplayer); + + // 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. + instr = (const u8 *)engineapi->vt->set_engine_window; + int mov_ecx_counter = 0; + for (const u8 *p = instr; p - instr < 64;) { + if (p[0] == X86_MOVRMW && p[1] == X86_MODRM(0, 1, 5) + && ++mov_ecx_counter == 2) { + videomode = *(struct videomode ***)(p + 2); + break; + } + int l = x86_len(p); + if (l == -1) + bail("invalid instruction looking for videomode"); + p += l; + } + debug("videomode = %p", (void *)videomode); return true; } -- cgit v1.2.3-54-g00ecf