Exemple #1
0
        /// <summary>
        ///     Read file entry
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        public Memory <byte> ReadEntry(LINKDATAEntry entry)
        {
            var pointer = entry.Offset * Header.OffsetMultiplier;
            var buffer  = new Span <byte>(new byte[entry.Size]);

            DataStream.Position = pointer;
            DataStream.Read(buffer);
            return(entry.DecompressedSize > 0 ? new Memory <byte>(StreamCompression.Decompress(buffer, new CompressionOptions {
                Length = entry.DecompressedSize, PrefixSize = true
            }).ToArray()) : new Memory <byte>(buffer.ToArray()));
        }
Exemple #2
0
        private static void Main(string[] args)
        {
            Logger.PrintVersion("Cethleann");
            var flags = CommandLineFlags.ParseFlags <GzFlags>(CommandLineFlags.PrintHelp, args);

            if (flags == null)
            {
                return;
            }

            var files = new List <string>();

            foreach (var arg in flags.Paths)
            {
                if (!Directory.Exists(arg))
                {
                    files.Add(arg);
                    continue;
                }

                files.AddRange(Directory.GetFiles(arg, flags.Mask, SearchOption.AllDirectories));
            }

            Func <byte[], byte[]>?method = null;
            string?ext = null;

            var options = new CompressionOptions
            {
                BlockSize        = flags.BlockSize,
                Alignment        = flags.Alignment,
                CompressionLevel = flags.Level,
                Length           = flags.Length,
                ForceLastBlock   = flags.CompressLast,
                PrefixSize       = flags.PrefixedSize,
                Type             = flags.Type
            };

            if (flags.IsDz)
            {
                ext = ".dz";
                if (flags.Compress)
                {
                    method = bytes => DzCompression.Compress(bytes, options).ToArray();
                }
                else
                {
                    method = bytes => DzCompression.Decompress(bytes, options).ToArray();
                }
            }
            else if (flags.IsStream)
            {
                ext = ".zl";
                if (flags.Compress)
                {
                    method = bytes => StreamCompression.Compress(bytes, options).ToArray();
                }
                else
                {
                    method = bytes => StreamCompression.Decompress(bytes, options).ToArray();
                }
            }
            else if (flags.IsStream8000)
            {
                ext = ".z";
                if (flags.Compress)
                {
                    method = bytes => Stream8000Compression.Compress(bytes, options).ToArray();
                }
                else
                {
                    method = bytes => Stream8000Compression.Decompress(bytes, options).ToArray();
                }
            }
            else if (flags.IsTable)
            {
                ext = ".gz";
                if (flags.Compress)
                {
                    method = bytes => TableCompression.Compress(bytes, options).ToArray();
                }
                else
                {
                    method = bytes => TableCompression.Decompress(bytes, options).ToArray();
                }
            }

            if (method == null)
            {
                Logger.Error("Cethleann", "You must specify a compression method!");
                return;
            }

            foreach (var file in files)
            {
                var target     = flags.Compress ? file + ext : Path.Combine(Path.GetDirectoryName(file) ?? "", Path.GetFileNameWithoutExtension(file));
                var baseTarget = target;
                var modulo     = 0;
                while (File.Exists(target) && flags.Compress)
                {
                    target = baseTarget + $"_{++modulo}";
                }
                Logger.Info("Cethleann", $"{(flags.Compress ? "C" : "Dec")}ompressing {Path.GetFileName(file)} to {target}");

                var bytes = File.ReadAllBytes(file);
                if (bytes.Length == 0)
                {
                    Logger.Info("Cethleann", $"{Path.GetFileName(file)} is empty");
                    continue;
                }

                File.WriteAllBytes(target, method(bytes));

                if (flags.Delete)
                {
                    File.Delete(file);
                }
            }
        }
