aboutsummaryrefslogtreecommitdiff
path: root/api.c
diff options
context:
space:
mode:
authorGravatar Matthew Wozniak <me@woz.blue> 2024-11-03 00:16:00 -0400
committerGravatar Matthew Wozniak <me@woz.blue> 2024-11-03 00:16:00 -0400
commitd00096fe2ea3dd64cff9878879c077f23a783e4a (patch)
tree38da364a01d63d8796dc5c38b20ff73539ac1c82 /api.c
parenta2f7e37d8adf2047e1f3b0ea1227ac9d51514783 (diff)
downloadrt-d00096fe2ea3dd64cff9878879c077f23a783e4a.tar.gz
rt-d00096fe2ea3dd64cff9878879c077f23a783e4a.zip
find videomode
Diffstat (limited to 'api.c')
-rw-r--r--api.c34
1 files changed, 31 insertions, 3 deletions
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;
}