示例#1
0
文件: vm.cpp 项目: kinkofer/OpenJK
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;
    char		filename[MAX_QPATH];

    if ( !module || !module[0] || !systemCalls ) {
        Com_Error( ERR_FATAL, "VM_Create: bad parms" );
    }

    // 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;

    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->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 = (unsigned char *)VM_Alloc( dataLength );
    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 = (int *)VM_Alloc( vm->instructionPointersLength );

    // 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;

    return vm;
}
示例#2
0
/*
====================
CL_UISystemCalls

The ui module is making a system call
====================
*/
intptr_t CL_UISystemCalls( intptr_t *args ) {
	switch ( args[0] ) {
	case UI_ERROR:
		Com_Error( ERR_DROP, "%s", (const char*)VMA(1) );
		return 0;

	case UI_PRINT:
		Com_Printf( "%s", (const char*)VMA(1) );
		return 0;

	case UI_MILLISECONDS:
		return Sys_Milliseconds();

	case UI_CVAR_REGISTER:
		Cvar_Register( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[4] );
		return 0;

	case UI_CVAR_UPDATE:
		Cvar_Update( VMA( 1 ) );
		return 0;

	case UI_CVAR_SET:
		Cvar_SetSafe( VMA(1), VMA(2) );
		return 0;

	case UI_CVAR_VARIABLEVALUE:
		return FloatAsInt( Cvar_VariableValue( VMA( 1 ) ) );

	case UI_CVAR_VARIABLESTRINGBUFFER:
		Cvar_VariableStringBuffer( VMA( 1 ), VMA( 2 ), args[3] );
		return 0;

	case UI_CVAR_SETVALUE:
		Cvar_SetValueSafe( VMA(1), VMF(2) );
		return 0;

	case UI_CVAR_RESET:
		Cvar_Reset( VMA( 1 ) );
		return 0;

	case UI_CVAR_CREATE:
		Cvar_Register( NULL, VMA(1), VMA(2), args[3] );
		return 0;

	case UI_CVAR_INFOSTRINGBUFFER:
		Cvar_InfoStringBuffer( args[1], VMA( 2 ), args[3] );
		return 0;

	case UI_ARGC:
		return Cmd_Argc();

	case UI_ARGV:
		Cmd_ArgvBuffer( args[1], VMA( 2 ), args[3] );
		return 0;

	case UI_CMD_EXECUTETEXT:
		if(args[1] == EXEC_NOW
		&& (!strncmp(VMA(2), "snd_restart", 11)
		|| !strncmp(VMA(2), "vid_restart", 11)
		|| !strncmp(VMA(2), "quit", 5)))
		{
			Com_Printf (S_COLOR_YELLOW "turning EXEC_NOW '%.11s' into EXEC_INSERT\n", (const char*)VMA(2));
			args[1] = EXEC_INSERT;
		}
		Cbuf_ExecuteText( args[1], VMA( 2 ) );
		return 0;

	case UI_FS_FOPENFILE:
		return FS_FOpenFileByMode( VMA( 1 ), VMA( 2 ), args[3] );

	case UI_FS_READ:
		FS_Read( VMA( 1 ), args[2], args[3] );
		return 0;

//----(SA)	added
	case UI_FS_SEEK:
		FS_Seek( args[1], args[2], args[3] );
		return 0;
//----(SA)	end

	case UI_FS_WRITE:
		FS_Write( VMA( 1 ), args[2], args[3] );
		return 0;

	case UI_FS_FCLOSEFILE:
		FS_FCloseFile( args[1] );
		return 0;

	case UI_FS_DELETEFILE:
		return FS_Delete( VMA( 1 ) );

	case UI_FS_GETFILELIST:
		return FS_GetFileList( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[4] );

	case UI_R_REGISTERMODEL:
		return re.RegisterModel( VMA( 1 ) );

	case UI_R_REGISTERSKIN:
		return re.RegisterSkin( VMA( 1 ) );

	case UI_R_REGISTERSHADERNOMIP:
		return re.RegisterShaderNoMip( VMA( 1 ) );

	case UI_R_CLEARSCENE:
		re.ClearScene();
		return 0;

	case UI_R_ADDREFENTITYTOSCENE:
		re.AddRefEntityToScene( VMA( 1 ) );
		return 0;

	case UI_R_ADDPOLYTOSCENE:
		re.AddPolyToScene( args[1], args[2], VMA( 3 ) );
		return 0;

		// Ridah
	case UI_R_ADDPOLYSTOSCENE:
		re.AddPolysToScene( args[1], args[2], VMA( 3 ), args[4] );
		return 0;
		// done.

	case UI_R_ADDLIGHTTOSCENE:
		re.AddLightToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[6] );
		return 0;

	case UI_R_ADDCORONATOSCENE:
		re.AddCoronaToScene( VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[6], args[7] );
		return 0;

	case UI_R_RENDERSCENE:
		re.RenderScene( VMA( 1 ) );
		return 0;

	case UI_R_SETCOLOR:
		re.SetColor( VMA( 1 ) );
		return 0;

	case UI_R_DRAWSTRETCHPIC:
		re.DrawStretchPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[9] );
		return 0;

	case UI_R_MODELBOUNDS:
		re.ModelBounds( args[1], VMA( 2 ), VMA( 3 ) );
		return 0;

	case UI_UPDATESCREEN:
		SCR_UpdateScreen();
		return 0;

	case UI_CM_LERPTAG:
		return re.LerpTag( VMA( 1 ), VMA( 2 ), VMA( 3 ), args[4] );

	case UI_S_REGISTERSOUND:
