From a14f84a0b025eecf65780b97ff55e5845f53d257 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Sun, 8 Mar 2026 07:58:45 +0200 Subject: [PATCH 01/15] renamed "mod" type to "qmm_mod" and "plugin" type to "qmm_plugin". condensed supportedgame_funcs.pfndllEntry and .pfnGetGameAPI into a single .pfnEntry. cleaned up main_handle_entry and mod_load as a result of the combined entrypoint handlers --- include/game_api.h | 51 +++++++------------ include/mod.h | 13 ++--- include/plugin.h | 10 ++-- src/game_api.cpp | 2 +- src/game_cod11mp.cpp | 17 ++++--- src/game_codmp.cpp | 17 ++++--- src/game_coduomp.cpp | 17 ++++--- src/game_jamp.cpp | 92 ++++++++++++++-------------------- src/game_jasp.cpp | 13 +++-- src/game_jk2mp.cpp | 17 ++++--- src/game_jk2sp.cpp | 13 +++-- src/game_mohaa.cpp | 13 +++-- src/game_mohbt.cpp | 13 +++-- src/game_mohsh.cpp | 13 +++-- src/game_q2r.cpp | 13 +++-- src/game_q3a.cpp | 17 ++++--- src/game_quake2.cpp | 13 +++-- src/game_rtcwmp.cpp | 17 ++++--- src/game_rtcwsp.cpp | 21 +++++--- src/game_sin.cpp | 13 +++-- src/game_sof2mp.cpp | 17 ++++--- src/game_sof2sp.cpp | 13 +++-- src/game_stef2.cpp | 13 +++-- src/game_stvoyhm.cpp | 17 ++++--- src/game_stvoysp.cpp | 13 +++-- src/game_wet.cpp | 17 ++++--- src/main.cpp | 69 +++++++++++-------------- src/mod.cpp | 116 +++++++++++++++++++------------------------ src/plugin.cpp | 18 +++---- 29 files changed, 359 insertions(+), 329 deletions(-) diff --git a/include/game_api.h b/include/game_api.h index a9ab35e..fc9f576 100644 --- a/include/game_api.h +++ b/include/game_api.h @@ -20,22 +20,21 @@ Created By: #include "qvm.h" struct supportedgame; +// this struct is defined by GEN_FUNCS_QVM(GAME) or GEN_FUNCS(GAME) struct supportedgame_funcs { - // this section is made by GEN_INFO(GAME) int* qmm_eng_msgs; // array of engine messages used by QMM int* qmm_mod_msgs; // array of mod messages used by QMM const char* (*pfnEngMsgNames)(intptr_t); // pointer to a function that returns a string for a given engine message const char* (*pfnModMsgNames)(intptr_t); // pointer to a function that returns a string for a given mod message - // this section is made by GEN_DLLQVM(GAME), GEN_DLL(GAME), or GEN_GGA(GAME) - bool(*pfnAutoDetect)(bool, supportedgame*); // pointer to a function that handles auto-detection logic for a game (NULL = no auto-detection) + bool(*pfnAutoDetect)(bool, supportedgame*); // pointer to a function that handles auto-detection logic for a game qvm_syscall pfnqvmsyscall; // pointer to a function that handles mod->engine calls from a QVM (NULL = not supported) - mod_dllEntry pfndllEntry; // pointer to a function that handles dllEntry entry for a game (NULL = not supported) - mod_GetGameAPI pfnGetGameAPI; // pointer to a function that handles GetGameAPI entry for a game (NULL = not supported) + void* (*pfnEntry)(void*, void*, bool); // pointer to a function that handles dllEntry or GetGameAPI entry for a game bool(*pfnModLoad)(void*, bool); // pointer to a function that handles mod loading logic after a DLL is loaded void(*pfnModUnload)(); // pointer to a function that handles mod unloading logic before a DLL is unloaded }; + // some information for each game engine supported by QMM struct supportedgame { const char* dllname; // default dll mod filename @@ -69,53 +68,39 @@ extern std::vector g_supportedgames; // ====== // generate struct info for the game-specific functions and arrays -// dllEntry/vmMain game with QVM support -#define GEN_DLLQVM(game) \ +// game with QVM support +#define GEN_FUNCS_QVM(game) \ static const char* game##_eng_msg_names(intptr_t); \ static const char* game##_mod_msg_names(intptr_t); \ static bool game##_autodetect(bool, supportedgame*); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ static int game##_qvmsyscall(uint8_t*, int, int*); \ -static void game##_dllEntry(eng_syscall); \ -static bool game##_mod_load(void*, bool); \ -static void game##_mod_unload(); \ -supportedgame_funcs game##_funcs = { \ - game##_qmm_eng_msgs, game##_qmm_mod_msgs, game##_eng_msg_names, game##_mod_msg_names, \ - game##_autodetect, game##_qvmsyscall, game##_dllEntry, nullptr, \ - game##_mod_load, game##_mod_unload \ -} - -// dllEntry/vmMain game with no QVM support -#define GEN_DLL(game) \ -static const char* game##_eng_msg_names(intptr_t); \ -static const char* game##_mod_msg_names(intptr_t); \ -static bool game##_autodetect(bool, supportedgame*); \ -static intptr_t game##_syscall(intptr_t cmd, ...); \ -static intptr_t game##_vmMain(intptr_t cmd, ...); \ -static void game##_dllEntry(eng_syscall); \ +static void* game##_entry(void*, void*, bool); \ static bool game##_mod_load(void*, bool); \ static void game##_mod_unload(); \ supportedgame_funcs game##_funcs = { \ - game##_qmm_eng_msgs, game##_qmm_mod_msgs, game##_eng_msg_names, game##_mod_msg_names, \ - game##_autodetect, nullptr, game##_dllEntry, nullptr, \ - game##_mod_load, game##_mod_unload \ + game##_qmm_eng_msgs, game##_qmm_mod_msgs, \ + game##_eng_msg_names, game##_mod_msg_names, \ + game##_autodetect, game##_qvmsyscall, game##_entry, \ + game##_mod_load, game##_mod_unload, \ } -// GetGameAPI game -#define GEN_GGA(game) \ +// game with no QVM support +#define GEN_FUNCS(game) \ static const char* game##_eng_msg_names(intptr_t); \ static const char* game##_mod_msg_names(intptr_t); \ static bool game##_autodetect(bool, supportedgame*); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ -static void* game##_GetGameAPI(void*, void*); \ +static void* game##_entry(void*, void*, bool); \ static bool game##_mod_load(void*, bool); \ static void game##_mod_unload(); \ supportedgame_funcs game##_funcs = { \ - game##_qmm_eng_msgs, game##_qmm_mod_msgs, game##_eng_msg_names, game##_mod_msg_names, \ - game##_autodetect, nullptr, nullptr, game##_GetGameAPI, \ - game##_mod_load, game##_mod_unload \ + game##_qmm_eng_msgs, game##_qmm_mod_msgs, \ + game##_eng_msg_names, game##_mod_msg_names, \ + game##_autodetect, nullptr, game##_entry, \ + game##_mod_load, game##_mod_unload, \ } // generate a case/string line for use in the _msg_names functions diff --git a/include/mod.h b/include/mod.h index 1919c31..ada7ded 100644 --- a/include/mod.h +++ b/include/mod.h @@ -16,17 +16,18 @@ Created By: #include "qmmapi.h" #include "qvm.h" -struct mod { - void* dll = nullptr; +struct qmm_mod { + std::string path; qvm vm = {}; + void* dll = nullptr; intptr_t vmbase = 0; - std::string path; + bool is_GetGameAPI = false; }; -extern mod g_mod; +extern qmm_mod g_mod; -bool mod_load(mod& mod, std::string file); -void mod_unload(mod& mod); +bool mod_load(qmm_mod& mod, std::string file); +void mod_unload(qmm_mod& mod); #endif // QMM2_MOD_H diff --git a/include/plugin.h b/include/plugin.h index 23079b1..36bbe55 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -30,7 +30,7 @@ using plugin_pluginmessage = void (*)(plugin_id from_plid, const char* message, // QMM_QVMHandler using plugin_qvmhandler = int (*)(int cmd, int* args); -struct plugin { +struct qmm_plugin { void* dll = nullptr; std::string path; plugin_query QMM_Query = nullptr; @@ -54,18 +54,18 @@ struct plugin_globals { extern plugin_globals g_plugin_globals; -extern std::vector g_plugins; +extern std::vector g_plugins; // this ID is like the various syscall values. they go through the following function y=-x-1 when used as QVM function pointers // once the handler function is called, this is already undone with another y=-x-1 to get a positive number again #define QMM_QVM_FUNC_STARTING_ID 10000 -extern std::map g_registered_qvm_funcs; +extern std::map g_registered_qvm_funcs; const char* plugin_result_to_str(plugin_res res); // returns: -1 if failed to load and don't continue, 0 if failed to load and continue, 1 if loaded -int plugin_load(plugin& p, std::string file); +int plugin_load(qmm_plugin& p, std::string file); -void plugin_unload(plugin& p); +void plugin_unload(qmm_plugin& p); #endif // QMM2_PLUGIN_H diff --git a/src/game_api.cpp b/src/game_api.cpp index 548dd9a..ab81d1f 100644 --- a/src/game_api.cpp +++ b/src/game_api.cpp @@ -103,7 +103,7 @@ std::vector g_supportedgames = { { "efgame" MOD_DLL, nullptr, ".", "Star Trek Voyager: Elite Force (SP)", GEN_INFO(STVOYSP), 13, 9 }, #endif - // Q2R only exists for 64-bit Windows +// Q2R only exists for 64-bit Windows #if defined(QMM_OS_WINDOWS) && defined(QMM_ARCH_64) { "game_x64.dll", nullptr, "baseq2", "Quake 2 Remastered", GEN_INFO(Q2R), 9, 6 }, #endif diff --git a/src/game_cod11mp.cpp b/src/game_cod11mp.cpp index d8ebb6a..a82d827 100644 --- a/src/game_cod11mp.cpp +++ b/src/game_cod11mp.cpp @@ -21,7 +21,7 @@ Created By: GEN_QMM_MSGS(COD11MP); GEN_EXTS(COD11MP); -GEN_DLL(COD11MP); +GEN_FUNCS(COD11MP); // auto-detection logic for COD11MP (never auto-detect) @@ -109,11 +109,11 @@ static intptr_t COD11MP_vmMain(intptr_t cmd, ...) { } -static void COD11MP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_dllEntry({}) called\n", (void*)syscall); +static void* COD11MP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = COD11MP_vmMain; @@ -121,11 +121,16 @@ static void COD11MP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = COD11MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_entry({}) returning\n", syscall); + + return nullptr; } -static bool COD11MP_mod_load(void* entry, bool) { +static bool COD11MP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_codmp.cpp b/src/game_codmp.cpp index c63cae8..15aa32d 100644 --- a/src/game_codmp.cpp +++ b/src/game_codmp.cpp @@ -27,7 +27,7 @@ GEN_QMM_MSGS(CODMP); #undef GAME_INIT GEN_EXTS(CODMP); -GEN_DLL(CODMP); +GEN_FUNCS(CODMP); // auto-detection logic for CODMP @@ -124,11 +124,11 @@ static intptr_t CODMP_vmMain(intptr_t cmd, ...) { } -static void CODMP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_dllEntry({}) called\n", (void*)syscall); +static void* CODMP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = CODMP_vmMain; @@ -136,11 +136,16 @@ static void CODMP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = CODMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_entry({}) returning\n", syscall); + + return nullptr; } -static bool CODMP_mod_load(void* entry, bool) { +static bool CODMP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_coduomp.cpp b/src/game_coduomp.cpp index 21eba54..fe329fc 100644 --- a/src/game_coduomp.cpp +++ b/src/game_coduomp.cpp @@ -27,7 +27,7 @@ GEN_QMM_MSGS(CODUOMP); #undef GAME_INIT GEN_EXTS(CODUOMP); -GEN_DLL(CODUOMP); +GEN_FUNCS(CODUOMP); // auto-detection logic for CODUOMP @@ -124,11 +124,11 @@ static intptr_t CODUOMP_vmMain(intptr_t cmd, ...) { } -static void CODUOMP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_dllEntry({}) called\n", (void*)syscall); +static void* CODUOMP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = CODUOMP_vmMain; @@ -136,11 +136,16 @@ static void CODUOMP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = CODUOMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_entry({}) returning\n", syscall); + + return nullptr; } -static bool CODUOMP_mod_load(void* entry, bool) { +static bool CODUOMP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_jamp.cpp b/src/game_jamp.cpp index cd50b90..77b7c22 100644 --- a/src/game_jamp.cpp +++ b/src/game_jamp.cpp @@ -23,28 +23,7 @@ Created By: GEN_QMM_MSGS(JAMP); GEN_EXTS(JAMP); -// do not use macro since this game supports both dllEntry and GetGameAPI entry points -static const char* JAMP_eng_msg_names(intptr_t); -static const char* JAMP_mod_msg_names(intptr_t); -static bool JAMP_autodetect(bool, supportedgame*); -static intptr_t JAMP_syscall(intptr_t cmd, ...); -static intptr_t JAMP_vmMain(intptr_t cmd, ...); -static void JAMP_dllEntry(eng_syscall); -static void* JAMP_GetGameAPI(void*, void*); -static bool JAMP_mod_load(void*, bool); -static void JAMP_mod_unload(); -supportedgame_funcs JAMP_funcs = { - JAMP_qmm_eng_msgs, - JAMP_qmm_mod_msgs, - JAMP_eng_msg_names, - JAMP_mod_msg_names, - JAMP_autodetect, - nullptr, // JAMP_qvmsyscall - JAMP_dllEntry, - JAMP_GetGameAPI, - JAMP_mod_load, - JAMP_mod_unload, -}; +GEN_FUNCS(JAMP); // auto-detection logic for JAMP @@ -53,10 +32,16 @@ static bool JAMP_autodetect(bool is_GetGameAPI, supportedgame* game) { if (!str_striequal(g_gameinfo.qmm_file, game->dllname) && !str_striequal(g_gameinfo.qmm_file.substr(0, 3), "ojk") && !str_striequal(path_baseext(g_gameinfo.qmm_file), "tmp")) + { return false; + } - if (!str_stristr(g_gameinfo.exe_file, "jamp") && !str_stristr(g_gameinfo.exe_file, "openjk.") && !str_stristr(g_gameinfo.exe_file, "openjkded")) + if (!str_stristr(g_gameinfo.exe_file, "jamp") + && !str_stristr(g_gameinfo.exe_file, "openjk.") + && !str_stristr(g_gameinfo.exe_file, "openjkded")) + { return false; + } return true; } @@ -836,12 +821,12 @@ static intptr_t JAMP_vmMain(intptr_t cmd, ...) { // store return value since we do some stuff after the function call is over intptr_t ret = 0; - // if QMM was loaded with the official JAMP or OpenJK "legacy" API (which shouldn't happen, but whatever) + // if the loaded JAMP mod uses the official JAMP or OpenJK "legacy" API if (orig_vmMain) { // all normal mod functions go to mod ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); } - // if QMM was loaded with the OpenJK "new" API + // if the loaded JAMP mod uses the OpenJK "new" API else if (orig_export) { switch (cmd) { ROUTE_EXPORT(InitGame, GAME_INIT); @@ -898,46 +883,45 @@ static intptr_t JAMP_vmMain(intptr_t cmd, ...) { } -static void JAMP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_dllEntry({}) called\n", (void*)syscall); - - // store original syscall from engine - orig_syscall = syscall; +static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) called\n", arg0, arg1, is_GetGameAPI); - // pointer to wrapper vmMain function that calls either orig_vmMain or func in orig_export - g_gameinfo.pfnvmMain = JAMP_vmMain; - - // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import - g_gameinfo.pfnsyscall = JAMP_syscall; + if (is_GetGameAPI) { + orig_apiversion = (intptr_t)arg0; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_dllEntry({}) returning\n", (void*)syscall); -} + // original import struct from engine + // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing + game_import_t* gi = (game_import_t*)arg1; + orig_import = *gi; + // fill in variables of our hooked import struct to pass to the mod -static void* JAMP_GetGameAPI(void* apiversion, void* import) { - orig_apiversion = (intptr_t)apiversion; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_GetGameAPI({}, {}) called\n", orig_apiversion, import); + // pointer to wrapper vmMain function that calls either orig_vmMain or func in orig_export + g_gameinfo.pfnvmMain = JAMP_vmMain; - // original import struct from engine - // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing - game_import_t* gi = (game_import_t*)import; - orig_import = *gi; + // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import + g_gameinfo.pfnsyscall = JAMP_syscall; - // fill in variables of our hooked import struct to pass to the mod + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning\n", arg0, arg1, is_GetGameAPI); - // pointer to wrapper vmMain function that calls either orig_vmMain or func in orig_export - g_gameinfo.pfnvmMain = JAMP_vmMain; + return nullptr; + } + else { + // store original syscall from engine + orig_syscall = (eng_syscall)arg0; - // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import - g_gameinfo.pfnsyscall = JAMP_syscall; + // pointer to wrapper vmMain function that calls either orig_vmMain or func in orig_export + g_gameinfo.pfnvmMain = JAMP_vmMain; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_GetGameAPI({}, {}) returning {}\n", orig_apiversion, import, (void*)&qmm_export); + // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import + g_gameinfo.pfnsyscall = JAMP_syscall; - // struct full of export lambdas to QMM's vmMain - // this gets returned to the game engine, but we haven't loaded the mod yet. - // the only thing in this struct the engine uses before calling Init is the apiversion - return &qmm_export; + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning {}\n", arg0, arg1, is_GetGameAPI, (void*)&qmm_export); + // struct full of export lambdas to QMM's vmMain + // this gets returned to the game engine, but we haven't loaded the mod yet. + return &qmm_export; + } } diff --git a/src/game_jasp.cpp b/src/game_jasp.cpp index a92909b..570310a 100644 --- a/src/game_jasp.cpp +++ b/src/game_jasp.cpp @@ -25,7 +25,7 @@ Created By: GEN_QMM_MSGS(JASP); GEN_EXTS(JASP); -GEN_GGA(JASP); +GEN_FUNCS(JASP); // auto-detection logic for JASP @@ -552,8 +552,8 @@ static intptr_t JASP_vmMain(intptr_t cmd, ...) { } -static void* JASP_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_GetGameAPI({}) called\n", import); +static void* JASP_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -569,7 +569,7 @@ static void* JASP_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = JASP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -578,7 +578,10 @@ static void* JASP_GetGameAPI(void* import, void*) { } -static bool JASP_mod_load(void* entry, bool) { +static bool JASP_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_jk2mp.cpp b/src/game_jk2mp.cpp index c38a502..d2b4417 100644 --- a/src/game_jk2mp.cpp +++ b/src/game_jk2mp.cpp @@ -24,7 +24,7 @@ Created By: GEN_QMM_MSGS(JK2MP); GEN_EXTS(JK2MP); -GEN_DLLQVM(JK2MP); +GEN_FUNCS_QVM(JK2MP); // auto-detection logic for JK2MP @@ -127,11 +127,11 @@ static intptr_t JK2MP_vmMain(intptr_t cmd, ...) { } -static void JK2MP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_dllEntry({}) called\n", (void*)syscall); +static void* JK2MP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = JK2MP_vmMain; @@ -139,11 +139,16 @@ static void JK2MP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = JK2MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_entry({}) returning\n", syscall); + + return nullptr; } -static bool JK2MP_mod_load(void* entry, bool) { +static bool JK2MP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_jk2sp.cpp b/src/game_jk2sp.cpp index 64a6555..b92378d 100644 --- a/src/game_jk2sp.cpp +++ b/src/game_jk2sp.cpp @@ -24,7 +24,7 @@ Created By: GEN_QMM_MSGS(JK2SP); GEN_EXTS(JK2SP); -GEN_GGA(JK2SP); +GEN_FUNCS(JK2SP); // auto-detection logic for JK2SP @@ -473,8 +473,8 @@ static intptr_t JK2SP_vmMain(intptr_t cmd, ...) { } -static void* JK2SP_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_GetGameAPI({}) called\n", import); +static void* JK2SP_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -490,7 +490,7 @@ static void* JK2SP_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = JK2SP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -499,7 +499,10 @@ static void* JK2SP_GetGameAPI(void* import, void*) { } -static bool JK2SP_mod_load(void* entry, bool) { +static bool JK2SP_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_mohaa.cpp b/src/game_mohaa.cpp index 785ca36..e5920f3 100644 --- a/src/game_mohaa.cpp +++ b/src/game_mohaa.cpp @@ -29,7 +29,7 @@ Created By: GEN_QMM_MSGS(MOHAA); GEN_EXTS(MOHAA); -GEN_GGA(MOHAA); +GEN_FUNCS(MOHAA); // auto-detection logic for MOHAA @@ -743,8 +743,8 @@ static intptr_t MOHAA_vmMain(intptr_t cmd, ...) { } -static void* MOHAA_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_GetGameAPI({}) called\n", import); +static void* MOHAA_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -764,7 +764,7 @@ static void* MOHAA_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHAA_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -773,7 +773,10 @@ static void* MOHAA_GetGameAPI(void* import, void*) { } -static bool MOHAA_mod_load(void* entry, bool) { +static bool MOHAA_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_mohbt.cpp b/src/game_mohbt.cpp index 37a4a74..731a4bf 100644 --- a/src/game_mohbt.cpp +++ b/src/game_mohbt.cpp @@ -29,7 +29,7 @@ Created By: GEN_QMM_MSGS(MOHBT); GEN_EXTS(MOHBT); -GEN_GGA(MOHBT); +GEN_FUNCS(MOHBT); // auto-detection logic for MOHBT @@ -782,8 +782,8 @@ static intptr_t MOHBT_vmMain(intptr_t cmd, ...) { } -static void* MOHBT_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_GetGameAPI({}) called\n", import); +static void* MOHBT_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -803,7 +803,7 @@ static void* MOHBT_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHBT_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -812,7 +812,10 @@ static void* MOHBT_GetGameAPI(void* import, void*) { } -static bool MOHBT_mod_load(void* entry, bool) { +static bool MOHBT_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_mohsh.cpp b/src/game_mohsh.cpp index ce8d97d..b5d2910 100644 --- a/src/game_mohsh.cpp +++ b/src/game_mohsh.cpp @@ -29,7 +29,7 @@ Created By: GEN_QMM_MSGS(MOHSH); GEN_EXTS(MOHSH); -GEN_GGA(MOHSH); +GEN_FUNCS(MOHSH); // auto-detection logic for MOHSH @@ -782,8 +782,8 @@ static intptr_t MOHSH_vmMain(intptr_t cmd, ...) { } -static void* MOHSH_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_GetGameAPI({}) called\n", import); +static void* MOHSH_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -803,7 +803,7 @@ static void* MOHSH_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHSH_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -812,7 +812,10 @@ static void* MOHSH_GetGameAPI(void* import, void*) { } -static bool MOHSH_mod_load(void* entry, bool) { +static bool MOHSH_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_q2r.cpp b/src/game_q2r.cpp index bbb1f44..b6680cf 100644 --- a/src/game_q2r.cpp +++ b/src/game_q2r.cpp @@ -38,7 +38,7 @@ GEN_QMM_MSGS(Q2R); #undef GAME_INIT GEN_EXTS(Q2R); -GEN_GGA(Q2R); +GEN_FUNCS(Q2R); // auto-detection logic for Q2R @@ -598,8 +598,8 @@ static intptr_t Q2R_vmMain(intptr_t cmd, ...) { } -static void* Q2R_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_GetGameAPI({}) called\n", import); +static void* Q2R_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -617,7 +617,7 @@ static void* Q2R_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = Q2R_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -626,7 +626,10 @@ static void* Q2R_GetGameAPI(void* import, void*) { } -static bool Q2R_mod_load(void* entry, bool) { +static bool Q2R_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_q3a.cpp b/src/game_q3a.cpp index d90766a..1fad7a8 100644 --- a/src/game_q3a.cpp +++ b/src/game_q3a.cpp @@ -24,7 +24,7 @@ Created By: GEN_QMM_MSGS(Q3A); GEN_EXTS(Q3A); -GEN_DLLQVM(Q3A); +GEN_FUNCS_QVM(Q3A); // auto-detection logic for Q3A @@ -126,11 +126,11 @@ static intptr_t Q3A_vmMain(intptr_t cmd, ...) { } -static void Q3A_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_dllEntry({}) called\n", (void*)syscall); +static void* Q3A_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func g_gameinfo.pfnvmMain = Q3A_vmMain; @@ -138,11 +138,16 @@ static void Q3A_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = Q3A_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_entry({}) returning\n", syscall); + + return nullptr; } -static bool Q3A_mod_load(void* entry, bool) { +static bool Q3A_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_quake2.cpp b/src/game_quake2.cpp index 7bfbb0d..622ba48 100644 --- a/src/game_quake2.cpp +++ b/src/game_quake2.cpp @@ -28,7 +28,7 @@ Created By: GEN_QMM_MSGS(QUAKE2); GEN_EXTS(QUAKE2); -GEN_GGA(QUAKE2); +GEN_FUNCS(QUAKE2); // auto-detection logic for QUAKE2 @@ -517,8 +517,8 @@ static intptr_t QUAKE2_vmMain(intptr_t cmd, ...) { } -static void* QUAKE2_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_GetGameAPI({}) called\n", import); +static void* QUAKE2_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -534,7 +534,7 @@ static void* QUAKE2_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = QUAKE2_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -543,7 +543,10 @@ static void* QUAKE2_GetGameAPI(void* import, void*) { } -static bool QUAKE2_mod_load(void* entry, bool) { +static bool QUAKE2_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_rtcwmp.cpp b/src/game_rtcwmp.cpp index 4cfc5a3..e84dcca 100644 --- a/src/game_rtcwmp.cpp +++ b/src/game_rtcwmp.cpp @@ -23,7 +23,7 @@ Created By: GEN_QMM_MSGS(RTCWMP); GEN_EXTS(RTCWMP); -GEN_DLLQVM(RTCWMP); +GEN_FUNCS_QVM(RTCWMP); // auto-detection logic for RTCWMP @@ -120,11 +120,11 @@ static intptr_t RTCWMP_vmMain(intptr_t cmd, ...) { } -static void RTCWMP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_dllEntry({}) called\n", (void*)syscall); +static void* RTCWMP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = RTCWMP_vmMain; @@ -132,11 +132,16 @@ static void RTCWMP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = RTCWMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_entry({}) returning\n", syscall); + + return nullptr; } -static bool RTCWMP_mod_load(void* entry, bool) { +static bool RTCWMP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_rtcwsp.cpp b/src/game_rtcwsp.cpp index 741669a..3a55471 100644 --- a/src/game_rtcwsp.cpp +++ b/src/game_rtcwsp.cpp @@ -25,7 +25,7 @@ Created By: GEN_QMM_MSGS(RTCWSP); GEN_EXTS(RTCWSP); -GEN_DLL(RTCWSP); +GEN_FUNCS(RTCWSP); #if defined(QMM_ARCH_32) && defined(QMM_OS_WINDOWS) #define MOD_DLL "x86.dll" @@ -58,7 +58,7 @@ static bool RTCWSP_autodetect(bool is_GetGameAPI, supportedgame* game) { game->moddir = "main"; } - // set the default dllname to whatever we loaded as to load the correct mod DLL + // set the default dllname to whatever QMM loaded as to load the correct mod DLL game->dllname = g_gameinfo.qmm_file.c_str(); return true; @@ -160,11 +160,11 @@ static intptr_t RTCWSP_vmMain(intptr_t cmd, ...) { } -static void RTCWSP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_dllEntry({}) called\n", (void*)syscall); +static void* RTCWSP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = RTCWSP_vmMain; @@ -172,11 +172,16 @@ static void RTCWSP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = RTCWSP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_entry({}) returning\n", syscall); + + return nullptr; } -static bool RTCWSP_mod_load(void* entry, bool) { +static bool RTCWSP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; @@ -189,6 +194,8 @@ static void RTCWSP_mod_unload() { // free the G_ALLOC list for (void* ptr : alloc_list) free(ptr); + + alloc_list.clear(); } diff --git a/src/game_sin.cpp b/src/game_sin.cpp index 390950c..6c52ea9 100644 --- a/src/game_sin.cpp +++ b/src/game_sin.cpp @@ -28,7 +28,7 @@ Created By: GEN_QMM_MSGS(SIN); GEN_EXTS(SIN); -GEN_GGA(SIN); +GEN_FUNCS(SIN); // auto-detection logic for SIN @@ -633,8 +633,8 @@ static intptr_t SIN_vmMain(intptr_t cmd, ...) { } -static void* SIN_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_GetGameAPI({}) called\n", import); +static void* SIN_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -651,7 +651,7 @@ static void* SIN_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = SIN_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -660,7 +660,10 @@ static void* SIN_GetGameAPI(void* import, void*) { } -static bool SIN_mod_load(void* entry, bool) { +static bool SIN_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_sof2mp.cpp b/src/game_sof2mp.cpp index 2ace1a7..b7c54d3 100644 --- a/src/game_sof2mp.cpp +++ b/src/game_sof2mp.cpp @@ -25,7 +25,7 @@ Created By: GEN_QMM_MSGS(SOF2MP); GEN_EXTS(SOF2MP); -GEN_DLLQVM(SOF2MP); +GEN_FUNCS_QVM(SOF2MP); // auto-detection logic for SOF2MP @@ -163,11 +163,11 @@ static intptr_t SOF2MP_vmMain(intptr_t cmd, ...) { } -static void SOF2MP_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_dllEntry({}) called\n", (void*)syscall); +static void* SOF2MP_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = SOF2MP_vmMain; @@ -175,12 +175,17 @@ static void SOF2MP_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = SOF2MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_entry({}) returning\n", syscall); + + return nullptr; } // get mod's vmMain function pointer from mod.cpp::mod_load -static bool SOF2MP_mod_load(void* entry, bool) { +static bool SOF2MP_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; // we cannot verify data in the QVM since this engine both provides malloc functionality and has the gametype module, diff --git a/src/game_sof2sp.cpp b/src/game_sof2sp.cpp index 8bee164..060ce06 100644 --- a/src/game_sof2sp.cpp +++ b/src/game_sof2sp.cpp @@ -21,7 +21,7 @@ Created By: GEN_QMM_MSGS(SOF2SP); GEN_EXTS(SOF2SP); -GEN_GGA(SOF2SP); +GEN_FUNCS(SOF2SP); // auto-detection logic for SOF2SP @@ -442,9 +442,9 @@ static intptr_t SOF2SP_vmMain(intptr_t cmd, ...) { } -static void* SOF2SP_GetGameAPI(void* apiversion, void* import) { +static void* SOF2SP_entry(void* apiversion, void* import, bool) { orig_apiversion = (intptr_t)apiversion; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_GetGameAPI({}, {}) called\n", orig_apiversion, import); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_entry({}, {}) called\n", orig_apiversion, import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -460,7 +460,7 @@ static void* SOF2SP_GetGameAPI(void* apiversion, void* import) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = SOF2SP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_GetGameAPI({}, {}) returning {}\n", orig_apiversion, import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_entry({}, {}) returning {}\n", orig_apiversion, import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -469,7 +469,10 @@ static void* SOF2SP_GetGameAPI(void* apiversion, void* import) { } -static bool SOF2SP_mod_load(void* entry, bool) { +static bool SOF2SP_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; // api version gets passed before import pointer orig_export = (game_export_t*)pfnGGA((void*)orig_apiversion, &qmm_import); diff --git a/src/game_stef2.cpp b/src/game_stef2.cpp index c07061a..83bfa66 100644 --- a/src/game_stef2.cpp +++ b/src/game_stef2.cpp @@ -26,7 +26,7 @@ Created By: GEN_QMM_MSGS(STEF2); GEN_EXTS(STEF2); -GEN_GGA(STEF2); +GEN_FUNCS(STEF2); // auto-detection logic for STEF2 @@ -960,8 +960,8 @@ static intptr_t STEF2_vmMain(intptr_t cmd, ...) { } -static void* STEF2_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_GetGameAPI({}) called\n", import); +static void* STEF2_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -978,7 +978,7 @@ static void* STEF2_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = STEF2_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -987,7 +987,10 @@ static void* STEF2_GetGameAPI(void* import, void*) { } -static bool STEF2_mod_load(void* entry, bool) { +static bool STEF2_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_stvoyhm.cpp b/src/game_stvoyhm.cpp index 3b23d65..d1b5378 100644 --- a/src/game_stvoyhm.cpp +++ b/src/game_stvoyhm.cpp @@ -24,7 +24,7 @@ Created By: GEN_QMM_MSGS(STVOYHM); GEN_EXTS(STVOYHM); -GEN_DLLQVM(STVOYHM); +GEN_FUNCS_QVM(STVOYHM); // auto-detection logic for Q3A @@ -127,11 +127,11 @@ static intptr_t STVOYHM_vmMain(intptr_t cmd, ...) { } -static void STVOYHM_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_dllEntry({}) called\n", (void*)syscall); +static void* STVOYHM_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = STVOYHM_vmMain; @@ -139,11 +139,16 @@ static void STVOYHM_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = STVOYHM_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_entry({}) returning\n", syscall); + + return nullptr; } -static bool STVOYHM_mod_load(void* entry, bool) { +static bool STVOYHM_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/game_stvoysp.cpp b/src/game_stvoysp.cpp index 41da018..13b9915 100644 --- a/src/game_stvoysp.cpp +++ b/src/game_stvoysp.cpp @@ -24,7 +24,7 @@ Created By: GEN_QMM_MSGS(STVOYSP); GEN_EXTS(STVOYSP); -GEN_GGA(STVOYSP); +GEN_FUNCS(STVOYSP); // auto-detection logic for STVOYSP @@ -348,8 +348,8 @@ static intptr_t STVOYSP_vmMain(intptr_t cmd, ...) { } -static void* STVOYSP_GetGameAPI(void* import, void*) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_GetGameAPI({}) called\n", import); +static void* STVOYSP_entry(void* import, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -365,7 +365,7 @@ static void* STVOYSP_GetGameAPI(void* import, void*) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = STVOYSP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_GetGameAPI({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -374,7 +374,10 @@ static void* STVOYSP_GetGameAPI(void* import, void*) { } -static bool STVOYSP_mod_load(void* entry, bool) { +static bool STVOYSP_mod_load(void* entry, bool is_GetGameAPI) { + if (!is_GetGameAPI) + return false; + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; orig_export = (game_export_t*)pfnGGA(&qmm_import, nullptr); diff --git a/src/game_wet.cpp b/src/game_wet.cpp index d35c980..8206697 100644 --- a/src/game_wet.cpp +++ b/src/game_wet.cpp @@ -23,7 +23,7 @@ Created By: GEN_QMM_MSGS(WET); GEN_EXTS(WET); -GEN_DLL(WET); +GEN_FUNCS(WET); // auto-detection logic for WET @@ -120,11 +120,11 @@ intptr_t WET_vmMain(intptr_t cmd, ...) { } -void WET_dllEntry(eng_syscall syscall) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_dllEntry({}) called\n", (void*)syscall); +void* WET_entry(void* syscall, void*, bool) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_entry({}) called\n", syscall); // store original syscall from engine - orig_syscall = syscall; + orig_syscall = (eng_syscall)syscall; // pointer to wrapper vmMain function that calls actual mod vmMain func orig_vmMain g_gameinfo.pfnvmMain = WET_vmMain; @@ -132,11 +132,16 @@ void WET_dllEntry(eng_syscall syscall) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = WET_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_dllEntry({}) returning\n", (void*)syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_entry({}) returning\n", syscall); + + return nullptr; } -bool WET_mod_load(void* entry, bool) { +bool WET_mod_load(void* entry, bool is_GetGameAPI) { + if (is_GetGameAPI) + return false; + orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; diff --git a/src/main.cpp b/src/main.cpp index 1b85a6d..428d818 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -134,6 +134,10 @@ C_DLLEXPORT void dllEntry(void* syscall) { return; } + // store the given syscall pointer as a backup (should get overwritten in game-specific entry handler), and so + // if we don't detect a game, we can call syscall(G_ERROR) to shutdown in vmMain + g_gameinfo.pfnsyscall = (eng_syscall)syscall; + main_handle_entry(syscall, nullptr, false); // false = !is_GetGameAPI return; } @@ -304,7 +308,7 @@ C_DLLEXPORT intptr_t vmMain(intptr_t cmd, ...) { LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("Successfully loaded {} mod \"{}\"\n", g_mod.vmbase ? "VM" : "DLL", g_mod.path); // cgame passthrough hack: - // mod DLL is loaded, so find the vmMain and dllEntry functions and call dllEntry + // mod DLL is loaded, so find the vmMain and dllEntry functions and call dllEntry. // JASP+JK2SP's cgame dllEntry functions actually call into the syscall almost immediately, // so make sure we store vmMain first in case there's some re-entrancy if (cgame.syscall) { @@ -380,7 +384,7 @@ C_DLLEXPORT intptr_t vmMain(intptr_t cmd, ...) { // unload each plugin (call QMM_Detach, and then dlclose) LOG(QMM_LOG_NOTICE, "QMM") << "Shutting down plugins\n"; - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { plugin_unload(p); } g_plugins.clear(); @@ -452,13 +456,11 @@ static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { cfg_game = util_get_cmdline_arg("--qmm_game", cfg_game); main_detect_game(cfg_game, is_GetGameAPI); - // failed to get engine information - // return nullptr to error out now. if GetGameAPI, Init() will never be called - if (!g_gameinfo.game) { + // failed to get engine information, or game does not have an entry handler + // if GetGameAPI, returning nullptr to error out now will make sure Init() will never be called. + // if dllEntry, will check g_gameinfo.game in vmMain(GAME_INIT). + if (!g_gameinfo.game || !g_gameinfo.game->funcs->pfnEntry) { LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): Unable to determine game engine using \"{}\"\n", func_name, cfg_game); - // if dllEntry, store the given syscall pointer so we can call G_ERROR to shutdown in vmMain - if (!is_GetGameAPI) - g_gameinfo.pfnsyscall = (eng_syscall)import; return nullptr; } @@ -468,30 +470,9 @@ static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { msg_GAME_CONSOLE_COMMAND = QMM_MOD_MSG[QMM_GAME_CONSOLE_COMMAND]; msg_GAME_SHUTDOWN = QMM_MOD_MSG[QMM_GAME_SHUTDOWN]; - if (is_GetGameAPI) { - // supported games table is missing game-specific GetGameAPI handler? - // return nullptr to error out now. Init() will never be called - if (!g_gameinfo.game->funcs->pfnGetGameAPI) { - LOG(QMM_LOG_FATAL, "QMM") << fmt::format("GetGameAPI(): pfnGetGameAPI handler for game \"{}\" is NULL!\n", g_gameinfo.game->gamename_short); - return nullptr; - } - - // call the game-specific GetGameAPI function (e.g. MOHAA_GetGameAPI) which will set up the exports for - // returning here back to the game engine, as well as save the imports in preparation of loading the mod - return g_gameinfo.game->funcs->pfnGetGameAPI(import, extra); - } - - // call the game-specific dllEntry function (e.g. Q3A_dllEntry) which will set up the functions to handle - // vmMain and syscalls from the mod, engine, and plugins - if (g_gameinfo.game->funcs->pfndllEntry) - g_gameinfo.game->funcs->pfndllEntry((eng_syscall)import); - // supported games table is missing game-specific dllEntry handler? we can try to fake it by storing the - // syscall pointer in g_gameinfo.pfnsyscall. also as a hack, s_mod_load_vmmain & s_mod_load_qvm will store - // vmMain in g_gameinfo.pfnvmMain if it wasn't set already by the game-specific dllEntry - else - g_gameinfo.pfnsyscall = (eng_syscall)import; - - return nullptr; + // call the game-specific entry handler (e.g. Q3A_entry) which will set up the internals to interact + // the engine and the mod + return g_gameinfo.game->funcs->pfnEntry(import, extra, is_GetGameAPI); } @@ -569,7 +550,10 @@ static void main_detect_game(std::string cfg_game, bool is_GetGameAPI) { } // otherwise, if auto, call the game's auto-detect function if available - if (str_striequal(cfg_game, "auto") && game.funcs->pfnAutoDetect && game.funcs->pfnAutoDetect(is_GetGameAPI, &game)) { + if (str_striequal(cfg_game, "auto") + && game.funcs->pfnAutoDetect + && game.funcs->pfnAutoDetect(is_GetGameAPI, &game)) + { LOG(QMM_LOG_INFO, "QMM") << fmt::format("Found game match with auto-detection - \"{}\"\n", game.gamename_short); g_gameinfo.game = &game; g_gameinfo.is_auto_detected = true; @@ -633,7 +617,7 @@ static bool main_load_mod(std::string cfg_mod) { // general code to find a plugin file to load static bool main_load_plugin(std::string plugin_path) { - plugin p; + qmm_plugin p; // absolute path, just attempt to load it directly if (!path_is_relative(plugin_path)) { // plugin_load returns 0 if no plugin file was found, 1 if success, and -1 if file was found but failure @@ -680,12 +664,12 @@ static void main_handle_command_qmm(intptr_t arg_start) { CONSOLE_PRINT("(QMM) QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ")\n"); CONSOLE_PRINTF("(QMM) Game: {}/\"{}\" (Source: {})\n", g_gameinfo.game->gamename_short, g_gameinfo.game->gamename_long, g_gameinfo.is_auto_detected ? "Auto-detected" : "Config file"); CONSOLE_PRINTF("(QMM) ModDir: {}\n", g_gameinfo.mod_dir); - CONSOLE_PRINTF("(QMM) Config file: \"{}\" {}\n", g_gameinfo.cfg_path, g_cfg.is_discarded() ? " (error)" : ""); + CONSOLE_PRINTF("(QMM) Config file: \"{}\" {}\n", g_gameinfo.cfg_path, g_cfg.empty() ? "(error)" : ""); CONSOLE_PRINT("(QMM) Built: " QMM_COMPILE " by " QMM_BUILDER "\n"); CONSOLE_PRINT("(QMM) URL: " QMM_URL "\n"); CONSOLE_PRINT("(QMM) Plugin interface: " STRINGIFY(QMM_PIFV_MAJOR) ":" STRINGIFY(QMM_PIFV_MINOR) "\n"); CONSOLE_PRINTF("(QMM) Plugins loaded: {}\n", g_plugins.size()); - CONSOLE_PRINTF("(QMM) Loaded mod file: {}\n", g_mod.path); + CONSOLE_PRINTF("(QMM) Loaded mod: {} ({})\n", g_mod.path, g_mod.is_GetGameAPI ? "GetGameAPI" : "dllEntry"); if (g_mod.vmbase) { CONSOLE_PRINTF("(QMM) QVM magic number : {:x} ({})\n", g_mod.vm.magic, g_mod.vm.magic == QVM_MAGIC ? "QVM_MAGIC" : "QVM_MAGIC_VER2"); CONSOLE_PRINTF("(QMM) QVM file size : {}\n", g_mod.vm.filesize); @@ -702,7 +686,7 @@ static void main_handle_command_qmm(intptr_t arg_start) { CONSOLE_PRINT("(QMM) id - plugin [version]\n"); CONSOLE_PRINT("(QMM) ---------------------\n"); int num = 1; - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { CONSOLE_PRINTF("(QMM) {:>2} - {} [{}]\n", num, p.plugininfo->name, p.plugininfo->version); num++; } @@ -714,7 +698,7 @@ static void main_handle_command_qmm(intptr_t arg_start) { } size_t pid = (size_t)atoi(arg2); if (pid > 0 && pid <= g_plugins.size()) { - plugin& p = g_plugins[pid - 1]; + qmm_plugin& p = g_plugins[pid - 1]; CONSOLE_PRINTF("(QMM) Plugin info for #{}:\n", arg2); CONSOLE_PRINTF("(QMM) Name: {}\n", p.plugininfo->name); CONSOLE_PRINTF("(QMM) Version: {}\n", p.plugininfo->version); @@ -738,6 +722,10 @@ static void main_handle_command_qmm(intptr_t arg_start) { log_set_severity(severity); CONSOLE_PRINTF("(QMM) Log level set to {}\n", log_name_from_severity(severity)); } + else if (str_striequal("reload", arg1)) { + g_cfg = cfg_load(g_gameinfo.cfg_path); + CONSOLE_PRINT("(QMM) Configuration file reloaded!\n"); + } else { CONSOLE_PRINT("(QMM) Usage: qmm [params]\n"); CONSOLE_PRINT("(QMM) Available commands:\n"); @@ -745,6 +733,7 @@ static void main_handle_command_qmm(intptr_t arg_start) { CONSOLE_PRINT("(QMM) qmm list - displays information about loaded QMM plugins\n"); CONSOLE_PRINT("(QMM) qmm plugin - outputs info on plugin with id\n"); CONSOLE_PRINT("(QMM) qmm loglevel - changes QMM log level: TRACE, DEBUG, INFO, NOTICE, WARNING, ERROR, FATAL\n"); + CONSOLE_PRINT("(QMM) qmm reload - reloads the QMM configuration file\n"); } } @@ -777,7 +766,7 @@ static intptr_t main_route(bool is_syscall, intptr_t cmd, intptr_t* args) { intptr_t final_ret = 0; // begin passing calls to plugins' pre-hook functions - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { g_plugin_globals.plugin_result = QMM_UNUSED; // allow plugins to see the current final_ret value g_plugin_globals.final_return = final_ret; @@ -839,7 +828,7 @@ static intptr_t main_route(bool is_syscall, intptr_t cmd, intptr_t* args) { final_ret = real_ret; // pass calls to plugins' post-hook functions (QMM_OVERRIDE or QMM_SUPERCEDE can still change final_ret) - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { g_plugin_globals.plugin_result = QMM_UNUSED; // allow plugins to see the current final_ret value g_plugin_globals.final_return = final_ret; diff --git a/src/mod.cpp b/src/mod.cpp index bf8dda8..8bcad01 100644 --- a/src/mod.cpp +++ b/src/mod.cpp @@ -23,14 +23,14 @@ Created By: #include "plugin.h" #include "util.h" -mod g_mod; +qmm_mod g_mod; static intptr_t s_mod_qvm_vmmain(intptr_t cmd, ...); static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args); -static bool s_mod_load_qvm(mod& mod); +static bool s_mod_load_qvm(qmm_mod& mod); -bool mod_load(mod& mod, std::string file) { +bool mod_load(qmm_mod& mod, std::string file) { // if this mod somehow already has a dll or qvm pointer, wipe it first if (mod.dll || mod.vm.memory) mod_unload(mod); @@ -40,93 +40,80 @@ bool mod_load(mod& mod, std::string file) { std::string ext = path_baseext(file); // only allow qvm mods if the game engine supports it - if (str_striequal(ext, EXT_QVM) && g_gameinfo.game->funcs->pfnqvmsyscall) + if (str_striequal(ext, EXT_QVM) && g_gameinfo.game->funcs->pfnqvmsyscall) { return s_mod_load_qvm(mod); - + } // if DLL else if (str_striequal(ext, EXT_DLL)) { // load DLL if (!(mod.dll = dlopen(file.c_str(), RTLD_NOW))) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): DLL load failed: {}\n", file, dlerror()); - return false; + goto fail; } // if this DLL is the same as QMM, cancel if (mod.dll == g_gameinfo.qmm_module_ptr) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): DLL is actually QMM?\n", file); dlclose(mod.dll); - return false; + goto fail; } mod.vmbase = 0; - // if game supports GetGameAPI, look for GetGameAPI function - if (g_gameinfo.game->funcs->pfnGetGameAPI) { - mod_GetGameAPI pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetGameAPI"); - - // try for "GetModuleAPI", which is what OpenJK uses - if (!pfnGGA) { - pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetModuleAPI"); - } - - if (pfnGGA) { - // pass the GetGameAPI function pointer to the game-specific mod load handler - if (g_gameinfo.game->funcs->pfnModLoad && - g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, true)) { // true = is_GetGameAPI - return true; - } - else { - LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): \"GetGameAPI\" function failed\n", mod.path); - } - } - else { - LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unable to find \"GetGameAPI\" function\n", mod.path); - } + // look for GetGameAPI function + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetGameAPI"); + // if no GGA, look for "GetModuleAPI", which is what OpenJK uses + if (!pfnGGA) + pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetModuleAPI"); + // if we found the function, try passing it to the game-specific mod load handler + if (pfnGGA + && g_gameinfo.game->funcs->pfnModLoad + && g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, true)) // true = is_GetGameAPI + { + mod.is_GetGameAPI = true; + return true; } - // if game supports dllEntry, look for dllEntry function - if (g_gameinfo.game->funcs->pfndllEntry) { - mod_dllEntry pfndllEntry = (mod_dllEntry)dlsym(mod.dll, "dllEntry"); - mod_vmMain pfnvmMain = (mod_vmMain)dlsym(mod.dll, "vmMain"); - - if (pfndllEntry && pfnvmMain) { - if (g_gameinfo.game->funcs->pfnModLoad) { - // pass the vmMain function pointer to the game-specific mod load handler - if (g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, false)) { // false = !is_GetGameAPI - // pass qmm_syscall to mod's dllEntry function - pfndllEntry(qmm_syscall); - return true; - } - else { - LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Mod load failed?\n", mod.path); - } - } - // hack in case there isn't a game-specific dllEntry or ModLoad function - else if (!g_gameinfo.pfnvmMain) { - g_gameinfo.pfnvmMain = pfnvmMain; - } - } - else { - LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unable to find \"dllEntry\" and/or \"vmMain\" function\n", mod.path); - } + // if no GetGameAPI function, OR the mod load handler returned false, look for dllEntry and vmMain + mod_dllEntry pfndllEntry = (mod_dllEntry)dlsym(mod.dll, "dllEntry"); + mod_vmMain pfnvmMain = (mod_vmMain)dlsym(mod.dll, "vmMain"); + // store the vmMain pointer as a backup (should get overwritten in game-specific mod load handler) + g_gameinfo.pfnvmMain = pfnvmMain; + + // if we found both functions, and mod load handler returned true, pass vmMain to the game-specific + // mod load handler + if (pfndllEntry + && pfnvmMain + && g_gameinfo.game->funcs->pfnModLoad + && g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, false)) // false = !is_GetGameAPI + { + // pass qmm_syscall to mod's dllEntry function + pfndllEntry(qmm_syscall); + mod.is_GetGameAPI = false; + return true; } + + LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unable to locate mod entry point\n", file); + goto fail; + } + else { + LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unknown mod file format\n", file); } +fail: mod_unload(mod); - - LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unknown file format\n", file); return false; } -void mod_unload(mod& mod) { +void mod_unload(qmm_mod& mod) { // call the game-specific mod unload callback if (g_gameinfo.game->funcs->pfnModUnload) g_gameinfo.game->funcs->pfnModUnload(); qvm_unload(&mod.vm); if (mod.dll) dlclose(mod.dll); - mod = ::mod(); + mod = qmm_mod(); } @@ -169,7 +156,7 @@ static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args) { // check for plugin qvm function registration if (cmd >= QMM_QVM_FUNC_STARTING_ID && g_registered_qvm_funcs.count(cmd)) { - plugin* p = g_registered_qvm_funcs[cmd]; + qmm_plugin* p = g_registered_qvm_funcs[cmd]; // make sure plugin has the handler function (shouldn't have been registered, but check anyway) if (!p->QMM_QVMHandler) @@ -185,7 +172,7 @@ static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args) { // load a QVM mod -static bool s_mod_load_qvm(mod& mod) { +static bool s_mod_load_qvm(qmm_mod& mod) { int fpk3 = 0; intptr_t filelen; std::vector filemem; @@ -216,19 +203,18 @@ static bool s_mod_load_qvm(mod& mod) { } mod.vmbase = (intptr_t)mod.vm.datasegment; + // store the qvm vmMain pointer as a backup (should get overwritten in game-specific mod load handler) + g_gameinfo.pfnvmMain = s_mod_qvm_vmmain; // pass the qvm vmMain function pointer to the game-specific mod load handler - if (g_gameinfo.game->funcs->pfnModLoad && + if (!g_gameinfo.game->funcs->pfnModLoad || !g_gameinfo.game->funcs->pfnModLoad((void*)s_mod_qvm_vmmain, false)) // false = !is_GetGameAPI { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Mod load failed?\n", mod.path); goto fail; } - // hack in case there isn't a game-specific dllEntry or ModLoad function - if (!g_gameinfo.pfnvmMain) { - g_gameinfo.pfnvmMain = s_mod_qvm_vmmain; - } + mod.is_GetGameAPI = false; return true; diff --git a/src/plugin.cpp b/src/plugin.cpp index fc9a302..2939ba0 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -84,10 +84,10 @@ plugin_globals g_plugin_globals = { QMM_UNUSED, // plugin_result }; -std::vector g_plugins; +std::vector g_plugins; // store registered QVM function IDs for plugins -std::map g_registered_qvm_funcs; +std::map g_registered_qvm_funcs; static int s_next_qvm_func = QMM_QVM_FUNC_STARTING_ID; static plugin_vars s_pluginvars = { @@ -112,7 +112,7 @@ const char* plugin_result_to_str(plugin_res res) { // returns: -1 if failed to load and don't continue, 0 if failed to load and continue, 1 if loaded -int plugin_load(plugin& p, std::string file) { +int plugin_load(qmm_plugin& p, std::string file) { int ret = 0; // if this plugin somehow already has a dll pointer, wipe it first @@ -134,7 +134,7 @@ int plugin_load(plugin& p, std::string file) { } // if this DLL is the same as another loaded plugin, cancel - for (plugin& t : g_plugins) { + for (qmm_plugin& t : g_plugins) { if (p.dll == t.dll) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("plugin_load(\"{}\"): DLL is already loaded as plugin\n", file); // treat this failure specially. this is a valid plugin, but it is already loaded @@ -228,14 +228,14 @@ int plugin_load(plugin& p, std::string file) { } -void plugin_unload(plugin& p) { +void plugin_unload(qmm_plugin& p) { if (p.dll) { if (p.QMM_Detach) p.QMM_Detach(); dlclose(p.dll); } - p = plugin(); + p = qmm_plugin(); } @@ -510,7 +510,7 @@ static void s_plugin_helper_GetConfigString(plugin_id plid [[maybe_unused]], int static int s_plugin_helper_PluginBroadcast(plugin_id plid, const char* message, void* buf, intptr_t buflen) { // count how many plugins were called int total = 0; - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { // skip the calling plugin if (p.plugininfo == (plugin_info*)plid) continue; @@ -535,7 +535,7 @@ static int s_plugin_helper_PluginSend(plugin_id plid, plugin_id to_plid, const c if (plid == to_plid) return 0; - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { // if this is the destination plugin if (p.plugininfo == (plugin_info*)to_plid) { // if the plugin doesn't have the message function @@ -559,7 +559,7 @@ static int s_plugin_helper_QVMRegisterFunc(plugin_id plid) { int ret = 0; // find the calling plugin - for (plugin& p : g_plugins) { + for (qmm_plugin& p : g_plugins) { // found it if (p.plugininfo == (plugin_info*)plid) { // make sure the plugin actually has a QVM handler func From 592df8f44e9a113bb8a4a6daf47091d942cb4610 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Sun, 8 Mar 2026 19:49:20 +0200 Subject: [PATCH 02/15] update G_ALLOC comment --- src/game_rtcwsp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game_rtcwsp.cpp b/src/game_rtcwsp.cpp index 3a55471..10b670f 100644 --- a/src/game_rtcwsp.cpp +++ b/src/game_rtcwsp.cpp @@ -106,9 +106,9 @@ static intptr_t RTCWSP_syscall(intptr_t cmd, ...) { break; } case G_ALLOC: { - // if we are using the iortcw game dll but not the engine, we need to handle G_ALLOC ourselves - // just malloc and store the pointer in alloc_list - // (at this time, it doesn't look like the rtcwsp game dll actually uses trap_Alloc) + // if we are using the iortcw single player game dll but not the engine, we need to handle G_ALLOC + // ourselves just malloc and store the pointer in alloc_list (although, at this time, it doesn't + // look like the iortcw single player game dll actually uses trap_Alloc) if (is_iortcw) { ret = orig_syscall(G_ALLOC, args[0]); break; From 7af706956a417ce7f840ae7fa405dae1550e285a Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Sun, 8 Mar 2026 23:16:41 +0200 Subject: [PATCH 03/15] fix bug with JAMP_entry --- src/game_jamp.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game_jamp.cpp b/src/game_jamp.cpp index 77b7c22..6517423 100644 --- a/src/game_jamp.cpp +++ b/src/game_jamp.cpp @@ -27,7 +27,7 @@ GEN_FUNCS(JAMP); // auto-detection logic for JAMP -static bool JAMP_autodetect(bool is_GetGameAPI, supportedgame* game) { +static bool JAMP_autodetect(bool, supportedgame* game) { // QMM filename must match default or an OpenJK temp filename (if DLL was pulled from .pk3) if (!str_striequal(g_gameinfo.qmm_file, game->dllname) && !str_striequal(g_gameinfo.qmm_file.substr(0, 3), "ojk") @@ -902,9 +902,11 @@ static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning\n", arg0, arg1, is_GetGameAPI); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning {}\n", arg0, arg1, is_GetGameAPI, (void*)&qmm_export); - return nullptr; + // struct full of export lambdas to QMM's vmMain + // this gets returned to the game engine, but we haven't loaded the mod yet. + return &qmm_export; } else { // store original syscall from engine @@ -916,11 +918,9 @@ static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning {}\n", arg0, arg1, is_GetGameAPI, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning\n", arg0, arg1, is_GetGameAPI); - // struct full of export lambdas to QMM's vmMain - // this gets returned to the game engine, but we haven't loaded the mod yet. - return &qmm_export; + return nullptr; } } From c7b772bb0d835ff85e84c27ecbd2941f16a02ec0 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Mon, 9 Mar 2026 04:43:59 +0200 Subject: [PATCH 04/15] changed "is_GetGameAPI" bool concept over to an enum with engine types. renamed a lot of game_api.h types, macros, and functions. --- include/game_api.h | 96 ++++++++++++++++++++++------------------ include/main.h | 2 +- include/mod.h | 2 +- src/game_api.cpp | 101 ++++++++++++++++++++++++------------------- src/game_cod11mp.cpp | 32 +++++++------- src/game_codmp.cpp | 34 +++++++-------- src/game_coduomp.cpp | 34 +++++++-------- src/game_jamp.cpp | 48 +++++++++++--------- src/game_jasp.cpp | 34 +++++++-------- src/game_jk2mp.cpp | 40 ++++++++--------- src/game_jk2sp.cpp | 34 +++++++-------- src/game_mohaa.cpp | 34 +++++++-------- src/game_mohbt.cpp | 34 +++++++-------- src/game_mohsh.cpp | 34 +++++++-------- src/game_q2r.cpp | 34 +++++++-------- src/game_q3a.cpp | 40 ++++++++--------- src/game_quake2.cpp | 34 +++++++-------- src/game_rtcwmp.cpp | 40 ++++++++--------- src/game_rtcwsp.cpp | 34 +++++++-------- src/game_sin.cpp | 34 +++++++-------- src/game_sof2mp.cpp | 40 ++++++++--------- src/game_sof2sp.cpp | 34 +++++++-------- src/game_stef2.cpp | 34 +++++++-------- src/game_stvoyhm.cpp | 40 ++++++++--------- src/game_stvoysp.cpp | 34 +++++++-------- src/game_wet.cpp | 38 ++++++++-------- src/main.cpp | 44 +++++++++++-------- src/mod.cpp | 19 ++++---- 28 files changed, 549 insertions(+), 509 deletions(-) diff --git a/include/game_api.h b/include/game_api.h index fc9f576..43256ad 100644 --- a/include/game_api.h +++ b/include/game_api.h @@ -19,94 +19,108 @@ Created By: #include "qmmapi.h" #include "qvm.h" -struct supportedgame; -// this struct is defined by GEN_FUNCS_QVM(GAME) or GEN_FUNCS(GAME) -struct supportedgame_funcs { +// engine API type +enum api_engine { + QMM_ENGINEAPI_NONE, + + QMM_ENGINEAPI_DLLENTRY, + QMM_ENGINEAPI_GETGAMEAPI, + + QMM_VMMAIN = QMM_ENGINEAPI_DLLENTRY, +}; +extern const char* EngineAPIName(api_engine); + +struct api_supportedgame; +// this struct is defined by GEN_GAME_FUNCS_QVM(GAME) or GEN_GAME_FUNCS(GAME) +struct api_supportedgame_funcs { int* qmm_eng_msgs; // array of engine messages used by QMM int* qmm_mod_msgs; // array of mod messages used by QMM const char* (*pfnEngMsgNames)(intptr_t); // pointer to a function that returns a string for a given engine message const char* (*pfnModMsgNames)(intptr_t); // pointer to a function that returns a string for a given mod message - bool(*pfnAutoDetect)(bool, supportedgame*); // pointer to a function that handles auto-detection logic for a game - qvm_syscall pfnqvmsyscall; // pointer to a function that handles mod->engine calls from a QVM (NULL = not supported) - void* (*pfnEntry)(void*, void*, bool); // pointer to a function that handles dllEntry or GetGameAPI entry for a game - bool(*pfnModLoad)(void*, bool); // pointer to a function that handles mod loading logic after a DLL is loaded + bool(*pfnAutoDetect)(api_supportedgame*, api_engine); // pointer to a function that handles auto-detection logic for a game. return true to say "that's me!" + void*(*pfnEntry)(void*, void*, api_engine); // pointer to a function that handles entry point logic for a game + bool(*pfnModLoad)(void*, api_engine); // pointer to a function that handles mod loading logic after a DLL is loaded void(*pfnModUnload)(); // pointer to a function that handles mod unloading logic before a DLL is unloaded + + qvm_syscall pfnQVMSyscall; // pointer to a function that handles mod->engine calls from a QVM (NULL = not supported) }; // some information for each game engine supported by QMM -struct supportedgame { +struct api_supportedgame { const char* dllname; // default dll mod filename const char* qvmname; // default qvm mod filename (NULL = not supported) const char* moddir; // default moddir name const char* gamename_long; // long, descriptive, game name - // this section is made by GEN_FUNCS(GAME) + // this section is made by GEN_GAME_INFO(GAME) const char* gamename_short; // short initials for game - supportedgame_funcs* funcs; // function pointers for this game + api_supportedgame_funcs* funcs; // function pointers for this game int max_syscall_args; // max number of syscall args that this game needs (unused for now, but nice to have easily available) int max_vmmain_args; // max number of vmmain args that this game needs (unused for now, but nice to have easily available) }; -extern std::vector g_supportedgames; +extern std::vector api_supportedgames; // macros to make game support a bit easier to do // used at the top of game_api.cpp and game_XYZ.cpp // ====== // generate extern for each game's functions -#define GEN_EXTS(game) extern supportedgame_funcs game##_funcs; +#define GEN_GAME_EXTS(game) extern api_supportedgame_funcs game##_funcs; // used in supportedgames entry in game_api.cpp // ====== // generate extern for each game's shortcode and supportedgame_funcs struct (used in game_api.cpp) -#define GEN_INFO(game) #game , &game##_funcs +#define GEN_GAME_INFO(game) #game , &game##_funcs // used in game_XYZ.cpp // ====== // generate struct info for the game-specific functions and arrays // game with QVM support -#define GEN_FUNCS_QVM(game) \ -static const char* game##_eng_msg_names(intptr_t); \ -static const char* game##_mod_msg_names(intptr_t); \ -static bool game##_autodetect(bool, supportedgame*); \ +#define GEN_GAME_FUNCS_QVM(game) \ +static const char* game##_EngMsgNames(intptr_t); \ +static const char* game##_ModMsgNames(intptr_t); \ +static bool game##_AutoDetect(api_supportedgame*, api_engine); \ +static void* game##_Entry(void*, void*, api_engine); \ +static bool game##_ModLoad(void*, api_engine); \ +static void game##_ModUnload(); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ -static int game##_qvmsyscall(uint8_t*, int, int*); \ -static void* game##_entry(void*, void*, bool); \ -static bool game##_mod_load(void*, bool); \ -static void game##_mod_unload(); \ -supportedgame_funcs game##_funcs = { \ +static int game##_QVMSyscall(uint8_t*, int, int*); \ +api_supportedgame_funcs game##_funcs = { \ game##_qmm_eng_msgs, game##_qmm_mod_msgs, \ - game##_eng_msg_names, game##_mod_msg_names, \ - game##_autodetect, game##_qvmsyscall, game##_entry, \ - game##_mod_load, game##_mod_unload, \ + game##_EngMsgNames, game##_ModMsgNames, \ + game##_AutoDetect, game##_Entry, \ + game##_ModLoad, game##_ModUnload, \ + game##_QVMSyscall, \ } // game with no QVM support -#define GEN_FUNCS(game) \ -static const char* game##_eng_msg_names(intptr_t); \ -static const char* game##_mod_msg_names(intptr_t); \ -static bool game##_autodetect(bool, supportedgame*); \ +#define GEN_GAME_FUNCS(game) \ +static const char* game##_EngMsgNames(intptr_t); \ +static const char* game##_ModMsgNames(intptr_t); \ +static bool game##_AutoDetect(api_supportedgame*, api_engine); \ +static void* game##_Entry(void*, void*, api_engine); \ +static bool game##_ModLoad(void*, api_engine); \ +static void game##_ModUnload(); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ -static void* game##_entry(void*, void*, bool); \ -static bool game##_mod_load(void*, bool); \ -static void game##_mod_unload(); \ -supportedgame_funcs game##_funcs = { \ +api_supportedgame_funcs game##_funcs = { \ game##_qmm_eng_msgs, game##_qmm_mod_msgs, \ - game##_eng_msg_names, game##_mod_msg_names, \ - game##_autodetect, nullptr, game##_entry, \ - game##_mod_load, game##_mod_unload, \ + game##_EngMsgNames, game##_ModMsgNames, \ + game##_AutoDetect, game##_Entry, \ + game##_ModLoad, game##_ModUnload, \ + nullptr, \ } -// generate a case/string line for use in the _msg_names functions +// generate a case/string line for use in the *MsgNames functions #define GEN_CASE(x) case x: return #x -// a list of all the engine messages/constants used by QMM. if you change this, update the GEN_QMM_MSGS macro +// a list of all the engine messages/constants used by QMM. if you change this, update the GEN_GAME_QMM_MSGS macro enum { // general purpose QMM_G_PRINT, QMM_G_ERROR, QMM_G_ARGV, QMM_G_ARGC, QMM_G_SEND_CONSOLE_COMMAND, QMM_G_GET_CONFIGSTRING, @@ -116,11 +130,11 @@ enum { QMM_G_FS_FOPEN_FILE, QMM_G_FS_READ, QMM_G_FS_WRITE, QMM_G_FS_FCLOSE_FILE, QMM_EXEC_APPEND, QMM_FS_READ, }; -// a list of all the mod messages used by QMM. if you change this, update the GEN_QMM_MSGS macro +// a list of all the mod messages used by QMM. if you change this, update the GEN_GAME_QMM_MSGS macro enum { QMM_GAME_INIT, QMM_GAME_SHUTDOWN, QMM_GAME_CONSOLE_COMMAND, }; // macro to easily output game-specific message values to match the enums above. this macro goes in game_*.cpp -#define GEN_QMM_MSGS(game) \ +#define GEN_GAME_QMM_MSGS(game) \ static int game##_qmm_eng_msgs[] = { \ G_PRINT, G_ERROR, G_ARGV, G_ARGC, G_SEND_CONSOLE_COMMAND, G_GET_CONFIGSTRING, \ G_CVAR_REGISTER, G_CVAR_VARIABLE_STRING_BUFFER, G_CVAR_VARIABLE_INTEGER_VALUE, CVAR_SERVERINFO, CVAR_ROM, \ @@ -220,7 +234,7 @@ constexpr int QMM_MAX_SYSCALL_ARGS = 17; // ----- QVM stuff ----- // --------------------- -// these macros handle qvm syscall arguments in GAME_qvmsyscall functions in game_*.cpp +// these macros handle qvm syscall arguments in GAME_QVMSyscall functions in game_*.cpp // this gets an argument value (evaluate to an intptr_t) #define VMARG(arg) (intptr_t)args[arg] diff --git a/include/main.h b/include/main.h index 30b4d7a..b6d5e21 100644 --- a/include/main.h +++ b/include/main.h @@ -29,7 +29,7 @@ struct gameinfo { std::string cfg_path; // qmm config file path eng_syscall pfnsyscall = nullptr; // game-specific wrapper for syscall. given to plugins and called by QMM mod_vmMain pfnvmMain = nullptr; // game-specific wrapper for vmMain. given to plugins and called by QMM - supportedgame* game = nullptr; // loaded engine from supported games table from game_api.cpp + api_supportedgame* game = nullptr; // loaded engine from supported games table from game_api.cpp void* qmm_module_ptr = nullptr; // qmm module pointer bool is_auto_detected = false; // was this engine auto-detected? bool is_shutdown = false; // is game shutting down due to G_ERROR? avoids calling G_ERROR again from GAME_SHUTDOWN diff --git a/include/mod.h b/include/mod.h index ada7ded..e3d8069 100644 --- a/include/mod.h +++ b/include/mod.h @@ -21,7 +21,7 @@ struct qmm_mod { qvm vm = {}; void* dll = nullptr; intptr_t vmbase = 0; - bool is_GetGameAPI = false; + api_engine engine; }; extern qmm_mod g_mod; diff --git a/src/game_api.cpp b/src/game_api.cpp index ab81d1f..e78f9ce 100644 --- a/src/game_api.cpp +++ b/src/game_api.cpp @@ -18,29 +18,29 @@ Created By: intptr_t msg_G_PRINT, msg_GAME_INIT, msg_GAME_CONSOLE_COMMAND, msg_GAME_SHUTDOWN; // externs for each game's functions/structs -GEN_EXTS(COD11MP); -GEN_EXTS(CODMP); -GEN_EXTS(CODUOMP); -GEN_EXTS(JAMP); -GEN_EXTS(JK2MP); -GEN_EXTS(Q3A); -GEN_EXTS(RTCWMP); -GEN_EXTS(RTCWSP); -GEN_EXTS(SOF2MP); -GEN_EXTS(STVOYHM); -GEN_EXTS(WET); +GEN_GAME_EXTS(COD11MP); +GEN_GAME_EXTS(CODMP); +GEN_GAME_EXTS(CODUOMP); +GEN_GAME_EXTS(JAMP); +GEN_GAME_EXTS(JK2MP); +GEN_GAME_EXTS(Q3A); +GEN_GAME_EXTS(RTCWMP); +GEN_GAME_EXTS(RTCWSP); +GEN_GAME_EXTS(SOF2MP); +GEN_GAME_EXTS(STVOYHM); +GEN_GAME_EXTS(WET); -GEN_EXTS(JASP); -GEN_EXTS(JK2SP); -GEN_EXTS(MOHAA); -GEN_EXTS(MOHSH); -GEN_EXTS(MOHBT); -GEN_EXTS(Q2R); -GEN_EXTS(QUAKE2); -GEN_EXTS(SIN); -GEN_EXTS(SOF2SP); -GEN_EXTS(STEF2); -GEN_EXTS(STVOYSP); +GEN_GAME_EXTS(JASP); +GEN_GAME_EXTS(JK2SP); +GEN_GAME_EXTS(MOHAA); +GEN_GAME_EXTS(MOHSH); +GEN_GAME_EXTS(MOHBT); +GEN_GAME_EXTS(Q2R); +GEN_GAME_EXTS(QUAKE2); +GEN_GAME_EXTS(SIN); +GEN_GAME_EXTS(SOF2SP); +GEN_GAME_EXTS(STEF2); +GEN_GAME_EXTS(STVOYSP); // SP_DLL + MP_DLL - COD, RTCWMP & WET filename changes between linux/windows // UO_DLL - CODUO filename changes between linux/windows @@ -67,44 +67,55 @@ GEN_EXTS(STVOYSP); #define X64_DLL X64_SUF_DLL "." EXT_DLL // add your game's info data here -std::vector g_supportedgames = { +std::vector api_supportedgames = { // mod filename qvm mod filename default moddir full gamename short name/funcs #syscall#vmmain // vmMain games - { "qagame" MOD_DLL, "vm/qagame.qvm", "baseq3", "Quake 3 Arena", GEN_INFO(Q3A), 13, 4 }, - { "qagame" SP_DLL X64_DLL, nullptr, ".", "Return to Castle Wolfenstein (SP)", GEN_INFO(RTCWSP), 13, 5 }, - { "jk2mpgame" MOD_DLL, "vm/jk2mpgame.qvm", "base", "Jedi Knight 2: Jedi Outcast (MP)", GEN_INFO(JK2MP), 13, 3 }, - { "jampgame" MOD_DLL, nullptr, "base", "Jedi Knight: Jedi Academy (MP)", GEN_INFO(JAMP), 13, 6 }, - { "qagame" MP_DLL X64_DLL, nullptr, "etmain", "Wolfenstein: Enemy Territory", GEN_INFO(WET), 13, 5 }, - { "qagame" MP_DLL X64_DLL, "vm/qagame.mp.qvm", "main", "Return to Castle Wolfenstein (MP)", GEN_INFO(RTCWMP), 13, 5 }, + { "qagame" MOD_DLL, "vm/qagame.qvm", "baseq3", "Quake 3 Arena", GEN_GAME_INFO(Q3A), 13, 4 }, + { "qagame" SP_DLL X64_DLL, nullptr, ".", "Return to Castle Wolfenstein (SP)", GEN_GAME_INFO(RTCWSP), 13, 5 }, + { "jk2mpgame" MOD_DLL, "vm/jk2mpgame.qvm", "base", "Jedi Knight 2: Jedi Outcast (MP)", GEN_GAME_INFO(JK2MP), 13, 3 }, + { "jampgame" MOD_DLL, nullptr, "base", "Jedi Knight: Jedi Academy (MP)", GEN_GAME_INFO(JAMP), 13, 6 }, + { "qagame" MP_DLL X64_DLL, nullptr, "etmain", "Wolfenstein: Enemy Territory", GEN_GAME_INFO(WET), 13, 5 }, + { "qagame" MP_DLL X64_DLL, "vm/qagame.mp.qvm", "main", "Return to Castle Wolfenstein (MP)", GEN_GAME_INFO(RTCWMP), 13, 5 }, // these games don't appear to have an official 64-bit version or source port #if defined(QMM_ARCH_32) - { "qagame" MOD_DLL, "vm/qagame.qvm", "baseef", "Star Trek Voyager: Elite Force (Holomatch)", GEN_INFO(STVOYHM), 13, 3 }, - { "sof2mp_game" MOD_DLL, "vm/sof2mp_game.qvm","base/mp", "Soldier of Fortune 2: Double Helix (MP)", GEN_INFO(SOF2MP), 13, 6 }, - { "game" MP_DLL MOD_DLL, nullptr, "Main", "Call of Duty (MP)", GEN_INFO(CODMP), 8, 4 }, - { "" UO_DLL MOD_DLL, nullptr, "uo", "Call of Duty: United Offensive (MP)", GEN_INFO(CODUOMP), 8, 4 }, + { "qagame" MOD_DLL, "vm/qagame.qvm", "baseef", "Star Trek Voyager: Elite Force (Holomatch)", GEN_GAME_INFO(STVOYHM), 13, 3 }, + { "sof2mp_game" MOD_DLL, "vm/sof2mp_game.qvm","base/mp", "Soldier of Fortune 2: Double Helix (MP)", GEN_GAME_INFO(SOF2MP), 13, 6 }, + { "game" MP_DLL MOD_DLL, nullptr, "Main", "Call of Duty (MP)", GEN_GAME_INFO(CODMP), 8, 4 }, + { "" UO_DLL MOD_DLL, nullptr, "uo", "Call of Duty: United Offensive (MP)", GEN_GAME_INFO(CODUOMP), 8, 4 }, // allow a user to choose "COD11MP" manually if they are playing an old version of CoD (no auto-detection) - { "game" MP_DLL MOD_DLL, nullptr, "Main", "Call of Duty v1.1 (MP)", GEN_INFO(COD11MP), 8, 4 }, + { "game" MP_DLL MOD_DLL, nullptr, "Main", "Call of Duty v1.1 (MP)", GEN_GAME_INFO(COD11MP), 8, 4 }, #endif // GetGameAPI games - { "jk2game" MOD_DLL, nullptr, ".", "Jedi Knight 2: Jedi Outcast (SP)", GEN_INFO(JK2SP), 13, 9 }, - { "jagame" MOD_DLL, nullptr, ".", "Jedi Knight: Jedi Academy (SP)", GEN_INFO(JASP), 13, 9 }, - { "game" MOD_DLL, nullptr, "baseq2", "Quake 2", GEN_INFO(QUAKE2), 7, 3 }, - { "game" MOD_DLL, nullptr, "base", "SiN", GEN_INFO(SIN), 10, 3 }, + { "jk2game" MOD_DLL, nullptr, ".", "Jedi Knight 2: Jedi Outcast (SP)", GEN_GAME_INFO(JK2SP), 13, 9 }, + { "jagame" MOD_DLL, nullptr, ".", "Jedi Knight: Jedi Academy (SP)", GEN_GAME_INFO(JASP), 13, 9 }, + { "game" MOD_DLL, nullptr, "baseq2", "Quake 2", GEN_GAME_INFO(QUAKE2), 7, 3 }, + { "game" MOD_DLL, nullptr, "base", "SiN", GEN_GAME_INFO(SIN), 10, 3 }, // OpenMOHAA adds 64-bit MoH support but the API is very different, so disable it for now // the rest of the games don't appear to have an official 64-bit version or source port #if defined(QMM_ARCH_32) - { "game" MOD_DLL, nullptr, "main", "Medal of Honor: Allied Assault", GEN_INFO(MOHAA), 9, 7 }, - { "game" MOD_DLL, nullptr, "mainta", "Medal of Honor: Spearhead", GEN_INFO(MOHSH), 9, 7 }, - { "game" MOD_DLL, nullptr, "maintt", "Medal of Honor: Breakthrough", GEN_INFO(MOHBT), 9, 7 }, - { "game" MOD_DLL, nullptr, "base", "Star Trek: Elite Force II", GEN_INFO(STEF2), 17, 4 }, - { "game" MOD_DLL, nullptr, ".", "Soldier of Fortune 2: Double Helix (SP)", GEN_INFO(SOF2SP), 0, 0 }, - { "efgame" MOD_DLL, nullptr, ".", "Star Trek Voyager: Elite Force (SP)", GEN_INFO(STVOYSP), 13, 9 }, + { "game" MOD_DLL, nullptr, "main", "Medal of Honor: Allied Assault", GEN_GAME_INFO(MOHAA), 9, 7 }, + { "game" MOD_DLL, nullptr, "mainta", "Medal of Honor: Spearhead", GEN_GAME_INFO(MOHSH), 9, 7 }, + { "game" MOD_DLL, nullptr, "maintt", "Medal of Honor: Breakthrough", GEN_GAME_INFO(MOHBT), 9, 7 }, + { "game" MOD_DLL, nullptr, "base", "Star Trek: Elite Force II", GEN_GAME_INFO(STEF2), 17, 4 }, + { "game" MOD_DLL, nullptr, ".", "Soldier of Fortune 2: Double Helix (SP)", GEN_GAME_INFO(SOF2SP), 0, 0 }, + { "efgame" MOD_DLL, nullptr, ".", "Star Trek Voyager: Elite Force (SP)", GEN_GAME_INFO(STVOYSP), 13, 9 }, #endif // Q2R only exists for 64-bit Windows #if defined(QMM_OS_WINDOWS) && defined(QMM_ARCH_64) - { "game_x64.dll", nullptr, "baseq2", "Quake 2 Remastered", GEN_INFO(Q2R), 9, 6 }, + { "game_x64.dll", nullptr, "baseq2", "Quake 2 Remastered", GEN_GAME_INFO(Q2R), 9, 6 }, #endif }; + +const char* EngineAPIName(api_engine engine) { + switch (engine) { + GEN_CASE(QMM_ENGINEAPI_NONE); + + GEN_CASE(QMM_ENGINEAPI_DLLENTRY); + GEN_CASE(QMM_ENGINEAPI_GETGAMEAPI); + default: + return ""; + }; +} diff --git a/src/game_cod11mp.cpp b/src/game_cod11mp.cpp index a82d827..7407d4c 100644 --- a/src/game_cod11mp.cpp +++ b/src/game_cod11mp.cpp @@ -18,14 +18,14 @@ Created By: #include "game_cod11mp.h" #include "main.h" -GEN_QMM_MSGS(COD11MP); -GEN_EXTS(COD11MP); +GEN_GAME_QMM_MSGS(COD11MP); +GEN_GAME_EXTS(COD11MP); -GEN_FUNCS(COD11MP); +GEN_GAME_FUNCS(COD11MP); // auto-detection logic for COD11MP (never auto-detect) -static bool COD11MP_autodetect(bool, supportedgame*) { +static bool COD11MP_AutoDetect(api_supportedgame*, api_engine) { return false; } @@ -43,7 +43,7 @@ static intptr_t COD11MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_syscall({} {}) called\n", COD11MP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_syscall({} {}) called\n", COD11MP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -76,7 +76,7 @@ static intptr_t COD11MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_syscall({} {}) returning {}\n", COD11MP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_syscall({} {}) returning {}\n", COD11MP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -89,7 +89,7 @@ static intptr_t COD11MP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_vmMain({} {}) called\n", COD11MP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_vmMain({} {}) called\n", COD11MP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -102,15 +102,15 @@ static intptr_t COD11MP_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_vmMain({} {}) returning {}\n", COD11MP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_vmMain({} {}) returning {}\n", COD11MP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* COD11MP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_entry({}) called\n", syscall); +static void* COD11MP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -121,14 +121,14 @@ static void* COD11MP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = COD11MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_Entry({}) returning\n", syscall); return nullptr; } -static bool COD11MP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool COD11MP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -137,12 +137,12 @@ static bool COD11MP_mod_load(void* entry, bool is_GetGameAPI) { } -static void COD11MP_mod_unload() { +static void COD11MP_ModUnload() { orig_vmMain = nullptr; } -static const char* COD11MP_eng_msg_names(intptr_t cmd) { +static const char* COD11MP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_ERROR); @@ -289,7 +289,7 @@ static const char* COD11MP_eng_msg_names(intptr_t cmd) { } -static const char* COD11MP_mod_msg_names(intptr_t cmd) { +static const char* COD11MP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); diff --git a/src/game_codmp.cpp b/src/game_codmp.cpp index 15aa32d..adfeace 100644 --- a/src/game_codmp.cpp +++ b/src/game_codmp.cpp @@ -23,16 +23,16 @@ Created By: // don't want to make plugins have to use separate code to handle the actual GAME_INIT message, so just // do a dirty redefine here for the QMM_GAME_INIT message definition #define GAME_INIT GAME_GET_APIVERSION -GEN_QMM_MSGS(CODMP); +GEN_GAME_QMM_MSGS(CODMP); #undef GAME_INIT -GEN_EXTS(CODMP); +GEN_GAME_EXTS(CODMP); -GEN_FUNCS(CODMP); +GEN_GAME_FUNCS(CODMP); // auto-detection logic for CODMP -static bool CODMP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool CODMP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -58,7 +58,7 @@ static intptr_t CODMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_syscall({} {}) called\n", CODMP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_syscall({} {}) called\n", CODMP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -91,7 +91,7 @@ static intptr_t CODMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_syscall({} {}) returning {}\n", CODMP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_syscall({} {}) returning {}\n", CODMP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -104,7 +104,7 @@ static intptr_t CODMP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_vmMain({} {}) called\n", CODMP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_vmMain({} {}) called\n", CODMP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -117,15 +117,15 @@ static intptr_t CODMP_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_vmMain({} {}) returning {}\n", CODMP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_vmMain({} {}) returning {}\n", CODMP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* CODMP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_entry({}) called\n", syscall); +static void* CODMP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -136,14 +136,14 @@ static void* CODMP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = CODMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_Entry({}) returning\n", syscall); return nullptr; } -static bool CODMP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool CODMP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -152,12 +152,12 @@ static bool CODMP_mod_load(void* entry, bool is_GetGameAPI) { } -static void CODMP_mod_unload() { +static void CODMP_ModUnload() { orig_vmMain = nullptr; } -static const char* CODMP_eng_msg_names(intptr_t cmd) { +static const char* CODMP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_ERROR); @@ -309,7 +309,7 @@ static const char* CODMP_eng_msg_names(intptr_t cmd) { } -static const char* CODMP_mod_msg_names(intptr_t cmd) { +static const char* CODMP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_DEFAULT_0); GEN_CASE(GAME_GET_APIVERSION); diff --git a/src/game_coduomp.cpp b/src/game_coduomp.cpp index fe329fc..f1cf5cc 100644 --- a/src/game_coduomp.cpp +++ b/src/game_coduomp.cpp @@ -23,16 +23,16 @@ Created By: // don't want to make plugins have to use separate code to handle the actual GAME_INIT message, so just // do a dirty redefine here for the QMM_GAME_INIT message definition #define GAME_INIT GAME_GET_APIVERSION -GEN_QMM_MSGS(CODUOMP); +GEN_GAME_QMM_MSGS(CODUOMP); #undef GAME_INIT -GEN_EXTS(CODUOMP); +GEN_GAME_EXTS(CODUOMP); -GEN_FUNCS(CODUOMP); +GEN_GAME_FUNCS(CODUOMP); // auto-detection logic for CODUOMP -static bool CODUOMP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool CODUOMP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -58,7 +58,7 @@ static intptr_t CODUOMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_syscall({} {}) called\n", CODUOMP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_syscall({} {}) called\n", CODUOMP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -91,7 +91,7 @@ static intptr_t CODUOMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_syscall({} {}) returning {}\n", CODUOMP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_syscall({} {}) returning {}\n", CODUOMP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -104,7 +104,7 @@ static intptr_t CODUOMP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_vmMain({} {}) called\n", CODUOMP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_vmMain({} {}) called\n", CODUOMP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -117,15 +117,15 @@ static intptr_t CODUOMP_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_vmMain({} {}) returning {}\n", CODUOMP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_vmMain({} {}) returning {}\n", CODUOMP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* CODUOMP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_entry({}) called\n", syscall); +static void* CODUOMP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -136,14 +136,14 @@ static void* CODUOMP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = CODUOMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_Entry({}) returning\n", syscall); return nullptr; } -static bool CODUOMP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool CODUOMP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -152,12 +152,12 @@ static bool CODUOMP_mod_load(void* entry, bool is_GetGameAPI) { } -static void CODUOMP_mod_unload() { +static void CODUOMP_ModUnload() { orig_vmMain = nullptr; } -static const char* CODUOMP_eng_msg_names(intptr_t cmd) { +static const char* CODUOMP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_ERROR); @@ -309,7 +309,7 @@ static const char* CODUOMP_eng_msg_names(intptr_t cmd) { } -static const char* CODUOMP_mod_msg_names(intptr_t cmd) { +static const char* CODUOMP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_DEFAULT_0); GEN_CASE(GAME_GET_APIVERSION); diff --git a/src/game_jamp.cpp b/src/game_jamp.cpp index 6517423..2c957ca 100644 --- a/src/game_jamp.cpp +++ b/src/game_jamp.cpp @@ -20,14 +20,17 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(JAMP); -GEN_EXTS(JAMP); +GEN_GAME_QMM_MSGS(JAMP); +GEN_GAME_EXTS(JAMP); -GEN_FUNCS(JAMP); +GEN_GAME_FUNCS(JAMP); // auto-detection logic for JAMP -static bool JAMP_autodetect(bool, supportedgame* game) { +static bool JAMP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY && engine != QMM_ENGINEAPI_GETGAMEAPI) + return false; + // QMM filename must match default or an OpenJK temp filename (if DLL was pulled from .pk3) if (!str_striequal(g_gameinfo.qmm_file, game->dllname) && !str_striequal(g_gameinfo.qmm_file.substr(0, 3), "ojk") @@ -430,13 +433,13 @@ static intptr_t JAMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_syscall({} {}) called\n", JAMP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_syscall({} {}) called\n", JAMP_EngMsgNames(cmd), cmd); #endif // store return value since we do some stuff after the function call is over intptr_t ret = 0; - // if QMM was loaded with the official JAMP or OpenJK "legacy" API (which shouldn't happen, but whatever) + // if QMM was loaded with the official JAMP or OpenJK "legacy" API if (orig_syscall) { switch (cmd) { // handle special cmds which QMM uses but JAMP doesn't have an analogue for @@ -802,7 +805,7 @@ static intptr_t JAMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_syscall({} {}) returning {}\n", JAMP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_syscall({} {}) returning {}\n", JAMP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -815,7 +818,7 @@ static intptr_t JAMP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_vmMain({} {}) called\n", JAMP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_vmMain({} {}) called\n", JAMP_ModMsgNames(cmd), cmd); #endif // store return value since we do some stuff after the function call is over @@ -876,17 +879,17 @@ static intptr_t JAMP_vmMain(intptr_t cmd, ...) { } #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_vmMain({} {}) returning {}\n", JAMP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_vmMain({} {}) returning {}\n", JAMP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) called\n", arg0, arg1, is_GetGameAPI); +static void* JAMP_Entry(void* arg0, void* arg1, api_engine engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) called\n", arg0, arg1, EngineAPIName(engine)); - if (is_GetGameAPI) { + if (engine == QMM_ENGINEAPI_GETGAMEAPI) { orig_apiversion = (intptr_t)arg0; // original import struct from engine @@ -902,13 +905,13 @@ static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning {}\n", arg0, arg1, is_GetGameAPI, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning {}\n", arg0, arg1, EngineAPIName(engine), (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. return &qmm_export; } - else { + else if (engine == QMM_ENGINEAPI_DLLENTRY) { // store original syscall from engine orig_syscall = (eng_syscall)arg0; @@ -918,35 +921,38 @@ static void* JAMP_entry(void* arg0, void* arg1, bool is_GetGameAPI) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_entry({}, {}, {}) returning\n", arg0, arg1, is_GetGameAPI); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning\n", arg0, arg1, EngineAPIName(engine)); return nullptr; } + + return nullptr; } -static bool JAMP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) { +static bool JAMP_ModLoad(void* entry, api_engine engine) { + if (engine == QMM_ENGINEAPI_GETGAMEAPI) { mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; // api version gets passed before import pointer orig_export = (game_export_t*)pfnGGA((void*)orig_apiversion, &qmm_import); return !!orig_export; } - else { + else if (engine == QMM_ENGINEAPI_DLLENTRY) { orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; } + return false; } -static void JAMP_mod_unload() { +static void JAMP_ModUnload() { orig_export = nullptr; orig_vmMain = nullptr; } -static const char* JAMP_eng_msg_names(intptr_t cmd) { +static const char* JAMP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -1287,7 +1293,7 @@ static const char* JAMP_eng_msg_names(intptr_t cmd) { } -static const char* JAMP_mod_msg_names(intptr_t cmd) { +static const char* JAMP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); diff --git a/src/game_jasp.cpp b/src/game_jasp.cpp index 570310a..4e30ad5 100644 --- a/src/game_jasp.cpp +++ b/src/game_jasp.cpp @@ -22,15 +22,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(JASP); -GEN_EXTS(JASP); +GEN_GAME_QMM_MSGS(JASP); +GEN_GAME_EXTS(JASP); -GEN_FUNCS(JASP); +GEN_GAME_FUNCS(JASP); // auto-detection logic for JASP -static bool JASP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool JASP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -262,7 +262,7 @@ static intptr_t JASP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_syscall({} {}) called\n", JASP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_syscall({} {}) called\n", JASP_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -492,7 +492,7 @@ static intptr_t JASP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_syscall({} {}) returning {}\n", JASP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_syscall({} {}) returning {}\n", JASP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -505,7 +505,7 @@ static intptr_t JASP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_vmMain({} {}) called\n", JASP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_vmMain({} {}) called\n", JASP_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -545,15 +545,15 @@ static intptr_t JASP_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_vmMain({} {}) returning {}\n", JASP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_vmMain({} {}) returning {}\n", JASP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* JASP_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_entry({}) called\n", import); +static void* JASP_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -569,7 +569,7 @@ static void* JASP_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = JASP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -578,8 +578,8 @@ static void* JASP_entry(void* import, void*, bool) { } -static bool JASP_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool JASP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -589,12 +589,12 @@ static bool JASP_mod_load(void* entry, bool is_GetGameAPI) { } -static void JASP_mod_unload() { +static void JASP_ModUnload() { orig_export = nullptr; } -static const char* JASP_eng_msg_names(intptr_t cmd) { +static const char* JASP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_WRITECAM); @@ -740,7 +740,7 @@ static const char* JASP_eng_msg_names(intptr_t cmd) { } -static const char* JASP_mod_msg_names(intptr_t cmd) { +static const char* JASP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_jk2mp.cpp b/src/game_jk2mp.cpp index d2b4417..451612a 100644 --- a/src/game_jk2mp.cpp +++ b/src/game_jk2mp.cpp @@ -21,15 +21,15 @@ Created By: #include "mod.h" #include "util.h" -GEN_QMM_MSGS(JK2MP); -GEN_EXTS(JK2MP); +GEN_GAME_QMM_MSGS(JK2MP); +GEN_GAME_EXTS(JK2MP); -GEN_FUNCS_QVM(JK2MP); +GEN_GAME_FUNCS_QVM(JK2MP); // auto-detection logic for JK2MP -static bool JK2MP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool JK2MP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -55,7 +55,7 @@ static intptr_t JK2MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_syscall({} {}) called\n", JK2MP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_syscall({} {}) called\n", JK2MP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -88,7 +88,7 @@ static intptr_t JK2MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_syscall({} {}) returning {}\n", JK2MP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_syscall({} {}) returning {}\n", JK2MP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -101,7 +101,7 @@ static intptr_t JK2MP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_vmMain({} {}) called\n", JK2MP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_vmMain({} {}) called\n", JK2MP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -120,15 +120,15 @@ static intptr_t JK2MP_vmMain(intptr_t cmd, ...) { } #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_vmMain({} {}) returning {}\n", JK2MP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_vmMain({} {}) returning {}\n", JK2MP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* JK2MP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_entry({}) called\n", syscall); +static void* JK2MP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -139,14 +139,14 @@ static void* JK2MP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = JK2MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_Entry({}) returning\n", syscall); return nullptr; } -static bool JK2MP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool JK2MP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -155,12 +155,12 @@ static bool JK2MP_mod_load(void* entry, bool is_GetGameAPI) { } -static void JK2MP_mod_unload() { +static void JK2MP_ModUnload() { orig_vmMain = nullptr; } -static const char* JK2MP_eng_msg_names(intptr_t cmd) { +static const char* JK2MP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -399,7 +399,7 @@ static const char* JK2MP_eng_msg_names(intptr_t cmd) { } -static const char* JK2MP_mod_msg_names(intptr_t cmd) { +static const char* JK2MP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); @@ -427,9 +427,9 @@ static const char* JK2MP_mod_msg_names(intptr_t cmd) { // vec3_t are arrays, so convert them as pointers // do NOT convert the "ghoul" void pointers, treat them as plain ints // for double pointers (gentity_t**, vec3_t*, void**), convert them once with vmptr() -int JK2MP_qvmsyscall(uint8_t* membase, int cmd, int* args) { +int JK2MP_QVMSyscall(uint8_t* membase, int cmd, int* args) { #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("JK2MP_qvmsyscall({} {}) called\n", JK2MP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("JK2MP_QVMSyscall({} {}) called\n", JK2MP_EngMsgNames(cmd), cmd); #endif int ret = 0; @@ -754,7 +754,7 @@ int JK2MP_qvmsyscall(uint8_t* membase, int cmd, int* args) { } #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("JK2MP_qvmsyscall({} {}) returning {}\n", JK2MP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("JK2MP_QVMSyscall({} {}) returning {}\n", JK2MP_EngMsgNames(cmd), cmd, ret); #endif return ret; diff --git a/src/game_jk2sp.cpp b/src/game_jk2sp.cpp index b92378d..b93b04e 100644 --- a/src/game_jk2sp.cpp +++ b/src/game_jk2sp.cpp @@ -21,15 +21,15 @@ Created By: #include "util.h" -GEN_QMM_MSGS(JK2SP); -GEN_EXTS(JK2SP); +GEN_GAME_QMM_MSGS(JK2SP); +GEN_GAME_EXTS(JK2SP); -GEN_FUNCS(JK2SP); +GEN_GAME_FUNCS(JK2SP); // auto-detection logic for JK2SP -static bool JK2SP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool JK2SP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -231,7 +231,7 @@ static intptr_t JK2SP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_syscall({} {}) called\n", JK2SP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_syscall({} {}) called\n", JK2SP_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -413,7 +413,7 @@ static intptr_t JK2SP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_syscall({} {}) returning {}\n", JK2SP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_syscall({} {}) returning {}\n", JK2SP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -426,7 +426,7 @@ static intptr_t JK2SP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_vmMain({} {}) called\n", JK2SP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_vmMain({} {}) called\n", JK2SP_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -466,15 +466,15 @@ static intptr_t JK2SP_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_vmMain({} {}) returning {}\n", JK2SP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_vmMain({} {}) returning {}\n", JK2SP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* JK2SP_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_entry({}) called\n", import); +static void* JK2SP_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -490,7 +490,7 @@ static void* JK2SP_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = JK2SP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -499,8 +499,8 @@ static void* JK2SP_entry(void* import, void*, bool) { } -static bool JK2SP_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool JK2SP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -510,12 +510,12 @@ static bool JK2SP_mod_load(void* entry, bool is_GetGameAPI) { } -static void JK2SP_mod_unload() { +static void JK2SP_ModUnload() { orig_export = nullptr; } -static const char* JK2SP_eng_msg_names(intptr_t cmd) { +static const char* JK2SP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_WRITECAM); @@ -633,7 +633,7 @@ static const char* JK2SP_eng_msg_names(intptr_t cmd) { } -static const char* JK2SP_mod_msg_names(intptr_t cmd) { +static const char* JK2SP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_mohaa.cpp b/src/game_mohaa.cpp index e5920f3..415661f 100644 --- a/src/game_mohaa.cpp +++ b/src/game_mohaa.cpp @@ -26,15 +26,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(MOHAA); -GEN_EXTS(MOHAA); +GEN_GAME_QMM_MSGS(MOHAA); +GEN_GAME_EXTS(MOHAA); -GEN_FUNCS(MOHAA); +GEN_GAME_FUNCS(MOHAA); // auto-detection logic for MOHAA -static bool MOHAA_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool MOHAA_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -334,7 +334,7 @@ static intptr_t MOHAA_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_syscall({} {}) called\n", MOHAA_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_syscall({} {}) called\n", MOHAA_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -661,7 +661,7 @@ static intptr_t MOHAA_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_syscall({} {}) returning {}\n", MOHAA_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_syscall({} {}) returning {}\n", MOHAA_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -674,7 +674,7 @@ static intptr_t MOHAA_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_vmMain({} {}) called\n", MOHAA_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_vmMain({} {}) called\n", MOHAA_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -736,15 +736,15 @@ static intptr_t MOHAA_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_vmMain({} {}) returning {}\n", MOHAA_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_vmMain({} {}) returning {}\n", MOHAA_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* MOHAA_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_entry({}) called\n", import); +static void* MOHAA_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -764,7 +764,7 @@ static void* MOHAA_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHAA_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -773,8 +773,8 @@ static void* MOHAA_entry(void* import, void*, bool) { } -static bool MOHAA_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool MOHAA_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -784,12 +784,12 @@ static bool MOHAA_mod_load(void* entry, bool is_GetGameAPI) { } -static void MOHAA_mod_unload() { +static void MOHAA_ModUnload() { orig_export = nullptr; } -static const char* MOHAA_eng_msg_names(intptr_t cmd) { +static const char* MOHAA_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_DPRINTF); @@ -971,7 +971,7 @@ static const char* MOHAA_eng_msg_names(intptr_t cmd) { } -static const char* MOHAA_mod_msg_names(intptr_t cmd) { +static const char* MOHAA_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_mohbt.cpp b/src/game_mohbt.cpp index 731a4bf..c2d37c9 100644 --- a/src/game_mohbt.cpp +++ b/src/game_mohbt.cpp @@ -26,15 +26,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(MOHBT); -GEN_EXTS(MOHBT); +GEN_GAME_QMM_MSGS(MOHBT); +GEN_GAME_EXTS(MOHBT); -GEN_FUNCS(MOHBT); +GEN_GAME_FUNCS(MOHBT); // auto-detection logic for MOHBT -static bool MOHBT_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool MOHBT_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -342,7 +342,7 @@ static intptr_t MOHBT_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_syscall({} {}) called\n", MOHBT_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_syscall({} {}) called\n", MOHBT_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -700,7 +700,7 @@ static intptr_t MOHBT_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_syscall({} {}) returning {}\n", MOHBT_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_syscall({} {}) returning {}\n", MOHBT_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -713,7 +713,7 @@ static intptr_t MOHBT_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_vmMain({} {}) called\n", MOHBT_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_vmMain({} {}) called\n", MOHBT_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -775,15 +775,15 @@ static intptr_t MOHBT_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_vmMain({} {}) returning {}\n", MOHBT_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_vmMain({} {}) returning {}\n", MOHBT_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* MOHBT_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_entry({}) called\n", import); +static void* MOHBT_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -803,7 +803,7 @@ static void* MOHBT_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHBT_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -812,8 +812,8 @@ static void* MOHBT_entry(void* import, void*, bool) { } -static bool MOHBT_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool MOHBT_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -823,12 +823,12 @@ static bool MOHBT_mod_load(void* entry, bool is_GetGameAPI) { } -static void MOHBT_mod_unload() { +static void MOHBT_ModUnload() { orig_export = nullptr; } -static const char* MOHBT_eng_msg_names(intptr_t cmd) { +static const char* MOHBT_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_DPRINTF); @@ -1017,7 +1017,7 @@ static const char* MOHBT_eng_msg_names(intptr_t cmd) { } -static const char* MOHBT_mod_msg_names(intptr_t cmd) { +static const char* MOHBT_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_mohsh.cpp b/src/game_mohsh.cpp index b5d2910..44139c7 100644 --- a/src/game_mohsh.cpp +++ b/src/game_mohsh.cpp @@ -26,15 +26,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(MOHSH); -GEN_EXTS(MOHSH); +GEN_GAME_QMM_MSGS(MOHSH); +GEN_GAME_EXTS(MOHSH); -GEN_FUNCS(MOHSH); +GEN_GAME_FUNCS(MOHSH); // auto-detection logic for MOHSH -static bool MOHSH_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool MOHSH_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -342,7 +342,7 @@ static intptr_t MOHSH_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_syscall({} {}) called\n", MOHSH_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_syscall({} {}) called\n", MOHSH_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -700,7 +700,7 @@ static intptr_t MOHSH_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_syscall({} {}) returning {}\n", MOHSH_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_syscall({} {}) returning {}\n", MOHSH_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -713,7 +713,7 @@ static intptr_t MOHSH_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_vmMain({} {}) called\n", MOHSH_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_vmMain({} {}) called\n", MOHSH_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -775,15 +775,15 @@ static intptr_t MOHSH_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_vmMain({} {}) returning {}\n", MOHSH_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_vmMain({} {}) returning {}\n", MOHSH_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* MOHSH_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_entry({}) called\n", import); +static void* MOHSH_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -803,7 +803,7 @@ static void* MOHSH_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = MOHSH_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -812,8 +812,8 @@ static void* MOHSH_entry(void* import, void*, bool) { } -static bool MOHSH_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool MOHSH_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -823,12 +823,12 @@ static bool MOHSH_mod_load(void* entry, bool is_GetGameAPI) { } -static void MOHSH_mod_unload() { +static void MOHSH_ModUnload() { orig_export = nullptr; } -static const char* MOHSH_eng_msg_names(intptr_t cmd) { +static const char* MOHSH_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_DPRINTF); @@ -1017,7 +1017,7 @@ static const char* MOHSH_eng_msg_names(intptr_t cmd) { } -static const char* MOHSH_mod_msg_names(intptr_t cmd) { +static const char* MOHSH_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_q2r.cpp b/src/game_q2r.cpp index b6680cf..8085f1a 100644 --- a/src/game_q2r.cpp +++ b/src/game_q2r.cpp @@ -34,16 +34,16 @@ Created By: // don't want to make plugins have to use separate code to handle the actual GAME_INIT message, so just // do a dirty redefine here for the QMM_GAME_INIT message definition #define GAME_INIT GAME_PREINIT -GEN_QMM_MSGS(Q2R); +GEN_GAME_QMM_MSGS(Q2R); #undef GAME_INIT -GEN_EXTS(Q2R); +GEN_GAME_EXTS(Q2R); -GEN_FUNCS(Q2R); +GEN_GAME_FUNCS(Q2R); // auto-detection logic for Q2R -static bool Q2R_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool Q2R_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -284,7 +284,7 @@ static intptr_t Q2R_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_syscall({} {}) called\n", Q2R_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_syscall({} {}) called\n", Q2R_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -523,7 +523,7 @@ static intptr_t Q2R_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_syscall({} {}) returning {}\n", Q2R_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_syscall({} {}) returning {}\n", Q2R_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -536,7 +536,7 @@ static intptr_t Q2R_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_vmMain({} {}) called\n", Q2R_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_vmMain({} {}) called\n", Q2R_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -591,15 +591,15 @@ static intptr_t Q2R_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_vmMain({} {}) returning {}\n", Q2R_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_vmMain({} {}) returning {}\n", Q2R_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* Q2R_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_entry({}) called\n", import); +static void* Q2R_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -617,7 +617,7 @@ static void* Q2R_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = Q2R_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -626,8 +626,8 @@ static void* Q2R_entry(void* import, void*, bool) { } -static bool Q2R_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool Q2R_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -637,12 +637,12 @@ static bool Q2R_mod_load(void* entry, bool is_GetGameAPI) { } -static void Q2R_mod_unload() { +static void Q2R_ModUnload() { orig_export = nullptr; } -static const char* Q2R_eng_msg_names(intptr_t cmd) { +static const char* Q2R_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_BROADCAST_PRINT); GEN_CASE(G_COM_PRINT); @@ -737,7 +737,7 @@ static const char* Q2R_eng_msg_names(intptr_t cmd) { } -static const char* Q2R_mod_msg_names(intptr_t cmd) { +static const char* Q2R_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_PREINIT); diff --git a/src/game_q3a.cpp b/src/game_q3a.cpp index 1fad7a8..c51ff55 100644 --- a/src/game_q3a.cpp +++ b/src/game_q3a.cpp @@ -21,15 +21,15 @@ Created By: #include "mod.h" #include "util.h" -GEN_QMM_MSGS(Q3A); -GEN_EXTS(Q3A); +GEN_GAME_QMM_MSGS(Q3A); +GEN_GAME_EXTS(Q3A); -GEN_FUNCS_QVM(Q3A); +GEN_GAME_FUNCS_QVM(Q3A); // auto-detection logic for Q3A -static bool Q3A_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool Q3A_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -55,7 +55,7 @@ static intptr_t Q3A_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_syscall({} {}) called\n", Q3A_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_syscall({} {}) called\n", Q3A_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -87,7 +87,7 @@ static intptr_t Q3A_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_syscall({} {}) returning {}\n", Q3A_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_syscall({} {}) returning {}\n", Q3A_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -100,7 +100,7 @@ static intptr_t Q3A_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_vmMain({} {}) called\n", Q3A_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_vmMain({} {}) called\n", Q3A_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -119,15 +119,15 @@ static intptr_t Q3A_vmMain(intptr_t cmd, ...) { } #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_vmMain({} {}) returning {}\n", Q3A_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_vmMain({} {}) returning {}\n", Q3A_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* Q3A_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_entry({}) called\n", syscall); +static void* Q3A_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -138,14 +138,14 @@ static void* Q3A_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = Q3A_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_Entry({}) returning\n", syscall); return nullptr; } -static bool Q3A_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool Q3A_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -154,12 +154,12 @@ static bool Q3A_mod_load(void* entry, bool is_GetGameAPI) { } -static void Q3A_mod_unload() { +static void Q3A_ModUnload() { orig_vmMain = nullptr; } -static const char* Q3A_eng_msg_names(intptr_t cmd) { +static const char* Q3A_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -368,7 +368,7 @@ static const char* Q3A_eng_msg_names(intptr_t cmd) { } -static const char* Q3A_mod_msg_names(intptr_t cmd) { +static const char* Q3A_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); @@ -394,9 +394,9 @@ static const char* Q3A_mod_msg_names(intptr_t cmd) { */ // vec3_t are arrays, so convert them as pointers // for double pointers (gentity_t** and vec3_t*), convert them once with vmptr() -static int Q3A_qvmsyscall(uint8_t* membase, int cmd, int* args) { +static int Q3A_QVMSyscall(uint8_t* membase, int cmd, int* args) { #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("Q3A_qvmsyscall({} {}) called\n", Q3A_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("Q3A_QVMSyscall({} {}) called\n", Q3A_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -681,7 +681,7 @@ static int Q3A_qvmsyscall(uint8_t* membase, int cmd, int* args) { } #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("Q3A_qvmsyscall({} {}) returning {}\n", Q3A_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("Q3A_QVMSyscall({} {}) returning {}\n", Q3A_EngMsgNames(cmd), cmd, ret); #endif return ret; diff --git a/src/game_quake2.cpp b/src/game_quake2.cpp index 622ba48..73bf2b7 100644 --- a/src/game_quake2.cpp +++ b/src/game_quake2.cpp @@ -25,15 +25,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(QUAKE2); -GEN_EXTS(QUAKE2); +GEN_GAME_QMM_MSGS(QUAKE2); +GEN_GAME_EXTS(QUAKE2); -GEN_FUNCS(QUAKE2); +GEN_GAME_FUNCS(QUAKE2); // auto-detection logic for QUAKE2 -static bool QUAKE2_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool QUAKE2_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -227,7 +227,7 @@ static intptr_t QUAKE2_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_syscall({} {}) called\n", QUAKE2_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_syscall({} {}) called\n", QUAKE2_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -456,7 +456,7 @@ static intptr_t QUAKE2_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_syscall({} {}) returning {}\n", QUAKE2_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_syscall({} {}) returning {}\n", QUAKE2_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -469,7 +469,7 @@ static intptr_t QUAKE2_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_vmMain({} {}) called\n", QUAKE2_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_vmMain({} {}) called\n", QUAKE2_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -510,15 +510,15 @@ static intptr_t QUAKE2_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_vmMain({} {}) returning {}\n", QUAKE2_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_vmMain({} {}) returning {}\n", QUAKE2_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* QUAKE2_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_entry({}) called\n", import); +static void* QUAKE2_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -534,7 +534,7 @@ static void* QUAKE2_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = QUAKE2_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -543,8 +543,8 @@ static void* QUAKE2_entry(void* import, void*, bool) { } -static bool QUAKE2_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool QUAKE2_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -554,12 +554,12 @@ static bool QUAKE2_mod_load(void* entry, bool is_GetGameAPI) { } -static void QUAKE2_mod_unload() { +static void QUAKE2_ModUnload() { orig_export = nullptr; } -static const char* QUAKE2_eng_msg_names(intptr_t cmd) { +static const char* QUAKE2_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_BPRINTF); GEN_CASE(G_DPRINTF); @@ -630,7 +630,7 @@ static const char* QUAKE2_eng_msg_names(intptr_t cmd) { } -static const char* QUAKE2_mod_msg_names(intptr_t cmd) { +static const char* QUAKE2_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_rtcwmp.cpp b/src/game_rtcwmp.cpp index e84dcca..0b5f198 100644 --- a/src/game_rtcwmp.cpp +++ b/src/game_rtcwmp.cpp @@ -20,15 +20,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(RTCWMP); -GEN_EXTS(RTCWMP); +GEN_GAME_QMM_MSGS(RTCWMP); +GEN_GAME_EXTS(RTCWMP); -GEN_FUNCS_QVM(RTCWMP); +GEN_GAME_FUNCS_QVM(RTCWMP); // auto-detection logic for RTCWMP -static bool RTCWMP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool RTCWMP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -54,7 +54,7 @@ static intptr_t RTCWMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_syscall({} {}) called\n", RTCWMP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_syscall({} {}) called\n", RTCWMP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -87,7 +87,7 @@ static intptr_t RTCWMP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_syscall({} {}) returning {}\n", RTCWMP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_syscall({} {}) returning {}\n", RTCWMP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -100,7 +100,7 @@ static intptr_t RTCWMP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_vmMain({} {}) called\n", RTCWMP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_vmMain({} {}) called\n", RTCWMP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -113,15 +113,15 @@ static intptr_t RTCWMP_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_vmMain({} {}) returning {}\n", RTCWMP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_vmMain({} {}) returning {}\n", RTCWMP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* RTCWMP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_entry({}) called\n", syscall); +static void* RTCWMP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -132,14 +132,14 @@ static void* RTCWMP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = RTCWMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_Entry({}) returning\n", syscall); return nullptr; } -static bool RTCWMP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool RTCWMP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -148,12 +148,12 @@ static bool RTCWMP_mod_load(void* entry, bool is_GetGameAPI) { } -static void RTCWMP_mod_unload() { +static void RTCWMP_ModUnload() { orig_vmMain = nullptr; } -static const char* RTCWMP_eng_msg_names(intptr_t cmd) { +static const char* RTCWMP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -373,7 +373,7 @@ static const char* RTCWMP_eng_msg_names(intptr_t cmd) { } -static const char* RTCWMP_mod_msg_names(intptr_t cmd) { +static const char* RTCWMP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); @@ -402,9 +402,9 @@ static const char* RTCWMP_mod_msg_names(intptr_t cmd) { */ // vec3_t are arrays, so convert them as pointers // for double pointers (gentity_t** and vec3_t*), convert them once with vmptr() -static int RTCWMP_qvmsyscall(uint8_t* membase, int cmd, int* args) { +static int RTCWMP_QVMSyscall(uint8_t* membase, int cmd, int* args) { #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("RTCWMP_qvmsyscall({} {}) called\n", RTCWMP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("RTCWMP_QVMSyscall({} {}) called\n", RTCWMP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -701,7 +701,7 @@ static int RTCWMP_qvmsyscall(uint8_t* membase, int cmd, int* args) { } #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("RTCWMP_qvmsyscall({} {}) returning {}\n", RTCWMP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("RTCWMP_QVMSyscall({} {}) returning {}\n", RTCWMP_EngMsgNames(cmd), cmd, ret); #endif return ret; diff --git a/src/game_rtcwsp.cpp b/src/game_rtcwsp.cpp index 10b670f..f4e95ad 100644 --- a/src/game_rtcwsp.cpp +++ b/src/game_rtcwsp.cpp @@ -22,10 +22,10 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(RTCWSP); -GEN_EXTS(RTCWSP); +GEN_GAME_QMM_MSGS(RTCWSP); +GEN_GAME_EXTS(RTCWSP); -GEN_FUNCS(RTCWSP); +GEN_GAME_FUNCS(RTCWSP); #if defined(QMM_ARCH_32) && defined(QMM_OS_WINDOWS) #define MOD_DLL "x86.dll" @@ -38,8 +38,8 @@ GEN_FUNCS(RTCWSP); static bool is_iortcw = false; // auto-detection logic for RTCWSP -static bool RTCWSP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool RTCWSP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; const char* official_dllname = "qagame" MOD_DLL; @@ -82,7 +82,7 @@ static intptr_t RTCWSP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_syscall({} {}) called\n", RTCWSP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_syscall({} {}) called\n", RTCWSP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -127,7 +127,7 @@ static intptr_t RTCWSP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_syscall({} {}) returning {}\n", RTCWSP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_syscall({} {}) returning {}\n", RTCWSP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -140,7 +140,7 @@ static intptr_t RTCWSP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_vmMain({} {}) called\n", RTCWSP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_vmMain({} {}) called\n", RTCWSP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -153,15 +153,15 @@ static intptr_t RTCWSP_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_vmMain({} {}) returning {}\n", RTCWSP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_vmMain({} {}) returning {}\n", RTCWSP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* RTCWSP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_entry({}) called\n", syscall); +static void* RTCWSP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -172,14 +172,14 @@ static void* RTCWSP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = RTCWSP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_Entry({}) returning\n", syscall); return nullptr; } -static bool RTCWSP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool RTCWSP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -188,7 +188,7 @@ static bool RTCWSP_mod_load(void* entry, bool is_GetGameAPI) { } -static void RTCWSP_mod_unload() { +static void RTCWSP_ModUnload() { orig_vmMain = nullptr; // free the G_ALLOC list @@ -199,7 +199,7 @@ static void RTCWSP_mod_unload() { } -static const char* RTCWSP_eng_msg_names(intptr_t cmd) { +static const char* RTCWSP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -411,7 +411,7 @@ static const char* RTCWSP_eng_msg_names(intptr_t cmd) { } -static const char* RTCWSP_mod_msg_names(intptr_t cmd) { +static const char* RTCWSP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); diff --git a/src/game_sin.cpp b/src/game_sin.cpp index 6c52ea9..0cac304 100644 --- a/src/game_sin.cpp +++ b/src/game_sin.cpp @@ -25,15 +25,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(SIN); -GEN_EXTS(SIN); +GEN_GAME_QMM_MSGS(SIN); +GEN_GAME_EXTS(SIN); -GEN_FUNCS(SIN); +GEN_GAME_FUNCS(SIN); // auto-detection logic for SIN -static bool SIN_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool SIN_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -294,7 +294,7 @@ static intptr_t SIN_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_syscall({} {}) called\n", SIN_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_syscall({} {}) called\n", SIN_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -562,7 +562,7 @@ static intptr_t SIN_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_syscall({} {}) returning {}\n", SIN_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_syscall({} {}) returning {}\n", SIN_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -575,7 +575,7 @@ static intptr_t SIN_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_vmMain({} {}) called\n", SIN_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_vmMain({} {}) called\n", SIN_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -626,15 +626,15 @@ static intptr_t SIN_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_vmMain({} {}) returning {}\n", SIN_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_vmMain({} {}) returning {}\n", SIN_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* SIN_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_entry({}) called\n", import); +static void* SIN_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -651,7 +651,7 @@ static void* SIN_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = SIN_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -660,8 +660,8 @@ static void* SIN_entry(void* import, void*, bool) { } -static bool SIN_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool SIN_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -671,12 +671,12 @@ static bool SIN_mod_load(void* entry, bool is_GetGameAPI) { } -static void SIN_mod_unload() { +static void SIN_ModUnload() { orig_export = nullptr; } -static const char* SIN_eng_msg_names(intptr_t cmd) { +static const char* SIN_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_BPRINTF); GEN_CASE(G_DPRINTF); @@ -792,7 +792,7 @@ static const char* SIN_eng_msg_names(intptr_t cmd) { } -static const char* SIN_mod_msg_names(intptr_t cmd) { +static const char* SIN_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_sof2mp.cpp b/src/game_sof2mp.cpp index b7c54d3..f54aa89 100644 --- a/src/game_sof2mp.cpp +++ b/src/game_sof2mp.cpp @@ -22,15 +22,15 @@ Created By: #include "mod.h" #include "util.h" -GEN_QMM_MSGS(SOF2MP); -GEN_EXTS(SOF2MP); +GEN_GAME_QMM_MSGS(SOF2MP); +GEN_GAME_EXTS(SOF2MP); -GEN_FUNCS_QVM(SOF2MP); +GEN_GAME_FUNCS_QVM(SOF2MP); // auto-detection logic for SOF2MP -static bool SOF2MP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool SOF2MP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -56,7 +56,7 @@ static intptr_t SOF2MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_syscall({} {}) called\n", SOF2MP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_syscall({} {}) called\n", SOF2MP_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -90,7 +90,7 @@ static intptr_t SOF2MP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_syscall({} {}) returning {}\n", SOF2MP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_syscall({} {}) returning {}\n", SOF2MP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -103,7 +103,7 @@ static intptr_t SOF2MP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_vmMain({} {}) called\n", SOF2MP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_vmMain({} {}) called\n", SOF2MP_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -156,15 +156,15 @@ static intptr_t SOF2MP_vmMain(intptr_t cmd, ...) { } #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_vmMain({} {}) returning {}\n", SOF2MP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_vmMain({} {}) returning {}\n", SOF2MP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* SOF2MP_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_entry({}) called\n", syscall); +static void* SOF2MP_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -175,15 +175,15 @@ static void* SOF2MP_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = SOF2MP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_Entry({}) returning\n", syscall); return nullptr; } // get mod's vmMain function pointer from mod.cpp::mod_load -static bool SOF2MP_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool SOF2MP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -197,12 +197,12 @@ static bool SOF2MP_mod_load(void* entry, bool is_GetGameAPI) { } -static void SOF2MP_mod_unload() { +static void SOF2MP_ModUnload() { orig_vmMain = nullptr; } -static const char* SOF2MP_eng_msg_names(intptr_t cmd) { +static const char* SOF2MP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -475,7 +475,7 @@ static const char* SOF2MP_eng_msg_names(intptr_t cmd) { } -static const char* SOF2MP_mod_msg_names(intptr_t cmd) { +static const char* SOF2MP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); @@ -507,9 +507,9 @@ static const char* SOF2MP_mod_msg_names(intptr_t cmd) { // do NOT convert the "ghoul" void pointers, treat them as plain ints // TGPValue, TGPGroup, and TGenericParser2 are void*, but treat them as plain ints // for double pointers (gentity_t**, vec3_t*, void**), convert them once with vmptr() -static int SOF2MP_qvmsyscall(uint8_t* membase, int cmd, int* args) { +static int SOF2MP_QVMSyscall(uint8_t* membase, int cmd, int* args) { #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("SOF2MP_qvmsyscall({} {}) called\n", SOF2MP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("SOF2MP_QVMSyscall({} {}) called\n", SOF2MP_EngMsgNames(cmd), cmd); #endif int ret = 0; @@ -881,7 +881,7 @@ static int SOF2MP_qvmsyscall(uint8_t* membase, int cmd, int* args) { } #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("SOF2MP_qvmsyscall({} {}) returning {}\n", SOF2MP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("SOF2MP_QVMSyscall({} {}) returning {}\n", SOF2MP_EngMsgNames(cmd), cmd, ret); #endif return ret; diff --git a/src/game_sof2sp.cpp b/src/game_sof2sp.cpp index 060ce06..45ecf2f 100644 --- a/src/game_sof2sp.cpp +++ b/src/game_sof2sp.cpp @@ -18,15 +18,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(SOF2SP); -GEN_EXTS(SOF2SP); +GEN_GAME_QMM_MSGS(SOF2SP); +GEN_GAME_EXTS(SOF2SP); -GEN_FUNCS(SOF2SP); +GEN_GAME_FUNCS(SOF2SP); // auto-detection logic for SOF2SP -static bool SOF2SP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool SOF2SP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -214,7 +214,7 @@ static intptr_t SOF2SP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_syscall({} {}) called\n", SOF2SP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_syscall({} {}) called\n", SOF2SP_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -376,7 +376,7 @@ static intptr_t SOF2SP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_syscall({} {}) returning {}\n", SOF2SP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_syscall({} {}) returning {}\n", SOF2SP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -389,7 +389,7 @@ static intptr_t SOF2SP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_vmMain({} {}) called\n", SOF2SP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_vmMain({} {}) called\n", SOF2SP_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -435,16 +435,16 @@ static intptr_t SOF2SP_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_vmMain({} {}) returning {}\n", SOF2SP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_vmMain({} {}) returning {}\n", SOF2SP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* SOF2SP_entry(void* apiversion, void* import, bool) { +static void* SOF2SP_Entry(void* apiversion, void* import, api_engine) { orig_apiversion = (intptr_t)apiversion; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_entry({}, {}) called\n", orig_apiversion, import); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_Entry({}, {}) called\n", orig_apiversion, import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -460,7 +460,7 @@ static void* SOF2SP_entry(void* apiversion, void* import, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = SOF2SP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_entry({}, {}) returning {}\n", orig_apiversion, import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_Entry({}, {}) returning {}\n", orig_apiversion, import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -469,8 +469,8 @@ static void* SOF2SP_entry(void* apiversion, void* import, bool) { } -static bool SOF2SP_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool SOF2SP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -481,12 +481,12 @@ static bool SOF2SP_mod_load(void* entry, bool is_GetGameAPI) { } -static void SOF2SP_mod_unload() { +static void SOF2SP_ModUnload() { orig_export = nullptr; } -static const char* SOF2SP_eng_msg_names(intptr_t cmd) { +static const char* SOF2SP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_DPRINTF); @@ -611,7 +611,7 @@ static const char* SOF2SP_eng_msg_names(intptr_t cmd) { } -static const char* SOF2SP_mod_msg_names(intptr_t cmd) { +static const char* SOF2SP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); diff --git a/src/game_stef2.cpp b/src/game_stef2.cpp index 83bfa66..cfeff94 100644 --- a/src/game_stef2.cpp +++ b/src/game_stef2.cpp @@ -23,15 +23,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(STEF2); -GEN_EXTS(STEF2); +GEN_GAME_QMM_MSGS(STEF2); +GEN_GAME_EXTS(STEF2); -GEN_FUNCS(STEF2); +GEN_GAME_FUNCS(STEF2); // auto-detection logic for STEF2 -static bool STEF2_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool STEF2_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -491,7 +491,7 @@ static intptr_t STEF2_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_syscall({} {}) called\n", STEF2_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_syscall({} {}) called\n", STEF2_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -882,7 +882,7 @@ static intptr_t STEF2_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_syscall({} {}) returning {}\n", STEF2_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_syscall({} {}) returning {}\n", STEF2_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -895,7 +895,7 @@ static intptr_t STEF2_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_vmMain({} {}) called\n", STEF2_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_vmMain({} {}) called\n", STEF2_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -953,15 +953,15 @@ static intptr_t STEF2_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_vmMain({} {}) returning {}\n", STEF2_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_vmMain({} {}) returning {}\n", STEF2_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* STEF2_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_entry({}) called\n", import); +static void* STEF2_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -978,7 +978,7 @@ static void* STEF2_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = STEF2_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -987,8 +987,8 @@ static void* STEF2_entry(void* import, void*, bool) { } -static bool STEF2_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool STEF2_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -998,12 +998,12 @@ static bool STEF2_mod_load(void* entry, bool is_GetGameAPI) { } -static void STEF2_mod_unload() { +static void STEF2_ModUnload() { orig_export = nullptr; } -static const char* STEF2_eng_msg_names(intptr_t cmd) { +static const char* STEF2_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_DPRINTF); @@ -1356,7 +1356,7 @@ static const char* STEF2_eng_msg_names(intptr_t cmd) { } -static const char* STEF2_mod_msg_names(intptr_t cmd) { +static const char* STEF2_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_stvoyhm.cpp b/src/game_stvoyhm.cpp index d1b5378..a2a6b14 100644 --- a/src/game_stvoyhm.cpp +++ b/src/game_stvoyhm.cpp @@ -21,15 +21,15 @@ Created By: #include "mod.h" #include "util.h" -GEN_QMM_MSGS(STVOYHM); -GEN_EXTS(STVOYHM); +GEN_GAME_QMM_MSGS(STVOYHM); +GEN_GAME_EXTS(STVOYHM); -GEN_FUNCS_QVM(STVOYHM); +GEN_GAME_FUNCS_QVM(STVOYHM); // auto-detection logic for Q3A -static bool STVOYHM_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool STVOYHM_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -55,7 +55,7 @@ static intptr_t STVOYHM_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_syscall({} {}) called\n", STVOYHM_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_syscall({} {}) called\n", STVOYHM_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -88,7 +88,7 @@ static intptr_t STVOYHM_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_syscall({} {}) returning {}\n", STVOYHM_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_syscall({} {}) returning {}\n", STVOYHM_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -101,7 +101,7 @@ static intptr_t STVOYHM_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_vmMain({} {}) called\n", STVOYHM_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_vmMain({} {}) called\n", STVOYHM_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -120,15 +120,15 @@ static intptr_t STVOYHM_vmMain(intptr_t cmd, ...) { } #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_vmMain({} {}) returning {}\n", STVOYHM_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_vmMain({} {}) returning {}\n", STVOYHM_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* STVOYHM_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_entry({}) called\n", syscall); +static void* STVOYHM_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -139,14 +139,14 @@ static void* STVOYHM_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = STVOYHM_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_Entry({}) returning\n", syscall); return nullptr; } -static bool STVOYHM_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool STVOYHM_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -155,12 +155,12 @@ static bool STVOYHM_mod_load(void* entry, bool is_GetGameAPI) { } -static void STVOYHM_mod_unload() { +static void STVOYHM_ModUnload() { orig_vmMain = nullptr; } -static const char* STVOYHM_eng_msg_names(intptr_t cmd) { +static const char* STVOYHM_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -360,7 +360,7 @@ static const char* STVOYHM_eng_msg_names(intptr_t cmd) { } -static const char* STVOYHM_mod_msg_names(intptr_t cmd) { +static const char* STVOYHM_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); @@ -386,9 +386,9 @@ static const char* STVOYHM_mod_msg_names(intptr_t cmd) { */ // vec3_t are arrays, so convert them as pointers // for double pointers (gentity_t** and vec3_t*), convert them once with vmptr() -static int STVOYHM_qvmsyscall(uint8_t* membase, int cmd, int* args) { +static int STVOYHM_QVMSyscall(uint8_t* membase, int cmd, int* args) { #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("STVOYHM_qvmsyscall({} {}) called\n", STVOYHM_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("STVOYHM_QVMSyscall({} {}) called\n", STVOYHM_EngMsgNames(cmd), cmd); #endif int ret = 0; @@ -653,7 +653,7 @@ static int STVOYHM_qvmsyscall(uint8_t* membase, int cmd, int* args) { } #ifdef _DEBUG - LOG(QMM_LOG_TRACE, "QMM") << fmt::format("STVOYHM_qvmsyscall({} {}) returning {}\n", STVOYHM_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_TRACE, "QMM") << fmt::format("STVOYHM_QVMSyscall({} {}) returning {}\n", STVOYHM_EngMsgNames(cmd), cmd, ret); #endif return ret; diff --git a/src/game_stvoysp.cpp b/src/game_stvoysp.cpp index 13b9915..df17c45 100644 --- a/src/game_stvoysp.cpp +++ b/src/game_stvoysp.cpp @@ -21,15 +21,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(STVOYSP); -GEN_EXTS(STVOYSP); +GEN_GAME_QMM_MSGS(STVOYSP); +GEN_GAME_EXTS(STVOYSP); -GEN_FUNCS(STVOYSP); +GEN_GAME_FUNCS(STVOYSP); // auto-detection logic for STVOYSP -static bool STVOYSP_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (!is_GetGameAPI) +static bool STVOYSP_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -169,7 +169,7 @@ static intptr_t STVOYSP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_syscall({} {}) called\n", STVOYSP_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_syscall({} {}) called\n", STVOYSP_EngMsgNames(cmd), cmd); #endif // update export vars before calling into the engine @@ -290,7 +290,7 @@ static intptr_t STVOYSP_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_syscall({} {}) returning {}\n", STVOYSP_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_syscall({} {}) returning {}\n", STVOYSP_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -303,7 +303,7 @@ static intptr_t STVOYSP_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_vmMain({} {}) called\n", STVOYSP_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_vmMain({} {}) called\n", STVOYSP_ModMsgNames(cmd), cmd); #endif if (!orig_export) @@ -341,15 +341,15 @@ static intptr_t STVOYSP_vmMain(intptr_t cmd, ...) { s_update_export(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_vmMain({} {}) returning {}\n", STVOYSP_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_vmMain({} {}) returning {}\n", STVOYSP_ModMsgNames(cmd), cmd, ret); #endif return ret; } -static void* STVOYSP_entry(void* import, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_entry({}) called\n", import); +static void* STVOYSP_Entry(void* import, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_Entry({}) called\n", import); // original import struct from engine // the struct given by the engine goes out of scope after this returns so we have to copy the whole thing @@ -365,7 +365,7 @@ static void* STVOYSP_entry(void* import, void*, bool) { // pointer to wrapper syscall function that calls actual engine func from orig_import g_gameinfo.pfnsyscall = STVOYSP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_entry({}) returning {}\n", import, (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_Entry({}) returning {}\n", import, (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. @@ -374,8 +374,8 @@ static void* STVOYSP_entry(void* import, void*, bool) { } -static bool STVOYSP_mod_load(void* entry, bool is_GetGameAPI) { - if (!is_GetGameAPI) +static bool STVOYSP_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; @@ -385,12 +385,12 @@ static bool STVOYSP_mod_load(void* entry, bool is_GetGameAPI) { } -static void STVOYSP_mod_unload() { +static void STVOYSP_ModUnload() { orig_export = nullptr; } -static const char* STVOYSP_eng_msg_names(intptr_t cmd) { +static const char* STVOYSP_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINTF); GEN_CASE(G_WRITECAM); @@ -447,7 +447,7 @@ static const char* STVOYSP_eng_msg_names(intptr_t cmd) { } -static const char* STVOYSP_mod_msg_names(intptr_t cmd) { +static const char* STVOYSP_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAMEV_APIVERSION); GEN_CASE(GAME_INIT); diff --git a/src/game_wet.cpp b/src/game_wet.cpp index 8206697..e586e0b 100644 --- a/src/game_wet.cpp +++ b/src/game_wet.cpp @@ -20,15 +20,15 @@ Created By: #include "main.h" #include "util.h" -GEN_QMM_MSGS(WET); -GEN_EXTS(WET); +GEN_GAME_QMM_MSGS(WET); +GEN_GAME_EXTS(WET); -GEN_FUNCS(WET); +GEN_GAME_FUNCS(WET); // auto-detection logic for WET -static bool WET_autodetect(bool is_GetGameAPI, supportedgame* game) { - if (is_GetGameAPI) +static bool WET_AutoDetect(api_supportedgame* game, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -49,12 +49,12 @@ static mod_vmMain orig_vmMain = nullptr; // wrapper syscall function that calls actual engine func in orig_syscall // this is how QMM and plugins will call into the engine -intptr_t WET_syscall(intptr_t cmd, ...) { +static intptr_t WET_syscall(intptr_t cmd, ...) { QMM_GET_SYSCALL_ARGS(); #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_syscall({} {}) called\n", WET_eng_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_syscall({} {}) called\n", WET_EngMsgNames(cmd), cmd); #endif intptr_t ret = 0; @@ -87,7 +87,7 @@ intptr_t WET_syscall(intptr_t cmd, ...) { #ifdef _DEBUG if (cmd != G_PRINT) - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_syscall({} {}) returning {}\n", WET_eng_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_syscall({} {}) returning {}\n", WET_EngMsgNames(cmd), cmd, ret); #endif return ret; @@ -96,11 +96,11 @@ intptr_t WET_syscall(intptr_t cmd, ...) { // wrapper vmMain function that calls actual mod func in orig_vmMain // this is how QMM and plugins will call into the mod -intptr_t WET_vmMain(intptr_t cmd, ...) { +static intptr_t WET_vmMain(intptr_t cmd, ...) { QMM_GET_VMMAIN_ARGS(); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_vmMain({} {}) called\n", WET_mod_msg_names(cmd), cmd); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_vmMain({} {}) called\n", WET_ModMsgNames(cmd), cmd); #endif if (!orig_vmMain) @@ -113,15 +113,15 @@ intptr_t WET_vmMain(intptr_t cmd, ...) { ret = orig_vmMain(cmd, QMM_PUT_VMMAIN_ARGS()); #ifdef _DEBUG - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_vmMain({} {}) returning {}\n", WET_mod_msg_names(cmd), cmd, ret); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_vmMain({} {}) returning {}\n", WET_ModMsgNames(cmd), cmd, ret); #endif return ret; } -void* WET_entry(void* syscall, void*, bool) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_entry({}) called\n", syscall); +static void* WET_Entry(void* syscall, void*, api_engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_Entry({}) called\n", syscall); // store original syscall from engine orig_syscall = (eng_syscall)syscall; @@ -132,14 +132,14 @@ void* WET_entry(void* syscall, void*, bool) { // pointer to wrapper syscall function that calls actual engine syscall func g_gameinfo.pfnsyscall = WET_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_entry({}) returning\n", syscall); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_Entry({}) returning\n", syscall); return nullptr; } -bool WET_mod_load(void* entry, bool is_GetGameAPI) { - if (is_GetGameAPI) +static bool WET_ModLoad(void* entry, api_engine engine) { + if (engine != QMM_ENGINEAPI_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; @@ -148,12 +148,12 @@ bool WET_mod_load(void* entry, bool is_GetGameAPI) { } -void WET_mod_unload() { +static void WET_ModUnload() { orig_vmMain = nullptr; } -const char* WET_eng_msg_names(intptr_t cmd) { +static const char* WET_EngMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(G_PRINT); GEN_CASE(G_ERROR); @@ -384,7 +384,7 @@ const char* WET_eng_msg_names(intptr_t cmd) { } -const char* WET_mod_msg_names(intptr_t cmd) { +static const char* WET_ModMsgNames(intptr_t cmd) { switch (cmd) { GEN_CASE(GAME_INIT); GEN_CASE(GAME_SHUTDOWN); diff --git a/src/main.cpp b/src/main.cpp index 428d818..b9f2a93 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,13 +27,13 @@ Created By: gameinfo g_gameinfo; // shared code for dllEntry and GetGameAPI entry points -static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI); +static void* main_handle_entry(void* import, void* extra, api_engine engine); // general code to get path/module/binary/etc information static void main_detect_env(); // general code to load config file static void main_load_config(std::string config_filename); // general code to auto-detect what game engine loaded us -static void main_detect_game(std::string cfg_game, bool is_GetGameAPI); +static void main_detect_game(std::string cfg_game, api_engine engine); // general code to find a mod file to load static bool main_load_mod(std::string cfg_mod); // general code to find a plugin file to load @@ -65,7 +65,7 @@ static intptr_t main_route(bool is_syscall, intptr_t cmd, intptr_t* args); is returned to engine syscall (mod->engine) call flow for QVM mods only: - 1. QVM system calls _qvmsyscall function + 1. QVM system calls _QVMSyscall function 2. pointer arguments are converted: if not NULL, the QVM data segment base address is added 3. call qmm_syscall with converted arguments (continue with next section as if it were a DLL mod) @@ -138,7 +138,7 @@ C_DLLEXPORT void dllEntry(void* syscall) { // if we don't detect a game, we can call syscall(G_ERROR) to shutdown in vmMain g_gameinfo.pfnsyscall = (eng_syscall)syscall; - main_handle_entry(syscall, nullptr, false); // false = !is_GetGameAPI + main_handle_entry(syscall, nullptr, QMM_ENGINEAPI_DLLENTRY); return; } @@ -194,13 +194,13 @@ C_DLLEXPORT void dllEntry(void* syscall) { to the proper function pointer in the struct. */ C_DLLEXPORT void* GetGameAPI(void* import, void* extra) { - return main_handle_entry(import, extra, true); // true = is_GetGameAPI + return main_handle_entry(import, extra, QMM_ENGINEAPI_GETGAMEAPI); } // this is the same as the 2-arg GetGameAPI but OpenJK renamed it C_DLLEXPORT void* GetModuleAPI(void* import, void* extra) { - return main_handle_entry(import, extra, true); // true = is_GetGameAPI + return main_handle_entry(import, extra, QMM_ENGINEAPI_GETGAMEAPI); } @@ -423,14 +423,22 @@ intptr_t qmm_syscall(intptr_t cmd, ...) { } -static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { - const char* func_name = is_GetGameAPI ? "GetGameAPI" : "dllEntry"; +static void* main_handle_entry(void* import, void* extra, api_engine engine) { + const char* func_name = "unknown"; + switch (engine) { + case QMM_ENGINEAPI_DLLENTRY: + func_name = "dllEntry"; + break; + case QMM_ENGINEAPI_GETGAMEAPI: + func_name = "GetGameAPI"; + break; + } main_detect_env(); log_init(fmt::format("{}/qmm2.log", g_gameinfo.qmm_dir)); - LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ") ({}) loaded!\n", func_name); + LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ") ({}) loaded!\n", EngineAPIName(engine)); LOG(QMM_LOG_INFO, "QMM") << fmt::format("QMM path: \"{}\"\n", g_gameinfo.qmm_path); LOG(QMM_LOG_INFO, "QMM") << fmt::format("Engine path: \"{}\"\n", g_gameinfo.exe_path); LOG(QMM_LOG_INFO, "QMM") << fmt::format("Mod directory (?): \"{}\"\n", g_gameinfo.mod_dir); @@ -438,7 +446,7 @@ static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { // ??? // return nullptr to error out now. if GetGameAPI, Init() will never be called if (!import) { - LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): {} is NULL!\n", func_name, is_GetGameAPI ? "import" : "syscall"); + LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): engine pointer is NULL!\n", func_name); return nullptr; } @@ -454,7 +462,7 @@ static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { std::string cfg_game = cfg_get_string(g_cfg, "game", "auto"); // check command line arguments for a game code cfg_game = util_get_cmdline_arg("--qmm_game", cfg_game); - main_detect_game(cfg_game, is_GetGameAPI); + main_detect_game(cfg_game, engine); // failed to get engine information, or game does not have an entry handler // if GetGameAPI, returning nullptr to error out now will make sure Init() will never be called. @@ -470,9 +478,9 @@ static void* main_handle_entry(void* import, void* extra, bool is_GetGameAPI) { msg_GAME_CONSOLE_COMMAND = QMM_MOD_MSG[QMM_GAME_CONSOLE_COMMAND]; msg_GAME_SHUTDOWN = QMM_MOD_MSG[QMM_GAME_SHUTDOWN]; - // call the game-specific entry handler (e.g. Q3A_entry) which will set up the internals to interact + // call the game-specific entry handler (e.g. Q3A_Entry) which will set up the internals to interact // the engine and the mod - return g_gameinfo.game->funcs->pfnEntry(import, extra, is_GetGameAPI); + return g_gameinfo.game->funcs->pfnEntry(import, extra, engine); } @@ -536,8 +544,8 @@ static void main_load_config(std::string config_filename) { // general code to auto-detect what game engine loaded us -static void main_detect_game(std::string cfg_game, bool is_GetGameAPI) { - for (supportedgame& game : g_supportedgames) { +static void main_detect_game(std::string cfg_game, api_engine engine) { + for (api_supportedgame& game : api_supportedgames) { // if short name matches config option, we found it! if (str_striequal(cfg_game, game.gamename_short)) { LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("Found game match for config option \"{}\"\n", cfg_game); @@ -545,14 +553,14 @@ static void main_detect_game(std::string cfg_game, bool is_GetGameAPI) { g_gameinfo.is_auto_detected = false; // call the game's auto-detect function if it exists, since it may do some logic if (game.funcs->pfnAutoDetect) - (void)game.funcs->pfnAutoDetect(is_GetGameAPI, &game); + (void)game.funcs->pfnAutoDetect(&game, engine); return; } // otherwise, if auto, call the game's auto-detect function if available if (str_striequal(cfg_game, "auto") && game.funcs->pfnAutoDetect - && game.funcs->pfnAutoDetect(is_GetGameAPI, &game)) + && game.funcs->pfnAutoDetect(&game, engine)) { LOG(QMM_LOG_INFO, "QMM") << fmt::format("Found game match with auto-detection - \"{}\"\n", game.gamename_short); g_gameinfo.game = &game; @@ -669,7 +677,7 @@ static void main_handle_command_qmm(intptr_t arg_start) { CONSOLE_PRINT("(QMM) URL: " QMM_URL "\n"); CONSOLE_PRINT("(QMM) Plugin interface: " STRINGIFY(QMM_PIFV_MAJOR) ":" STRINGIFY(QMM_PIFV_MINOR) "\n"); CONSOLE_PRINTF("(QMM) Plugins loaded: {}\n", g_plugins.size()); - CONSOLE_PRINTF("(QMM) Loaded mod: {} ({})\n", g_mod.path, g_mod.is_GetGameAPI ? "GetGameAPI" : "dllEntry"); + CONSOLE_PRINTF("(QMM) Loaded mod: {} ({})\n", g_mod.path, EngineAPIName(g_mod.engine)); if (g_mod.vmbase) { CONSOLE_PRINTF("(QMM) QVM magic number : {:x} ({})\n", g_mod.vm.magic, g_mod.vm.magic == QVM_MAGIC ? "QVM_MAGIC" : "QVM_MAGIC_VER2"); CONSOLE_PRINTF("(QMM) QVM file size : {}\n", g_mod.vm.filesize); diff --git a/src/mod.cpp b/src/mod.cpp index 8bcad01..c66b07f 100644 --- a/src/mod.cpp +++ b/src/mod.cpp @@ -40,7 +40,7 @@ bool mod_load(qmm_mod& mod, std::string file) { std::string ext = path_baseext(file); // only allow qvm mods if the game engine supports it - if (str_striequal(ext, EXT_QVM) && g_gameinfo.game->funcs->pfnqvmsyscall) { + if (str_striequal(ext, EXT_QVM) && g_gameinfo.game->funcs->pfnQVMSyscall) { return s_mod_load_qvm(mod); } // if DLL @@ -68,9 +68,9 @@ bool mod_load(qmm_mod& mod, std::string file) { // if we found the function, try passing it to the game-specific mod load handler if (pfnGGA && g_gameinfo.game->funcs->pfnModLoad - && g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, true)) // true = is_GetGameAPI + && g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, QMM_ENGINEAPI_GETGAMEAPI)) { - mod.is_GetGameAPI = true; + mod.engine = QMM_ENGINEAPI_GETGAMEAPI; return true; } @@ -85,11 +85,11 @@ bool mod_load(qmm_mod& mod, std::string file) { if (pfndllEntry && pfnvmMain && g_gameinfo.game->funcs->pfnModLoad - && g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, false)) // false = !is_GetGameAPI + && g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, QMM_ENGINEAPI_DLLENTRY)) { // pass qmm_syscall to mod's dllEntry function pfndllEntry(qmm_syscall); - mod.is_GetGameAPI = false; + mod.engine = QMM_ENGINEAPI_DLLENTRY; return true; } @@ -145,7 +145,7 @@ static intptr_t s_mod_qvm_vmmain(intptr_t cmd, ...) { // handle syscalls from the QVM. passed to qvm_load static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args) { // if no game-specific qvm handler, we need to error - if (!g_gameinfo.game->funcs->pfnqvmsyscall) { + if (!g_gameinfo.game->funcs->pfnQVMSyscall) { if (!g_gameinfo.is_shutdown) { g_gameinfo.is_shutdown = true; LOG(QMM_LOG_FATAL, "QMM") << fmt::format("s_mod_qvm_syscall({}): No QVM syscall handler found\n", g_gameinfo.game->funcs->pfnEngMsgNames(cmd)); @@ -167,7 +167,7 @@ static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args) { } // call the game-specific QVM syscall handler - return g_gameinfo.game->funcs->pfnqvmsyscall(membase, cmd, args); + return g_gameinfo.game->funcs->pfnQVMSyscall(membase, cmd, args); } @@ -203,18 +203,19 @@ static bool s_mod_load_qvm(qmm_mod& mod) { } mod.vmbase = (intptr_t)mod.vm.datasegment; + // store the qvm vmMain pointer as a backup (should get overwritten in game-specific mod load handler) g_gameinfo.pfnvmMain = s_mod_qvm_vmmain; // pass the qvm vmMain function pointer to the game-specific mod load handler if (!g_gameinfo.game->funcs->pfnModLoad || - !g_gameinfo.game->funcs->pfnModLoad((void*)s_mod_qvm_vmmain, false)) // false = !is_GetGameAPI + !g_gameinfo.game->funcs->pfnModLoad((void*)s_mod_qvm_vmmain, QMM_ENGINEAPI_DLLENTRY)) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Mod load failed?\n", mod.path); goto fail; } - mod.is_GetGameAPI = false; + mod.engine = QMM_ENGINEAPI_DLLENTRY; return true; From 38c543a679d001e8df6c5d5b9b2387aa62ccba89 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:42:59 +0200 Subject: [PATCH 05/15] rename qmm_mod::engine to "api" and add gameinfo::api --- include/main.h | 1 + include/mod.h | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/main.h b/include/main.h index b6d5e21..cbab503 100644 --- a/include/main.h +++ b/include/main.h @@ -33,6 +33,7 @@ struct gameinfo { void* qmm_module_ptr = nullptr; // qmm module pointer bool is_auto_detected = false; // was this engine auto-detected? bool is_shutdown = false; // is game shutting down due to G_ERROR? avoids calling G_ERROR again from GAME_SHUTDOWN + APIType api = QMM_API_ERROR; // engine api that QMM was loaded with }; extern gameinfo g_gameinfo; diff --git a/include/mod.h b/include/mod.h index e3d8069..6ec7347 100644 --- a/include/mod.h +++ b/include/mod.h @@ -17,11 +17,11 @@ Created By: #include "qvm.h" struct qmm_mod { - std::string path; - qvm vm = {}; - void* dll = nullptr; - intptr_t vmbase = 0; - api_engine engine; + std::string path; // mod file path + qvm vm = {}; // QVM object + void* dll = nullptr; // OS DLL handle + intptr_t vmbase = 0; // base data segment address for QVMs (0 if DLL mod) + APIType api = QMM_API_ERROR; // engine api the mod DLL was loaded with }; extern qmm_mod g_mod; From 3b78f6e2ac1345cfc551a89221a694127ebf3c17 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:44:35 +0200 Subject: [PATCH 06/15] rename "api_engine" to "APIType" and add "QMM_API_QVM" and "QMM_API_GETMODULEAPI" --- include/game_api.h | 36 +++++++++++++++++++----------------- src/game_api.cpp | 35 +++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/include/game_api.h b/include/game_api.h index 43256ad..c7fc12c 100644 --- a/include/game_api.h +++ b/include/game_api.h @@ -19,28 +19,30 @@ Created By: #include "qmmapi.h" #include "qvm.h" -// engine API type -enum api_engine { - QMM_ENGINEAPI_NONE, +// engine/mod API type +enum APIType { + QMM_API_ERROR, - QMM_ENGINEAPI_DLLENTRY, - QMM_ENGINEAPI_GETGAMEAPI, + QMM_API_QVM, - QMM_VMMAIN = QMM_ENGINEAPI_DLLENTRY, + QMM_API_DLLENTRY, + QMM_API_GETGAMEAPI, + QMM_API_GETMODULEAPI, }; -extern const char* EngineAPIName(api_engine); +const char* APIType_Name(APIType); +const char* APIType_Function(APIType); struct api_supportedgame; // this struct is defined by GEN_GAME_FUNCS_QVM(GAME) or GEN_GAME_FUNCS(GAME) struct api_supportedgame_funcs { int* qmm_eng_msgs; // array of engine messages used by QMM int* qmm_mod_msgs; // array of mod messages used by QMM - const char* (*pfnEngMsgNames)(intptr_t); // pointer to a function that returns a string for a given engine message + const char* (*pfnEngMsgNames)(intptr_t); // pointer to a function that returns a string for a given api message const char* (*pfnModMsgNames)(intptr_t); // pointer to a function that returns a string for a given mod message - bool(*pfnAutoDetect)(api_supportedgame*, api_engine); // pointer to a function that handles auto-detection logic for a game. return true to say "that's me!" - void*(*pfnEntry)(void*, void*, api_engine); // pointer to a function that handles entry point logic for a game - bool(*pfnModLoad)(void*, api_engine); // pointer to a function that handles mod loading logic after a DLL is loaded + bool(*pfnAutoDetect)(api_supportedgame*, APIType); // pointer to a function that handles auto-detection logic for a game. return true to say "that's me!" + void*(*pfnEntry)(void*, void*, APIType); // pointer to a function that handles entry point logic for a game + bool(*pfnModLoad)(void*, APIType); // pointer to a function that handles mod loading logic after a DLL is loaded with LoadLibrary/dlopen void(*pfnModUnload)(); // pointer to a function that handles mod unloading logic before a DLL is unloaded qvm_syscall pfnQVMSyscall; // pointer to a function that handles mod->engine calls from a QVM (NULL = not supported) @@ -84,9 +86,9 @@ extern std::vector api_supportedgames; #define GEN_GAME_FUNCS_QVM(game) \ static const char* game##_EngMsgNames(intptr_t); \ static const char* game##_ModMsgNames(intptr_t); \ -static bool game##_AutoDetect(api_supportedgame*, api_engine); \ -static void* game##_Entry(void*, void*, api_engine); \ -static bool game##_ModLoad(void*, api_engine); \ +static bool game##_AutoDetect(api_supportedgame*, APIType); \ +static void* game##_Entry(void*, void*, APIType); \ +static bool game##_ModLoad(void*, APIType); \ static void game##_ModUnload(); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ @@ -103,9 +105,9 @@ api_supportedgame_funcs game##_funcs = { \ #define GEN_GAME_FUNCS(game) \ static const char* game##_EngMsgNames(intptr_t); \ static const char* game##_ModMsgNames(intptr_t); \ -static bool game##_AutoDetect(api_supportedgame*, api_engine); \ -static void* game##_Entry(void*, void*, api_engine); \ -static bool game##_ModLoad(void*, api_engine); \ +static bool game##_AutoDetect(api_supportedgame*, APIType); \ +static void* game##_Entry(void*, void*, APIType); \ +static bool game##_ModLoad(void*, APIType); \ static void game##_ModUnload(); \ static intptr_t game##_syscall(intptr_t cmd, ...); \ static intptr_t game##_vmMain(intptr_t cmd, ...); \ diff --git a/src/game_api.cpp b/src/game_api.cpp index e78f9ce..d754419 100644 --- a/src/game_api.cpp +++ b/src/game_api.cpp @@ -109,13 +109,36 @@ std::vector api_supportedgames = { #endif }; -const char* EngineAPIName(api_engine engine) { - switch (engine) { - GEN_CASE(QMM_ENGINEAPI_NONE); - GEN_CASE(QMM_ENGINEAPI_DLLENTRY); - GEN_CASE(QMM_ENGINEAPI_GETGAMEAPI); +const char* APIType_Name(APIType api) { + switch (api) { + GEN_CASE(QMM_API_ERROR); + + GEN_CASE(QMM_API_QVM); + + GEN_CASE(QMM_API_DLLENTRY); + GEN_CASE(QMM_API_GETGAMEAPI); + GEN_CASE(QMM_API_GETMODULEAPI); + default: + return "unknown"; + }; +} + + +const char* APIType_Function(APIType api) { + switch (api) { + case QMM_API_ERROR: + return "(error)"; + + case QMM_API_QVM: + return "QVM"; + case QMM_API_DLLENTRY: + return "dllEntry"; + case QMM_API_GETGAMEAPI: + return "GetGameAPI"; + case QMM_API_GETMODULEAPI: + return "GetModuleAPI"; default: - return ""; + return "unknown"; }; } From b654502dd02ed09334b9ae2044e21107b0bc193e Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:46:20 +0200 Subject: [PATCH 07/15] api type name change, use new APIType_Function for log/qmm info output --- src/main.cpp | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b9f2a93..9455c09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,13 +27,13 @@ Created By: gameinfo g_gameinfo; // shared code for dllEntry and GetGameAPI entry points -static void* main_handle_entry(void* import, void* extra, api_engine engine); +static void* main_handle_entry(void* import, void* extra, APIType engine); // general code to get path/module/binary/etc information static void main_detect_env(); // general code to load config file static void main_load_config(std::string config_filename); // general code to auto-detect what game engine loaded us -static void main_detect_game(std::string cfg_game, api_engine engine); +static void main_detect_game(std::string cfg_game, APIType engine); // general code to find a mod file to load static bool main_load_mod(std::string cfg_mod); // general code to find a plugin file to load @@ -138,7 +138,7 @@ C_DLLEXPORT void dllEntry(void* syscall) { // if we don't detect a game, we can call syscall(G_ERROR) to shutdown in vmMain g_gameinfo.pfnsyscall = (eng_syscall)syscall; - main_handle_entry(syscall, nullptr, QMM_ENGINEAPI_DLLENTRY); + main_handle_entry(syscall, nullptr, QMM_API_DLLENTRY); return; } @@ -194,13 +194,13 @@ C_DLLEXPORT void dllEntry(void* syscall) { to the proper function pointer in the struct. */ C_DLLEXPORT void* GetGameAPI(void* import, void* extra) { - return main_handle_entry(import, extra, QMM_ENGINEAPI_GETGAMEAPI); + return main_handle_entry(import, extra, QMM_API_GETGAMEAPI); } // this is the same as the 2-arg GetGameAPI but OpenJK renamed it C_DLLEXPORT void* GetModuleAPI(void* import, void* extra) { - return main_handle_entry(import, extra, QMM_ENGINEAPI_GETGAMEAPI); + return main_handle_entry(import, extra, QMM_API_GETMODULEAPI); } @@ -305,7 +305,7 @@ C_DLLEXPORT intptr_t vmMain(intptr_t cmd, ...) { ENG_SYSCALL(QMM_FAIL_G_ERROR, "\nFatal QMM Error:\nQMM was unable to load the mod file.\nPlease set the \"mod\" option in qmm2.json.\nRefer to the documentation for more information.\n"); return 0; } - LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("Successfully loaded {} mod \"{}\"\n", g_mod.vmbase ? "VM" : "DLL", g_mod.path); + LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("Successfully loaded {} mod \"{}\"\n", APIType_Function(g_mod.api), g_mod.path); // cgame passthrough hack: // mod DLL is loaded, so find the vmMain and dllEntry functions and call dllEntry. @@ -423,22 +423,12 @@ intptr_t qmm_syscall(intptr_t cmd, ...) { } -static void* main_handle_entry(void* import, void* extra, api_engine engine) { - const char* func_name = "unknown"; - switch (engine) { - case QMM_ENGINEAPI_DLLENTRY: - func_name = "dllEntry"; - break; - case QMM_ENGINEAPI_GETGAMEAPI: - func_name = "GetGameAPI"; - break; - } - +static void* main_handle_entry(void* import, void* extra, APIType engine) { main_detect_env(); log_init(fmt::format("{}/qmm2.log", g_gameinfo.qmm_dir)); - LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ") ({}) loaded!\n", EngineAPIName(engine)); + LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ") ({}) loaded!\n", APIType_Function(engine)); LOG(QMM_LOG_INFO, "QMM") << fmt::format("QMM path: \"{}\"\n", g_gameinfo.qmm_path); LOG(QMM_LOG_INFO, "QMM") << fmt::format("Engine path: \"{}\"\n", g_gameinfo.exe_path); LOG(QMM_LOG_INFO, "QMM") << fmt::format("Mod directory (?): \"{}\"\n", g_gameinfo.mod_dir); @@ -446,7 +436,7 @@ static void* main_handle_entry(void* import, void* extra, api_engine engine) { // ??? // return nullptr to error out now. if GetGameAPI, Init() will never be called if (!import) { - LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): engine pointer is NULL!\n", func_name); + LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): engine pointer is NULL!\n", APIType_Function(engine)); return nullptr; } @@ -468,7 +458,7 @@ static void* main_handle_entry(void* import, void* extra, api_engine engine) { // if GetGameAPI, returning nullptr to error out now will make sure Init() will never be called. // if dllEntry, will check g_gameinfo.game in vmMain(GAME_INIT). if (!g_gameinfo.game || !g_gameinfo.game->funcs->pfnEntry) { - LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): Unable to determine game engine using \"{}\"\n", func_name, cfg_game); + LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): Unable to determine game engine using \"{}\"\n", APIType_Function(engine), cfg_game); return nullptr; } @@ -670,14 +660,14 @@ static void main_handle_command_qmm(intptr_t arg_start) { if (str_striequal("status", arg1) || str_striequal("info", arg1)) { CONSOLE_PRINT("(QMM) QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ")\n"); - CONSOLE_PRINTF("(QMM) Game: {}/\"{}\" (Source: {})\n", g_gameinfo.game->gamename_short, g_gameinfo.game->gamename_long, g_gameinfo.is_auto_detected ? "Auto-detected" : "Config file"); + CONSOLE_PRINTF("(QMM) Game: {}/\"{}\" ({}) (Source: {})\n", g_gameinfo.game->gamename_short, g_gameinfo.game->gamename_long, APIType_Function(g_gameinfo.api), g_gameinfo.is_auto_detected ? "Auto-detected" : "Config file"); CONSOLE_PRINTF("(QMM) ModDir: {}\n", g_gameinfo.mod_dir); CONSOLE_PRINTF("(QMM) Config file: \"{}\" {}\n", g_gameinfo.cfg_path, g_cfg.empty() ? "(error)" : ""); CONSOLE_PRINT("(QMM) Built: " QMM_COMPILE " by " QMM_BUILDER "\n"); CONSOLE_PRINT("(QMM) URL: " QMM_URL "\n"); CONSOLE_PRINT("(QMM) Plugin interface: " STRINGIFY(QMM_PIFV_MAJOR) ":" STRINGIFY(QMM_PIFV_MINOR) "\n"); CONSOLE_PRINTF("(QMM) Plugins loaded: {}\n", g_plugins.size()); - CONSOLE_PRINTF("(QMM) Loaded mod: {} ({})\n", g_mod.path, EngineAPIName(g_mod.engine)); + CONSOLE_PRINTF("(QMM) Loaded mod: {} ({})\n", g_mod.path, APIType_Function(g_mod.api)); if (g_mod.vmbase) { CONSOLE_PRINTF("(QMM) QVM magic number : {:x} ({})\n", g_mod.vm.magic, g_mod.vm.magic == QVM_MAGIC ? "QVM_MAGIC" : "QVM_MAGIC_VER2"); CONSOLE_PRINTF("(QMM) QVM file size : {}\n", g_mod.vm.filesize); From 8b5e3fc7ec69d9c5ef01ca005f550fee3cbc4870 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:46:40 +0200 Subject: [PATCH 08/15] comments --- src/plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin.cpp b/src/plugin.cpp index 2939ba0..5cb4d6d 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -491,7 +491,7 @@ static void s_plugin_helper_GetConfigString(plugin_id plid [[maybe_unused]], int // char* (*getConfigstring)(int index); // void trap_GetConfigstring(int num, char* buffer, int bufferSize); // some games don't return pointers because of QVM interaction, so if this returns anything but null - // (or true?), we probably are in an api game, and need to get the configstring from the return value + // (or true?), we need to get the configstring from the return value // instead if (buf && buflen) { intptr_t ret = ENG_SYSCALL(QMM_ENG_MSG[QMM_G_GET_CONFIGSTRING], index, buf, buflen); From 56d045d4f471fb5d2c44f88eb8c7bf9c93362e46 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:47:44 +0200 Subject: [PATCH 09/15] move DLL mod loading to s_mod_load_dll which loads different functions based on APIType --- src/mod.cpp | 95 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/src/mod.cpp b/src/mod.cpp index c66b07f..4b0d2e0 100644 --- a/src/mod.cpp +++ b/src/mod.cpp @@ -28,6 +28,7 @@ qmm_mod g_mod; static intptr_t s_mod_qvm_vmmain(intptr_t cmd, ...); static int s_mod_qvm_syscall(uint8_t* membase, int cmd, int* args); static bool s_mod_load_qvm(qmm_mod& mod); +static bool s_mod_load_dll(qmm_mod& mod, APIType api); bool mod_load(qmm_mod& mod, std::string file) { @@ -46,7 +47,8 @@ bool mod_load(qmm_mod& mod, std::string file) { // if DLL else if (str_striequal(ext, EXT_DLL)) { // load DLL - if (!(mod.dll = dlopen(file.c_str(), RTLD_NOW))) { + mod.dll = dlopen(file.c_str(), RTLD_NOW); + if (!mod.dll) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): DLL load failed: {}\n", file, dlerror()); goto fail; } @@ -54,44 +56,17 @@ bool mod_load(qmm_mod& mod, std::string file) { // if this DLL is the same as QMM, cancel if (mod.dll == g_gameinfo.qmm_module_ptr) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): DLL is actually QMM?\n", file); - dlclose(mod.dll); goto fail; } mod.vmbase = 0; - // look for GetGameAPI function - mod_GetGameAPI pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetGameAPI"); - // if no GGA, look for "GetModuleAPI", which is what OpenJK uses - if (!pfnGGA) - pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, "GetModuleAPI"); - // if we found the function, try passing it to the game-specific mod load handler - if (pfnGGA - && g_gameinfo.game->funcs->pfnModLoad - && g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, QMM_ENGINEAPI_GETGAMEAPI)) - { - mod.engine = QMM_ENGINEAPI_GETGAMEAPI; + if (s_mod_load_dll(mod, QMM_API_GETGAMEAPI)) return true; - } - - // if no GetGameAPI function, OR the mod load handler returned false, look for dllEntry and vmMain - mod_dllEntry pfndllEntry = (mod_dllEntry)dlsym(mod.dll, "dllEntry"); - mod_vmMain pfnvmMain = (mod_vmMain)dlsym(mod.dll, "vmMain"); - // store the vmMain pointer as a backup (should get overwritten in game-specific mod load handler) - g_gameinfo.pfnvmMain = pfnvmMain; - - // if we found both functions, and mod load handler returned true, pass vmMain to the game-specific - // mod load handler - if (pfndllEntry - && pfnvmMain - && g_gameinfo.game->funcs->pfnModLoad - && g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, QMM_ENGINEAPI_DLLENTRY)) - { - // pass qmm_syscall to mod's dllEntry function - pfndllEntry(qmm_syscall); - mod.engine = QMM_ENGINEAPI_DLLENTRY; + if (s_mod_load_dll(mod, QMM_API_GETMODULEAPI)) + return true; + if (s_mod_load_dll(mod, QMM_API_DLLENTRY)) return true; - } LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Unable to locate mod entry point\n", file); goto fail; @@ -101,6 +76,8 @@ bool mod_load(qmm_mod& mod, std::string file) { } fail: + if (mod.dll) + dlclose(mod.dll); mod_unload(mod); return false; } @@ -209,13 +186,13 @@ static bool s_mod_load_qvm(qmm_mod& mod) { // pass the qvm vmMain function pointer to the game-specific mod load handler if (!g_gameinfo.game->funcs->pfnModLoad || - !g_gameinfo.game->funcs->pfnModLoad((void*)s_mod_qvm_vmmain, QMM_ENGINEAPI_DLLENTRY)) + !g_gameinfo.game->funcs->pfnModLoad((void*)s_mod_qvm_vmmain, QMM_API_QVM)) { LOG(QMM_LOG_ERROR, "QMM") << fmt::format("mod_load(\"{}\"): Mod load failed?\n", mod.path); goto fail; } - mod.engine = QMM_ENGINEAPI_DLLENTRY; + mod.api = QMM_API_QVM; return true; @@ -223,3 +200,53 @@ static bool s_mod_load_qvm(qmm_mod& mod) { mod_unload(mod); return false; } + + +static bool s_mod_load_dll(qmm_mod& mod, APIType api) { + switch (api) { + case QMM_API_GETGAMEAPI: + case QMM_API_GETMODULEAPI: { + // these are together because they work the same, just with a different function name + + // mod load handler is needed for these api types + if (!g_gameinfo.game->funcs->pfnModLoad) + return false; + + // look for GetGameAPI/GetModuleAPI function + mod_GetGameAPI pfnGGA = (mod_GetGameAPI)dlsym(mod.dll, APIType_Function(api)); + if (!pfnGGA) + return false; + + // if mod load handler says good to go, we do too + if (g_gameinfo.game->funcs->pfnModLoad((void*)pfnGGA, api)) { + mod.api = api; + return true; + } + + return false; + } + case QMM_API_DLLENTRY: { + mod_dllEntry pfndllEntry = (mod_dllEntry)dlsym(mod.dll, "dllEntry"); + mod_vmMain pfnvmMain = (mod_vmMain)dlsym(mod.dll, "vmMain"); + if (!pfndllEntry || !pfnvmMain) + return false; + + // store the vmMain pointer as a backup (should get overwritten in game-specific mod load handler) + g_gameinfo.pfnvmMain = pfnvmMain; + + // mod load handler isn't explicitly required for this api type, but pass vmMain to it if it exists + if (!g_gameinfo.game->funcs->pfnModLoad + || g_gameinfo.game->funcs->pfnModLoad((void*)pfnvmMain, api)) + { + // pass qmm_syscall to mod's dllEntry function + pfndllEntry(qmm_syscall); + mod.api = api; + return true; + } + + return false; + } + default: + return false; + }; +} From 5b53b94163f286ac9ef8d9953d058813c849a509 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 00:56:58 +0200 Subject: [PATCH 10/15] missed an api_engine --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9455c09..a051e27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -534,7 +534,7 @@ static void main_load_config(std::string config_filename) { // general code to auto-detect what game engine loaded us -static void main_detect_game(std::string cfg_game, api_engine engine) { +static void main_detect_game(std::string cfg_game, APIType engine) { for (api_supportedgame& game : api_supportedgames) { // if short name matches config option, we found it! if (str_striequal(cfg_game, game.gamename_short)) { From d937aeb70d39ee0c305961a029f7aaf3722fafff Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 01:27:34 +0200 Subject: [PATCH 11/15] update AutoDetect, Entry and ModLoad functions to use APIType --- src/game_cod11mp.cpp | 10 +++++----- src/game_codmp.cpp | 12 ++++++------ src/game_coduomp.cpp | 12 ++++++------ src/game_jamp.cpp | 27 +++++++++++++++------------ src/game_jasp.cpp | 10 +++++----- src/game_jk2mp.cpp | 12 ++++++------ src/game_jk2sp.cpp | 10 +++++----- src/game_mohaa.cpp | 10 +++++----- src/game_mohbt.cpp | 10 +++++----- src/game_mohsh.cpp | 10 +++++----- src/game_q2r.cpp | 10 +++++----- src/game_q3a.cpp | 12 ++++++------ src/game_quake2.cpp | 10 +++++----- src/game_rtcwmp.cpp | 12 ++++++------ src/game_rtcwsp.cpp | 14 +++++++------- src/game_sin.cpp | 10 +++++----- src/game_sof2mp.cpp | 15 +++++++-------- src/game_sof2sp.cpp | 10 +++++----- src/game_stef2.cpp | 10 +++++----- src/game_stvoyhm.cpp | 12 ++++++------ src/game_stvoysp.cpp | 10 +++++----- src/game_wet.cpp | 12 ++++++------ 22 files changed, 131 insertions(+), 129 deletions(-) diff --git a/src/game_cod11mp.cpp b/src/game_cod11mp.cpp index 7407d4c..b022891 100644 --- a/src/game_cod11mp.cpp +++ b/src/game_cod11mp.cpp @@ -25,7 +25,7 @@ GEN_GAME_FUNCS(COD11MP); // auto-detection logic for COD11MP (never auto-detect) -static bool COD11MP_AutoDetect(api_supportedgame*, api_engine) { +static bool COD11MP_AutoDetect(api_supportedgame*, APIType) { return false; } @@ -68,7 +68,7 @@ static intptr_t COD11MP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -109,7 +109,7 @@ static intptr_t COD11MP_vmMain(intptr_t cmd, ...) { } -static void* COD11MP_Entry(void* syscall, void*, api_engine) { +static void* COD11MP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("COD11MP_Entry({}) called\n", syscall); // store original syscall from engine @@ -127,8 +127,8 @@ static void* COD11MP_Entry(void* syscall, void*, api_engine) { } -static bool COD11MP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool COD11MP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_codmp.cpp b/src/game_codmp.cpp index adfeace..4b40c22 100644 --- a/src/game_codmp.cpp +++ b/src/game_codmp.cpp @@ -31,8 +31,8 @@ GEN_GAME_FUNCS(CODMP); // auto-detection logic for CODMP -static bool CODMP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool CODMP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -83,7 +83,7 @@ static intptr_t CODMP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -124,7 +124,7 @@ static intptr_t CODMP_vmMain(intptr_t cmd, ...) { } -static void* CODMP_Entry(void* syscall, void*, api_engine) { +static void* CODMP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODMP_Entry({}) called\n", syscall); // store original syscall from engine @@ -142,8 +142,8 @@ static void* CODMP_Entry(void* syscall, void*, api_engine) { } -static bool CODMP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool CODMP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_coduomp.cpp b/src/game_coduomp.cpp index f1cf5cc..a9c9aca 100644 --- a/src/game_coduomp.cpp +++ b/src/game_coduomp.cpp @@ -31,8 +31,8 @@ GEN_GAME_FUNCS(CODUOMP); // auto-detection logic for CODUOMP -static bool CODUOMP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool CODUOMP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -83,7 +83,7 @@ static intptr_t CODUOMP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -124,7 +124,7 @@ static intptr_t CODUOMP_vmMain(intptr_t cmd, ...) { } -static void* CODUOMP_Entry(void* syscall, void*, api_engine) { +static void* CODUOMP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("CODUOMP_Entry({}) called\n", syscall); // store original syscall from engine @@ -142,8 +142,8 @@ static void* CODUOMP_Entry(void* syscall, void*, api_engine) { } -static bool CODUOMP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool CODUOMP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_jamp.cpp b/src/game_jamp.cpp index 2c957ca..218bd35 100644 --- a/src/game_jamp.cpp +++ b/src/game_jamp.cpp @@ -27,8 +27,8 @@ GEN_GAME_FUNCS(JAMP); // auto-detection logic for JAMP -static bool JAMP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY && engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool JAMP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY && engineapi != QMM_API_GETMODULEAPI) return false; // QMM filename must match default or an OpenJK temp filename (if DLL was pulled from .pk3) @@ -461,7 +461,7 @@ static intptr_t JAMP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } } @@ -886,10 +886,10 @@ static intptr_t JAMP_vmMain(intptr_t cmd, ...) { } -static void* JAMP_Entry(void* arg0, void* arg1, api_engine engine) { - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) called\n", arg0, arg1, EngineAPIName(engine)); +static void* JAMP_Entry(void* arg0, void* arg1, APIType engine) { + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) called\n", arg0, arg1, APIType_Name(engine)); - if (engine == QMM_ENGINEAPI_GETGAMEAPI) { + if (engine == QMM_API_GETMODULEAPI) { orig_apiversion = (intptr_t)arg0; // original import struct from engine @@ -905,13 +905,13 @@ static void* JAMP_Entry(void* arg0, void* arg1, api_engine engine) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning {}\n", arg0, arg1, EngineAPIName(engine), (void*)&qmm_export); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning {}\n", arg0, arg1, APIType_Name(engine), (void*)&qmm_export); // struct full of export lambdas to QMM's vmMain // this gets returned to the game engine, but we haven't loaded the mod yet. return &qmm_export; } - else if (engine == QMM_ENGINEAPI_DLLENTRY) { + else if (engine == QMM_API_DLLENTRY) { // store original syscall from engine orig_syscall = (eng_syscall)arg0; @@ -921,7 +921,7 @@ static void* JAMP_Entry(void* arg0, void* arg1, api_engine engine) { // pointer to wrapper syscall function that calls either orig_syscall or func in orig_import g_gameinfo.pfnsyscall = JAMP_syscall; - LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning\n", arg0, arg1, EngineAPIName(engine)); + LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JAMP_Entry({}, {}, {}) returning\n", arg0, arg1, APIType_Name(engine)); return nullptr; } @@ -930,15 +930,18 @@ static void* JAMP_Entry(void* arg0, void* arg1, api_engine engine) { } -static bool JAMP_ModLoad(void* entry, api_engine engine) { - if (engine == QMM_ENGINEAPI_GETGAMEAPI) { +static bool JAMP_ModLoad(void* entry, APIType modapi) { + if (modapi == QMM_API_GETMODULEAPI) { mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; // api version gets passed before import pointer + // if QMM was loaded with dllEntry, then orig_apiversion is 0 so try to get it from SDK + if (orig_syscall || !orig_apiversion) + orig_apiversion = GAME_API_VERSION; orig_export = (game_export_t*)pfnGGA((void*)orig_apiversion, &qmm_import); return !!orig_export; } - else if (engine == QMM_ENGINEAPI_DLLENTRY) { + else if (modapi == QMM_API_DLLENTRY) { orig_vmMain = (mod_vmMain)entry; return !!orig_vmMain; } diff --git a/src/game_jasp.cpp b/src/game_jasp.cpp index 4e30ad5..cda382d 100644 --- a/src/game_jasp.cpp +++ b/src/game_jasp.cpp @@ -29,8 +29,8 @@ GEN_GAME_FUNCS(JASP); // auto-detection logic for JASP -static bool JASP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool JASP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -552,7 +552,7 @@ static intptr_t JASP_vmMain(intptr_t cmd, ...) { } -static void* JASP_Entry(void* import, void*, api_engine) { +static void* JASP_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JASP_Entry({}) called\n", import); // original import struct from engine @@ -578,8 +578,8 @@ static void* JASP_Entry(void* import, void*, api_engine) { } -static bool JASP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool JASP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_jk2mp.cpp b/src/game_jk2mp.cpp index 451612a..844220f 100644 --- a/src/game_jk2mp.cpp +++ b/src/game_jk2mp.cpp @@ -28,8 +28,8 @@ GEN_GAME_FUNCS_QVM(JK2MP); // auto-detection logic for JK2MP -static bool JK2MP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool JK2MP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -80,7 +80,7 @@ static intptr_t JK2MP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -127,7 +127,7 @@ static intptr_t JK2MP_vmMain(intptr_t cmd, ...) { } -static void* JK2MP_Entry(void* syscall, void*, api_engine) { +static void* JK2MP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2MP_Entry({}) called\n", syscall); // store original syscall from engine @@ -145,8 +145,8 @@ static void* JK2MP_Entry(void* syscall, void*, api_engine) { } -static bool JK2MP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool JK2MP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY && modapi != QMM_API_QVM) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_jk2sp.cpp b/src/game_jk2sp.cpp index b93b04e..a9c582a 100644 --- a/src/game_jk2sp.cpp +++ b/src/game_jk2sp.cpp @@ -28,8 +28,8 @@ GEN_GAME_FUNCS(JK2SP); // auto-detection logic for JK2SP -static bool JK2SP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool JK2SP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -473,7 +473,7 @@ static intptr_t JK2SP_vmMain(intptr_t cmd, ...) { } -static void* JK2SP_Entry(void* import, void*, api_engine) { +static void* JK2SP_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("JK2SP_Entry({}) called\n", import); // original import struct from engine @@ -499,8 +499,8 @@ static void* JK2SP_Entry(void* import, void*, api_engine) { } -static bool JK2SP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool JK2SP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_mohaa.cpp b/src/game_mohaa.cpp index 415661f..e60dc27 100644 --- a/src/game_mohaa.cpp +++ b/src/game_mohaa.cpp @@ -33,8 +33,8 @@ GEN_GAME_FUNCS(MOHAA); // auto-detection logic for MOHAA -static bool MOHAA_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHAA_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -743,7 +743,7 @@ static intptr_t MOHAA_vmMain(intptr_t cmd, ...) { } -static void* MOHAA_Entry(void* import, void*, api_engine) { +static void* MOHAA_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHAA_Entry({}) called\n", import); // original import struct from engine @@ -773,8 +773,8 @@ static void* MOHAA_Entry(void* import, void*, api_engine) { } -static bool MOHAA_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHAA_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_mohbt.cpp b/src/game_mohbt.cpp index c2d37c9..a78cbbb 100644 --- a/src/game_mohbt.cpp +++ b/src/game_mohbt.cpp @@ -33,8 +33,8 @@ GEN_GAME_FUNCS(MOHBT); // auto-detection logic for MOHBT -static bool MOHBT_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHBT_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -782,7 +782,7 @@ static intptr_t MOHBT_vmMain(intptr_t cmd, ...) { } -static void* MOHBT_Entry(void* import, void*, api_engine) { +static void* MOHBT_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHBT_Entry({}) called\n", import); // original import struct from engine @@ -812,8 +812,8 @@ static void* MOHBT_Entry(void* import, void*, api_engine) { } -static bool MOHBT_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHBT_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_mohsh.cpp b/src/game_mohsh.cpp index 44139c7..3fdd689 100644 --- a/src/game_mohsh.cpp +++ b/src/game_mohsh.cpp @@ -33,8 +33,8 @@ GEN_GAME_FUNCS(MOHSH); // auto-detection logic for MOHSH -static bool MOHSH_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHSH_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -782,7 +782,7 @@ static intptr_t MOHSH_vmMain(intptr_t cmd, ...) { } -static void* MOHSH_Entry(void* import, void*, api_engine) { +static void* MOHSH_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("MOHSH_Entry({}) called\n", import); // original import struct from engine @@ -812,8 +812,8 @@ static void* MOHSH_Entry(void* import, void*, api_engine) { } -static bool MOHSH_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool MOHSH_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_q2r.cpp b/src/game_q2r.cpp index 8085f1a..1644f74 100644 --- a/src/game_q2r.cpp +++ b/src/game_q2r.cpp @@ -42,8 +42,8 @@ GEN_GAME_FUNCS(Q2R); // auto-detection logic for Q2R -static bool Q2R_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool Q2R_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -598,7 +598,7 @@ static intptr_t Q2R_vmMain(intptr_t cmd, ...) { } -static void* Q2R_Entry(void* import, void*, api_engine) { +static void* Q2R_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q2R_Entry({}) called\n", import); // original import struct from engine @@ -626,8 +626,8 @@ static void* Q2R_Entry(void* import, void*, api_engine) { } -static bool Q2R_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool Q2R_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_q3a.cpp b/src/game_q3a.cpp index c51ff55..11ef35c 100644 --- a/src/game_q3a.cpp +++ b/src/game_q3a.cpp @@ -28,8 +28,8 @@ GEN_GAME_FUNCS_QVM(Q3A); // auto-detection logic for Q3A -static bool Q3A_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool Q3A_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -79,7 +79,7 @@ static intptr_t Q3A_syscall(intptr_t cmd, ...) { break; } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -126,7 +126,7 @@ static intptr_t Q3A_vmMain(intptr_t cmd, ...) { } -static void* Q3A_Entry(void* syscall, void*, api_engine) { +static void* Q3A_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("Q3A_Entry({}) called\n", syscall); // store original syscall from engine @@ -144,8 +144,8 @@ static void* Q3A_Entry(void* syscall, void*, api_engine) { } -static bool Q3A_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool Q3A_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY && modapi != QMM_API_QVM) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_quake2.cpp b/src/game_quake2.cpp index 73bf2b7..be08e57 100644 --- a/src/game_quake2.cpp +++ b/src/game_quake2.cpp @@ -32,8 +32,8 @@ GEN_GAME_FUNCS(QUAKE2); // auto-detection logic for QUAKE2 -static bool QUAKE2_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool QUAKE2_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -517,7 +517,7 @@ static intptr_t QUAKE2_vmMain(intptr_t cmd, ...) { } -static void* QUAKE2_Entry(void* import, void*, api_engine) { +static void* QUAKE2_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("QUAKE2_Entry({}) called\n", import); // original import struct from engine @@ -543,8 +543,8 @@ static void* QUAKE2_Entry(void* import, void*, api_engine) { } -static bool QUAKE2_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool QUAKE2_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_rtcwmp.cpp b/src/game_rtcwmp.cpp index 0b5f198..230b3e9 100644 --- a/src/game_rtcwmp.cpp +++ b/src/game_rtcwmp.cpp @@ -27,8 +27,8 @@ GEN_GAME_FUNCS_QVM(RTCWMP); // auto-detection logic for RTCWMP -static bool RTCWMP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool RTCWMP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -79,7 +79,7 @@ static intptr_t RTCWMP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -120,7 +120,7 @@ static intptr_t RTCWMP_vmMain(intptr_t cmd, ...) { } -static void* RTCWMP_Entry(void* syscall, void*, api_engine) { +static void* RTCWMP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWMP_Entry({}) called\n", syscall); // store original syscall from engine @@ -138,8 +138,8 @@ static void* RTCWMP_Entry(void* syscall, void*, api_engine) { } -static bool RTCWMP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool RTCWMP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY && modapi != QMM_API_QVM) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_rtcwsp.cpp b/src/game_rtcwsp.cpp index f4e95ad..504d212 100644 --- a/src/game_rtcwsp.cpp +++ b/src/game_rtcwsp.cpp @@ -38,13 +38,13 @@ GEN_GAME_FUNCS(RTCWSP); static bool is_iortcw = false; // auto-detection logic for RTCWSP -static bool RTCWSP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool RTCWSP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; const char* official_dllname = "qagame" MOD_DLL; - // check for iortcw name in game->dllname or official engine name + // game->dllname holds the iortcw filenames, but we also need to check for official engine dll name if (!str_striequal(g_gameinfo.qmm_file, game->dllname) && !str_striequal(g_gameinfo.qmm_file, official_dllname)) return false; @@ -119,7 +119,7 @@ static intptr_t RTCWSP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -160,7 +160,7 @@ static intptr_t RTCWSP_vmMain(intptr_t cmd, ...) { } -static void* RTCWSP_Entry(void* syscall, void*, api_engine) { +static void* RTCWSP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("RTCWSP_Entry({}) called\n", syscall); // store original syscall from engine @@ -178,8 +178,8 @@ static void* RTCWSP_Entry(void* syscall, void*, api_engine) { } -static bool RTCWSP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool RTCWSP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_sin.cpp b/src/game_sin.cpp index 0cac304..6a7dd6f 100644 --- a/src/game_sin.cpp +++ b/src/game_sin.cpp @@ -32,8 +32,8 @@ GEN_GAME_FUNCS(SIN); // auto-detection logic for SIN -static bool SIN_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool SIN_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -633,7 +633,7 @@ static intptr_t SIN_vmMain(intptr_t cmd, ...) { } -static void* SIN_Entry(void* import, void*, api_engine) { +static void* SIN_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SIN_Entry({}) called\n", import); // original import struct from engine @@ -660,8 +660,8 @@ static void* SIN_Entry(void* import, void*, api_engine) { } -static bool SIN_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool SIN_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_sof2mp.cpp b/src/game_sof2mp.cpp index f54aa89..f36c114 100644 --- a/src/game_sof2mp.cpp +++ b/src/game_sof2mp.cpp @@ -29,8 +29,8 @@ GEN_GAME_FUNCS_QVM(SOF2MP); // auto-detection logic for SOF2MP -static bool SOF2MP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool SOF2MP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -81,7 +81,7 @@ static intptr_t SOF2MP_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -163,7 +163,7 @@ static intptr_t SOF2MP_vmMain(intptr_t cmd, ...) { } -static void* SOF2MP_Entry(void* syscall, void*, api_engine) { +static void* SOF2MP_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2MP_Entry({}) called\n", syscall); // store original syscall from engine @@ -182,16 +182,15 @@ static void* SOF2MP_Entry(void* syscall, void*, api_engine) { // get mod's vmMain function pointer from mod.cpp::mod_load -static bool SOF2MP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool SOF2MP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY && modapi != QMM_API_QVM) return false; orig_vmMain = (mod_vmMain)entry; // we cannot verify data in the QVM since this engine both provides malloc functionality and has the gametype module, // so some pointers may point into the engine or the gametype module - if (g_mod.vmbase) - g_mod.vm.verify_data = false; + g_mod.vm.verify_data = false; return !!orig_vmMain; } diff --git a/src/game_sof2sp.cpp b/src/game_sof2sp.cpp index 45ecf2f..908f75e 100644 --- a/src/game_sof2sp.cpp +++ b/src/game_sof2sp.cpp @@ -25,8 +25,8 @@ GEN_GAME_FUNCS(SOF2SP); // auto-detection logic for SOF2SP -static bool SOF2SP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool SOF2SP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -442,7 +442,7 @@ static intptr_t SOF2SP_vmMain(intptr_t cmd, ...) { } -static void* SOF2SP_Entry(void* apiversion, void* import, api_engine) { +static void* SOF2SP_Entry(void* apiversion, void* import, APIType) { orig_apiversion = (intptr_t)apiversion; LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("SOF2SP_Entry({}, {}) called\n", orig_apiversion, import); @@ -469,8 +469,8 @@ static void* SOF2SP_Entry(void* apiversion, void* import, api_engine) { } -static bool SOF2SP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool SOF2SP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_stef2.cpp b/src/game_stef2.cpp index cfeff94..2c72628 100644 --- a/src/game_stef2.cpp +++ b/src/game_stef2.cpp @@ -30,8 +30,8 @@ GEN_GAME_FUNCS(STEF2); // auto-detection logic for STEF2 -static bool STEF2_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool STEF2_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -960,7 +960,7 @@ static intptr_t STEF2_vmMain(intptr_t cmd, ...) { } -static void* STEF2_Entry(void* import, void*, api_engine) { +static void* STEF2_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STEF2_Entry({}) called\n", import); // original import struct from engine @@ -987,8 +987,8 @@ static void* STEF2_Entry(void* import, void*, api_engine) { } -static bool STEF2_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool STEF2_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_stvoyhm.cpp b/src/game_stvoyhm.cpp index a2a6b14..da617d4 100644 --- a/src/game_stvoyhm.cpp +++ b/src/game_stvoyhm.cpp @@ -28,8 +28,8 @@ GEN_GAME_FUNCS_QVM(STVOYHM); // auto-detection logic for Q3A -static bool STVOYHM_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool STVOYHM_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -80,7 +80,7 @@ static intptr_t STVOYHM_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -127,7 +127,7 @@ static intptr_t STVOYHM_vmMain(intptr_t cmd, ...) { } -static void* STVOYHM_Entry(void* syscall, void*, api_engine) { +static void* STVOYHM_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYHM_Entry({}) called\n", syscall); // store original syscall from engine @@ -145,8 +145,8 @@ static void* STVOYHM_Entry(void* syscall, void*, api_engine) { } -static bool STVOYHM_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool STVOYHM_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY && modapi != QMM_API_QVM) return false; orig_vmMain = (mod_vmMain)entry; diff --git a/src/game_stvoysp.cpp b/src/game_stvoysp.cpp index df17c45..96ea858 100644 --- a/src/game_stvoysp.cpp +++ b/src/game_stvoysp.cpp @@ -28,8 +28,8 @@ GEN_GAME_FUNCS(STVOYSP); // auto-detection logic for STVOYSP -static bool STVOYSP_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool STVOYSP_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_GETGAMEAPI) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -348,7 +348,7 @@ static intptr_t STVOYSP_vmMain(intptr_t cmd, ...) { } -static void* STVOYSP_Entry(void* import, void*, api_engine) { +static void* STVOYSP_Entry(void* import, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("STVOYSP_Entry({}) called\n", import); // original import struct from engine @@ -374,8 +374,8 @@ static void* STVOYSP_Entry(void* import, void*, api_engine) { } -static bool STVOYSP_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_GETGAMEAPI) +static bool STVOYSP_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_GETGAMEAPI) return false; mod_GetGameAPI pfnGGA = (mod_GetGameAPI)entry; diff --git a/src/game_wet.cpp b/src/game_wet.cpp index e586e0b..cd5c0ee 100644 --- a/src/game_wet.cpp +++ b/src/game_wet.cpp @@ -27,8 +27,8 @@ GEN_GAME_FUNCS(WET); // auto-detection logic for WET -static bool WET_AutoDetect(api_supportedgame* game, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool WET_AutoDetect(api_supportedgame* game, APIType engineapi) { + if (engineapi != QMM_API_DLLENTRY) return false; if (!str_striequal(g_gameinfo.qmm_file, game->dllname)) @@ -79,7 +79,7 @@ static intptr_t WET_syscall(intptr_t cmd, ...) { } default: - // all normal engine functions go to engine + // all normal engine functions go to syscall ret = orig_syscall(cmd, QMM_PUT_SYSCALL_ARGS()); } @@ -120,7 +120,7 @@ static intptr_t WET_vmMain(intptr_t cmd, ...) { } -static void* WET_Entry(void* syscall, void*, api_engine) { +static void* WET_Entry(void* syscall, void*, APIType) { LOG(QMM_LOG_DEBUG, "QMM") << fmt::format("WET_Entry({}) called\n", syscall); // store original syscall from engine @@ -138,8 +138,8 @@ static void* WET_Entry(void* syscall, void*, api_engine) { } -static bool WET_ModLoad(void* entry, api_engine engine) { - if (engine != QMM_ENGINEAPI_DLLENTRY) +static bool WET_ModLoad(void* entry, APIType modapi) { + if (modapi != QMM_API_DLLENTRY) return false; orig_vmMain = (mod_vmMain)entry; From 8fe6d58f0a368bab2325cdda90af8b886f8f0d21 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 01:29:23 +0200 Subject: [PATCH 12/15] update some osdef macros in windows --- include/osdef.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/include/osdef.h b/include/osdef.h index d6dd2c4..f78c487 100644 --- a/include/osdef.h +++ b/include/osdef.h @@ -36,14 +36,13 @@ Created By: #define EXT_DLL "dll" #define EXT_QVM "qvm" - #define PATH_MAX 4096 - #define strcasecmp _stricmp + #define PATH_MAX MAX_PATH #define dlopen(file, x) ((void*)LoadLibrary(file)) - #define dlsym(dll, func) ((void*)GetProcAddress((HMODULE)(dll), (func))) - #define dlclose(dll) FreeLibrary((HMODULE)(dll)) - #define mkdir(path, x) _mkdir(path) - #define osdef_get_milliseconds GetTickCount64 - const char* dlerror(); // this will return the last error from any win32 function, not just library functions + #define dlsym(dll, func) ((void*)GetProcAddress((HMODULE)(dll), (func))) + #define dlclose(dll) FreeLibrary((HMODULE)(dll)) + #define mkdir(path, x) _mkdir(path) + #define osdef_get_milliseconds GetTickCount64 + const char* dlerror(); // this will return the last error from any win32 function, not just library functions #elif defined(QMM_OS_LINUX) @@ -67,7 +66,6 @@ Created By: #define EXT_DLL "so" #define EXT_QVM "qvm" uint64_t osdef_get_milliseconds(); - void MessageBoxA(void* handle, const char* message, const char* title, int flags); #else // !QMM_OS_WINDOWS && !QMM_OS_LINUX From afa7f4ec881cb37c599966a06e1bace85b294e91 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 03:58:19 +0200 Subject: [PATCH 13/15] actually store the engine api in g_gameinfo.api --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index a051e27..ffb8f7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -426,6 +426,8 @@ intptr_t qmm_syscall(intptr_t cmd, ...) { static void* main_handle_entry(void* import, void* extra, APIType engine) { main_detect_env(); + g_gameinfo.api = engine; + log_init(fmt::format("{}/qmm2.log", g_gameinfo.qmm_dir)); LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("QMM v" QMM_VERSION " (" QMM_OS " " QMM_ARCH ") ({}) loaded!\n", APIType_Function(engine)); From 771fd361b7e9fad6e2d1bb56f37b9e9c5d442ed4 Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 03:58:39 +0200 Subject: [PATCH 14/15] update comments --- include/game_api.h | 12 +++--------- src/game_api.cpp | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/game_api.h b/include/game_api.h index c7fc12c..17d0e20 100644 --- a/include/game_api.h +++ b/include/game_api.h @@ -68,19 +68,13 @@ extern std::vector api_supportedgames; // macros to make game support a bit easier to do -// used at the top of game_api.cpp and game_XYZ.cpp -// ====== -// generate extern for each game's functions +// generate extern for each game's functions (used at the top of game_api.cpp and game_XYZ.cpp) #define GEN_GAME_EXTS(game) extern api_supportedgame_funcs game##_funcs; -// used in supportedgames entry in game_api.cpp -// ====== -// generate extern for each game's shortcode and supportedgame_funcs struct (used in game_api.cpp) +// generate extern for each game's shortcode and funcs struct (used in supportedgames entry in game_api.cpp) #define GEN_GAME_INFO(game) #game , &game##_funcs -// used in game_XYZ.cpp -// ====== -// generate struct info for the game-specific functions and arrays +// generate struct info for the game-specific functions and arrays (used in game_XYZ.cpp) // game with QVM support #define GEN_GAME_FUNCS_QVM(game) \ diff --git a/src/game_api.cpp b/src/game_api.cpp index d754419..548015b 100644 --- a/src/game_api.cpp +++ b/src/game_api.cpp @@ -127,17 +127,17 @@ const char* APIType_Name(APIType api) { const char* APIType_Function(APIType api) { switch (api) { - case QMM_API_ERROR: - return "(error)"; - - case QMM_API_QVM: - return "QVM"; - case QMM_API_DLLENTRY: - return "dllEntry"; - case QMM_API_GETGAMEAPI: - return "GetGameAPI"; - case QMM_API_GETMODULEAPI: - return "GetModuleAPI"; + case QMM_API_ERROR: + return "(error)"; + + case QMM_API_QVM: + return "QVM"; + case QMM_API_DLLENTRY: + return "dllEntry"; + case QMM_API_GETGAMEAPI: + return "GetGameAPI"; + case QMM_API_GETMODULEAPI: + return "GetModuleAPI"; default: return "unknown"; }; From bd9eed1208786fc7e468d557b7a1f11e75763e1e Mon Sep 17 00:00:00 2001 From: Kevin Masterson Date: Tue, 10 Mar 2026 04:43:31 +0200 Subject: [PATCH 15/15] add extra checks for missing required game support funcs --- src/main.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ffb8f7f..a7b3a7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -192,6 +192,8 @@ C_DLLEXPORT void dllEntry(void* syscall) { The original import/export tables are stored. When QMM and plugins need to call the mod or engine, g_gameinfo.pfnvmMain or g_gameinfo.pfnsyscall point to game-specific functions which will take the cmd, and route to the proper function pointer in the struct. + + SOF2SP engine passes an apiversion as the first arg, and import is the second arg */ C_DLLEXPORT void* GetGameAPI(void* import, void* extra) { return main_handle_entry(import, extra, QMM_API_GETGAMEAPI); @@ -437,6 +439,7 @@ static void* main_handle_entry(void* import, void* extra, APIType engine) { // ??? // return nullptr to error out now. if GetGameAPI, Init() will never be called + // if dllEntry, will check g_gameinfo.game in vmMain(GAME_INIT) and call G_ERROR if (!import) { LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): engine pointer is NULL!\n", APIType_Function(engine)); return nullptr; @@ -456,14 +459,25 @@ static void* main_handle_entry(void* import, void* extra, APIType engine) { cfg_game = util_get_cmdline_arg("--qmm_game", cfg_game); main_detect_game(cfg_game, engine); - // failed to get engine information, or game does not have an entry handler + // failed to get engine information // if GetGameAPI, returning nullptr to error out now will make sure Init() will never be called. - // if dllEntry, will check g_gameinfo.game in vmMain(GAME_INIT). - if (!g_gameinfo.game || !g_gameinfo.game->funcs->pfnEntry) { + // if dllEntry, will check g_gameinfo.game in vmMain(GAME_INIT) and call G_ERROR + if (!g_gameinfo.game) { LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): Unable to determine game engine using \"{}\"\n", APIType_Function(engine), cfg_game); return nullptr; } + // game support must have an entry function and message arrays+functions + if (!g_gameinfo.game->funcs->pfnEntry + || !g_gameinfo.game->funcs->qmm_eng_msgs + || !g_gameinfo.game->funcs->qmm_mod_msgs + || !g_gameinfo.game->funcs->pfnEngMsgNames + || !g_gameinfo.game->funcs->pfnModMsgNames) + { + LOG(QMM_LOG_FATAL, "QMM") << fmt::format("{}(): Missing required function(s) for game \"{}\"\n", APIType_Function(engine), g_gameinfo.game->gamename_short); + return nullptr; + } + // now that the game is detected, cache some dynamic message values that get evaluated a lot msg_G_PRINT = QMM_ENG_MSG[QMM_G_PRINT]; msg_GAME_INIT = QMM_MOD_MSG[QMM_GAME_INIT]; @@ -471,7 +485,7 @@ static void* main_handle_entry(void* import, void* extra, APIType engine) { msg_GAME_SHUTDOWN = QMM_MOD_MSG[QMM_GAME_SHUTDOWN]; // call the game-specific entry handler (e.g. Q3A_Entry) which will set up the internals to interact - // the engine and the mod + // the engine and the mod return g_gameinfo.game->funcs->pfnEntry(import, extra, engine); }