Пример #1
0
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;
}
Пример #2
0
vm_t *VM_Create(const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret)
{
	vm_t *vm;
	int  i;

	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
		vm->dllHandle = Sys_LoadGameDll(module, &vm->entryPoint, VM_DllSyscall);

		// never try qvm
		if (vm->dllHandle)
		{
			return vm;
		}
		return NULL;
	}

#if 0
	// 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;
#else
	return NULL;
#endif
}