#ifdef DOOMSOUND    ///// (SA) DOOMSOUND
		return S_RegisterSound( VMA( 1 ) );
#else
		return S_RegisterSound( VMA( 1 ), qfalse );
#endif  ///// (SA) DOOMSOUND

	case UI_S_STARTLOCALSOUND:
		S_StartLocalSound( args[1], args[2] );
		return 0;

//----(SA)	added
	case UI_S_FADESTREAMINGSOUND:
		S_FadeStreamingSound( VMF( 1 ), args[2], args[3] );
		return 0;

	case UI_S_FADEALLSOUNDS:
		S_FadeAllSounds( VMF( 1 ), args[2] );
		return 0;
//----(SA)	end

	case UI_KEY_KEYNUMTOSTRINGBUF:
		Key_KeynumToStringBuf( args[1], VMA( 2 ), args[3] );
		return 0;

	case UI_KEY_GETBINDINGBUF:
		Key_GetBindingBuf( args[1], VMA( 2 ), args[3] );
		return 0;

	case UI_KEY_SETBINDING:
		Key_SetBinding( args[1], VMA( 2 ) );
		return 0;

	case UI_KEY_ISDOWN:
		return Key_IsDown( args[1] );

	case UI_KEY_GETOVERSTRIKEMODE:
		return Key_GetOverstrikeMode();

	case UI_KEY_SETOVERSTRIKEMODE:
		Key_SetOverstrikeMode( args[1] );
		return 0;

	case UI_KEY_CLEARSTATES:
		Key_ClearStates();
		return 0;

	case UI_KEY_GETCATCHER:
		return Key_GetCatcher();

	case UI_KEY_SETCATCHER:
		// Don't allow the ui module to close the console
		Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) );
		return 0;

	case UI_GETCLIPBOARDDATA:
		CL_GetClipboardData( VMA(1), args[2] );
		return 0;

	case UI_GETCLIENTSTATE:
		GetClientState( VMA( 1 ) );
		return 0;

	case UI_GETGLCONFIG:
		CL_GetGlconfig( VMA( 1 ) );
		return 0;

	case UI_GETCONFIGSTRING:
		return GetConfigString( args[1], VMA( 2 ), args[3] );

	case UI_LAN_LOADCACHEDSERVERS:
		LAN_LoadCachedServers();
		return 0;

	case UI_LAN_SAVECACHEDSERVERS:
		LAN_SaveServersToCache();
		return 0;

	case UI_LAN_ADDSERVER:
		return LAN_AddServer( args[1], VMA( 2 ), VMA( 3 ) );

	case UI_LAN_REMOVESERVER:
		LAN_RemoveServer( args[1], VMA( 2 ) );
		return 0;

	case UI_LAN_GETPINGQUEUECOUNT:
		return LAN_GetPingQueueCount();

	case UI_LAN_CLEARPING:
		LAN_ClearPing( args[1] );
		return 0;

	case UI_LAN_GETPING:
		LAN_GetPing( args[1], VMA( 2 ), args[3], VMA( 4 ) );
		return 0;

	case UI_LAN_GETPINGINFO:
		LAN_GetPingInfo( args[1], VMA( 2 ), args[3] );
		return 0;

	case UI_LAN_GETSERVERCOUNT:
		return LAN_GetServerCount( args[1] );

	case UI_LAN_GETSERVERADDRESSSTRING:
		LAN_GetServerAddressString( args[1], args[2], VMA( 3 ), args[4] );
		return 0;

	case UI_LAN_GETSERVERINFO:
		LAN_GetServerInfo( args[1], args[2], VMA( 3 ), args[4] );
		return 0;

	case UI_LAN_GETSERVERPING:
		return LAN_GetServerPing( args[1], args[2] );

	case UI_LAN_MARKSERVERVISIBLE:
		LAN_MarkServerVisible( args[1], args[2], args[3] );
		return 0;

	case UI_LAN_SERVERISVISIBLE:
		return LAN_ServerIsVisible( args[1], args[2] );

	case UI_LAN_UPDATEVISIBLEPINGS:
		return LAN_UpdateVisiblePings( args[1] );

	case UI_LAN_RESETPINGS:
		LAN_ResetPings( args[1] );
		return 0;

	case UI_LAN_SERVERSTATUS:
		return LAN_GetServerStatus( VMA( 1 ), VMA( 2 ), args[3] );

	case UI_LAN_COMPARESERVERS:
		return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] );

	case UI_MEMORY_REMAINING:
		return Hunk_MemoryRemaining();

	case UI_GET_CDKEY:
		CLUI_GetCDKey( VMA( 1 ), args[2] );
		return 0;

	case UI_SET_CDKEY:
