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; }
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 ); } }
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], §ion); 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); } }
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; }