diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index e9098a3b..989e09b2 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -93,6 +93,7 @@ namespace FModel if (Properties.Settings.Default.UseDiscordRpc) DiscordIntegration.StartClient(); await AesGrabber.Load(Properties.Settings.Default.ReloadAesKeys).ConfigureAwait(false); await CdnDataGrabber.DoCDNStuff().ConfigureAwait(false); + await Folders.DownloadAndExtractVgm().ConfigureAwait(false); } private void AeConfiguration() diff --git a/FModel/PakReader/Parsers/Class/UTexture2D.cs b/FModel/PakReader/Parsers/Class/UTexture2D.cs index 5e353216..17b88778 100644 --- a/FModel/PakReader/Parsers/Class/UTexture2D.cs +++ b/FModel/PakReader/Parsers/Class/UTexture2D.cs @@ -32,20 +32,17 @@ namespace PakReader.Parsers.Class { var data = new List(1); // Probably gonna be only one texture anyway var PixelFormatName = reader.ReadFName(); - if (FModel.Globals.Game.Version < EPakVersion.INDEX_ENCRYPTION) + while (!PixelFormatName.IsNone) { _ = reader.ReadInt32(); // SkipOffset + if (FModel.Globals.Game.Version >= EPakVersion.RELATIVE_CHUNK_OFFSETS) + _ = reader.ReadInt32(); // SkipOffsetH + data.Add(new FTexturePlatformData(reader, ubulk, bulkOffset)); - reader.ReadFName(); - } - else - { - while (!PixelFormatName.IsNone) - { - _ = reader.ReadInt64(); // SkipOffset - data.Add(new FTexturePlatformData(reader, ubulk, bulkOffset)); - PixelFormatName = reader.ReadFName(); - } + PixelFormatName = reader.ReadFName(); + + if (FModel.Globals.Game.Version < EPakVersion.RELATIVE_CHUNK_OFFSETS) + break; } PlatformDatas = data.ToArray(); } diff --git a/FModel/PakReader/Parsers/Objects/FByteBulkData.cs b/FModel/PakReader/Parsers/Objects/FByteBulkData.cs index a2f9bd8c..629d3caf 100644 --- a/FModel/PakReader/Parsers/Objects/FByteBulkData.cs +++ b/FModel/PakReader/Parsers/Objects/FByteBulkData.cs @@ -4,12 +4,6 @@ namespace PakReader.Parsers.Objects { public readonly struct FByteBulkData : IUStruct { - // Memory saving, we don't need this - //uint BulkDataFlags; - //long ElementCount; - //long BulkDataOffsetInFile; - //long BulkDataSizeOnDisk; - public readonly byte[] Data; internal FByteBulkData(BinaryReader reader, Stream ubulk, long ubulkOffset) @@ -21,12 +15,23 @@ namespace PakReader.Parsers.Objects var BulkDataOffsetInFile = reader.ReadInt64(); Data = null; - if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_ForceInlinePayload) != 0 && ElementCount > 0) + if ((BulkDataFlags & 0x20) != 0 || ElementCount == 0) + return; + if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_PayloadAtEndOfFile) != 0) { - Data = reader.ReadBytes((int)ElementCount); + long rememberMe = reader.BaseStream.Position; + if (BulkDataOffsetInFile + ElementCount <= reader.BaseStream.Length) + { + reader.BaseStream.Seek(BulkDataOffsetInFile, SeekOrigin.Begin); + Data = reader.ReadBytes(ElementCount); + } + reader.BaseStream.Seek(rememberMe, SeekOrigin.Begin); } - - if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_PayloadInSeperateFile) != 0) + if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_OptionalPayload) != 0) //.uptnl + return; + if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_ForceInlinePayload) != 0) //.uexp + Data = reader.ReadBytes(ElementCount); + if ((BulkDataFlags & (uint)EBulkDataFlags.BULKDATA_PayloadInSeperateFile) != 0) //.ubulk { if (ubulk != null) { diff --git a/FModel/PakReader/Parsers/Objects/FPakEntry.cs b/FModel/PakReader/Parsers/Objects/FPakEntry.cs index 187ceacd..14ecb8f6 100644 --- a/FModel/PakReader/Parsers/Objects/FPakEntry.cs +++ b/FModel/PakReader/Parsers/Objects/FPakEntry.cs @@ -253,6 +253,7 @@ namespace PakReader.Parsers.Objects int stop = Name.LastIndexOf(".") - start; return Name.Substring(start, stop); } + public string GetFirstFolder() => Name.Substring(Name.StartsWith('/') ? 1 : 0, Name.IndexOf('/')); public override string ToString() => Name; } diff --git a/FModel/Utils/Assets.cs b/FModel/Utils/Assets.cs index c4b1e698..a33d3665 100644 --- a/FModel/Utils/Assets.cs +++ b/FModel/Utils/Assets.cs @@ -267,7 +267,7 @@ namespace FModel.Utils ((AudioPlayer)FWindows.GetOpenedWindow(Properties.Resources.AudioPlayer)).LoadFiles(new Dictionary(1) { { entry.GetNameWithoutExtension() + "." + s.AudioFormat.String.ToLowerInvariant(), s.Sound } }, entry.GetPathWithoutFile()); }); } - else if (s != null) // ADPCM and others + else if (s != null) { string path = Properties.Settings.Default.OutputPath + "\\Sounds\\" + mount + entry.GetPathWithoutExtension() + "." + s.AudioFormat.String.ToLowerInvariant(); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/FModel/Utils/Folders.cs b/FModel/Utils/Folders.cs index 1e8492f4..23b94b6d 100644 --- a/FModel/Utils/Folders.cs +++ b/FModel/Utils/Folders.cs @@ -1,9 +1,11 @@ using FModel.Logger; using FModel.Windows.CustomNotifier; +using Ionic.Zip; using System; using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; +using System.Threading.Tasks; namespace FModel.Utils { @@ -90,6 +92,25 @@ namespace FModel.Utils Directory.CreateDirectory(Properties.Settings.Default.OutputPath + "\\Logs\\"); } + public static async Task DownloadAndExtractVgm() + { + if (!Directory.Exists(Properties.Settings.Default.OutputPath + "\\Vgm\\")) + { + DirectoryInfo vgm = Directory.CreateDirectory(Properties.Settings.Default.OutputPath + "\\Vgm\\"); + vgm.Attributes = FileAttributes.Directory | FileAttributes.Hidden; + + string zipFile = $"{vgm.FullName}test.zip"; + using var client = new HttpClientDownloadWithProgress("https://github.com/losnoco/vgmstream/releases/latest/download/test.zip", zipFile); + await client.StartDownload().ConfigureAwait(false); + if (new FileInfo(zipFile).Length > 0) + { + ZipFile zip = ZipFile.Read(zipFile); + foreach (ZipEntry e in zip) + e.Extract(vgm.FullName, ExtractExistingFileAction.OverwriteSilently); + } + } + } + public static void CheckWatermarks() { bool bSave = false; diff --git a/FModel/Utils/Paks.cs b/FModel/Utils/Paks.cs index 02f291bc..62123944 100644 --- a/FModel/Utils/Paks.cs +++ b/FModel/Utils/Paks.cs @@ -179,8 +179,7 @@ namespace FModel.Utils return string.Empty; } - public static void Merge(Dictionary tempFiles, out Dictionary files, - string mount) + public static void Merge(Dictionary tempFiles, out Dictionary files, string mount) { files = new Dictionary(); foreach (FPakEntry entry in tempFiles.Values) @@ -226,6 +225,8 @@ namespace FModel.Utils } files[mount + entry.GetPathWithoutExtension()] = entry; + if (Globals.Game.ActualGame == EGame.Unknown) + Folders.SetGameName((mount.Length == 1 ? entry.GetFirstFolder() : mount) + "\\Content\\Paks"); } } diff --git a/FModel/ViewModels/MenuItem/BackupMenuItemViewModel.cs b/FModel/ViewModels/MenuItem/BackupMenuItemViewModel.cs index 40335420..0b0c7d7f 100644 --- a/FModel/ViewModels/MenuItem/BackupMenuItemViewModel.cs +++ b/FModel/ViewModels/MenuItem/BackupMenuItemViewModel.cs @@ -108,7 +108,7 @@ namespace FModel.ViewModels.MenuItem Stopwatch downloadTimer = Stopwatch.StartNew(); StatusBarVm.statusBarViewModel.Set($"{Properties.Resources.Downloading} {Header}", Properties.Resources.Waiting); - string path = $"{Properties.Settings.Default.OutputPath}//Backups//{Header}"; + string path = $"{Properties.Settings.Default.OutputPath}\\Backups\\{Header}"; using var client = new HttpClientDownloadWithProgress(DownloadUrl, path); client.ProgressChanged += (totalFileSize, totalBytesDownloaded, progressPercentage) => { diff --git a/FModel/ViewModels/MenuItem/MenuItems.cs b/FModel/ViewModels/MenuItem/MenuItems.cs index 73cd78d4..5a358a18 100644 --- a/FModel/ViewModels/MenuItem/MenuItems.cs +++ b/FModel/ViewModels/MenuItem/MenuItems.cs @@ -112,6 +112,6 @@ namespace FModel.ViewModels.MenuItem public static IEnumerable GetPakFileReaders(this ObservableCollection o) => Application.Current.Dispatcher.Invoke(() => o.GetMenuItemWithPakFiles().Select(x => x.PakFile)); public static IEnumerable GetDynamicPakFileReaders(this ObservableCollection o) => - Application.Current.Dispatcher.Invoke(() => o.GetPakFileReaders().Where(x => !x.Info.EncryptionKeyGuid.Equals(new FGuid(0u, 0u, 0u, 0u)))); + Application.Current.Dispatcher.Invoke(() => o.GetPakFileReaders().Where(x => x.Info.bEncryptedIndex && !x.Info.EncryptionKeyGuid.Equals(new FGuid(0u, 0u, 0u, 0u)))); } } diff --git a/FModel/Windows/SoundPlayer/AudioPlayer.xaml.cs b/FModel/Windows/SoundPlayer/AudioPlayer.xaml.cs index 7aa3b24b..6d30cfd0 100644 --- a/FModel/Windows/SoundPlayer/AudioPlayer.xaml.cs +++ b/FModel/Windows/SoundPlayer/AudioPlayer.xaml.cs @@ -281,7 +281,7 @@ namespace FModel.Windows.SoundPlayer /// private bool TryVGMStreamConvert(ListBoxViewModel2 selectedItem, out string wavFilePath) { - if (File.Exists(Properties.Settings.Default.OutputPath + "\\vgmstream\\test.exe")) + if (File.Exists(Properties.Settings.Default.OutputPath + "\\Vgm\\test.exe")) { Directory.CreateDirectory(Properties.Settings.Default.OutputPath + "\\Sounds\\" + selectedItem.Folder + "\\"); File.WriteAllBytes(Properties.Settings.Default.OutputPath + "\\Sounds\\" + selectedItem.Folder + "\\" + selectedItem.Content, selectedItem.Data); @@ -289,7 +289,7 @@ namespace FModel.Windows.SoundPlayer wavFilePath = Path.ChangeExtension(Properties.Settings.Default.OutputPath + "\\Sounds\\" + selectedItem.Folder + "\\" + selectedItem.Content, ".wav"); var vgmstream = Process.Start(new ProcessStartInfo { - FileName = Properties.Settings.Default.OutputPath + "\\vgmstream\\test.exe", + FileName = Properties.Settings.Default.OutputPath + "\\Vgm\\test.exe", Arguments = $"-o \"{wavFilePath}\" \"{Properties.Settings.Default.OutputPath + "\\Sounds\\" + selectedItem.Folder + "\\" + selectedItem.Content}\"", UseShellExecute = false, RedirectStandardOutput = true,