Пример #1
0
        private static Task <MS2Archive> LoadMS2F(MS2CryptoMode cryptoMode, BinaryReader br, string name, MemoryMappedFile dataMemoryMappedFile)
        {
            return(Task.Run(async() =>
            {
                uint unk = br.ReadUInt32(); // TODO: unknown/unused?
                uint dataCompressedSize = br.ReadUInt32() | br.ReadUInt32();
                uint dataEncodedSize = br.ReadUInt32() | br.ReadUInt32();
                uint size = br.ReadUInt32() | br.ReadUInt32();
                uint compressedSize = br.ReadUInt32() | br.ReadUInt32();
                uint encodedSize = br.ReadUInt32() | br.ReadUInt32();
                uint fileCount = br.ReadUInt32() | br.ReadUInt32();
                uint dataSize = br.ReadUInt32() | br.ReadUInt32();

                if (unk != 0)
                {
                    Logger.Debug($"Archive header unk is \"{unk}\".");
                }

                var header = new MS2SizeHeader(encodedSize, compressedSize, size);
                var data = new MS2SizeHeader(dataEncodedSize, dataCompressedSize, dataSize);
                Logger.Verbose($"There are {fileCount} files in the archive.");
                List <MS2File> files = await LoadFiles(cryptoMode, header, data, fileCount, br, dataMemoryMappedFile).ConfigureAwait(false);

                var archive = new MS2Archive(cryptoMode, header, data, name, dataMemoryMappedFile, files);

                return archive;
            }));
        }
Пример #2
0
        private static Task <MS2FileHeader> CreateMS2F(BinaryReader br)
        {
            return(Task.Run(() =>
            {
                uint unk = br.ReadUInt32(); // TODO: unknown/unused?
                uint fileId = br.ReadUInt32();
                var compressionType = (CompressionType)br.ReadUInt32();
                uint unk2 = br.ReadUInt32(); // TODO: unknown/unused?
                uint offset = br.ReadUInt32() | br.ReadUInt32();
                uint encodedSize = br.ReadUInt32() | br.ReadUInt32();
                uint compressedSize = br.ReadUInt32() | br.ReadUInt32();
                uint size = br.ReadUInt32() | br.ReadUInt32();

                if (unk != 0)
                {
                    Logger.Debug($"File Header unk is \"{unk}\".");
                }
                if (unk2 != 0)
                {
                    Logger.Debug($"File Header second unk is \"{unk2}\".");
                }

                return new MS2FileHeader(encodedSize, compressedSize, size, fileId, offset, compressionType);
            }));
        }
Пример #3
0
        private static bool ParseArgs(string[] args)
        {
            if (args.Length < MinNumberArgs)
            {
                Logger.Error("not enough args");
                return(false);
            }

            if (args.Any(s => String.IsNullOrWhiteSpace(s)))
            {
                Logger.Error("one or more of the args is not valid");
                return(false);
            }

            SourcePath      = Path.GetFullPath(args[0]);
            DestinationPath = Path.GetFullPath(args[1]);

            if (args.Length >= OptionalNumberArgSyncMode)
            {
                ArgsSyncMode = (SyncMode)Enum.Parse(typeof(SyncMode), args[OptionalNumberArgSyncMode - 1]);

                if (args.Length >= OptionalNumberArgLog)
                {
                    ArgsLogMode = (LogMode)Enum.Parse(typeof(LogMode), args[OptionalNumberArgLog - 1]);
                }
            }

            return(true);
        }
Пример #4
0
        private static async Task ExtractArchiveSync(string headerFile, string dataFile, string destinationPath)
        {
            using (MS2Archive archive = await MS2Archive.Load(headerFile, dataFile).ConfigureAwait(false))
            {
                List <MS2File> files = archive.Files;

                for (int i = 0; i < files.Count; i++)
                {
                    MS2File file = files[i];
                    Logger.Info($"Extracting file \"{file.Name}\", \"{FileEx.FormatStorage(file.Header.Size)}\". ({file.Header.Id}/{files.Count})");
                    await ExtractFileAsync(destinationPath, file).ConfigureAwait(false);
                }
            }
        }
