/* ============== VM_Clear ============== */ void VM_Clear(void) { int i; for (i=0;i<MAX_VM; i++) { VM_Free(&vmTable[i]); } }
vm_t *VM_Create( vmSlots_t vmSlot ) { vm_t *vm = NULL; // see if we already have the VM if ( vmTable[vmSlot] ) return vmTable[vmSlot]; // find a free vm vmTable[vmSlot] = (vm_t *)Z_Malloc( sizeof( *vm ), TAG_VM, qtrue ); vm = vmTable[vmSlot]; // initialise it vm->slot = vmSlot; Q_strncpyz( vm->name, vmNames[vmSlot], sizeof( vm->name ) ); // find the module api FS_FindPureDLL( vm->name ); Com_Printf( "VM_Create: %s"ARCH_STRING DLL_EXT, vm->name ); vm->dllHandle = Sys_LoadGameDll( vm->name, &vm->GetModuleAPI ); if ( vm->dllHandle ) { if ( com_developer->integer ) Com_Printf( " succeeded [0x%X+0x%X]\n", vm->dllHandle, (intptr_t)vm->GetModuleAPI - (intptr_t)vm->dllHandle ); else Com_Printf( " succeeded\n" ); return vm; } VM_Free( vm ); Com_Printf( " failed!\n" ); return NULL; }
/* ==================== CL_InitUI ==================== */ void CL_InitUI( void ) { int v; uivm = VM_Create( "ui", CL_UISystemCalls, VMI_NATIVE ); if ( !uivm ) { Com_Error( ERR_FATAL, "VM_Create on UI failed" ); } // sanity check v = VM_Call( uivm, UI_GETAPIVERSION ); if ( v != UI_API_VERSION ) { // Free uivm now, so UI_SHUTDOWN doesn't get called later. VM_Free( uivm ); uivm = NULL; Com_Error( ERR_FATAL, "User Interface is version %d, expected %d", v, UI_API_VERSION ); } // init for this gamestate VM_Call( uivm, UI_INIT, ( cls.state >= CA_CONNECTING && cls.state < CA_ACTIVE ) ); }
void VM_Clear( void ) { for ( int i=0; i<MAX_VM; i++ ) VM_Free( vmTable[i] ); currentVM = NULL; lastVM = NULL; }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { vm_t saved; memcpy( &saved, vm, sizeof( saved ) ); VM_Free( vm ); return VM_Create( saved.slot ); }
void CLT3_ShutdownCGame() { in_keyCatchers &= ~KEYCATCH_CGAME; cls.q3_cgameStarted = false; if ( !cgvm ) { return; } VM_Call( cgvm, CG_SHUTDOWN ); VM_Free( cgvm ); cgvm = NULL; }
/* ==================== CL_ShutdonwCGame ==================== */ void CL_ShutdownCGame( void ) { cls.keyCatchers &= ~KEYCATCH_CGAME; cls.cgameStarted = qfalse; if ( !cgvm ) { return; } VM_Call( cgvm, CG_SHUTDOWN ); VM_Free( cgvm ); cgvm = NULL; }
/* ==================== CL_ShutdownUI ==================== */ void CL_ShutdownUI( void ) { Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_UI ); cls.uiStarted = qfalse; if ( !uivm ) { return; } VM_Call( uivm, UI_SHUTDOWN ); VM_Free( uivm ); uivm = NULL; }
/* ==================== CL_ShutdownUI ==================== */ void CL_ShutdownUI( void ) { cls.keyCatchers &= ~KEYCATCH_UI; cls.uiStarted = qfalse; if ( !uivm ) { return; } VM_Call( uivm, UI_SHUTDOWN ); VM_Free( uivm ); uivm = NULL; }
/* ==================== CL_ShutdonwCGame ==================== */ void CL_ShutdownCGame( void ) { Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME ); cls.cgameStarted = qfalse; if ( !cgvm ) { return; } VM_Call( cgvm, CG_SHUTDOWN ); VM_Free( cgvm ); cgvm = NULL; }
// Reload the data, but leave everything else in place // This allows a server to do a map_restart without changing memory allocation vm_t *VM_Restart( vm_t *vm ) { const vm_t saved = *vm; VM_Free( vm ); if ( saved.isLegacy ) return VM_CreateLegacy( saved.slot, saved.legacy.syscall ); else return VM_Create( saved.slot ); }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { vm_t saved; memcpy( &saved, vm, sizeof( saved ) ); VM_Free( vm ); if ( saved.isLegacy ) return VM_CreateLegacy( saved.slot, saved.legacy.syscall ); else return VM_Create( saved.slot ); }
void CL_InitCGameCVars( void ) { vm_t *cgv_vm = VM_Create( "cgame", CL_CgameSystemCalls, Cvar_VariableValue( "vm_cgame" ) ); if ( !cgv_vm ) { Com_Error( ERR_DROP, "VM_Create on cgame failed" ); } VM_Call( cgv_vm, CG_INIT_CVARS ); VM_Free( cgv_vm ); }
/* =============== SV_ShutdownGameProgs Called every time a map changes =============== */ void SV_ShutdownGameProgs(void) { if(!gvm) { return; } VM_Call(gvm, GAME_SHUTDOWN, false); VM_Free(gvm); gvm = NULL; if ( sv_newGameShlib->string[0] ) { FS_Rename( sv_newGameShlib->string, "game" DLL_EXT); Cvar_Set( "sv_newGameShlib", "" ); } }
/* ==================== CL_ShutdownUI ==================== */ void CL_ShutdownUI( void ) { Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_UI ); cls.uiStarted = qfalse; if ( !uivm ) { return; } VM_Call( uivm, UI_SHUTDOWN ); VM_Free( uivm ); uivm = NULL; #if EMSCRIPTEN cls.uiGlConfig = NULL; cls.numUiPatches = 0; #endif }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { // DLL's can't be restarted in place char name[MAX_QPATH]; vmInterpret_t interpret; intptr_t(*systemCall) (intptr_t * parms); systemCall = vm->systemCall; Q_strncpyz(name, vm->name, sizeof(name)); interpret = vm->interpret; VM_Free(vm); vm = VM_Create(name, systemCall, interpret); return vm; }
void CL_InitUI(void) { int v; vmInterpret_t interpret; // load the dll or bytecode interpret = Cvar_VariableValue("vm_ui"); if (cl_connectedToPureServer) { // if sv_pure is set we only allow qvms to be loaded if (interpret != VMI_COMPILED && interpret != VMI_BYTECODE) interpret = VMI_COMPILED; } uivm = VM_Create("ui", CL_UISystemCalls, interpret); if (!uivm) { Com_Error(ERR_FATAL, "VM_Create on UI failed"); } // sanity check v = VM_Call(uivm, UI_GETAPIVERSION); if (v == UI_OLD_API_VERSION) { // Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v ); // init for this gamestate VM_Call(uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE)); } else if (v != UI_API_VERSION) { // Free uivm now, so UI_SHUTDOWN doesn't get called later. VM_Free(uivm); uivm = NULL; Com_Error(ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION); cls.uiStarted = qfalse; } else { // init for this gamestate VM_Call(uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE)); } }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { // DLL's can't be restarted in place if ( vm->dllHandle ) { char name[MAX_QPATH]; intptr_t ( *systemCall )( intptr_t *parms ); systemCall = vm->systemCall; Q_strncpyz( name, vm->name, sizeof( name ) ); VM_Free( vm ); vm = VM_Create( name, systemCall, VMI_NATIVE ); return vm; } return NULL; }
/* ==================== CL_ShutdownUI ==================== */ void CL_ShutdownUI( qboolean delayFreeVM ) { Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_UI ); cls.uiStarted = qfalse; if ( !uivm ) { return; } VM_Call( uivm, UI_SHUTDOWN ); VM_Call( uivm, UI_MENU_RESET ); if ( delayFreeVM ) { VM_DelayedFree (uivm); } else { VM_Free( uivm ); } uivm = NULL; }
vm_t *VM_CreateLegacy( vmSlots_t vmSlot, intptr_t( *systemCalls )(intptr_t *) ) { vm_t *vm = NULL; if ( !systemCalls ) { Com_Error( ERR_FATAL, "VM_CreateLegacy: bad parms" ); return NULL; } // see if we already have the VM if ( vmTable[vmSlot] ) return vmTable[vmSlot]; // find a free vm vmTable[vmSlot] = (vm_t *)Z_Malloc( sizeof(*vm), TAG_VM, qtrue ); vm = vmTable[vmSlot]; // initialise it vm->isLegacy = qtrue; vm->slot = vmSlot; Q_strncpyz( vm->name, vmNames[vmSlot], sizeof(vm->name) ); vm->legacy.syscall = systemCalls; // find the legacy syscall api FS_FindPureDLL( vm->name ); vm->dllHandle = Sys_LoadLegacyGameDll( vm->name, &vm->legacy.main, VM_DllSyscall ); Com_Printf( "VM_CreateLegacy: %s" ARCH_STRING DLL_EXT, vm->name ); if ( vm->dllHandle ) { if ( com_developer->integer ) Com_Printf( " succeeded [0x%" PRIxPTR "]\n", (uintptr_t)vm->dllHandle ); else Com_Printf( " succeeded\n" ); return vm; } VM_Free( vm ); Com_Printf( " failed!\n" ); return NULL; }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { int length; int dataLength; int i; char filename[MAX_QPATH]; // DLL's can't be restarted in place if ( vm->dllHandle ) { char name[MAX_QPATH]; int (*systemCall)( int *parms ); systemCall = vm->systemCall; Q_strncpyz( name, vm->name, sizeof( name ) ); VM_Free( vm ); vm = VM_Create( name, systemCall ); return vm; } Com_Error( ERR_FATAL, "Unable to load %s.", vm->name ); }
vm_t *VM_Create( const char *module, int (*systemCalls)(int *), vmInterpret_t interpret ) { vm_t *vm; vmHeader_t *header; int length; int dataLength; int i, remaining; char filename[MAX_QPATH]; if ( !module || !module[0] || !systemCalls ) { Com_Error( ERR_FATAL, "VM_Create: bad parms" ); } remaining = Hunk_MemoryRemaining(); // see if we already have the VM for ( i = 0 ; i < MAX_VM ; i++ ) { if (!Q_stricmp(vmTable[i].name, module)) { vm = &vmTable[i]; return vm; } } // find a free vm for ( i = 0 ; i < MAX_VM ; i++ ) { if ( !vmTable[i].name[0] ) { break; } } if ( i == MAX_VM ) { Com_Error( ERR_FATAL, "VM_Create: no free vm_t" ); } vm = &vmTable[i]; Q_strncpyz( vm->name, module, sizeof( vm->name ) ); vm->systemCall = systemCalls; // never allow dll loading with a demo if ( interpret == VMI_NATIVE ) { if ( Cvar_VariableValue( "fs_restrict" ) ) { interpret = VMI_COMPILED; } } if ( interpret == VMI_NATIVE ) { // try to load as a system dll Com_Printf( "Loading dll file %s.\n", vm->name ); vm->dllHandle = Sys_LoadDll( module, vm->fqpath , &vm->entryPoint, VM_DllSyscall ); if ( vm->dllHandle ) { return vm; } Com_Printf( "Failed to load dll, looking for qvm.\n" ); interpret = VMI_COMPILED; } // load the image Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); Com_Printf( "Loading vm file %s.\n", filename ); length = FS_ReadFile( filename, (void **)&header ); if ( !header ) { Com_Printf( "Failed.\n" ); VM_Free( vm ); return NULL; } // byte swap the header for ( i = 0 ; i < sizeof( *header ) / 4 ; i++ ) { ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } // validate if ( header->vmMagic != VM_MAGIC || header->bssLength < 0 || header->dataLength < 0 || header->litLength < 0 || header->codeLength <= 0 ) { VM_Free( vm ); Com_Error( ERR_FATAL, "%s has bad header", filename ); } // round up to next power of 2 so all data operations can // be mask protected dataLength = header->dataLength + header->litLength + header->bssLength; for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) { } dataLength = 1 << i; // allocate zero filled space for initialized and uninitialized data vm->dataBase = Hunk_Alloc( dataLength, h_high ); vm->dataMask = dataLength - 1; // copy the intialized data Com_Memcpy( vm->dataBase, (byte *)header + header->dataOffset, header->dataLength + header->litLength ); // byte swap the longs for ( i = 0 ; i < header->dataLength ; i += 4 ) { *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } // allocate space for the jump targets, which will be filled in by the compile/prep functions vm->instructionPointersLength = header->instructionCount * 4; vm->instructionPointers = Hunk_Alloc( vm->instructionPointersLength, h_high ); // copy or compile the instructions vm->codeLength = header->codeLength; if ( interpret >= VMI_COMPILED ) { vm->compiled = qtrue; VM_Compile( vm, header ); } else { vm->compiled = qfalse; VM_PrepareInterpreter( vm, header ); } // free the original file FS_FreeFile( header ); // load the map file VM_LoadSymbols( vm ); // the stack is implicitly at the end of the image vm->programStack = vm->dataMask + 1; vm->stackBottom = vm->programStack - STACK_SIZE; Com_Printf("%s loaded in %d bytes on the hunk\n", module, remaining - Hunk_MemoryRemaining()); return vm; }
/* ================= VM_Restart Reload the data, but leave everything else in place This allows a server to do a map_restart without changing memory allocation ================= */ vm_t *VM_Restart( vm_t *vm ) { vmHeader_t *header; int length; int dataLength; int i; char filename[MAX_QPATH]; // DLL's can't be restarted in place if ( vm->dllHandle ) { char name[MAX_QPATH]; int (*systemCall)( int *parms ); systemCall = vm->systemCall; Q_strncpyz( name, vm->name, sizeof( name ) ); VM_Free( vm ); vm = VM_Create( name, systemCall, VMI_NATIVE ); return vm; } // load the image Com_Printf( "VM_Restart()\n", filename ); Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); Com_Printf( "Loading vm file %s.\n", filename ); length = FS_ReadFile( filename, (void **)&header ); if ( !header ) { Com_Error( ERR_DROP, "VM_Restart failed.\n" ); } // byte swap the header for ( i = 0 ; i < sizeof( *header ) / 4 ; i++ ) { ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } // validate if ( header->vmMagic != VM_MAGIC || header->bssLength < 0 || header->dataLength < 0 || header->litLength < 0 || header->codeLength <= 0 ) { VM_Free( vm ); Com_Error( ERR_FATAL, "%s has bad header", filename ); } // round up to next power of 2 so all data operations can // be mask protected dataLength = header->dataLength + header->litLength + header->bssLength; for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) { } dataLength = 1 << i; // clear the data Com_Memset( vm->dataBase, 0, dataLength ); // copy the intialized data Com_Memcpy( vm->dataBase, (byte *)header + header->dataOffset, header->dataLength + header->litLength ); // byte swap the longs for ( i = 0 ; i < header->dataLength ; i += 4 ) { *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } // free the original file FS_FreeFile( header ); return vm; }
/* ================= VM_LoadQVM Load a .qvm file ================= */ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc, qboolean unpure) { int dataLength; int i; char filename[MAX_QPATH]; union { vmHeader_t *h; void *v; } header; // load the image Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); Com_Printf( "Loading vm file %s...\n", filename ); FS_ReadFileDir(filename, vm->searchPath, unpure, &header.v); if ( !header.h ) { Com_Printf( "Failed.\n" ); VM_Free( vm ); Com_Printf(S_COLOR_YELLOW "Warning: Couldn't open VM file %s\n", filename); return NULL; } // show where the qvm was loaded from FS_Which(filename, vm->searchPath); if( LittleLong( header.h->vmMagic ) == VM_MAGIC_VER2 ) { Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" ); // byte swap the header for ( i = 0 ; i < sizeof( vmHeader_t ) / 4 ; i++ ) { ((int *)header.h)[i] = LittleLong( ((int *)header.h)[i] ); } // validate if ( header.h->jtrgLength < 0 || header.h->bssLength < 0 || header.h->dataLength < 0 || header.h->litLength < 0 || header.h->codeLength <= 0 ) { VM_Free(vm); FS_FreeFile(header.v); Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename); return NULL; } } else if( LittleLong( header.h->vmMagic ) == VM_MAGIC ) { // byte swap the header // sizeof( vmHeader_t ) - sizeof( int ) is the 1.32b vm header size for ( i = 0 ; i < ( sizeof( vmHeader_t ) - sizeof( int ) ) / 4 ; i++ ) { ((int *)header.h)[i] = LittleLong( ((int *)header.h)[i] ); } // validate if ( header.h->bssLength < 0 || header.h->dataLength < 0 || header.h->litLength < 0 || header.h->codeLength <= 0 ) { VM_Free(vm); FS_FreeFile(header.v); Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename); return NULL; } } else { VM_Free( vm ); FS_FreeFile(header.v); Com_Printf(S_COLOR_YELLOW "Warning: %s does not have a recognisable " "magic number in its header\n", filename); return NULL; } // round up to next power of 2 so all data operations can // be mask protected dataLength = header.h->dataLength + header.h->litLength + header.h->bssLength; for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) { } dataLength = 1 << i; if(alloc) { // allocate zero filled space for initialized and uninitialized data vm->dataBase = Hunk_Alloc(dataLength, h_high); vm->dataMask = dataLength - 1; } else { // clear the data, but make sure we're not clearing more than allocated if(vm->dataMask + 1 != dataLength) { VM_Free(vm); FS_FreeFile(header.v); Com_Printf(S_COLOR_YELLOW "Warning: Data region size of %s not matching after " "VM_Restart()\n", filename); return NULL; } Com_Memset(vm->dataBase, 0, dataLength); } // copy the intialized data Com_Memcpy( vm->dataBase, (byte *)header.h + header.h->dataOffset, header.h->dataLength + header.h->litLength ); // byte swap the longs for ( i = 0 ; i < header.h->dataLength ; i += 4 ) { *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } if(header.h->vmMagic == VM_MAGIC_VER2) { int previousNumJumpTableTargets = vm->numJumpTableTargets; header.h->jtrgLength &= ~0x03; vm->numJumpTableTargets = header.h->jtrgLength >> 2; Com_Printf("Loading %d jump table targets\n", vm->numJumpTableTargets); if(alloc) { vm->jumpTableTargets = Hunk_Alloc(header.h->jtrgLength, h_high); } else { if(vm->numJumpTableTargets != previousNumJumpTableTargets) { VM_Free(vm); FS_FreeFile(header.v); Com_Printf(S_COLOR_YELLOW "Warning: Jump table size of %s not matching after " "VM_Restart()\n", filename); return NULL; } Com_Memset(vm->jumpTableTargets, 0, header.h->jtrgLength); } Com_Memcpy(vm->jumpTableTargets, (byte *) header.h + header.h->dataOffset + header.h->dataLength + header.h->litLength, header.h->jtrgLength); // byte swap the longs for ( i = 0 ; i < header.h->jtrgLength ; i += 4 ) { *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) ); } }
/* ================= VM_LoadQVM Load a .qvm file ================= */ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) { int length; int dataLength; int i; char filename[MAX_QPATH]; vmHeader_t *header; // load the image Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name ); Com_Printf( "Loading vm file %s...\n", filename ); length = FS_ReadFile( filename, (void **)&header ); if ( !header ) { Com_Printf( "Failed.\n" ); VM_Free( vm ); return NULL; } if( LittleLong( header->vmMagic ) == VM_MAGIC_VER2 ) { Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" ); // byte swap the header for ( i = 0 ; i < sizeof( vmHeader_t ) / 4 ; i++ ) { ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } // validate if ( header->jtrgLength < 0 || header->bssLength < 0 || header->dataLength < 0 || header->litLength < 0 || header->codeLength <= 0 ) { VM_Free( vm ); Com_Error( ERR_FATAL, "%s has bad header", filename ); } } else if( LittleLong( header->vmMagic ) == VM_MAGIC ) { // byte swap the header // sizeof( vmHeader_t ) - sizeof( int ) is the 1.32b vm header size for ( i = 0 ; i < ( sizeof( vmHeader_t ) - sizeof( int ) ) / 4 ; i++ ) { ((int *)header)[i] = LittleLong( ((int *)header)[i] ); } // validate if ( header->bssLength < 0 || header->dataLength < 0 || header->litLength < 0 || header->codeLength <= 0 ) { VM_Free( vm ); Com_Error( ERR_FATAL, "%s has bad header", filename ); } } else { VM_Free( vm ); Com_Error( ERR_FATAL, "%s does not have a recognisable " "magic number in its header", filename ); } // round up to next power of 2 so all data operations can // be mask protected dataLength = header->dataLength + header->litLength + header->bssLength; for ( i = 0 ; dataLength > ( 1 << i ) ; i++ ) { } dataLength = 1 << i; if( alloc ) { // allocate zero filled space for initialized and uninitialized data vm->dataBase = Hunk_Alloc( dataLength, h_high ); vm->dataMask = dataLength - 1; } else { // clear the data Com_Memset( vm->dataBase, 0, dataLength ); } // copy the intialized data Com_Memcpy( vm->dataBase, (byte *)header + header->dataOffset, header->dataLength + header->litLength ); // byte swap the longs for ( i = 0 ; i < header->dataLength ; i += 4 ) { *(int *)(vm->dataBase + i) = LittleLong( *(int *)(vm->dataBase + i ) ); } if( header->vmMagic == VM_MAGIC_VER2 ) { vm->numJumpTableTargets = header->jtrgLength >> 2; Com_Printf( "Loading %d jump table targets\n", vm->numJumpTableTargets ); if( alloc ) { vm->jumpTableTargets = Hunk_Alloc( header->jtrgLength, h_high ); } else { Com_Memset( vm->jumpTableTargets, 0, header->jtrgLength ); } Com_Memcpy( vm->jumpTableTargets, (byte *)header + header->dataOffset + header->dataLength + header->litLength, header->jtrgLength ); // byte swap the longs for ( i = 0 ; i < header->jtrgLength ; i += 4 ) { *(int *)(vm->jumpTableTargets + i) = LittleLong( *(int *)(vm->jumpTableTargets + i ) ); } }
void CL_UnbindUI( void ) { UIVM_Shutdown(); VM_Free( uivm ); uivm = NULL; }
void CL_UnbindCGame( void ) { CGVM_Shutdown(); VM_Free( cgvm ); cgvm = NULL; }