#ifndef STANDALONE
		CLUI_SetCDKey( VMA( 1 ) );
#endif
		return 0;

	case UI_R_REGISTERFONT:
		re.RegisterFont( VMA( 1 ), args[2], VMA( 3 ) );
		return 0;

	case UI_MEMSET:
		Com_Memset( VMA(1), args[2], args[3] );
		return args[1];

	case UI_MEMCPY:
		Com_Memset( VMA(1), args[2], args[3] );
		return args[1];

	case UI_STRNCPY:
		strncpy( VMA(1), VMA(2), args[3] );
		return args[1];

	case UI_SIN:
		return FloatAsInt( sin( VMF( 1 ) ) );

	case UI_COS:
		return FloatAsInt( cos( VMF( 1 ) ) );

	case UI_ATAN2:
		return FloatAsInt( atan2( VMF( 1 ), VMF( 2 ) ) );

	case UI_SQRT:
		return FloatAsInt( sqrt( VMF( 1 ) ) );

	case UI_FLOOR:
		return FloatAsInt( floor( VMF( 1 ) ) );

	case UI_CEIL:
		return FloatAsInt( ceil( VMF( 1 ) ) );

	case UI_PC_ADD_GLOBAL_DEFINE:
		return botlib_export->PC_AddGlobalDefine( VMA( 1 ) );
	case UI_PC_LOAD_SOURCE:
		return botlib_export->PC_LoadSourceHandle( VMA( 1 ) );
	case UI_PC_FREE_SOURCE:
		return botlib_export->PC_FreeSourceHandle( args[1] );
	case UI_PC_READ_TOKEN:
		return botlib_export->PC_ReadTokenHandle( args[1], VMA( 2 ) );
	case UI_PC_SOURCE_FILE_AND_LINE:
		return botlib_export->PC_SourceFileAndLine( args[1], VMA( 2 ), VMA( 3 ) );

	case UI_S_STOPBACKGROUNDTRACK:
		S_StopBackgroundTrack();
		return 0;
	case UI_S_STARTBACKGROUNDTRACK:
//		S_StartBackgroundTrack( VMA( 1 ), VMA( 2 ), args[3] );   //----(SA)	added fadeup time
		S_StartBackgroundTrack( VMA( 1 ), VMA( 2 ) );
		return 0;

	case UI_REAL_TIME:
		return Com_RealTime( VMA( 1 ) );

	case UI_CIN_PLAYCINEMATIC:
		Com_DPrintf( "UI_CIN_PlayCinematic\n" );
		return CIN_PlayCinematic( VMA( 1 ), args[2], args[3], args[4], args[5], args[6] );

	case UI_CIN_STOPCINEMATIC:
		return CIN_StopCinematic( args[1] );

	case UI_CIN_RUNCINEMATIC:
		return CIN_RunCinematic( args[1] );

	case UI_CIN_DRAWCINEMATIC:
		CIN_DrawCinematic( args[1] );
		return 0;

	case UI_CIN_SETEXTENTS:
		CIN_SetExtents( args[1], args[2], args[3], args[4], args[5] );
		return 0;

	case UI_R_REMAP_SHADER:
		re.RemapShader( VMA( 1 ), VMA( 2 ), VMA( 3 ) );
		return 0;

	case UI_VERIFY_CDKEY:
		return CL_CDKeyValidate( VMA( 1 ), VMA( 2 ) );

		// NERVE - SMF
	case UI_CL_GETLIMBOSTRING:
		return CL_GetLimboString( args[1], VMA( 2 ) );
		// -NERVE - SMF

	// New in IORTCW
	case UI_ALLOC:
		return VM_Alloc( args[1] );

	default:
		Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] );

	}

	return 0;
}
示例#3
0
文件: vm.cpp 项目: kinkofer/OpenJK
/*
===============
VM_LoadSymbols
===============
*/
void VM_LoadSymbols( vm_t *vm ) {
    int		len;
    char	*mapfile, *token;
    const	char *text_p;
    char	name[MAX_QPATH];
    char	symbols[MAX_QPATH];
    vmSymbol_t	**prev, *sym;
    int		count;
    int		value;
    int		chars;
    int		segment;
    int		numInstructions;

    // don't load symbols if not developer
    if ( !com_developer->integer ) {
        return;
    }

    COM_StripExtension( vm->name, name, sizeof( name ) );
    Com_sprintf( symbols, sizeof( symbols ), "vm/%s.map", name );
    len = FS_ReadFile( symbols, (void **)&mapfile );
    if ( !mapfile ) {
        Com_Printf( "Couldn't load symbol file: %s\n", symbols );
        return;
    }

    numInstructions = vm->instructionPointersLength >> 2;

    // parse the symbols
    text_p = mapfile;
    prev = &vm->symbols;
    count = 0;

#ifdef CRAZY_SYMBOL_MAP
    VM_SetSymbolMap(vm);
#endif

    while ( 1 ) {
        token = COM_Parse( &text_p );
        if ( !token[0] ) {
            break;
        }
        segment = ParseHex( token );
        if ( segment ) {
            COM_Parse( &text_p );
            COM_Parse( &text_p );
            continue;		// only load code segment values
        }

        token = COM_Parse( &text_p );
        if ( !token[0] ) {
            Com_Printf( "WARNING: incomplete line at end of file\n" );
            break;
        }
        value = ParseHex( token );

        token = COM_Parse( &text_p );
        if ( !token[0] ) {
            Com_Printf( "WARNING: incomplete line at end of file\n" );
            break;
        }
        chars = strlen( token );
        sym = (struct vmSymbol_s *)VM_Alloc( sizeof( *sym ) + chars );
        *prev = sym;
        prev = &sym->next;
        sym->next = NULL;

        // convert value from an instruction number to a code offset
        if ( value >= 0 && value < numInstructions ) {
            value = vm->instructionPointers[value];
        }

        sym->symValue = value;
        Q_strncpyz( sym->symName, token, chars + 1 );

#ifdef CRAZY_SYMBOL_MAP
        (*g_symbolMap)[value] = sym;
#endif

        count++;
    }

    vm->numSymbols = count;
    Com_Printf( "%i symbols parsed from %s\n", count, symbols );
    FS_FreeFile( mapfile );
}
示例#4
0
/*
=======================================================================================================================================
CL_CgameSystemCalls

The cgame module is making a system call.
=======================================================================================================================================
*/
intptr_t CL_CgameSystemCalls(intptr_t *args) {
	switch (args[0]) {
	case CG_PRINT:
		Com_Printf("%s", (const char *)VMA(1));
		return 0;
	case CG_ERROR:
		Com_Error(ERR_DROP, "%s", (const char *)VMA(1));
		return 0;
	case CG_MILLISECONDS:
		return Sys_Milliseconds();
	case CG_CVAR_REGISTER:
		Cvar_Register(VMA(1), VMA(2), VMA(3), args[4]);
		return 0;
	case CG_CVAR_UPDATE:
		Cvar_Update(VMA(1));
		return 0;
	case CG_CVAR_SET:
		Cvar_SetSafe(VMA(1), VMA(2));
		return 0;
	case CG_CVAR_VARIABLESTRINGBUFFER:
		Cvar_VariableStringBuffer(VMA(1), VMA(2), args[3]);
		return 0;
	case CG_ARGC:
		return Cmd_Argc();
	case CG_ARGV:
		Cmd_ArgvBuffer(args[1], VMA(2), args[3]);
		return 0;
	case CG_ARGS:
		Cmd_ArgsBuffer(VMA(1), args[2]);
		return 0;
	case CG_FS_FOPENFILE:
		return FS_FOpenFileByMode(VMA(1), VMA(2), args[3]);
	case CG_FS_READ:
		FS_Read(VMA(1), args[2], args[3]);
		return 0;
	case CG_FS_WRITE:
		return FS_Write(VMA(1), args[2], args[3]);
	case CG_FS_FCLOSEFILE:
		FS_FCloseFile(args[1]);
		return 0;
	case CG_SENDCONSOLECOMMAND:
		Cbuf_AddText(VMA(1));
		return 0;
	case CG_ADDCOMMAND:
		CL_AddCgameCommand(VMA(1));
		return 0;
	case CG_REMOVECOMMAND:
		Cmd_RemoveCommandSafe(VMA(1));
		return 0;
	case CG_SENDCLIENTCOMMAND:
		CL_AddReliableCommand(VMA(1), qfalse);
		return 0;
	case CG_UPDATESCREEN:
		// this is used during lengthy level loading, so pump message loop
// 		Com_EventLoop();	// FIXME: if a server restarts here, BAD THINGS HAPPEN!
// We can't call Com_EventLoop here, a restart will crash and this _does_ happen
// if there is a map change while we are downloading at pk3.
// ZOID
		SCR_UpdateScreen();
		return 0;
	case CG_CM_LOADMAP:
		CL_CM_LoadMap(VMA(1));
		return 0;
	case CG_CM_NUMINLINEMODELS:
		return CM_NumInlineModels();
	case CG_CM_INLINEMODEL:
		return CM_InlineModel(args[1]);
	case CG_CM_TEMPBOXMODEL:
		return CM_TempBoxModel(VMA(1), VMA(2), qfalse);
	case CG_CM_TEMPCAPSULEMODEL:
		return CM_TempBoxModel(VMA(1), VMA(2), qtrue);
	case CG_CM_POINTCONTENTS:
		return CM_PointContents(VMA(1), args[2]);
	case CG_CM_TRANSFORMEDPOINTCONTENTS:
		return CM_TransformedPointContents(VMA(1), args[2], VMA(3), VMA(4));
	case CG_CM_BOXTRACE:
		CM_BoxTrace(VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse);
		return 0;
	case CG_CM_TRANSFORMEDBOXTRACE:
		CM_TransformedBoxTrace(VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qfalse);
		return 0;
	case CG_CM_CAPSULETRACE:
		CM_BoxTrace(VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue);
		return 0;
	case CG_CM_TRANSFORMEDCAPSULETRACE:
		CM_TransformedBoxTrace(VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qtrue);
		return 0;
	case CG_CM_MARKFRAGMENTS:
		return re.MarkFragments(args[1], VMA(2), VMA(3), args[4], VMA(5), args[6], VMA(7));
	case CG_S_STARTSOUND:
		S_StartSound(VMA(1), args[2], args[3], args[4]);
		return 0;

	case CG_S_STARTSOUNDEX:
		S_StartSoundEx(VMA(1), args[2], args[3], args[4], args[5]);
		return 0;
// end
	case CG_S_STARTLOCALSOUND:
		S_StartLocalSound(args[1], args[2]);
		return 0;
	case CG_S_CLEARLOOPINGSOUNDS:
		S_ClearLoopingSounds(args[1]); // (SA) modified so no_pvs sounds can function
		// if killall, then stop all sounds
// 		if (args[1] == 1) {
// 			S_ClearSounds(qtrue, qfalse);
// 		} else if (args[1] == 2) {
// 			S_ClearSounds(qtrue, qtrue);
// 		}

		return 0;
	case CG_S_ADDLOOPINGSOUND:
		// FIXME MrE: handling of looping sounds changed
		S_AddLoopingSound(args[1], VMA(2), VMA(3), args[4], args[5], args[6]);
		return 0;
// not in use
// 	case CG_S_ADDREALLOOPINGSOUND:
// 		S_AddLoopingSound(args[1], VMA(2), VMA(3), args[4], args[5], args[6]);
// 		// S_AddRealLoopingSound(args[1], VMA(2), VMA(3), args[4], args[5]);
// 		return 0;

	case CG_S_STOPSTREAMINGSOUND:
		S_StopEntStreamingSound(args[1]);
		return 0;
	case CG_S_STOPLOOPINGSOUND:
		// not functional anymore, since we reverted to old looping code
		// S_StopLoopingSound(args[1]);
		return 0;
	case CG_S_UPDATEENTITYPOSITION:
		S_UpdateEntityPosition(args[1], VMA(2));
		return 0;
// talking animations
	case CG_S_GETVOICEAMPLITUDE:
		return S_GetVoiceAmplitude(args[1]);
// done.
	case CG_S_RESPATIALIZE:
		S_Respatialize(args[1], VMA(2), VMA(3), args[4]);
		return 0;
	case CG_S_REGISTERSOUND:
#ifdef DOOMSOUND   // / // (SA) DOOMSOUND
		return S_RegisterSound(VMA(1));
#else
		return S_RegisterSound(VMA(1), qfalse);
#endif // / // (SA) DOOMSOUND
	case CG_S_STARTBACKGROUNDTRACK:
// 		S_StartBackgroundTrack(VMA(1), VMA(2), args[3]); // added fadeup time
		S_StartBackgroundTrack(VMA(1), VMA(2));
		return 0;
	case CG_S_FADESTREAMINGSOUND:
		S_FadeStreamingSound(VMF(1), args[2], args[3]); // added music / all - streaming options
		return 0;
	case CG_S_STARTSTREAMINGSOUND:
		S_StartStreamingSound(VMA(1), VMA(2), args[3], args[4], args[5]);
		return 0;
	case CG_S_FADEALLSOUNDS:
		S_FadeAllSounds(VMF(1), args[2]);  
		return 0;
	case CG_R_LOADWORLDMAP:
		re.LoadWorld(VMA(1));
		return 0;
	case CG_R_REGISTERMODEL:
		return re.RegisterModel(VMA(1));
	case CG_R_REGISTERSKIN:
		return re.RegisterSkin(VMA(1));
		
	case CG_R_GETSKINMODEL:
		return re.GetSkinModel(args[1], VMA(2), VMA(3));
	case CG_R_GETMODELSHADER:
		return re.GetShaderFromModel(args[1], args[2], args[3]);
			case CG_R_REGISTERSHADER:
		return re.RegisterShader(VMA(1));
	case CG_R_REGISTERFONT:
		re.RegisterFont(VMA(1), args[2], VMA(3));
		return 0;
	case CG_R_REGISTERSHADERNOMIP:
		return re.RegisterShaderNoMip(VMA(1));
	case CG_R_CLEARSCENE:
		re.ClearScene();
		return 0;
	case CG_R_ADDREFENTITYTOSCENE:
		re.AddRefEntityToScene(VMA(1));
		return 0;
	case CG_R_ADDPOLYTOSCENE:
		re.AddPolyToScene(args[1], args[2], VMA(3));
		return 0;
		// Ridah
	case CG_R_ADDPOLYSTOSCENE:
		re.AddPolysToScene(args[1], args[2], VMA(3), args[4]);
		return 0;
	case CG_RB_ZOMBIEFXADDNEWHIT:
		re.ZombieFXAddNewHit(args[1], VMA(2), VMA(3));
		return 0;
		// done.
// 	case CG_R_LIGHTFORPOINT:
// 		return re.LightForPoint(VMA(1), VMA(2), VMA(3), VMA(4));
	case CG_R_ADDLIGHTTOSCENE:
		re.AddLightToScene(VMA(1), VMF(2), VMF(3), VMF(4), VMF(5), args[6]);
		return 0;
// 	case CG_R_ADDADDITIVELIGHTTOSCENE:
// 		re.AddAdditiveLightToScene(VMA(1), VMF(2), VMF(3), VMF(4), VMF(5));
// 		return 0;
	case CG_R_ADDCORONATOSCENE:
		re.AddCoronaToScene(VMA(1), VMF(2), VMF(3), VMF(4), VMF(5), args[6], args[7]);
		return 0;
	case CG_R_SETFOG:
		re.SetFog(args[1], args[2], args[3], VMF(4), VMF(5), VMF(6), VMF(7));
		return 0;
	case CG_R_RENDERSCENE:
		re.RenderScene(VMA(1));
		return 0;
	case CG_R_SETCOLOR:
		re.SetColor(VMA(1));
		return 0;
	case CG_R_DRAWSTRETCHPIC:
		re.DrawStretchPic(VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9]);
		return 0;
	case CG_R_DRAWSTRETCHPIC_GRADIENT:
		re.DrawStretchPicGradient(VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9], VMA(10), args[11]);
		return 0;
	case CG_R_MODELBOUNDS:
		re.ModelBounds(args[1], VMA(2), VMA(3));
		return 0;
	case CG_R_LERPTAG:
		return re.LerpTag(VMA(1), VMA(2), VMA(3), args[4]);
	case CG_GETGLCONFIG:
		CL_GetGlconfig(VMA(1));
		return 0;
	case CG_GETGAMESTATE:
		CL_GetGameState(VMA(1));
		return 0;
	case CG_GETCURRENTSNAPSHOTNUMBER:
		CL_GetCurrentSnapshotNumber(VMA(1), VMA(2));
		return 0;
	case CG_GETSNAPSHOT:
		return CL_GetSnapshot(args[1], VMA(2));
	case CG_GETSERVERCOMMAND:
		return CL_GetServerCommand(args[1]);
	case CG_GETCURRENTCMDNUMBER:
		return CL_GetCurrentCmdNumber();
	case CG_GETUSERCMD:
		return CL_GetUserCmd(args[1], VMA(2));
	case CG_SETUSERCMDVALUE:
		CL_SetUserCmdValue(args[1], args[2], VMF(3), args[4]);   // modified	// added fourth arg [cld]
		return 0;
	case CG_MEMORY_REMAINING:
		return Hunk_MemoryRemaining();
	case CG_KEY_ISDOWN:
		return Key_IsDown(args[1]);
	case CG_KEY_GETCATCHER:
		return Key_GetCatcher();
	case CG_KEY_SETCATCHER:
		// Don't allow the cgame module to close the console
		Key_SetCatcher(args[1]|(Key_GetCatcher() & KEYCATCH_CONSOLE));
		return 0;
	case CG_KEY_GETKEY:
		return Key_GetKey(VMA(1));



	case CG_MEMSET:
		Com_Memset(VMA(1), args[2], args[3]);
		return args[1];
	case CG_MEMCPY:
		Com_Memcpy(VMA(1), VMA(2), args[3]);
		return args[1];
	case CG_STRNCPY:
		strncpy(VMA(1), VMA(2), args[3]);
		return args[1];
	case CG_SIN:
		return FloatAsInt(sin(VMF(1)));
	case CG_COS:
		return FloatAsInt(cos(VMF(1)));
	case CG_ATAN2:
		return FloatAsInt(atan2(VMF(1), VMF(2)));
	case CG_SQRT:
		return FloatAsInt(sqrt(VMF(1)));
	case CG_FLOOR:
		return FloatAsInt(floor(VMF(1)));
	case CG_CEIL:
		return FloatAsInt(ceil(VMF(1)));
	case CG_ACOS:
		return FloatAsInt(Q_acos(VMF(1)));
	case CG_PC_ADD_GLOBAL_DEFINE:
		return botlib_export->PC_AddGlobalDefine(VMA(1));
	case CG_PC_LOAD_SOURCE:
		return botlib_export->PC_LoadSourceHandle(VMA(1));
	case CG_PC_FREE_SOURCE:
		return botlib_export->PC_FreeSourceHandle(args[1]);
	case CG_PC_READ_TOKEN:
		return botlib_export->PC_ReadTokenHandle(args[1], VMA(2));
	case CG_PC_SOURCE_FILE_AND_LINE:
		return botlib_export->PC_SourceFileAndLine(args[1], VMA(2), VMA(3));
	case CG_S_STOPBACKGROUNDTRACK:
		S_StopBackgroundTrack();
		return 0;
	case CG_REAL_TIME:
		return Com_RealTime(VMA(1));
	case CG_SNAPVECTOR:
		Q_SnapVector(VMA(1));
		return 0;
	case CG_SENDMOVESPEEDSTOGAME:
		SV_SendMoveSpeedsToGame(args[1], VMA(2));
		return 0;
	case CG_CIN_PLAYCINEMATIC:
		return CIN_PlayCinematic(VMA(1), args[2], args[3], args[4], args[5], args[6]);
	case CG_CIN_STOPCINEMATIC:
		return CIN_StopCinematic(args[1]);
	case CG_CIN_RUNCINEMATIC:
		return CIN_RunCinematic(args[1]);
	case CG_CIN_DRAWCINEMATIC:
		CIN_DrawCinematic(args[1]);
		return 0;
	case CG_CIN_SETEXTENTS:
		CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
		return 0;
	case CG_R_REMAP_SHADER:
		re.RemapShader(VMA(1), VMA(2), VMA(3));
		return 0;
	case CG_TESTPRINTINT:
// 		Com_Printf("%s%i\n", (const char *)VMA(1), args[2]);
		return 0;
	case CG_TESTPRINTFLOAT:
// 		Com_Printf("%s%f\n", (const char *)VMA(1), VMF(2));
		return 0;
	case CG_LOADCAMERA:
		return loadCamera(args[1], VMA(2));
	case CG_STARTCAMERA:
		if (args[1] == 0) { // CAM_PRIMARY
			cl.cameraMode = qtrue; 
		}

		startCamera(args[1], args[2]);
		return 0;

	case CG_STOPCAMERA:
		if (args[1] == 0) { // CAM_PRIMARY
			cl.cameraMode = qfalse;
		}
// 		stopCamera(args[1]);
		return 0;
	case CG_GETCAMERAINFO:
		return getCameraInfo(args[1], args[2], VMA(3), VMA(4), VMA(5));
	case CG_GET_ENTITY_TOKEN:
		return re.GetEntityToken(VMA(1), args[2]);
	case CG_INGAME_POPUP:
		if (VMA(1) && !Q_stricmp(VMA(1), "briefing")) { // ---- (SA) added
			VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_BRIEFING);
			return 0;
		}

		if (clc.state == CA_ACTIVE && !clc.demoplaying) {
			// NERVE - SMF
			if (VMA(1) && !Q_stricmp(VMA(1), "UIMENU_WM_PICKTEAM")) {
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_PICKTEAM);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "UIMENU_WM_PICKPLAYER")) {
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_PICKPLAYER);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "UIMENU_WM_QUICKMESSAGE")) {
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_QUICKMESSAGE);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "UIMENU_WM_LIMBO")) {
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_WM_LIMBO);
			}
			// - NERVE - SMF
			else if (VMA(1) && !Q_stricmp(VMA(1), "hbook1")) { // ---- (SA)
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK1);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "hbook2")) { // ---- (SA)
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK2);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "hbook3")) { // ---- (SA)
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_BOOK3);
			} else if (VMA(1) && !Q_stricmp(VMA(1), "pregame")) { // ---- (SA) added
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_PREGAME);
			} else {
				VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_CLIPBOARD);
			}
		}

		return 0;
		// NERVE - SMF
	case CG_INGAME_CLOSEPOPUP:
		VM_Call(uivm, UI_KEY_EVENT, K_ESCAPE, qtrue);
		return 0;
	case CG_LIMBOCHAT:
		if (VMA(1)) {
			CL_AddToLimboChat(VMA(1));
		}

		return 0;
		// - NERVE - SMF

	case CG_GETMODELINFO:
		return SV_GetModelInfo(args[1], VMA(2), VMA(3));
	// New in IORTCW
	case CG_ALLOC:
		return VM_Alloc(args[1]);
	default:
		assert(0);
		Com_Error(ERR_DROP, "Bad cgame system trap: %ld", (long int)args[0]);
	}

	return 0;
}