Пример #5
0
        private static async Task ExportArchiveAsync(string headerFile, string dataFile, string destinationFilePath)
        {
            using (var swExport = new StreamWriter(destinationFilePath))
                using (MS2Archive archive = await MS2Archive.Load(headerFile, dataFile).ConfigureAwait(false))
                {
                    List <MS2File> files = archive.Files;

                    for (int i = 0; i < files.Count; i++)
                    {
                        MS2File file = files[i];
                        Logger.Info($"Exporting file \"{file.Name}\". ({file.Header.Id}/{files.Count})");
                        await ExportFileAsync(swExport, file).ConfigureAwait(false);
                    }
                }
        }
Пример #6
0
        private static Task CreateExtractArchiveAsync(string destinationPath, string headerFile, string dataFile)
        {
            string dstPath = Path.Combine(destinationPath, Path.GetFileNameWithoutExtension(headerFile));

            Directory.CreateDirectory(dstPath);

            Logger.Verbose($"Starting extraction of: header \"{headerFile}\", data \"{dataFile}\".");
            if (ArgsSyncMode == SyncMode.Async)
            {
                return(ExtractArchiveAsync(headerFile, dataFile, dstPath));
            }
            else //if (ArgsSyncMode == SyncMode.Sync)
            {
                return(ExtractArchiveSync(headerFile, dataFile, dstPath));
            }
        }
Пример #7
0
        private static Task CreateArchiveAsync(string sourcePath, string destinationPath)
        {
            Directory.CreateDirectory(destinationPath);
            string dstArchive = Path.Combine(destinationPath, ArchiveName);
            string headerPath = Path.ChangeExtension(dstArchive, HeaderFileExtension);
            string dataPath   = Path.ChangeExtension(dstArchive, DataFileExtension);

            Logger.Info($"Archiving folder \"{SourcePath}\" into \"{headerPath}\" and \"{dataPath}\"");

            if (ArgsSyncMode == SyncMode.Async)
            {
                return(CreateArchiveAsync(sourcePath, headerPath, dataPath));
            }
            else //if (ArgsSyncMode == SyncMode.Sync)
            {
                return(CreateArchiveSync(sourcePath, headerPath, dataPath));
            }
        }
Пример #8
0
        private static async Task RunAsync(string[] args)
        {
            if (!ParseArgs(args))
            {
                DisplayArgsHelp();
                return;
            }

            if (ArgsLogMode.HasValue)
            {
                Logger.LoggingLevel = ArgsLogMode.Value;
            }

            if (Directory.Exists(SourcePath))
            {
                Logger.Debug("Directory specified");
                Logger.Verbose($"Extracting all archives from \"{SourcePath}\" to \"{DestinationPath}\".");
                try
                {
                    await ExtractArchivesInDirectoryAsync(SourcePath, DestinationPath).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    return;
                }
            }
            else
            {
                Logger.Debug("File Specified");
                Logger.Verbose($"Extracting archive \"{SourcePath}\" to \"{DestinationPath}\".");
                try
                {
                    await ExtractArchiveAsync(SourcePath, DestinationPath).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    return;
                }
            }
        }
Пример #9
0
        private static Task ExportFileAsync(StreamWriter swExport, MS2File file)
        {
            string fileName = file.Name;

            if (String.IsNullOrWhiteSpace(fileName))
            {
                Logger.Warning($"File number \"{file.Id}\" has no name and will be ignored.");
                return(Task.CompletedTask);
            }

            uint            id     = file.Header.Id;
            CompressionType typeId = file.CompressionType;

            FileTypes.AddOrUpdate(Path.GetExtension(fileName), new HashSet <string>()
            {
                typeId.ToString()
            }, (_, v) => { v.Add(typeId.ToString()); return(v); });

            string rootDirectory = PathEx.GetRootDirectory(fileName);

            if (!String.IsNullOrEmpty(rootDirectory))
            {
                if (String.IsNullOrEmpty(file.InfoHeader.RootFolderId))
                {
                    Logger.Warning($"Root folder id is empty but it has a root folder ({rootDirectory})!");
                }

                RootFolderIds.AddOrUpdate(rootDirectory, new HashSet <string>()
                {
                    file.InfoHeader.RootFolderId
                }, (_, v) => { v.Add(file.InfoHeader.RootFolderId); return(v); });
            }

            int    propCount = file.InfoHeader.Properties.Count;
            string info      = String.Join(",", file.InfoHeader.Properties);

            return(swExport.WriteLineAsync($"{id:d6} - Type:{typeId}; Properties:{propCount}; Info={info}"));
        }
