public IEnumerable <string> AllFileNames() { var lookup = new Dictionary <uint, string>(); if (Exists("local mix database.dat")) { var db = new XccLocalDatabase(GetContent("local mix database.dat")); foreach (var e in db.Entries) { var hash = PackageEntry.HashFilename(e, type); if (!lookup.ContainsKey(hash)) { lookup.Add(hash, e); } } } if (GlobalFileSystem.Exists("global mix database.dat")) { var db = new XccGlobalDatabase(GlobalFileSystem.Open("global mix database.dat")); foreach (var e in db.Entries) { var hash = PackageEntry.HashFilename(e, type); if (!lookup.ContainsKey(hash)) { lookup.Add(hash, e); } } } return(index.Keys.Select(k => lookup.ContainsKey(k) ? lookup[k] : "{0:X}".F(k))); }
public D2kSoundResources(string filename, int priority) { this.filename = filename; this.priority = priority; s = GlobalFileSystem.Open(filename); s.Seek(0, SeekOrigin.Begin); filenames = new List <string>(); var headerLength = s.ReadUInt32(); while (s.Position < headerLength + 4) { var name = s.ReadASCIIZ(); var offset = s.ReadUInt32(); var length = s.ReadUInt32(); var hash = PackageEntry.HashFilename(name, PackageHashType.Classic); if (!index.ContainsKey(hash)) { index.Add(hash, new PackageEntry(hash, offset, length)); } filenames.Add(name); } }
public D2kSoundResources(FileSystem context, string filename, int priority) { this.filename = filename; this.priority = priority; s = context.Open(filename); try { filenames = new List <string>(); var headerLength = s.ReadUInt32(); while (s.Position < headerLength + 4) { var name = s.ReadASCIIZ(); var offset = s.ReadUInt32(); var length = s.ReadUInt32(); var hash = PackageEntry.HashFilename(name, PackageHashType.Classic); if (!index.ContainsKey(hash)) { index.Add(hash, new PackageEntry(hash, offset, length)); } filenames.Add(name); } } catch { Dispose(); throw; } }
public IEnumerable <uint> ClassicHashes() { foreach (var filename in index.Keys) { yield return(PackageEntry.HashFilename(filename, PackageHashType.Classic)); } }
public IEnumerable <uint> ClassicHashes() { foreach (ZipEntry entry in pkg) { yield return(PackageEntry.HashFilename(entry.Name, PackageHashType.Classic)); } }
public IEnumerable <uint> ClassicHashes() { foreach (var filename in Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly)) { yield return(PackageEntry.HashFilename(Path.GetFileName(filename), PackageHashType.Classic)); } }
public Stream GetContent(PackageEntry entry) { Stream parentStream; var offset = dataStart + entry.Offset + SegmentStream.GetOverallNestedOffset(s, out parentStream); var path = ((FileStream)parentStream).Name; return(new SegmentStream(File.OpenRead(path), offset, entry.Length)); }
Dictionary <string, PackageEntry> ParseIndex(Dictionary <uint, PackageEntry> entries, HashSet <string> allPossibleFilenames) { var classicIndex = new Dictionary <string, PackageEntry>(); var crcIndex = new Dictionary <string, PackageEntry>(); // Try and find a local mix database var dbNameClassic = PackageEntry.HashFilename("local mix database.dat", PackageHashType.Classic); var dbNameCRC = PackageEntry.HashFilename("local mix database.dat", PackageHashType.CRC32); foreach (var kv in entries) { if (kv.Key == dbNameClassic || kv.Key == dbNameCRC) { using (var content = GetContent(kv.Value)) { var db = new XccLocalDatabase(content); foreach (var e in db.Entries) { allPossibleFilenames.Add(e); } } break; } } foreach (var filename in allPossibleFilenames) { var classicHash = PackageEntry.HashFilename(filename, PackageHashType.Classic); var crcHash = PackageEntry.HashFilename(filename, PackageHashType.CRC32); PackageEntry e; if (entries.TryGetValue(classicHash, out e)) { classicIndex.Add(filename, e); } if (entries.TryGetValue(crcHash, out e)) { crcIndex.Add(filename, e); } } var bestIndex = crcIndex.Count > classicIndex.Count ? crcIndex : classicIndex; var unknown = entries.Count - bestIndex.Count; if (unknown > 0) { Log.Write("debug", "{0}: failed to resolve filenames for {1} unknown hashes".F(Name, unknown)); } return(bestIndex); }
static Stream GetFromCache(PackageHashType type, string filename) { var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex; var folder = index[PackageEntry.HashFilename(filename, type)] .Where(x => x.Exists(filename)) .MinByOrDefault(x => x.Priority); if (folder != null) { return(folder.GetContent(filename)); } return(null); }
public void Write(Dictionary <string, byte[]> contents) { // Cannot modify existing mixfile - rename existing file and // create a new one with original content plus modifications GlobalFileSystem.Unmount(this); // TODO: Add existing data to the contents list if (index.Count > 0) { throw new NotImplementedException("Updating mix files unfinished"); } // Construct a list of entries for the file header uint dataSize = 0; var items = new List <PackageEntry>(); foreach (var kv in contents) { var length = (uint)kv.Value.Length; var hash = PackageEntry.HashFilename(Path.GetFileName(kv.Key), type); items.Add(new PackageEntry(hash, dataSize, length)); dataSize += length; } // Write the new file s.Seek(0, SeekOrigin.Begin); using (var writer = new BinaryWriter(s)) { // Write file header writer.Write((ushort)items.Count); writer.Write(dataSize); foreach (var item in items) { item.Write(writer); } writer.Flush(); // Copy file data foreach (var file in contents) { s.Write(file.Value); } } }
public Stream GetContent(PackageEntry entry) { Stream parentStream; var baseOffset = dataStart + entry.Offset; var nestedOffset = baseOffset + SegmentStream.GetOverallNestedOffset(s, out parentStream); // Special case FileStream - instead of creating an in-memory copy, // just reference the portion of the on-disk file that we need to save memory. // We use GetType instead of 'is' here since we can't handle any derived classes of FileStream. if (parentStream.GetType() == typeof(FileStream)) { var path = ((FileStream)parentStream).Name; return(new SegmentStream(File.OpenRead(path), nestedOffset, entry.Length)); } // For all other streams, create a copy in memory. // This uses more memory but is the only way in general to ensure the returned streams won't clash. s.Seek(baseOffset, SeekOrigin.Begin); return(new MemoryStream(s.ReadBytes((int)entry.Length))); }
uint?FindMatchingHash(string filename) { var hash = PackageEntry.HashFilename(filename, type); if (index.ContainsKey(hash)) { return(hash); } // Maybe we were given a raw hash? uint raw; if (!uint.TryParse(filename, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out raw)) { return(null); } if ("{0:X}".F(raw) == filename && index.ContainsKey(raw)) { return(raw); } return(null); }
void ParseFile(BinaryReader reader) { reader.ReadBytes(7); var CompressedSize = reader.ReadUInt32(); reader.ReadBytes(12); var ChunkSize = reader.ReadUInt16(); reader.ReadBytes(4); var NameLength = reader.ReadByte(); var FileName = new String(reader.ReadChars(NameLength)); var hash = PackageEntry.HashFilename(FileName, PackageHashType.Classic); if (!index.ContainsKey(hash)) { index.Add(hash, new PackageEntry(hash, AccumulatedData, CompressedSize)); } filenames.Add(FileName); AccumulatedData += CompressedSize; // Skip to the end of the chunk reader.ReadBytes(ChunkSize - NameLength - 30); }
public bool Exists(string filename) { return(index.ContainsKey(PackageEntry.HashFilename(filename, PackageHashType.Classic))); }
public IEnumerable <uint> ClassicHashes() { return(entries.Keys.Select(filename => PackageEntry.HashFilename(filename, PackageHashType.Classic))); }
public Stream GetContent(string filename) { return(GetContent(PackageEntry.HashFilename(filename, PackageHashType.Classic))); }
public IEnumerable <uint> ClassicHashes() { return(fileLookup.Keys.Select(k => PackageEntry.HashFilename(k, PackageHashType.Classic))); }
public static uint HashFilename(string name, PackageHashType type) { return(PackageEntry.HashFilename(name, type)); }