示例#1
0
int SkModelCooker::Compile(int flags) {
	// Make sure these get updated
	CompareVersion(flags);
	CompareModifiedTime(flags);
	CompareCachedFileTimeKey(flags, "Mesh.Source.File");

	const String *s = asset->entry->KeyValue<String>("AnimSet.Source", flags);
	if (!s || s->empty)
		return SR_MetaError;

	// CompileSkmData needs the ska info, so load it.

	Asset::Ref skaRef = engine->sys->packages->Resolve(s->c_str, asset->zone);
	if (!skaRef)
		return SR_FileNotFound;

	int r = skaRef->Process(
		xtime::TimeSlice::Infinite,
		flags|P_Parse|P_TargetDefault
	);

	if (r != SR_Success)
		return r;

	SkAnimSetParser *ska = SkAnimSetParser::Cast(skaRef);
	if (!ska || !ska->valid)
		return SR_ParseError;

	// AnimSet import index
	AddImport(s->c_str);

	s = asset->entry->KeyValue<String>("AnimStates.Source", flags);
	if (!s)
		return SR_MetaError;

	// AnimStates import index
	AddImport(s->c_str);

	// Load 3DX Mesh file
	s = asset->entry->KeyValue<String>("Mesh.Source.File", flags);
	if (!s)
		return SR_MetaError;

	file::MMFileInputBuffer::Ref ib = engine->sys->files->OpenInputBuffer(s->c_str, ZTools);
	if (!ib)
		return SR_FileNotFound;
	
	stream::InputStream is (*ib);

	tools::SceneFile mesh;
	if (!tools::LoadSceneFile(is, mesh, true))
		return SR_ParseError;

	ib.reset();

	if (mesh.worldspawn->models.size() != 1) {
		COut(C_Error) << "ERROR: 3DX file should only contain 1 model, it contains " << mesh.worldspawn->models.size() << ". File: '" << *s << "'" << std::endl;
		return SR_ParseError;
	}

	tools::SkmData::Ref skmd = tools::CompileSkmData(
		asset->name,
		mesh,
		0,
		ska::kSkinType_CPU,
		*ska->dska.get()
	);

	if (!skmd) {
		COut(C_Error) << "ERROR: " << asset->name.get() << " does not contain a skeletal animated mesh." << std::endl;
		return SR_CompilerError;
	}

	String path(CStr(asset->path));
	String path2(path);
	path2 += ".0.bin";

	// File 0 (discardable after load)
	{
		BinFile::Ref skmFile = OpenWrite(path2.c_str);
		if (!skmFile)
			return SR_IOError;

		stream::OutputStream skmOut(skmFile->ob);
		if (skmOut.Write(skmd->skmData[0], (stream::SPos)skmd->skmSize[0], 0) != (stream::SPos)skmd->skmSize[0])
			return SR_IOError;
	}

	path2 = path;
	path2 += ".1.bin";

	// File 1 (persisted)
	{
		BinFile::Ref skmFile = OpenWrite(path2.c_str);
		if (!skmFile)
			return SR_IOError;

		stream::OutputStream skmOut(skmFile->ob);
		if (skmOut.Write(skmd->skmData[1], (stream::SPos)skmd->skmSize[1], 0) != (stream::SPos)skmd->skmSize[1])
			return SR_IOError;
	}

	// add material imports

	for (ska::DSkMesh::Vec::const_iterator it = skmd->dskm.meshes.begin(); it != skmd->dskm.meshes.end(); ++it) {
		AddImport((*it).material);
	}

	return SR_Success;
}
示例#2
0
static void ProcessLibOrObj( char *name, objproc obj, void (*process)( arch_header *arch, libfile io ) )
{
    libfile     io;
    unsigned char   buff[ AR_IDENT_LEN ];
    arch_header arch;

    NewArchHeader( &arch, name );
    io = LibOpen( name, LIBOPEN_READ );
    if( LibRead( io, buff, sizeof( buff ) ) != sizeof( buff ) ) {
        FatalError( ERR_CANT_READ, name, strerror( errno ) );
    }
    if( memcmp( buff, AR_IDENT, sizeof( buff ) ) == 0 ) {
        // AR format
        AddInputLib( io, name );
        LibWalk( io, name, process );
        if( Options.libtype == WL_LTYPE_NONE ) {
            Options.libtype = WL_LTYPE_AR;
        }
    } else if( memcmp( buff, LIBMAG, LIBMAG_LEN ) == 0 ) {
        // MLIB format
        if( LibRead( io, buff, sizeof( buff ) ) != sizeof( buff ) ) {
            FatalError( ERR_CANT_READ, name, strerror( errno ) );
        }
        if( memcmp( buff, LIB_CLASS_DATA_SHOULDBE, LIB_CLASS_LEN + LIB_DATA_LEN ) ) {
            BadLibrary( name );
        }
        AddInputLib( io, name );
        LibWalk( io, name, process );
        if( Options.libtype == WL_LTYPE_NONE ) {
            Options.libtype = WL_LTYPE_MLIB;
        }
    } else if( AddImport( &arch, io ) ) {
        LibClose( io );
    } else if( buff[ 0 ] == LIB_HEADER_REC && buff[ 1 ] != 0x01 ) {
        /*
          The buff[ 1 ] != 1 bit above is a bad hack to get around
          the fact that the coff cpu_type for PPC object files is
          0x1f0.  Really, we should be reading in the first object
          record and doing the checksum and seeing if it is actually
          a LIB_HEADER_REC.  All file format designers who are too
          stupid to recognize the need for a signature should be
          beaten up with large blunt objects.
         */
        // OMF format
        AddInputLib( io, name );
        LibSeek( io, 0, SEEK_SET );
        if( Options.libtype == WL_LTYPE_NONE ) {
            Options.libtype = WL_LTYPE_OMF;
        }
        OMFLibWalk( io, name, process );
    } else if( obj == OBJ_PROCESS ) {
        // Object
        LibSeek( io, 0, SEEK_SET );
        AddObjectSymbols( &arch, io, 0 );
        LibClose( io );
    } else if( obj == OBJ_ERROR ) {
        BadLibrary( name );
    } else {
        LibClose( io );
    }
}
示例#3
0
static void BuildDepTree32or64 (LOADED_IMAGE *img, BuildTreeConfig* cfg, struct DepTreeElement *root, struct DepTreeElement *self, soff_entry *soffs, int soffs_len)
{
  IMAGE_DATA_DIRECTORY *idata;
  IMAGE_IMPORT_DESCRIPTOR *iid;
  IMAGE_EXPORT_DIRECTORY *ied;
  IMAGE_DELAYLOAD_DESCRIPTOR *idd;
  void *ith, *oith;
  void *opt_header = &img->FileHeader->OptionalHeader;
  DWORD i, j;

  idata = opt_header_get_dd_entry (opt_header, IMAGE_DIRECTORY_ENTRY_EXPORT, cfg);
  if (idata->Size > 0 && idata->VirtualAddress != 0)
  {
    int export_section = -2;
    ied = (IMAGE_EXPORT_DIRECTORY *) MapPointer (soffs, soffs_len, idata->VirtualAddress, &export_section);
    if (ied && ied->Name != 0)
    {
      char *export_module = MapPointer (soffs, soffs_len, ied->Name, NULL);
      if (export_module != NULL)
      {
        if (self->export_module == NULL)
          self->export_module = strdup (export_module);
      }
    }
    if (ied && ied->NumberOfFunctions > 0)
    {
      DWORD *addrs, *names;
      WORD *ords;
      int section = -1;
      self->exports_len = ied->NumberOfFunctions;
      self->exports = (struct ExportTableItem *) malloc (sizeof (struct ExportTableItem) * self->exports_len);
      memset (self->exports, 0, sizeof (struct ExportTableItem) * self->exports_len);
      addrs = (DWORD *) MapPointer (soffs, soffs_len, ied->AddressOfFunctions, NULL);
      ords = (WORD *) MapPointer (soffs, soffs_len, ied->AddressOfNameOrdinals, NULL);
      names = (DWORD *) MapPointer (soffs, soffs_len, ied->AddressOfNames, NULL);
      for (i = 0; i < ied->NumberOfNames; i++)
      {
        self->exports[ords[i]].ordinal = ords[i] + ied->Base;
        if (names[i] != 0)
        {
          char *s_name = (char *) MapPointer (soffs, soffs_len, names[i], NULL);
          if (s_name != NULL)
            self->exports[ords[i]].name = strdup (s_name);
        }
      }
      for (i = 0; i < ied->NumberOfFunctions; i++)
      {
        if (addrs[i] != 0)
        {
          int section_index = FindSectionByRawData (img, addrs[i]);
          if ((idata->VirtualAddress <= addrs[i]) && (idata->VirtualAddress + idata->Size > addrs[i]))
          {
            self->exports[i].address = NULL;
            self->exports[i].forward_str = strdup ((char *) MapPointer (soffs, soffs_len, addrs[i], NULL));
          }
          else
            self->exports[i].address = MapPointer (soffs, soffs_len, addrs[i], &section);
          self->exports[i].ordinal = i + ied->Base;
          self->exports[i].section_index = section_index;
          self->exports[i].address_offset = addrs[i];
        }
      }
    }
  }

  idata = opt_header_get_dd_entry (opt_header, IMAGE_DIRECTORY_ENTRY_IMPORT, cfg);
  if (idata->Size > 0 && idata->VirtualAddress != 0)
  {
    iid = (IMAGE_IMPORT_DESCRIPTOR *) MapPointer (soffs, soffs_len,
        idata->VirtualAddress, NULL);
    if (iid)
      for (i = 0; iid[i].Characteristics || iid[i].TimeDateStamp ||
          iid[i].ForwarderChain || iid[i].Name || iid[i].FirstThunk; i++)
      {
        struct DepTreeElement *dll;
        uint64_t impaddress;
        dll = ProcessDep (cfg, soffs, soffs_len, iid[i].Name, root, self, 0);
        if (dll == NULL)
          continue;
        ith = (void *) MapPointer (soffs, soffs_len, iid[i].FirstThunk, NULL);
        oith = (void *) MapPointer (soffs, soffs_len, iid[i].OriginalFirstThunk, NULL);
        for (j = 0; (impaddress = thunk_data_u1_function (ith, j, cfg)) != 0; j++)
        {
          struct ImportTableItem *imp = AddImport (self);
          imp->dll = dll;
          imp->ordinal = -1;
          if (oith);
            imp->orig_address = thunk_data_u1_function (oith, j, cfg);
          if (cfg->on_self)
          {
            imp->address = impaddress;
          }
          if (oith && imp->orig_address & (1 << (sizeof (DWORD) * 8 - 1)))
          {
            imp->ordinal = imp->orig_address & ~(1 << (sizeof (DWORD) * 8 - 1));
          }
          else if (oith)
          {
            IMAGE_IMPORT_BY_NAME *byname = (IMAGE_IMPORT_BY_NAME *) MapPointer (soffs, soffs_len, imp->orig_address, NULL);
            if (byname != NULL)
              imp->name = strdup ((char *) byname->Name);
          }
        }
      }
  }

  idata = opt_header_get_dd_entry (opt_header, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, cfg);
  if (idata->Size > 0 && idata->VirtualAddress != 0)
  {
    idd = (IMAGE_DELAYLOAD_DESCRIPTOR *) MapPointer (soffs, soffs_len, idata->VirtualAddress, NULL);
    if (idd)
      for (i = 0; idd[i].Attributes.AllAttributes || idd[i].DllNameRVA ||
          idd[i].ModuleHandleRVA || idd[i].ImportAddressTableRVA || idd[i].ImportNameTableRVA ||
          idd[i].BoundImportAddressTableRVA || idd[i].UnloadInformationTableRVA ||
          idd[i].TimeDateStamp; i++)
      {
        struct DepTreeElement *dll;
        uint64_t impaddress;
        dll = ProcessDep (cfg, soffs, soffs_len, idd[i].DllNameRVA, root, self, 0);
        if (dll == NULL)
          continue;
        if (idd[i].Attributes.AllAttributes & 0x00000001)
        {
          ith = (void *) MapPointer (soffs, soffs_len, idd[i].ImportAddressTableRVA, NULL);
          oith = (void *) MapPointer (soffs, soffs_len, idd[i].ImportNameTableRVA, NULL);
        }
        else
        {
          ith = (void *) idd[i].ImportAddressTableRVA;
          oith = (void *) idd[i].ImportNameTableRVA;
        }
        for (j = 0; (impaddress = thunk_data_u1_function (ith, j, cfg)) != 0; j++)
        {
          struct ImportTableItem *imp = AddImport (self);
          imp->dll = dll;
          imp->ordinal = -1;
          if (oith)
            imp->orig_address = thunk_data_u1_function (oith, j, cfg);
          if (cfg->on_self)
          {
            imp->address = impaddress;
          }
          if (oith && imp->orig_address & (1 << (sizeof (DWORD) * 8 - 1)))
          {
            imp->ordinal = imp->orig_address & ~(1 << (sizeof (DWORD) * 8 - 1));
          }
          else if (oith)
          {
            IMAGE_IMPORT_BY_NAME *byname = (IMAGE_IMPORT_BY_NAME *) MapPointer (soffs, soffs_len, imp->orig_address, NULL);
            if (byname != NULL)
              imp->name = strdup ((char *) byname->Name);
          }
        }
      }
  }

  idata = opt_header_get_dd_entry (opt_header, IMAGE_DIRECTORY_ENTRY_IMPORT, cfg);
  if (idata->Size > 0 && idata->VirtualAddress != 0)
  {
    iid = (IMAGE_IMPORT_DESCRIPTOR *) MapPointer (soffs, soffs_len,
        idata->VirtualAddress, NULL);
    if (iid)
      for (i = 0; iid[i].Characteristics || iid[i].TimeDateStamp ||
          iid[i].ForwarderChain || iid[i].Name || iid[i].FirstThunk; i++)
        ProcessDep (cfg, soffs, soffs_len, iid[i].Name, root, self, 1);
  }

  idata = opt_header_get_dd_entry (opt_header, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, cfg);
  if (idata->Size > 0 && idata->VirtualAddress != 0)
  {
    idd = (IMAGE_DELAYLOAD_DESCRIPTOR *) MapPointer (soffs, soffs_len, idata->VirtualAddress, NULL);
    if (idd)
      for (i = 0; idd[i].Attributes.AllAttributes || idd[i].DllNameRVA ||
          idd[i].ModuleHandleRVA || idd[i].ImportAddressTableRVA || idd[i].ImportNameTableRVA ||
          idd[i].BoundImportAddressTableRVA || idd[i].UnloadInformationTableRVA ||
          idd[i].TimeDateStamp; i++)
        ProcessDep (cfg, soffs, soffs_len, idd[i].DllNameRVA, root, self, 1);
  }
}
示例#4
0
int MapCooker::TickCompile(int flags) {
	
	if (m_parsing) {
		int r = m_mapBuilder->result;
		if (r != SR_Success)
			return r;

		tools::map_builder::EntSpawn spawn;
		r = MapParser::ParseEntity(m_script, spawn);
		if ((r != SR_Success) && (r != SR_End))
			return r;

		if (r == SR_End) {
			m_parsing = false;
			r = ParseCinematicCompressionMap(flags);
			if (r != SR_Success)
				return r;
			m_mapBuilder->SetCinematicActorCompression(m_caMap);
			if (!m_mapBuilder->SpawnCompile())
				return SR_ParseError;
			m_script.Reset();
		} else {
			RAD_ASSERT(r == SR_Success);
			// For static_mesh_scene, cache the 3DX filetime
			const char *sz = spawn.keys.StringForKey("classname");
			if (sz && !string::cmp(sz, "static_mesh_scene")) {
				sz = spawn.keys.StringForKey("file");
				if (sz) {
					String path(sz);
					path += ".3dx";
					CompareCachedFileTime(flags, path.c_str, path.c_str);
				}
			}

			if (!m_mapBuilder->LoadEntSpawn(spawn))
				return SR_ParseError;

			return SR_Pending;
		}
	}

	if (m_mapBuilder) {
		int r = m_mapBuilder->result;
		if (r != SR_Success)
			return r;

		String path(CStr(asset->path));
		path += ".bsp";
		BinFile::Ref fp = OpenWrite(path.c_str);
		if (!fp)
			return SR_IOError;

		stream::OutputStream os(fp->ob);
		if (m_mapBuilder->bspFileBuilder->Write(os) != pkg::SR_Success)
			return SR_IOError;

		world::bsp_file::BSPFile::Ref bspFile = m_mapBuilder->bspFile;
		RAD_ASSERT(bspFile);

		for (U32 i = 0; i < bspFile->numMaterials; ++i) { 
			// import materials.
			AddImport(bspFile->String((bspFile->Materials()+i)->string));
		}

		return SR_Success;
	}

	m_parsing = true;
	
	// Make sure these get updated
	CompareVersion(flags);
	CompareModifiedTime(flags);
	CompareCachedFileTimeKey(flags, "Source.File");
	CompareCachedFileTime(flags, "Meshes/World/common.3dx", "Meshes/World/common.3dx");

	const String *mapPath = asset->entry->KeyValue<String>("Source.File", flags);
	if (!mapPath || mapPath->empty)
		return SR_MetaError;

	String actorPath = file::SetFileExtension(mapPath->c_str, ".actors");
	CompareCachedFileTime(flags, "Source.File.Actors", actorPath.c_str, true, true);

	//	cout.get() << "********" << std::endl << "Loading :" << mapPath->c_str() << std::endl;

	file::MMFileInputBuffer::Ref ib = engine->sys->files->OpenInputBuffer(mapPath->c_str, ZTools);
	if (!ib)
		return SR_FileNotFound;
	
	m_script.Bind(ib);
	ib.reset();
		
	m_mapBuilder.reset(new (ZTools) tools::map_builder::MapBuilder(*engine.get()));
	m_mapBuilder->SetProgressIndicator(m_ui);

	return SR_Pending;
}