void NDSFile::readNames(Common::SeekableReadStream &nds, uint32 offset, uint32 length) { if (!nds.seek(offset + 8)) throw Common::Exception(Common::kSeekError); uint32 index = 0; while (((uint32) nds.pos()) < (offset + length)) { Resource res; byte nameLength = nds.readByte(); Common::UString name; name.readFixedASCII(nds, nameLength); name.tolower(); res.name = setFileType(name, kFileTypeNone); res.type = getFileType(name); res.index = index++; _resources.push_back(res); } while (!_resources.empty() && _resources.back().name.empty()) _resources.pop_back(); }
void ResourceManager::addResource(Resource &resource, Common::UString name, ChangeID &change) { name.tolower(); if (name.empty()) return; // Normalize resource type *sigh* if (resource.type == kFileTypeQST2) resource.type = kFileTypeQST; else if (resource.type == kFileTypeMDX2) resource.type = kFileTypeMDX; else if (resource.type == kFileTypeTXB2) resource.type = kFileTypeTXB; else if (resource.type == kFileTypeCRE) resource.type = kFileTypeBTC; // Resolve the type aliases std::map<FileType, FileType>::const_iterator alias = _typeAliases.find(resource.type); if (alias != _typeAliases.end()) resource.type = alias->second; ResourceMap::iterator resTypeMap = _resources.find(name); if (resTypeMap == _resources.end()) { // We don't yet have a resource with this name, create a new type map for it std::pair<ResourceMap::iterator, bool> result; result = _resources.insert(std::make_pair(name, ResourceTypeMap())); resTypeMap = result.first; } ResourceTypeMap::iterator resList = resTypeMap->second.find(resource.type); if (resList == resTypeMap->second.end()) { // We don't yet have a resource with that name and type, create a new resource list for it std::pair<ResourceTypeMap::iterator, bool> result; result = resTypeMap->second.insert(std::make_pair(resource.type, ResourceList())); resList = result.first; } // Add the resource to the list resList->second.push_back(resource); // And sort the list by priority resList->second.sort(); // Remember the resource in the change set change._change->resources.push_back(ResourceChange()); change._change->resources.back().nameIt = resTypeMap; change._change->resources.back().typeIt = resList; change._change->resources.back().resIt = --resList->second.end(); }
FileType FileTypeManager::getFileType(const Common::UString &path) { buildExtensionLookup(); Common::UString ext = Common::FilePath::getExtension(path); ext.tolower(); ExtensionLookup::const_iterator t = _extensionLookup.find(ext); if (t != _extensionLookup.end()) return t->second->type; return kFileTypeNone; }
void ResourceManager::checkHashCollision(const Resource &resource, ResourceMap::const_iterator resList) { if (resource.name.empty() || resList->second.empty()) return; Common::UString newName = TypeMan.setFileType(resource.name, resource.type); newName.tolower(); for (ResourceList::const_iterator r = resList->second.begin(); r != resList->second.end(); ++r) { if (r->name.empty()) continue; Common::UString oldName = TypeMan.setFileType(r->name, r->type); oldName.tolower(); if (oldName != newName) { warning("ResourceManager: Found hash collision: 0x%016llX (\"%s\" and \"%s\")", (unsigned long long) getHash(oldName), oldName.c_str(), newName.c_str()); return; } } }
void VISFile::load(Common::SeekableReadStream &vis) { clear(); Common::StreamTokenizer tokenizer(Common::StreamTokenizer::kRuleIgnoreAll); tokenizer.addSeparator(' '); tokenizer.addChunkEnd('\n'); tokenizer.addIgnore('\r'); for (;;) { std::vector<Common::UString> strings; tokenizer.getTokens(vis, strings); // Make sure we don't get any empty lines while (!vis.eos() && !vis.err() && strings.empty()) { tokenizer.nextChunk(vis); tokenizer.getTokens(vis, strings); } if (vis.eos() || vis.err()) break; if ((strings.size() == 1) && (strings[0] == "[Adjacent]")) // TODO: New in Jade Empire break; if (strings.size() > 2) throw Common::Exception("Malformed VIS file"); Common::UString room = strings[0]; std::vector<Common::UString> visibilityArray; int roomCount = 0; if (strings.size() > 1) roomCount = atoi(strings[1].c_str()); room.tolower(); int realRoomCount = 0; visibilityArray.reserve(roomCount); while (!vis.eos() && !vis.err()) { uint32 lineStart = vis.pos(); tokenizer.nextChunk(vis); if (((char) vis.readByte()) != ' ') { // Not indented => new room vis.seek(lineStart); break; } tokenizer.getTokens(vis, strings); if (strings.size() != 1) { // More than one token => new room vis.seek(lineStart); break; } visibilityArray.push_back(strings[0]); realRoomCount++; } if (roomCount != realRoomCount) // Thanks, BioWare! -.- warning("Malformed VIS file. Wanted %d rooms, got %d?!?", roomCount, realRoomCount); if (!visibilityArray.empty()) _map[room] = visibilityArray; } }
inline uint64 ResourceManager::getHash(Common::UString name) const { name.tolower(); return Common::hashString(name, _hashAlgo); }