public static Boolean Find(UInt32 qtRecordId, out Byte *filePath, out UInt32 offset) { offset = 0; DbRecordId dbRecordId = new DbRecordId(qtRecordId); if (_pinnedNames.TryGetValue(dbRecordId, out SafeGCHandle ptr)) { filePath = (Byte *)ptr.AddrOfPinnedObject(); return(true); } if (Indices.TryGetResourcePath(dbRecordId, out String resourcePath)) { Int32 arraySize = Encoding.ASCII.GetByteCount(resourcePath) + 1; // \0 Byte[] array = new Byte[arraySize]; Encoding.ASCII.GetBytes(resourcePath, 0, resourcePath.Length, array, 0); SafeGCHandle handle = new SafeGCHandle(array, GCHandleType.Pinned); _pinnedNames[dbRecordId] = handle; filePath = (Byte *)handle.AddrOfPinnedObject(); return(true); } filePath = null; return(false); }
public void Release(DbRecordId txRecordId) { lock (_lock) { if (_byId.TryGetValue(txRecordId, out var cachedData)) { Release(cachedData); } } }
public IntPtr Find(DbRecordId txRecordId) { lock (_lock) { if (_byId.TryGetValue(txRecordId, out var cachedData)) { return(cachedData.Pointer); } } return(IntPtr.Zero); }
public IntPtr Acquire(DbRecordId txRecordId) { if (!Indices.TryGetResourcePath(txRecordId, out var resourcePath)) { throw new FileNotFoundException($"Cannot load unknown text resource: {txRecordId}"); } lock (_lock) { if (_byId.TryGetValue(txRecordId, out var cachedData)) { cachedData.Acquire(); return(cachedData.Pointer); } } Byte[] fileContent = NativeFormatProvider.ReadAllBytes(resourcePath); IntPtr result; lock (_lock) { if (_byId.TryGetValue(txRecordId, out var cachedData)) { cachedData.Acquire(); return(cachedData.Pointer); } cachedData = new TxCachedData(txRecordId, resourcePath, fileContent); result = cachedData.Pointer; _byId.Add(txRecordId, cachedData); _byPtr.Add(result, cachedData); } Log.Message($"Loaded resource [0x{txRecordId}, {resourcePath}]."); return(result); }
public static Boolean TryGetRecordName(DbRecordId recordId, out String name) { return(KnownNames.TryGetValue(recordId.Value, out name)); }
private void Extract(DbPackage package, IdxEntry entry, ThreadContext context) { if (context.Package != package) { context.Stream?.Dispose(); context.Stream = File.OpenRead(package.FullPath); context.Package = package; } Byte[] buff = context.Buffer; if (buff == null) { buff = new Byte[entry.UncompressedSize]; context.Buffer = buff; } else if (buff.Length < entry.UncompressedSize) { Array.Resize(ref buff, entry.UncompressedSize); context.Buffer = buff; } FileStream inputStream = context.Stream; if (inputStream.Position != entry.Offset) { inputStream.Position = entry.Offset; } if (entry.IsCompressed) { unsafe { fixed(Byte *ptr = buff) { Int32 readedSize = context.Decompressor.ReadCompressedFile(entry.CompressedSize, ptr, inputStream); if (readedSize != entry.UncompressedSize) { throw new EndOfStreamException($"Failed to decompress the file {package.Name}:{entry.Offset}"); } } } } else { Int32 offset = 0; Int32 size = entry.UncompressedSize; while (size > 0) { Int32 readed = inputStream.Read(buff, offset, size); if (readed == 0 && size > 0) { throw new EndOfStreamException($"Failed to copy the file {package.Name}:{entry.Offset}"); } size -= readed; offset += readed; } } String directoryPath = Path.Combine(_outputDirectory, package.Name); if (entry.CompressedSize < 8) { throw new NotSupportedException($"Compressed size is too small: {entry.CompressedSize}"); } UInt16 version = UInt16.MaxValue; void CheckVersion(String name, Int32 supported) { version = UInt16.Parse(Encoding.ASCII.GetString(buff, 2, 2), NumberStyles.Integer, CultureInfo.InvariantCulture); if (version != supported) { throw new NotSupportedException($"Invalid {name} version: {version}. Expected: {supported}"); } } String GetOutputPath(String tag) { DbRecordId recordId = new DbRecordId(entry.ResourceId); return(Path.Combine(directoryPath, Rename && DbNames.TryGetRecordName(recordId, out var name) ? $"{recordId}_{name}.{tag.ToLowerInvariant()}" : $"{recordId}.{tag.ToLowerInvariant()}")); } String outputPath; ITarget target; String magicTag = Encoding.ASCII.GetString(buff, 0, 2); switch (magicTag) { case "LV": CheckVersion(magicTag, _version.LV); outputPath = GetOutputPath(magicTag); target = CopyTarget.Instance; break; case "AM": CheckVersion(magicTag, _version.AM); if (Convert) { outputPath = GetOutputPath("tiff"); target = ImageTarget.Instance; } else { outputPath = GetOutputPath(magicTag); target = CopyTarget.Instance; } break; case "GV": CheckVersion(magicTag, _version.GV); outputPath = GetOutputPath(magicTag); target = GVTarget.Instance; target = CopyTarget.Instance; break; case "TX": CheckVersion(magicTag, _version.TX); if (Convert) { outputPath = GetOutputPath("txt"); target = TextTarget.Instance; } else { outputPath = GetOutputPath(magicTag); target = CopyTarget.Instance; } break; case "CH": CheckVersion(magicTag, _version.CH); outputPath = GetOutputPath(magicTag); target = CopyTarget.Instance; break; case "IL": CheckVersion(magicTag, _version.IL); outputPath = GetOutputPath(magicTag); target = ILTarget.Instance; target = CopyTarget.Instance; break; case "VS": outputPath = GetOutputPath("vssf"); if (Convert) { outputPath = GetOutputPath("mp3"); target = SoundTarget.Instance; } else { outputPath = GetOutputPath(magicTag); target = CopyTarget.Instance; } break; default: { if (Encoding.ASCII.GetString(buff, 4, 4) != "moov") { throw new NotSupportedException($"Invalid magic number: {Encoding.ASCII.GetString(buff, 0, 8)}"); } directoryPath = _outputDirectory; outputPath = Path.Combine(directoryPath, $"{entry.ResourceId:X8}_{package.Name}.qt"); target = CopyTarget.Instance; break; } } if (!Convert) { target = CopyTarget.Instance; } Directory.CreateDirectory(directoryPath); ArraySegment <Byte> segment = new ArraySegment <Byte>(buff, 0, entry.UncompressedSize); target.Write(segment, outputPath, version); }