The original jka release used native binaries, but the vanilla jamp and jampded engine binaries were still capable of loading QVM mods and both, the 2003 SDK and the 2013 release of the code could be used to compile QVMs for jampgame, cgame and ui. It is unknown whether anyone tried to make use of that before 2013, but there seems to be no publicly known mods that made use of QVMs, thus OpenJK removed support for QVMs early on. However, the interest in QVM mods has increased over time for better mod-compatibility accross different platforms and there is currently at least one server running jampded with a QVM based mod. For those reasons this pull request readds QVM support by porting the QVM code from jk2mv (which ported parts of it from ioq3) and adjusting the module APIs to support QVMs.
Issues when using QVMs on vanilla jamp/jampded
The string pointers written into the glconfig_t instances inside of cgame and ui would point to engine memory, making them invalid
The notetrack callback for the roff system would pass a pointer to engine memory into the module, making it invalid (this issue already existed in jk2, but vanilla jk2 modules didn't properly support roff, leading to a very low chance of anyone actually having encountered the bug on there)
A few of the NAV VM_Calls would pass vec3_t (pointer to float) into the game module, possibly affecting NPC pathfinding
Pull Request
QVM related changes
Ports vm_arm.cpp, vm_interpreted.cpp, vm_local.h and vm_x86.c from mvdevs/jk2mv (which in turn got some of its code from ioq3 and multiple contributors)
Ports various QVM related functions from mvdevs/jk2mv
Reintroduces the cvars vm_game, vm_cgame and vm_ui
Reintroduces the commands vminfo and vmprofile
Maps G2 pointers to integer handles for the module APIs when using QVMs, because the types within the QVM are 32 bit, making 64 bit pointers incompatible
Replaces sharedEntity_t in the engine with sharedEntityMapper_t. As the QVM types are 32 bit the sharedEntity_t struct doesn't match when running the engine as 64 bit build. To work around this the engine stores the correct addresses for the members of sharedEntity_t in sharedEntityMapper_t when the game module passes the shared entities into SV_LocateGameData.
Solves the vanilla jamp/jampded issues by allocating additional memory for the QVM on load. This additional memory is used to write data into and then pass a pointer to that data into the module, which is valid, because it's within the datamask for the module.
Replaces the exceptions in qcommon.cpp with longjmp, because throwing exceptions within a VM_Call was unreliable
Other changes
Fixes undefined behavior in SV_ClipMoveToEntities, which becmae obvious when replacing sharedEntity_t with sharedEntityMapper_t
The vm_legacy cvar is no longer limited to _DEBUG builds to make potenital API tests with users easier, because it doesn't require extra builds
Adds com_dedicatedForceErrorsToFatal cvar to be able to disable the ERR_DROP to ERR_FATAL rewrite for Com_Error calls on dedicated servers
Blocks additional file extensions for write attempts from VMs (dll, exe, bat, cmd, dylib, so, qvm, pk3).
Resolves filenames for the extension check to cover symlinks and potential bypasses of the checks
Blocks a few characters in filenames specified by VMs (<>:"|?*)
Prologue
The original jka release used native binaries, but the vanilla jamp and jampded engine binaries were still capable of loading QVM mods and both, the 2003 SDK and the 2013 release of the code could be used to compile QVMs for
jampgame
,cgame
andui
. It is unknown whether anyone tried to make use of that before 2013, but there seems to be no publicly known mods that made use of QVMs, thus OpenJK removed support for QVMs early on. However, the interest in QVM mods has increased over time for better mod-compatibility accross different platforms and there is currently at least one server running jampded with a QVM based mod. For those reasons this pull request readds QVM support by porting the QVM code from jk2mv (which ported parts of it from ioq3) and adjusting the module APIs to support QVMs.Issues when using QVMs on vanilla jamp/jampded
glconfig_t
instances inside ofcgame
andui
would point to engine memory, making them invalidvec3_t
(pointer to float) into the game module, possibly affecting NPC pathfindingPull Request
QVM related changes
vm_arm.cpp
,vm_interpreted.cpp
,vm_local.h
andvm_x86.c
from mvdevs/jk2mv (which in turn got some of its code from ioq3 and multiple contributors)vm_game
,vm_cgame
andvm_ui
vminfo
andvmprofile
sharedEntity_t
in the engine withsharedEntityMapper_t
. As the QVM types are 32 bit thesharedEntity_t
struct doesn't match when running the engine as 64 bit build. To work around this the engine stores the correct addresses for the members ofsharedEntity_t
insharedEntityMapper_t
when the game module passes the shared entities intoSV_LocateGameData
.qcommon.cpp
withlongjmp
, because throwing exceptions within a VM_Call was unreliableOther changes
SV_ClipMoveToEntities
, which becmae obvious when replacingsharedEntity_t
withsharedEntityMapper_t
vm_legacy
cvar is no longer limited to_DEBUG
builds to make potenital API tests with users easier, because it doesn't require extra buildscom_dedicatedForceErrorsToFatal
cvar to be able to disable theERR_DROP
toERR_FATAL
rewrite for Com_Error calls on dedicated serversdll
,exe
,bat
,cmd
,dylib
,so
,qvm
,pk3
).<>:"|?*
)