-
Notifications
You must be signed in to change notification settings - Fork 2
Adding game support
Kevin Masterson edited this page Feb 26, 2026
·
5 revisions
Each game that QMM supports (this document will use the placeholder short-code "XYZ") gets a src/game_XYZ.cpp file and a include/game_XYZ.h file. These are the only files in QMM that will include XYZ's SDK, and nothing else in QMM (only plugins) should include game_XYZ.h.
The game_XYZ.h file should define any engine (e.g. G_PRINT) and mod (e.g. GAME_INIT) constants (if they are not defined by the SDK, in particular those that QMM uses for GetGameAPI games), including any additional ones handled by QMM as polyfills.
The game_XYZ.cpp file should define the following:
-
All games:
-
GEN_EXTS(XYZ);
This macro forward declares all the below functions/variables. -
GEN_QMM_MSGS(XYZ);
This macro defines internal arrays used by QMM to find the correct values for engine/mod messages that it uses directly. -
void intptr_t XYZ_syscall(intptr_t cmd, ...)
This is called by QMM and by plugins in order to pass calls to the engine. This is where polyfills are handled if needed. This should directly call into the engine. -
void intptr_t XYZ_vmMain(intptr_t cmd, ...)
This is called by QMM and by plugins in order to pass calls to the mod. This is where polyfills are handled if needed. This should directly call into the mod. -
bool XYZ_mod_load(void* entry)
This is called just after a mod DLL is loaded.entryis a pointer to either the mod'svmMainfunction orGetGameAPIfunction, depending on the type. This allows you to store the realvmMainpointer or real game export table returned fromGetGameAPIto pass calls to the mod inXYZ_vmMain. -
void XYZ_mod_unload()
This is called just before a mod DLL is unloaded. This allows you to clear the stored pointer fromXYZ_mod_loadto safely check before calling into an unloaded mod. -
const char* XYZ_eng_msg_names(intptr_t cmd)
This is called with an engine message constant (e.g.G_PRINT) and you should return the string form of it. The GEN_CASE macro is useful in this function. -
const char* XYZ_mod_msg_names(intptr_t cmd)
This is called with a mod message constsant (e.g.GAME_INIT) and you should return the string form of it. The GEN_CASE macro is useful in this function.
-
-
vmMain games only:
-
void XYZ_dllEntry(eng_syscall_t syscall)
This is called by QMM'sdllEntryonce the game was determined. This allows you to store the real engine syscall pointer to pass calls to it inXYZ_syscall. - QVM-supporting games only:
int XYZ_vmsyscall(uint8_t* membase, int cmd, int* args)
This is called byqvm_execwhenever the QVM calls an engine syscall/trap. All pointer arguments that get read by the engine (and QMM+plugins) need to be converted to real pointers, which is simply adding themembaseargument. TheVMARGandVMPTRmacros are useful in this function.
-
-
GetGameAPI games only:
-
void* XYZ_GetGameAPI(void* import, void*)
This is called by QMM'sGetGameAPIonce the game was determined. This allows you to store the real engine import table to pass calls to it inXYZ_syscall. Some games (e.g.SOF2SP) pass two parameters to this function, so you have access to both if needed.
-
You also need to add some lines in game_api.cpp:
-
GEN_EXTS(XYZ);
This macro forward declares all the above functions/variables for use in theg_supportedgamestable. -
g_supportedgamesentry:- mod filename
The base name of the mod file to load - e.g."jk2mpgamex86.dll"(you can use theMOD_DLLmacro to automatically generate the proper suffix - e.g."x86.dll") - QVM mod filename
The filename of the the .qvm file to load - e.g."vm/jk2mpgame.qvm"(leave null if this game has no QVM support) - default moddir
The mod directory for the default mod - e.g."base"(use"."for the base game directory, for single-player games) - full gamename
The full name of the game, e.g."Jedi Knight 2: Jedi Outcast (MP)" - exe hints
This is a list of unique strings that appear in the game or server binary/.exe filename that can be used to differentiate it from another game that uses the same mod filename, e.g.{ "jk2" } - msgs/short name
This is a series of entries that are all based on theXYZshort-code. Use theGEN_INFOmacro for this, e.g.GEN_INFO(JK2MP) - entry procs
This is a series of function pointers forXYZ_vmsyscall,XYZ_dllEntry,XYZ_GetGameAPI,XYZ_mod_load, andXYZ_mod_unload(null where not applicable). Use theGEN_DLL(vmMain, no QVM support),GEN_DLLQVM(vmMain, QVM support), andGEN_GGA(GetGameAPI) macros for this, e.g.GET_DLLQVM(JK2MP) - # syscall args
The largest amount of arguments that a syscall/import call uses. This is not used, but merely a reference to know when it may be necessary to increase theQMM_MAX_SYSCALL_ARGSconstant. - # vmMain args
The largest amount of arguments that a vmMain/export call uses. This is not used, but merely a reference to know when it may be necessary to increase theQMM_MAX_VMMAIN_ARGSconstant.
- mod filename
These should all be put into a single line like so:
{ "jk2mpgame" MOD_DLL, "vm/jk2mpgame.qvm", "base", "Jedi Knight 2: Jedi Outcast (MP)", { "jk2" }, GEN_INFO(JK2MP), GEN_DLLQVM(JK2MP), 13, 3 },