Пример #10
0
        private static async Task ExtractFileAsync(string destinationPath, MS2File file)
        {
            if (String.IsNullOrWhiteSpace(file.Name))
            {
                Logger.Warning($"File number \"{file.Id}\", \"{FileEx.FormatStorage(file.Header.Size)}\" has no name and will be ignored.");
                return;
            }

            string fileDestinationPath = Path.Combine(destinationPath, file.Name);

            (Stream stream, bool shouldDispose) = await file.GetDecryptedStreamAsync().ConfigureAwait(false);

            try
            {
                await stream.CopyToAsync(fileDestinationPath).ConfigureAwait(false);
            }
            finally
            {
                if (shouldDispose)
                {
                    stream.Dispose();
                }
            }
        }
Пример #11
0
        private static async Task RunAsync(string[] args)
        {
            if (!ParseArgs(args))
            {
                DisplayArgsHelp();
                return;
            }

            if (ArgsLogMode.HasValue)
            {
                Logger.LoggingLevel = ArgsLogMode.Value;
            }

            Logger.Verbose($"Archiving folder \"{SourcePath}\" to \"{DestinationPath}\".");
            try
            {
                await CreateArchiveAsync(SourcePath, DestinationPath).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                return;
            }
        }
Пример #12
0
        private static async Task RunAsync(string[] args)
        {
            if (!ParseArgs(args))
            {
                DisplayArgsHelp();
                return;
            }

            if (ArgsLogMode.HasValue)
            {
                Logger.LoggingLevel = ArgsLogMode.Value;
            }

            Directory.CreateDirectory(DestinationPath);

            if (Directory.Exists(SourcePath))
            {
                Logger.Debug("Directory specified");
                Logger.Verbose($"Exporting all archives from \"{SourcePath}\" to \"{DestinationPath}\".");
                try
                {
                    await ExportArchivesInDirectoryAsync(SourcePath, DestinationPath).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    return;
                }
            }
            else
            {
                Logger.Debug("File Specified");
                Logger.Verbose($"Exporting archive \"{SourcePath}\" to \"{DestinationPath}\".");
                try
                {
                    await ExportArchiveAsync(SourcePath, DestinationPath).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                    return;
                }
            }

            var fileTypesList = FileTypes.ToList();

            fileTypesList.Sort((kvp1, kvp2) => kvp1.Key.CompareTo(kvp2.Key));
            var rootFolderIdList = RootFolderIds.ToList();

            rootFolderIdList.Sort((kvp1, kvp2) => kvp1.Key.CompareTo(kvp2.Key));

            using (var sw = new StreamWriter(Path.Combine(DestinationPath, FileTypeMapFileName)))
            {
                foreach (KeyValuePair <string, HashSet <string> > kvp in fileTypesList)
                {
                    await sw.WriteLineAsync(kvp.Key.PadRight(FileTypesKeyPadding) + " - " + String.Join(", ", kvp.Value)).ConfigureAwait(false);
                }
            }

            using (var sw = new StreamWriter(Path.Combine(DestinationPath, RootFolderIdMapFileName)))
            {
                foreach (KeyValuePair <string, HashSet <string> > kvp in rootFolderIdList)
                {
                    await sw.WriteLineAsync(kvp.Key.PadRight(RootFolderIdsKeyPadding) + " - " + String.Join(", ", kvp.Value)).ConfigureAwait(false);
                }
            }
        }
Пример #13
0
 private static Task CreateExportArchiveAsync(string destinationPath, string headerFile, string dataFile)
 {
     Logger.Verbose($"Starting exporting of: header \"{headerFile}\", data \"{dataFile}\".");
     return(ExportArchiveAsync(headerFile, dataFile, destinationPath));
 }