From fea5c3c318170da69a9cf82960d06d30edaa3f68 Mon Sep 17 00:00:00 2001 From: Mgamerz Date: Sat, 13 Jul 2024 19:25:53 -0600 Subject: [PATCH] LECoalesced SingleFile: Fix and support packing the localized config files so game can properly print error messages to debug logger --- .../Coalesced/CoalescedConverter.cs | 41 +++++++++++-------- .../Coalesced/Config/ConfigAssetBundle.cs | 10 ++--- .../Coalesced/LECoalesced.cs | 20 +++++---- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/CoalescedConverter.cs b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/CoalescedConverter.cs index 253ffa028..865ad59cc 100644 --- a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/CoalescedConverter.cs +++ b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/CoalescedConverter.cs @@ -12,6 +12,7 @@ using LegendaryExplorerCore.Gammtek.Extensions.Collections.Generic; using LegendaryExplorerCore.Gammtek.IO; using LegendaryExplorerCore.Misc; +using LegendaryExplorerCore.Packages; namespace LegendaryExplorerCore.Coalesced { @@ -26,7 +27,7 @@ public static class CoalescedConverter public static readonly int CoalescedMagicNumber = 1718448749; /// - /// The list of filenames supported by this compiler + /// The list of ini filenames supported by this compiler /// public static readonly SortedSet ProperNames = new SortedSet @@ -44,21 +45,28 @@ public static class CoalescedConverter "BioUI", "BioQA", "BioWeapon", - "Core", - "Descriptions", - "EditorTips", - "Engine", - "GFxUI", - "IpDrv", - "Launch", - "OnlineSubsystemGamespy", - "Startup", - "Subtitles", - "UnrealEd", - "WinDrv", - "XWindow" }; + /// + /// These files go in the Localizations folder and have a localized suffix. They aren't used except for some error handling messages + /// + public static readonly SortedSet LocalizedFiles = new SortedSet + { + "Core", + "Descriptions", + "EditorTips", + "Engine", + "GFxUI", + "IpDrv", + "Launch", + "OnlineSubsystemGamespy", + "Startup", + "Subtitles", + "UnrealEd", + "WinDrv", + "XWindow" + }; + public static readonly Dictionary SpecialCharacters = new Dictionary { @@ -654,13 +662,14 @@ public static CaseInsensitiveDictionary DecompileLE1LE2ToMemory( /// Compiles a LE1/LE2 Coalesced file from a memory map. /// /// Mapping of filenames to the ini object that represents the file contents. + /// Localization of this config file. This is important as it enables debug logger appErrorF messages. /// Memorystream of the compiled Coalesced file - public static MemoryStream CompileLE1LE2FromMemory(Dictionary iniFileMap) + public static MemoryStream CompileLE1LE2FromMemory(Dictionary iniFileMap, MELocalization loc) { LECoalescedBundle cb = new LECoalescedBundle(""); cb.Files.AddRange(iniFileMap); MemoryStream ms = new MemoryStream(); - cb.WriteToStream(ms); + cb.WriteToStream(ms, loc); ms.Position = 0; return ms; } diff --git a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/Config/ConfigAssetBundle.cs b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/Config/ConfigAssetBundle.cs index 7c349aa93..4c66390b1 100644 --- a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/Config/ConfigAssetBundle.cs +++ b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/Config/ConfigAssetBundle.cs @@ -156,8 +156,8 @@ private ConfigAssetBundle(MEGame game, string cookedDir, string dlcFolderName) foreach (var ini in iniFiles) { var fname = Path.GetFileNameWithoutExtension(ini); - if (!CoalescedConverter.ProperNames.Contains(fname, StringComparer.InvariantCultureIgnoreCase)) - continue; // Not supported. + if (!CoalescedConverter.ProperNames.Contains(fname, StringComparer.OrdinalIgnoreCase)) + continue; // Not supported. localization files are only supported in the main single file. Assets[fname] = ConfigFileProxy.LoadIni(ini); } } @@ -197,7 +197,7 @@ public CoalesceAsset GetAsset(string assetName, bool createIfNotFound = true) /// /// Commits this bundle to the specified single config file /// - public void CommitAssets(string outPath) + public void CommitAssets(string outPath, MELocalization loc) { if (Game is MEGame.LE1 or MEGame.LE2) { @@ -208,7 +208,7 @@ public void CommitAssets(string outPath) inis[asset.Key] = CoalesceAsset.ToIni(asset.Value); } - var compiledStream = CoalescedConverter.CompileLE1LE2FromMemory(inis); + var compiledStream = CoalescedConverter.CompileLE1LE2FromMemory(inis, loc); compiledStream.WriteToFile(outPath); HasChanges = false; } @@ -242,7 +242,7 @@ public void CommitDLCAssets(string outPath = null) else if (Game.IsGame3()) { var coalFile = Path.Combine(outPath ?? CookedDir, $@"Default_{DLCFolderName}.bin"); - CommitAssets(coalFile); + CommitAssets(coalFile, MELocalization.INT); // DLC does not support localization files as part of config. HasChanges = false; } } diff --git a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/LECoalesced.cs b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/LECoalesced.cs index 0a396399d..3d061a414 100644 --- a/LegendaryExplorer/LegendaryExplorerCore/Coalesced/LECoalesced.cs +++ b/LegendaryExplorer/LegendaryExplorerCore/Coalesced/LECoalesced.cs @@ -7,6 +7,7 @@ using System.Text; using LegendaryExplorerCore.Helpers; using LegendaryExplorerCore.Misc; +using LegendaryExplorerCore.Packages; // Tools to unpack/repack LE1 and LE2 coalesced files. // Originally by d00t (https://github.com/d00telemental/LECoal) @@ -281,7 +282,7 @@ public void WriteToDirectory(string destinationPath) public void WriteToFile(string destinationPath) { var ms = new MemoryStream(); - WriteToStream(ms); + WriteToStream(ms, destinationPath.GetUnrealLocalization()); ms.WriteToFile(destinationPath); } @@ -309,13 +310,13 @@ internal List splitValue(string val) return splitVal; } - public void WriteToStream(Stream ms) + public void WriteToStream(Stream ms, MELocalization lang) { var writer = new BinaryWriter(ms); writer.Write(Files.Count); foreach (var file in Files) { - writer.WriteCoalescedString(GetIniFullPath(file.Key)); + writer.WriteCoalescedString(GetIniFullPath(file.Key, lang)); writer.Write(file.Value.Sections.Count); foreach (var section in file.Value.Sections) @@ -337,9 +338,10 @@ public void WriteToStream(Stream ms) } } - private string GetIniFullPath(string filename) + private string GetIniFullPath(string filename, MELocalization localization) { var extension = Path.GetExtension(filename).ToLower(); + var fNameNoExt = Path.GetFileNameWithoutExtension(filename); // strip this off to ensure we don't double them up switch (extension) { case ".int": @@ -347,13 +349,13 @@ private string GetIniFullPath(string filename) case ".deu": case ".pol": case ".fra": - return $@"..\..\Localization\{extension.Substring(1).ToUpper()}\{filename}"; + case "" when CoalescedConverter.LocalizedFiles.Contains(fNameNoExt, StringComparer.OrdinalIgnoreCase): // No extension, may have been stripped + return $@"..\..\Localization\{localization.ToString().ToUpper()}\{fNameNoExt}.{localization.ToString().ToLower()}"; case ".ini": return $@"..\..\BIOGame\Config\{filename}"; - case "" when CoalescedConverter.ProperNames.Contains(filename, StringComparer.InvariantCultureIgnoreCase): // No extension, may have been stripped - return $@"..\..\BIOGame\Config\{filename}.ini"; - case "": - return $@"..\..\BIOGame\Config\{filename}.int"; // It's one of those localization files. Just set it to int. These are never used anyways. + case "" when CoalescedConverter.ProperNames.Contains(fNameNoExt, StringComparer.OrdinalIgnoreCase): // No extension, may have been stripped + return $@"..\..\BIOGame\Config\{fNameNoExt}.ini"; + } throw new Exception($"Filename '{filename}' has invalid file extension for LE1/LE2 Coalesced filename"); }