Exemple #3
0
        private static void Main(string[] args)
        {
            Logger.PrintVersion("Cethleann");
            var flags = CommandLineFlags.ParseFlags <DataExporterFlags>(CommandLineFlags.PrintHelp, args);

            if (flags == null)
            {
                return;
            }

            IManagedFS?fs = default;

            if (flags.Flayn)
            {
                fs = new Flayn(flags);
                ((Flayn)fs).LoadPatterns();
                foreach (var gamedir in flags.GameDirs)
                {
                    fs.AddDataFS(gamedir);
                }
            }
            else if (flags.Leonhart)
            {
                fs = new Leonhart(flags);
                foreach (var gamedir in flags.GameDirs)
                {
                    fs.AddDataFS(gamedir);
                }
            }
            else if (flags.Mitsunari)
            {
                fs = new Mitsunari(flags);
                foreach (var gamedir in flags.GameDirs)
                {
                    fs.AddDataFS(gamedir);
                }
            }
            else if (flags.Nyotengu)
            {
                fs = new Nyotengu(flags);
                foreach (var rdb in flags.GameDirs.SelectMany(gamedir => Directory.GetFiles(gamedir, "*.rdb")))
                {
                    fs.AddDataFS(rdb);
                }

                ((Nyotengu)fs).LoadExtList();
            }
            else if (flags.Zhao) // yep it's identical, but filenames are suffixed with .hash
            // so it would try to load RDB BINs in normal installs since those are named .rdb.bin
            {
                fs = new Nyotengu(flags);
                foreach (var rdb in flags.GameDirs.SelectMany(gamedir => Directory.GetFiles(gamedir, "*.rdb.*")))
                {
                    fs.AddDataFS(rdb);
                }

                ((Nyotengu)fs).LoadExtList();
            }
            else if (flags.Reisalin)
            {
                fs = new Reisalin(flags);
                foreach (var gamedir in flags.GameDirs.SelectMany(gameDir => Directory.GetFiles(gameDir, "*.pak")))
                {
                    fs.AddDataFS(gamedir);
                }
            }
            else if (flags.Yshtola)
            {
                YshtolaSettings?settings = flags.GameId switch
                {
                    "DissidiaNT" => new YshtolaDissidiaSettings(),
                    "VenusVacation" => new YshtolaVenusVacationSettings(),
                    _ => default
                };
                if (settings == default)
                {
                    Logger.Error("Cethleann", $"No decryption settings found for {flags.GameId}!");
                    return;
                }

                fs = new Yshtola(flags, settings);
                var yshtola = (Yshtola)fs;
                yshtola.Root = flags.GameDirs.ToArray();
                foreach (var tableName in settings.TableNames)
                {
                    fs.AddDataFS(tableName);
                }
                if (!Directory.Exists(flags.OutputDirectory))
                {
                    Directory.CreateDirectory(flags.OutputDirectory);
                }
                for (var index = 0; index < yshtola.Tables.Count; index++)
                {
                    var table = yshtola.Tables[index];
                    var type  = Path.GetDirectoryName(yshtola.Settings.TableNames[index]);
                    var name  = $"manifest-{type ?? "COMMON"}.{flags.GameId.ToLower()}";
                    File.WriteAllBytes(Path.Combine(flags.OutputDirectory, name), table.Buffer.ToArray());
                }

                if (flags.YshtolaManifestOnly)
                {
                    return;
                }
            }

            if (fs == null)
            {
                Logger.Error("Cethleann", "No FS specified! Prove --flayn, --reisalin, --leonhart, --mitsunari, --nyotengu, or --yshtola!");
                return;
            }

            if (!flags.NoFilelist)
            {
                fs.LoadFileList(flags.FileList);
            }
            if (flags.NyotenguGeneratedFileList && fs is Nyotengu nyotengu)
            {
                nyotengu.SaveGeneratedFileList(flags.FileList);
                return;
            }

            for (var index = 0; index < fs.EntryCount; index++)
            {
                try
                {
                    var data     = fs.ReadEntry(index).Span;
                    var dt       = data.GetDataType();
                    var ext      = UnbundlerLogic.GetExtension(data);
                    var filepath = fs.GetFilename(index, ext, dt) ?? $"{index}.{ext}";
                    while (filepath.StartsWith("\\") || filepath.StartsWith("/"))
                    {
                        filepath = filepath.Substring(1);
                    }
                    if (flags.Reisalin && filepath.EndsWith(".gz", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (data[4] == 0x78)
                        {
                            data = StreamCompression.Decompress(data, new CompressionOptions
                            {
                                Length = -1,
                                Type   = DataCompression.Deflate
                            });
                        }
                        filepath = filepath.Substring(0, filepath.Length - 3);
                    }

                    var pathBase = $@"{flags.OutputDirectory}\{filepath}";
                    UnbundlerLogic.TryExtractBlob(pathBase, data, false, flags, false);
                }
                catch (Exception e)
                {
                    Logger.Error("Cethleann", e);
#if DEBUG
                    throw;
#endif
                }
            }

            fs.Dispose();
        }
Exemple #4
0
        /// <summary>
        /// Opens (or keeps) connection for receiving instrument profiles from server.
        /// </summary>
        private void Download()
        {
            var webRequest = URLInputStream.OpenConnection(address);

            webRequest.Headers.Add(Constants.LIVE_PROP_KEY, Constants.LIVE_PROP_REQUEST_YES);
            if (LastModified != DateTime.MinValue && !supportsLive &&
                webRequest.GetType() == typeof(HttpWebRequest))
            {
                ((HttpWebRequest)webRequest).IfModifiedSince = lastModified;
            }

            try
            {
                lock (webResponseLocker)
                {
                    webResponse = webRequest.GetResponse();
                }

                try
                {
                    var      isFileStream = webResponse.GetType() == typeof(FileWebResponse);
                    DateTime time;
                    if (isFileStream)
                    {
                        var fileUri = new Uri(address);
                        time = File.GetLastWriteTime(fileUri.AbsolutePath);
                    }
                    else
                    {
                        URLInputStream.CheckConnectionResponseCode(webResponse);
                        time         = ((HttpWebResponse)webResponse).LastModified;
                        supportsLive =
                            Constants.LIVE_PROP_RESPONSE.Equals(webResponse.Headers.Get(Constants.LIVE_PROP_KEY));
                    }

                    if (time == LastModified)
                    {
                        return; // nothing changed
                    }
                    MakeConnected();
                    using (var inputStream = webResponse.GetResponseStream())
                    {
                        var compress = isFileStream
                            ? StreamCompression.DetectCompressionByExtension(new Uri(address))
                            : StreamCompression.DetectCompressionByMimeType(webResponse.ContentType);
                        using (var decompressedIn = compress.Decompress(inputStream))
                        {
                            Process(decompressedIn);
                            // Update timestamp only after first successful processing
                            LastModified = time;
                        }
                    }
                }
                finally
                {
                    lock (webResponseLocker)
                    {
                        webResponse = null;
                    }
                }
            }
            catch (WebException we)
            {
                using (var webResponse = we.Response)
                {
                    if (webResponse != null && webResponse.GetType() == typeof(HttpWebResponse) &&
                        ((HttpWebResponse)webResponse).StatusCode == HttpStatusCode.NotModified)
                    {
                        return; // not modified
                    }
                }
                throw;
            }
        }