Esempio n. 1
0
        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);
        }
Esempio n. 2
0
 public void Release(DbRecordId txRecordId)
 {
     lock (_lock)
     {
         if (_byId.TryGetValue(txRecordId, out var cachedData))
         {
             Release(cachedData);
         }
     }
 }
Esempio n. 3
0
        public IntPtr Find(DbRecordId txRecordId)
        {
            lock (_lock)
            {
                if (_byId.TryGetValue(txRecordId, out var cachedData))
                {
                    return(cachedData.Pointer);
                }
            }

            return(IntPtr.Zero);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
 public static Boolean TryGetRecordName(DbRecordId recordId, out String name)
 {
     return(KnownNames.TryGetValue(recordId.Value, out name));
 }
Esempio n. 6
0
        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);
        }