From ab030009c5739810806aa48c562ba777855368f8 Mon Sep 17 00:00:00 2001 From: Amr Shaheen Date: Fri, 1 Sep 2023 20:48:54 +0300 Subject: [PATCH] Changes for v2.3 --- UE4localizationsTool/Commands.cs | 54 ++-- UE4localizationsTool/Core/AssetHelper.cs | 39 ++- UE4localizationsTool/Core/Function.cs | 2 +- .../Core/Games/OctopathTraveler.cs | 136 ++++++++++ .../Core/Games/TheLastOricru.cs | 5 +- UE4localizationsTool/Core/IUasset.cs | 34 +++ UE4localizationsTool/Core/IoPackage.cs | 251 ++++++++++++++++++ UE4localizationsTool/Core/Object/Objects.cs | 30 +++ UE4localizationsTool/Core/StructProperty.cs | 78 +++--- UE4localizationsTool/Core/Uasset.cs | 238 ++++------------- UE4localizationsTool/Core/Uexp.cs | 32 ++- .../Forms/FrmMain.Designer.cs | 34 ++- UE4localizationsTool/Forms/FrmMain.cs | 66 ++++- UE4localizationsTool/Helper/CSVFile.cs | 62 +++++ UE4localizationsTool/Helper/MemoryList.cs | 14 +- UE4localizationsTool/Program.cs | 2 +- .../Properties/AssemblyInfo.cs | 31 +-- .../Properties/Resources.Designer.cs | 2 +- .../UE4localizationsTool.csproj | 34 +-- UE4localizationsTool/UpdateInfo.txt | 4 +- cso.dat | 14 - 21 files changed, 813 insertions(+), 349 deletions(-) create mode 100644 UE4localizationsTool/Core/Games/OctopathTraveler.cs create mode 100644 UE4localizationsTool/Core/IUasset.cs create mode 100644 UE4localizationsTool/Core/IoPackage.cs create mode 100644 UE4localizationsTool/Core/Object/Objects.cs create mode 100644 UE4localizationsTool/Helper/CSVFile.cs delete mode 100644 cso.dat diff --git a/UE4localizationsTool/Commands.cs b/UE4localizationsTool/Commands.cs index ecac589..1e279fe 100644 --- a/UE4localizationsTool/Commands.cs +++ b/UE4localizationsTool/Commands.cs @@ -44,7 +44,7 @@ public Commands(string Options, string SourcePath, Args args) Strings = new List>(); Console.ForegroundColor = ConsoleColor.Blue; ConsoleText = $"Exporting... '{Path.GetFileName(SourcePath)}' "; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; Strings = Export(SourcePath); @@ -55,8 +55,7 @@ public Commands(string Options, string SourcePath, Args args) } Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; SaveTextFile(SourcePath + ".txt"); @@ -74,7 +73,7 @@ public Commands(string Options, string SourcePath, Args args) case "-import"://Single File Without rename Console.ForegroundColor = ConsoleColor.Blue; ConsoleText = $"Importing... '{Path.GetFileName(SourcePath)}' "; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; if (!SourcePath.EndsWith(".txt", StringComparison.OrdinalIgnoreCase)) @@ -84,8 +83,7 @@ public Commands(string Options, string SourcePath, Args args) Import(Path.ChangeExtension(SourcePath, null), File.ReadAllLines(SourcePath), Options.ToLower()); Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; @@ -113,7 +111,7 @@ private void SaveTextFile(string FilePath) { Console.ForegroundColor = ConsoleColor.Blue; string ConsoleText = "Saving text file... "; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; string[] stringsArray = new string[Strings.Count]; @@ -141,8 +139,7 @@ private void SaveTextFile(string FilePath) File.WriteAllLines(FilePath, stringsArray); Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; } @@ -163,16 +160,16 @@ private List> Export(string FilePath) } else if (FilePath.EndsWith(".uasset", StringComparison.OrdinalIgnoreCase) || FilePath.EndsWith(".umap", StringComparison.OrdinalIgnoreCase)) { - Uasset Uasset = new Uasset(FilePath); + IUasset Uasset = Uexp.GetUasset(FilePath); if (Flags.HasFlag(Args.method2)) { Uasset.UseMethod2 = true; } - Uexp Uexp = new Uexp(Uasset); - return Uexp.Strings; - // SizeOfRecord = Uexp.Strings.Count; + Uexp uexp = new Uexp(Uasset); + return uexp.Strings; + // SizeOfRecord = uexp.Strings.Count; } else { @@ -189,13 +186,12 @@ private void ExportFolder(string FolderPath) } Console.ForegroundColor = ConsoleColor.Blue; string ConsoleText = "Scaning for files..."; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; string[] LanguageFiles = Directory.GetFiles(FolderPath, "*.*", SearchOption.AllDirectories).Where(x => x.EndsWith(".locres", StringComparison.OrdinalIgnoreCase) || x.EndsWith(".uasset", StringComparison.OrdinalIgnoreCase) || x.EndsWith(".umap", StringComparison.OrdinalIgnoreCase)).ToArray(); Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; if (LanguageFiles.Count() == 0) @@ -207,7 +203,7 @@ private void ExportFolder(string FolderPath) { Console.ForegroundColor = ConsoleColor.Blue; ConsoleText = $"[{i + 1}:{LanguageFiles.Count()}] Exporting... '{Path.GetFileName(LanguageFiles[i])}' "; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; int ThisPosition = Strings.Count - 1; @@ -227,8 +223,7 @@ private void ExportFolder(string FolderPath) catch (Exception EX) { Console.ForegroundColor = ConsoleColor.Red; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Fail"); + Console.Write("Fail\n"); Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Yellow; @@ -238,8 +233,7 @@ private void ExportFolder(string FolderPath) } Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; } } @@ -304,18 +298,18 @@ private void Import(string FilePath, string[] Values, string Option) } else if (FilePath.EndsWith(".uasset", StringComparison.OrdinalIgnoreCase) || FilePath.EndsWith(".umap", StringComparison.OrdinalIgnoreCase)) { - Uasset Uasset = new Uasset(FilePath); + IUasset Uasset = Uexp.GetUasset(FilePath); if (Flags.HasFlag(Args.method2)) { Uasset.UseMethod2 = true; } - Uexp Uexp = new Uexp(Uasset); - EditList(Uexp.Strings, Values); + Uexp uexp = new Uexp(Uasset); + EditList(uexp.Strings, Values); if (Option == "-import") { - Uexp.SaveFile(FilePath); + uexp.SaveFile(FilePath); return; } @@ -328,7 +322,7 @@ private void Import(string FilePath, string[] Values, string Option) FilePath = Path.ChangeExtension(FilePath, null) + "_NEW.umap"; } - Uexp.SaveFile(FilePath); + uexp.SaveFile(FilePath); } else { @@ -368,7 +362,7 @@ private void ImportFolder(string FolderPath, string[] Values, string Option) FilePath = FilePath.Replace(@"\\", @"\"); Console.ForegroundColor = ConsoleColor.Blue; string ConsoleText = $"[{PathIndex + 1}:{Indexs.Length}] Importing... '{Path.GetFileName(FilePath)}' "; - Console.WriteLine(ConsoleText); + Console.Write(ConsoleText); Console.ForegroundColor = ConsoleColor.White; string[] StringArrayValues = new string[ArraySize]; Array.Copy(Values, Indexs[PathIndex] + 1, StringArrayValues, 0, ArraySize); @@ -383,8 +377,7 @@ private void ImportFolder(string FolderPath, string[] Values, string Option) catch (Exception EX) { Console.ForegroundColor = ConsoleColor.Red; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Fail"); + Console.Write("Fail\n"); Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Yellow; @@ -393,8 +386,7 @@ private void ImportFolder(string FolderPath, string[] Values, string Option) continue; } Console.ForegroundColor = ConsoleColor.Green; - Console.SetCursorPosition(ConsoleText.Length, Console.CursorTop - 1); - Console.WriteLine("Done"); + Console.Write("Done\n"); Console.ForegroundColor = ConsoleColor.White; } diff --git a/UE4localizationsTool/Core/AssetHelper.cs b/UE4localizationsTool/Core/AssetHelper.cs index 67e45f8..0475b42 100644 --- a/UE4localizationsTool/Core/AssetHelper.cs +++ b/UE4localizationsTool/Core/AssetHelper.cs @@ -8,7 +8,7 @@ namespace AssetParser public static class AssetHelper { - public static string GetPropertyName(this Uasset SourceFile, int Index) + public static string GetPropertyName(this IUasset SourceFile, int Index) { if (SourceFile.NAMES_DIRECTORY.Count > Index && Index > 0) { @@ -17,7 +17,7 @@ public static string GetPropertyName(this Uasset SourceFile, int Index) return Index.ToString(); } - public static string GetExportPropertyName(this Uasset SourceFile, int Index) + public static string GetExportPropertyName(this IUasset SourceFile, int Index) { if (SourceFile.IOFile) { @@ -69,10 +69,11 @@ private static int GetRequiredUtf16Padding(uint NameData) { return (int)(NameData & 1u); } - private static bool IsUtf16(byte NameData) + public static bool IsUtf16(byte NameData) { return (NameData & 0x80u) != 0; } + public static string GetStringUES(this MemoryList memoryList) { string Stringvalue = ""; @@ -98,6 +99,29 @@ public static string GetStringUES(this MemoryList memoryList) return ReplaceBreaklines(Stringvalue).TrimEnd('\0'); } + + public static string GetStringUES(this MemoryList memoryList, short namedata) + { + string Stringvalue; + byte[] Data = new byte[2]; + Data[0] = (byte)(namedata & 0xff); + Data[1] = (byte)(namedata >> 8); + + int len = (int)((Data[0] & 0x7Fu) << 8) + Data[1]; + + if (IsUtf16(Data[0])) + { + Stringvalue = memoryList.GetStringValue(len * 2, true, -1, Encoding.Unicode); + } + else + { + Stringvalue = memoryList.GetStringValue(len); + } + + + return ReplaceBreaklines(Stringvalue).TrimEnd('\0'); + } + public static string GetStringUE(this MemoryList memoryList, Encoding encoding) { string Stringvalue = ReplaceBreaklines(memoryList.GetStringValueN(true, -1, encoding)); @@ -119,20 +143,20 @@ public static string GetStringUE(this MemoryList memoryList, int Lenght, bool Sa - public static void ReplaceStringUE_Func(this MemoryList memoryList, string StringValue) + public static int ReplaceStringUE_Func(this MemoryList memoryList, string StringValue) { - + int StringLength = 0; StringValue = ReplaceBreaklines(StringValue, true); memoryList.Skip(-1); ExprToken eExpr = (ExprToken)memoryList.GetByteValue(); if (eExpr == ExprToken.EX_StringConst) { - memoryList.DeleteStringN(-1, Encoding.ASCII); + StringLength = memoryList.DeleteStringN(-1, Encoding.ASCII); } else if (eExpr == ExprToken.EX_UnicodeStringConst) { - memoryList.DeleteStringN(-1, Encoding.Unicode); + StringLength = memoryList.DeleteStringN(-1, Encoding.Unicode); } memoryList.Skip(-1); @@ -153,6 +177,7 @@ public static void ReplaceStringUE_Func(this MemoryList memoryList, string Strin memoryList.SetByteValue((byte)ExprToken.EX_UnicodeStringConst); memoryList.InsertStringValueN(StringValue, true, -1, encoding); } + return StringLength; } diff --git a/UE4localizationsTool/Core/Function.cs b/UE4localizationsTool/Core/Function.cs index 70a1fb2..4f6898a 100644 --- a/UE4localizationsTool/Core/Function.cs +++ b/UE4localizationsTool/Core/Function.cs @@ -41,7 +41,7 @@ public Function(MemoryList memoryList, Uexp Uexp, bool modify = false) int ExportIndex = memoryList.GetIntValue(); IndexEntries.Add(ExportIndex); } - + //TODO :( if (uexp.UassetData.Exports_Directory[Uexp.ExportIndex].Value >= 4 || uexp.UassetData.EngineVersion >= UEVersions.VER_UE4_ADDED_PACKAGE_OWNER) { diff --git a/UE4localizationsTool/Core/Games/OctopathTraveler.cs b/UE4localizationsTool/Core/Games/OctopathTraveler.cs new file mode 100644 index 0000000..d583f2e --- /dev/null +++ b/UE4localizationsTool/Core/Games/OctopathTraveler.cs @@ -0,0 +1,136 @@ +using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.Text; + +namespace AssetParser +{ + public class OctopathTraveler + { + //Octopath Traveler: Champions of the Continent + readonly MemoryList MemoryData; + public OctopathTraveler(MemoryList memoryList, string PropertyName, Uexp uexp, bool Modify = false) + { + MemoryData = memoryList; + if (GetString() != "m_DataList") + { + throw new Exception("Not supported data type: !m_DataList"); + } + MemoryData.Skip(1);//0xdc + int Count = MemoryData.GetUShortValue(true, -1, Endian.Big); + + + for (int i = 0; i < Count; i++) + { + while (GetString() != "m_gametext") + { + SkipIds(); + } + + for (int n = 0; n < 12; n++) + { + string value = GetString(); + if (value == null) continue; + + if (!Modify) + { + uexp.Strings.Add(new List() { "m_gametext", AssetHelper.ReplaceBreaklines(value) }); + ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 1][1], ConsoleColor.Magenta); + } + else + { + string replacevalue = AssetHelper.ReplaceBreaklines(uexp.Strings[uexp.CurrentIndex++][1], true); + if (value != replacevalue) + ReplaceString(replacevalue); + } + } + + } + + + } + + + + private int StringOffset; + private string GetString(int m_size) + { + return MemoryData.GetStringValue(m_size, true, -1, Encoding.UTF8); + } + + private void ReplaceString(string value) + { + byte[] bytes = Encoding.UTF8.GetBytes(value); + int StringLenght = MemoryData.GetPosition() - StringOffset; + MemoryData.Seek(StringOffset); + MemoryData.DeleteBytes(StringLenght); + + MemoryData.InsertByteValue(0xda); + MemoryData.InsertShortValue((short)bytes.Length, true, -1, Endian.Big); + MemoryData.InsertBytes(bytes); + } + + + private void SkipIds() + { + byte value = MemoryData.GetByteValue();//unsigned byte + + if (value >> 4 == 0xd) + { + byte casebyte = (byte)(value & 0xf); + //this should be m_id value (byte - word - dword) -> big endian + //0 -> dword + if (casebyte != 0) + MemoryData.Skip(sizeof(short) * casebyte); + else + MemoryData.Skip(sizeof(short) * 2); + } + + + if (value == 0x9c) + { + for (int n = 0; n < 12; n++) + { + SkipIds(); + } + } + + } + + + + private string GetString() + { + byte value = MemoryData.GetByteValue();//unsigned byte + if (value == 0xa0) + { + return null; + } + + if ((value >> 4) == 0xa) + { + StringOffset = MemoryData.GetPosition() - 1; + return GetString(value & 0xf); + } + + if (value >> 4 == 0xd) + { + byte casebyte = (byte)(value & 0xf); + if (casebyte == 0xa) + { + StringOffset = MemoryData.GetPosition() - 1; + return GetString(MemoryData.GetShortValue(true, -1, Endian.Big)); + } + } + + + if (value == 0x9c) + { + return GetString(); + } + + return GetString(); + } + + } +} diff --git a/UE4localizationsTool/Core/Games/TheLastOricru.cs b/UE4localizationsTool/Core/Games/TheLastOricru.cs index a630dc1..1e790f9 100644 --- a/UE4localizationsTool/Core/Games/TheLastOricru.cs +++ b/UE4localizationsTool/Core/Games/TheLastOricru.cs @@ -1,10 +1,9 @@ -using AssetParser; -using Helper.MemoryList; +using Helper.MemoryList; using System; using System.Collections.Generic; using System.Text; -namespace UE4localizationsTool.Core.Games +namespace AssetParser { public class TheLastOricru { diff --git a/UE4localizationsTool/Core/IUasset.cs b/UE4localizationsTool/Core/IUasset.cs new file mode 100644 index 0000000..76d8668 --- /dev/null +++ b/UE4localizationsTool/Core/IUasset.cs @@ -0,0 +1,34 @@ +using AssetParser.Object; +using Helper.MemoryList; +using System.Collections.Generic; + +namespace AssetParser +{ + public interface IUasset + { + int LegacyFileVersion { get; set; } + UEVersions EngineVersion { get; set; } + EPackageFlags PackageFlags { get; set; } + int File_Directory_Offset { get; set; } + int Number_of_Names { get; set; } + int Name_Directory_Offset { get; set; } + int Number_Of_Exports { get; set; } + int Exports_Directory_Offset { get; set; } + int Number_Of_Imports { get; set; } + int Imports_Directory_Offset { get; set; } + List NAMES_DIRECTORY { get; set; } + List Imports_Directory { get; set; } + List Exports_Directory { get; set; } + MemoryList UassetFile { get; set; } + bool IOFile { get; set; } + bool IsNotUseUexp { get; set; } + bool UseFromStruct { get; set; } + bool AutoVersion { get; set; } + bool UseMethod2 { get; set; } + int PathCount { get; set; } + bool PathModify { get; set; } + void EditName(string NewStr, int Index); + void ExportReadOrEdit(bool Modify = false); + void UpdateOffset(); + } +} \ No newline at end of file diff --git a/UE4localizationsTool/Core/IoPackage.cs b/UE4localizationsTool/Core/IoPackage.cs new file mode 100644 index 0000000..1a3e953 --- /dev/null +++ b/UE4localizationsTool/Core/IoPackage.cs @@ -0,0 +1,251 @@ +using AssetParser.Object; +using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace AssetParser +{ + public class IoPackage : IUasset + { + public int LegacyFileVersion { get; set; } + public UEVersions EngineVersion { get; set; } + public EPackageFlags PackageFlags { get; set; } + public int File_Directory_Offset { get; set; } + public int Number_of_Names { get; set; } + public int Name_Directory_Offset { get; set; } + public int Number_Of_Exports { get; set; } + public int Exports_Directory_Offset { get; set; } + public int Number_Of_Imports { get; set; } + public int Imports_Directory_Offset { get; set; } + public int ExportBundleEntriesOffset { get; set; } + public List NAMES_DIRECTORY { get; set; } + public List Imports_Directory { get; set; } + public List Exports_Directory { get; set; } + public MemoryList UassetFile { get; set; } + public bool IOFile { get; set; } = true; + public bool IsNotUseUexp { get; set; } + public bool UseFromStruct { get; set; } + public bool AutoVersion { get; set; } + public bool UseMethod2 { get; set; } + + + public int Header_Size { get; set; } + public int Name_Directory_Size { get; set; } + public int Hash_Directory_offset { get; set; } + public int Hash_Directory_Size { get; set; } + public int Bundles_Offset { get; set; } + public int GraphData_Offset { get; set; } + public int GraphData_Size { get; set; } + public int PathCount { get; set; } = 0; + public bool PathModify { get; set; } = true; + + public IoPackage(string FilePath) + { + UassetFile = new MemoryList(FilePath); + //Todo + + IsNotUseUexp = true; + + if (UassetFile.GetIntValue(false, 4) == 0) + { + EngineVersion = UEVersions.VER_UE4_16; //?! + UE4Header(); + } + else + { + EngineVersion = UEVersions.VER_UE5_0; //?! + UE5Header(); + } + + //ScarletNexus-> Game/L10N + if (NAMES_DIRECTORY.First().StartsWith("/Game/L10N/")) + { + UseMethod2 = true; + } + } + + private void UE4Header() + { + UassetFile.Skip(16 + 4); + Header_Size = UassetFile.GetIntValue(); + Name_Directory_Offset = UassetFile.GetIntValue(); + Name_Directory_Size = UassetFile.GetIntValue(); + Hash_Directory_offset = UassetFile.GetIntValue(); + Hash_Directory_Size = UassetFile.GetIntValue(); + Imports_Directory_Offset = UassetFile.GetIntValue(); + Exports_Directory_Offset = UassetFile.GetIntValue(); + Bundles_Offset = UassetFile.GetIntValue(); + GraphData_Offset = UassetFile.GetIntValue(); + GraphData_Size = UassetFile.GetIntValue(); + + + File_Directory_Offset = GraphData_Offset + GraphData_Size; + Number_of_Names = Hash_Directory_Size / 8; + Number_Of_Exports = (Bundles_Offset - Exports_Directory_Offset) / 72 /*Block Size*/; + Number_Of_Imports = (Exports_Directory_Offset - Imports_Directory_Offset) / 8 /*Block Size*/; + + + //seek to position + UassetFile.Seek(Name_Directory_Offset, SeekOrigin.Begin); + //Get Names + NAMES_DIRECTORY = new List(); + for (int n = 0; n < Number_of_Names; n++) + { + NAMES_DIRECTORY.Add(UassetFile.GetStringUES()); + if (NAMES_DIRECTORY[n].Contains(@"/") && PathModify) + { + PathCount++; + } + else + { + PathModify = false; + } + } + + //UassetFile.Seek(Hash_Directory_offset, SeekOrigin.Begin); + + //seek to position + UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); + //Get Exports + Exports_Directory = new List(); + ExportReadOrEdit(); + } + + private void UE5Header() + { + //this for ue5_0 only + bool bHasVersioningInfo = UassetFile.GetUIntValue() == 1; + Header_Size = UassetFile.GetIntValue(); + UassetFile.Skip(8); //name + UassetFile.Skip(4); //PackageFlags + UassetFile.Skip(4); //CookedHeaderSize + UassetFile.Skip(4); //ImportedPublicExportHashesOffset + Imports_Directory_Offset = UassetFile.GetIntValue(); + Exports_Directory_Offset = UassetFile.GetIntValue(); + ExportBundleEntriesOffset = UassetFile.GetIntValue(); + UassetFile.Skip(4); //GraphDataOffset + + File_Directory_Offset = Header_Size; + Number_Of_Exports = (ExportBundleEntriesOffset - Exports_Directory_Offset) / 72; + Number_Of_Imports = (Exports_Directory_Offset - Imports_Directory_Offset) / sizeof(long); + + + if (bHasVersioningInfo) + { + throw new Exception("Not supported uasset!"); + } + + //---------------------- + //Get Names + NAMES_DIRECTORY = new List(); + Number_of_Names = UassetFile.GetIntValue(); + int NamesBlockSize = UassetFile.GetIntValue(); + UassetFile.Skip(8); //hashVersion + UassetFile.Skip(Number_of_Names * sizeof(long));//hashes + var NamesHeader = UassetFile.GetShorts(Number_of_Names); + + foreach (var header in NamesHeader) + { + NAMES_DIRECTORY.Add(UassetFile.GetStringUES(header)); + } + + + //Get Exports + UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); + Exports_Directory = new List(); + ExportReadOrEdit(); + } + + public void EditName(string NewStr, int Index) + { + return; + } + + public void ExportReadOrEdit(bool Modify = false) + { + //seek to position + UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); + int NextExportPosition = File_Directory_Offset; + + for (int n = 0; n < Number_Of_Exports; n++) + { + int Start = UassetFile.GetPosition(); + ExportsDirectory ExportsDirectory = new ExportsDirectory(); + ExportsDirectory.ExportStart = File_Directory_Offset; + if (!Modify) + { + UassetFile.Skip(8); + ExportsDirectory.ExportLength = (int)UassetFile.GetInt64Value(); + } + else + { + UassetFile.SetInt64Value(Header_Size + (NextExportPosition - File_Directory_Offset)); + UassetFile.SetInt64Value(Exports_Directory[n].ExportData.Count); + } + ExportsDirectory.ExportName = UassetFile.GetIntValue(); + UassetFile.Skip(4); + UassetFile.Skip(8); + + //Wrong way + ulong Class = UassetFile.GetUInt64Value(); + + switch (Class) + { + case 0x71E24A29987BD1EDu: + if (!NAMES_DIRECTORY.Contains("DataTable")) + { + NAMES_DIRECTORY.Add("DataTable"); + } + ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("DataTable"); + break; + case 0x70289FB93F770603u: + + if (!NAMES_DIRECTORY.Contains("StringTable")) + { + NAMES_DIRECTORY.Add("StringTable"); + } + ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("StringTable"); + + break; + case 0x574F27AEC05072D0u: + if (!NAMES_DIRECTORY.Contains("Function")) + { + NAMES_DIRECTORY.Add("Function"); + } + ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("Function"); + break; + default: + { + if (!NAMES_DIRECTORY.Contains("StructProperty")) + { + NAMES_DIRECTORY.Add("StructProperty"); + } + ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("StructProperty"); + break; + } + } + + + if (!Modify) + { + ExportsDirectory.ExportData = new List(); + ExportsDirectory.ExportData.AddRange(UassetFile.GetBytes(ExportsDirectory.ExportLength, false, NextExportPosition)); + Exports_Directory.Add(ExportsDirectory); + } + + NextExportPosition += ExportsDirectory.ExportLength; + UassetFile.Seek(Start + 72); + } + + + } + + + public void UpdateOffset() + { + + } + } +} diff --git a/UE4localizationsTool/Core/Object/Objects.cs b/UE4localizationsTool/Core/Object/Objects.cs new file mode 100644 index 0000000..6c76ee4 --- /dev/null +++ b/UE4localizationsTool/Core/Object/Objects.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace AssetParser.Object +{ + public struct ImportsDirectory + { + + public long ParentDirectoryNameID { get; set; } + public long ClassID { get; set; } + public int ParentImportObjectID { get; set; } + public int NameID { get; set; } + + } + public struct ExportsDirectory + { + public int ExportClass { get; set; } + public int ExportParent_1 { get; set; } + public int ExportParent_2 { get; set; } + public int Value { get; set; } + public int ExportName { get; set; } + public short ExportMemberType { get; set; } + public int ExportLength { get; set; } + public int ExportStart { get; set; } + + public List ExportData; + } + + + +} diff --git a/UE4localizationsTool/Core/StructProperty.cs b/UE4localizationsTool/Core/StructProperty.cs index 13c9907..ed5e458 100644 --- a/UE4localizationsTool/Core/StructProperty.cs +++ b/UE4localizationsTool/Core/StructProperty.cs @@ -1,6 +1,6 @@ using Helper.MemoryList; using System; -using UE4localizationsTool.Core.Games; + namespace AssetParser { @@ -120,13 +120,13 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { string ArrayName /*?*/ = uexp.UassetData.GetPropertyName(ArrayData.GetIntValue()); ConsoleMode.Print("ArrayName-> " + ArrayName, ConsoleColor.DarkYellow); - ArrayData.Skip(12); //null bytes + ArrayData.Skip(12); //null Databytes int StructpositionEdit = ArrayData.GetPosition(); int StructLength = ArrayData.GetIntValue(); ArrayData.Skip(4); //null or something string StructType = uexp.UassetData.GetPropertyName(ArrayData.GetIntValue()); ConsoleMode.Print("ArrayStructType-> " + StructType, ConsoleColor.DarkYellow); - ArrayData.Skip(20); //Unkown bytes + ArrayData.Skip(20); //Unkown Databytes if (FromStruct) { ArrayData.Skip(1); //null For "Struct" @@ -147,20 +147,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, } else { - - if (ArrayType == "ByteProperty" && PropertyName == "bytes") - { - new TheLastOricru(ArrayData, PropertyName, uexp, Modify); - } - else - { - - - for (int Arrayindex = 0; Arrayindex < ArrayCount; Arrayindex++) - { - PropertyParser(ref PropertyName, ArrayType, -1, ArrayData, uexp, Modify); - } - } + PropertyName = ReadArrayData(uexp, Modify, PropertyName, ArrayType, ArrayData, ArrayCount); } } catch (Exception ex) @@ -183,7 +170,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, string StructType = uexp.UassetData.GetPropertyName(memoryList.GetIntValue()); ConsoleMode.Print("StructType-> " + StructType, ConsoleColor.Gray); memoryList.Skip(4); //null or something - memoryList.Skip(16); //null bytes + memoryList.Skip(16); //null Databytes if (FromStruct) { memoryList.Skip(1); //null For "Struct" @@ -449,6 +436,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, } + private void PropertyParser(ref string PropertyName, string Property, int PropertyLength, MemoryList memoryList, Uexp uexp, bool Modify = false) { if (Property == "Int8Property") @@ -513,7 +501,7 @@ private void PropertyParser(ref string PropertyName, string Property, int Proper } else if (Property == "LazyObjectProperty") { - memoryList.Skip(16);// bytes range + memoryList.Skip(16);// Databytes range } else if (Property == "InterfaceProperty") { @@ -610,26 +598,20 @@ private void PropertyParser(ref string PropertyName, string Property, int Proper if (ArrayType == "StructProperty") { string ArrayName /*?*/ = uexp.UassetData.GetPropertyName(memoryList.GetIntValue()); - memoryList.Skip(12); //null bytes + memoryList.Skip(12); //null Databytes int StructpositionEdit = memoryList.GetPosition(); int StructLength = memoryList.GetIntValue(); memoryList.Skip(4); //null or something string StructType = uexp.UassetData.GetPropertyName(memoryList.GetIntValue()); - memoryList.Skip(20); //Unkown bytes + memoryList.Skip(20); //Unkown Databytes int StructPosition = memoryList.GetPosition(); MemoryList StructData = new MemoryList(memoryList.GetBytes(StructLength)); try { - if (ArrayType == "ByteProperty" && PropertyName == "bytes") + + for (int Arrayindex = 0; Arrayindex < ArrayCount; Arrayindex++) { - new TheLastOricru(StructData, PropertyName, uexp, Modify); - } - else - { - for (int Arrayindex = 0; Arrayindex < ArrayCount; Arrayindex++) - { - PropertyParser(ref PropertyName, ArrayType, -1, StructData, uexp, Modify); - } + PropertyParser(ref PropertyName, ArrayType, -1, StructData, uexp, Modify); } } catch (Exception ex) @@ -647,10 +629,7 @@ private void PropertyParser(ref string PropertyName, string Property, int Proper } else { - for (int Arrayindex = 0; Arrayindex < ArrayCount; Arrayindex++) - { - PropertyParser(ref PropertyName, ArrayType, -1, memoryList, uexp, Modify); - } + PropertyName = ReadArrayData(uexp, Modify, PropertyName, ArrayType, memoryList, ArrayCount); } } @@ -808,7 +787,38 @@ private void PropertyParser(ref string PropertyName, string Property, int Proper } + private string ReadArrayData(Uexp uexp, bool Modify, string PropertyName, string ArrayType, MemoryList ArrayData, int ArrayCount) + { + if (ArrayType == "ByteProperty" && PropertyName == "Databytes" || + ArrayType == "ByteProperty" && PropertyName == "BinaryData") + { + + int StartPosition = ArrayData.GetPosition() - 4; //for get ArrayCount + var data = new MemoryList(ArrayData.GetBytes(ArrayCount)); + + if (ArrayType == "ByteProperty" && PropertyName == "Databytes") + new TheLastOricru(data, PropertyName, uexp, Modify); + if (ArrayType == "ByteProperty" && PropertyName == "BinaryData") + new OctopathTraveler(data, PropertyName, uexp, Modify); + + if (Modify) + { + ArrayData.Seek(StartPosition); + ArrayData.SetIntValue(data.GetSize()); + ArrayData.ReplaceBytes(ArrayCount, data.ToArray()); + } + } + else + { + for (int Arrayindex = 0; Arrayindex < ArrayCount; Arrayindex++) + { + PropertyParser(ref PropertyName, ArrayType, -1, ArrayData, uexp, Modify); + } + } + + return PropertyName; + } } } diff --git a/UE4localizationsTool/Core/Uasset.cs b/UE4localizationsTool/Core/Uasset.cs index 41dc2d8..301739d 100644 --- a/UE4localizationsTool/Core/Uasset.cs +++ b/UE4localizationsTool/Core/Uasset.cs @@ -1,54 +1,28 @@ -using Helper.MemoryList; +using AssetParser.Object; +using Helper.MemoryList; using System; using System.Collections.Generic; using System.IO; namespace AssetParser { - - - - public class Uasset + public class Uasset : IUasset { - - public struct ImportsDirectory - { - - public long ParentDirectoryNameID { get; set; } - public long ClassID { get; set; } - public int ParentImportObjectID { get; set; } - public int NameID { get; set; } - - } - public struct ExportsDirectory - { - public int ExportClass { get; set; } - public int ExportParent_1 { get; set; } - public int ExportParent_2 { get; set; } - public int Value { get; set; } - public int ExportName { get; set; } - public short ExportMemberType { get; set; } - public int ExportLength { get; set; } - public int ExportStart { get; set; } - - public List ExportData; - } - List OffsetsList = new List(); private int NewSize; - public int LegacyFileVersion; - public UEVersions EngineVersion; + public int LegacyFileVersion { get; set; } + public UEVersions EngineVersion { get; set; } int numCustomVersions; - public EPackageFlags PackageFlags; - public int File_Directory_Offset; - public int Number_of_Names; - public int Name_Directory_Offset; - public int Number_Of_Exports; + public EPackageFlags PackageFlags { get; set; } + public int File_Directory_Offset { get; set; } + public int Number_of_Names { get; set; } + public int Name_Directory_Offset { get; set; } + public int Number_Of_Exports { get; set; } public int GatherableTextDataCount; public int GatherableTextDataOffset; - public int Exports_Directory_Offset; - public int Number_Of_Imports; - public int Imports_Directory_Offset; + public int Exports_Directory_Offset { get; set; } + public int Number_Of_Imports { get; set; } + public int Imports_Directory_Offset { get; set; } public int DependsOffset; public int SoftPackageReferencesCount; public int SoftPackageReferencesOffset; @@ -60,27 +34,18 @@ public struct ExportsDirectory public int WorldTileInfoDataOffset; public int PreloadDependencyCount; public int PreloadDependencyOffset; - public List NAMES_DIRECTORY; - public List Imports_Directory; - public List Exports_Directory; - public MemoryList UassetFile; - public MemoryList UexpFile; - public bool IsNotUseUexp; - public bool UseFromStruct = true; - public bool AutoVersion = false; - - - public int Header_Size; - public int Name_Directory_Size; - public int Hash_Directory_offset; - public int Hash_Directory_Size; - public int Bundles_Offset; - public int GraphData_Offset; - public int GraphData_Size; - public bool IOFile = false; - public int PathCount = 0; - public bool PathModify = true; - public bool UseMethod2 = false; + public List NAMES_DIRECTORY { get; set; } + public List Imports_Directory { get; set; } + public List Exports_Directory { get; set; } + public MemoryList UassetFile { get; set; } + public MemoryList UexpFile { get; set; } + public bool IsNotUseUexp { get; set; } + public bool UseFromStruct { get; set; } = true; + public bool AutoVersion { get; set; } = false; + public bool IOFile { get; set; } = false; + public int PathCount { get; set; } = 0; + public bool PathModify { get; set; } = true; + public bool UseMethod2 { get; set; } = false; @@ -90,62 +55,13 @@ public Uasset(string FilePath) UassetFile = new MemoryList(FilePath); - if (UassetFile.GetUIntValue(false) != 0x9E2A83C1u) - { + //if (UassetFile.GetUIntValue(false) != 0x9E2A83C1u) + //{ - //Todo - EngineVersion = UEVersions.VER_UE4_16; //?! - IsNotUseUexp = true; - IOFile = true; - UassetFile.Skip(16 + 4); - Header_Size = UassetFile.GetIntValue(); - Name_Directory_Offset = UassetFile.GetIntValue(); - Name_Directory_Size = UassetFile.GetIntValue(); - Hash_Directory_offset = UassetFile.GetIntValue(); - Hash_Directory_Size = UassetFile.GetIntValue(); - Imports_Directory_Offset = UassetFile.GetIntValue(); - Exports_Directory_Offset = UassetFile.GetIntValue(); - Bundles_Offset = UassetFile.GetIntValue(); - GraphData_Offset = UassetFile.GetIntValue(); - GraphData_Size = UassetFile.GetIntValue(); - - - File_Directory_Offset = GraphData_Offset + GraphData_Size; - Number_of_Names = Hash_Directory_Size / 8; - Number_Of_Exports = (Bundles_Offset - Exports_Directory_Offset) / 72 /*Block Size*/; - Number_Of_Imports = (Exports_Directory_Offset - Imports_Directory_Offset) / 8 /*Block Size*/; - - - //seek to position - UassetFile.Seek(Name_Directory_Offset, SeekOrigin.Begin); - //Get Names - NAMES_DIRECTORY = new List(); - for (int n = 0; n < Number_of_Names; n++) - { - NAMES_DIRECTORY.Add(UassetFile.GetStringUES()); - if (NAMES_DIRECTORY[n].Contains(@"/") && PathModify) - { - PathCount++; - } - else - { - PathModify = false; - } - } - //UassetFile.Seek(Hash_Directory_offset, SeekOrigin.Begin); - - - - //seek to position - UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); - //Get Exports - Exports_Directory = new List(); - ExportReadOrEditIO(); - - return; - } + // return; + //} @@ -186,6 +102,8 @@ public Uasset(string FilePath) UassetFile.Skip(4); } + + //seek to position UassetFile.Seek(Imports_Directory_Offset, SeekOrigin.Begin); //Get Imports @@ -223,8 +141,11 @@ private void ReadHeader(bool saveoffsets = true) if (LegacyFileVersion <= -8) { - UassetFile.GetIntValue(); //FileVersionUE5 - EngineVersion = UEVersions.VER_UE5_0; + int FileVersionUE5 = UassetFile.GetIntValue(); //FileVersionUE5 + if (FileVersionUE5 > 0) + EngineVersion = (UEVersions)FileVersionUE5; + else + EngineVersion = UEVersions.VER_UE5_0; } UassetFile.Skip(4);//FileVersionLicenseeUE @@ -332,6 +253,12 @@ private void ReadHeader(bool saveoffsets = true) DependsOffset = UassetFile.GetIntValue(); + if (EngineVersion < UEVersions.VER_UE4_OLDEST_LOADABLE_PACKAGE || EngineVersion >= UEVersions.AUTOMATIC_VERSION) + { + return; + } + + if (EngineVersion >= UEVersions.VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP) { SoftPackageReferencesCount = UassetFile.GetIntValue(); @@ -434,8 +361,6 @@ private void ReadHeader(bool saveoffsets = true) public void EditName(string NewStr, int Index) { - if (IOFile) return; - if (NAMES_DIRECTORY[Index] == NewStr) { return; @@ -481,12 +406,6 @@ public void EditName(string NewStr, int Index) public void ExportReadOrEdit(bool Modify = false) { - if (IOFile) - { - ExportReadOrEditIO(Modify); - return; - } - int NextExportPosition = File_Directory_Offset; //seek to position UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); @@ -552,8 +471,14 @@ public void ExportReadOrEdit(bool Modify = false) UassetFile.Skip(4 * 3); + if (EngineVersion < UEVersions.REMOVE_OBJECT_EXPORT_PACKAGE_GUID) + UassetFile.Skip(16);// PackageGuid + + if (EngineVersion >= UEVersions.TRACK_OBJECT_EXPORT_IS_INHERITED) + { + UassetFile.Skip(4); + } - UassetFile.Skip(16);// PackageGuid UassetFile.Skip(4); // PackageFlags if (EngineVersion >= UEVersions.VER_UE4_LOAD_FOR_EDITOR_GAME) @@ -561,6 +486,11 @@ public void ExportReadOrEdit(bool Modify = false) UassetFile.Skip(4); } + if (EngineVersion >= UEVersions.OPTIONAL_RESOURCES) + { + UassetFile.Skip(4); + } + if (EngineVersion >= UEVersions.VER_UE4_COOKED_ASSETS_IN_EDITOR_SUPPORT) { UassetFile.Skip(4); @@ -593,66 +523,6 @@ public void ExportReadOrEdit(bool Modify = false) } - public void ExportReadOrEditIO(bool Modify = false) - { - //seek to position - UassetFile.Seek(Exports_Directory_Offset, SeekOrigin.Begin); - int NextExportPosition = File_Directory_Offset; - - for (int n = 0; n < Number_Of_Exports; n++) - { - int Start = UassetFile.GetPosition(); - ExportsDirectory ExportsDirectory = new ExportsDirectory(); - ExportsDirectory.ExportStart = File_Directory_Offset; - if (!Modify) - { - UassetFile.Skip(8); - ExportsDirectory.ExportLength = (int)UassetFile.GetInt64Value(); - } - else - { - UassetFile.SetInt64Value(Header_Size + (NextExportPosition - File_Directory_Offset)); - UassetFile.SetInt64Value(Exports_Directory[n].ExportData.Count); - } - ExportsDirectory.ExportName = UassetFile.GetIntValue(); - UassetFile.Skip(4); - UassetFile.Skip(8); - - //Wrong way - ulong Class = UassetFile.GetUInt64Value(); - - - if (Class == 0x71E24A29987BD1EDu) - { - ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("DataTable"); - } - else if (Class == 0x70289FB93F770603u) - { - ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("StringTable"); - } - else if (Class == 0x574F27AEC05072D0u) - { - ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("Function"); - } - else - { - ExportsDirectory.ExportClass = NAMES_DIRECTORY.IndexOf("StructProperty"); - } - - - - if (!Modify) - { - ExportsDirectory.ExportData = new List(); - ExportsDirectory.ExportData.AddRange(UassetFile.GetBytes(ExportsDirectory.ExportLength, false, NextExportPosition)); - Exports_Directory.Add(ExportsDirectory); - } - - NextExportPosition += ExportsDirectory.ExportLength; - UassetFile.Seek(Start + 72); - } - } - int ExportSize() { int Totalsize = 0; diff --git a/UE4localizationsTool/Core/Uexp.cs b/UE4localizationsTool/Core/Uexp.cs index bcecf51..4a6fb37 100644 --- a/UE4localizationsTool/Core/Uexp.cs +++ b/UE4localizationsTool/Core/Uexp.cs @@ -1,13 +1,15 @@ using Helper.MemoryList; using System; using System.Collections.Generic; +using System.IO; + namespace AssetParser { public class Uexp : IAsset { - public Uasset UassetData; + public IUasset UassetData; public List> Strings { get; set; } //[Text id,Text Value,...] private int _CurrentIndex; @@ -29,16 +31,33 @@ public int CurrentIndex - public Uexp(Uasset assets) + public Uexp(IUasset UassetObject) { - UassetData = assets; + UassetData = UassetObject; Strings = new List>(); CurrentIndex = 0; ReadOrEdit(); } + public static IUasset GetUasset(string uassetpath) + { + var StreamFile = File.Open(uassetpath, FileMode.Open, FileAccess.Read); + var array = new byte[4]; + StreamFile.Read(array, 0, array.Length); + StreamFile.Close(); + //Todo + if (array[0] == 0xC1 && array[1] == 0x83 && array[2] == 0x2A && array[3] == 0x9E)//pak -> uasset + { + return new Uasset(uassetpath); + } + else//utoc -> uasset + { + return new IoPackage(uassetpath); + } + + } private void ReadOrEdit(bool Modify = false) { @@ -124,18 +143,21 @@ private void ReadOrEdit(bool Modify = false) case "MuseStringTable": new MuseStringTable(memoryList, this, Modify); break; + case "SubtitlesText": + new MuseStringTable(memoryList, this, Modify); + break; } ConsoleMode.Print($"-----------End------------", ConsoleColor.DarkRed); } catch (Exception ex) { - ConsoleMode.Print("Skip this export:\n" + ex.ToString(), ConsoleColor.Red,ConsoleMode.ConsoleModeType.Error); + ConsoleMode.Print("Skip this export:\n" + ex.ToString(), ConsoleColor.Red, ConsoleMode.ConsoleModeType.Error); // Skip this export } } } - + } diff --git a/UE4localizationsTool/Forms/FrmMain.Designer.cs b/UE4localizationsTool/Forms/FrmMain.Designer.cs index 48b83d6..568c743 100644 --- a/UE4localizationsTool/Forms/FrmMain.Designer.cs +++ b/UE4localizationsTool/Forms/FrmMain.Designer.cs @@ -41,6 +41,7 @@ private void InitializeComponent() this.exportAllTextToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.noNamesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.withNamesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.csvFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.importAllTextToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.find = new System.Windows.Forms.ToolStripMenuItem(); @@ -64,10 +65,10 @@ private void InitializeComponent() this.fontToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.rightToLeftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.darkModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Checkforupdates = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.Method2 = new System.Windows.Forms.ToolStripMenuItem(); this.UseFixedSize = new System.Windows.Forms.ToolStripMenuItem(); - this.Checkforupdates = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.commandLinesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.donateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -176,7 +177,8 @@ private void InitializeComponent() // this.exportAllTextToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.noNamesToolStripMenuItem, - this.withNamesToolStripMenuItem}); + this.withNamesToolStripMenuItem, + this.csvFileToolStripMenuItem}); this.exportAllTextToolStripMenuItem.Enabled = false; this.exportAllTextToolStripMenuItem.Name = "exportAllTextToolStripMenuItem"; this.exportAllTextToolStripMenuItem.Size = new System.Drawing.Size(229, 22); @@ -187,7 +189,7 @@ private void InitializeComponent() this.noNamesToolStripMenuItem.Enabled = false; this.noNamesToolStripMenuItem.Name = "noNamesToolStripMenuItem"; this.noNamesToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); - this.noNamesToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.noNamesToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.noNamesToolStripMenuItem.Text = "No names"; this.noNamesToolStripMenuItem.Click += new System.EventHandler(this.noNamesToolStripMenuItem_Click); // @@ -196,10 +198,17 @@ private void InitializeComponent() this.withNamesToolStripMenuItem.Enabled = false; this.withNamesToolStripMenuItem.Name = "withNamesToolStripMenuItem"; this.withNamesToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R))); - this.withNamesToolStripMenuItem.Size = new System.Drawing.Size(178, 22); + this.withNamesToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.withNamesToolStripMenuItem.Text = "With names"; this.withNamesToolStripMenuItem.Click += new System.EventHandler(this.withNamesToolStripMenuItem_Click); // + // csvFileToolStripMenuItem + // + this.csvFileToolStripMenuItem.Name = "csvFileToolStripMenuItem"; + this.csvFileToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.csvFileToolStripMenuItem.Text = "CSV file"; + this.csvFileToolStripMenuItem.Click += new System.EventHandler(this.csvFileToolStripMenuItem_Click); + // // importAllTextToolStripMenuItem // this.importAllTextToolStripMenuItem.Enabled = false; @@ -386,6 +395,14 @@ private void InitializeComponent() this.darkModeToolStripMenuItem.Text = "Dark mode"; this.darkModeToolStripMenuItem.CheckedChanged += new System.EventHandler(this.darkModeToolStripMenuItem_CheckedChanged); // + // Checkforupdates + // + this.Checkforupdates.CheckOnClick = true; + this.Checkforupdates.Name = "Checkforupdates"; + this.Checkforupdates.Size = new System.Drawing.Size(229, 22); + this.Checkforupdates.Text = "Check for Updates"; + this.Checkforupdates.CheckedChanged += new System.EventHandler(this.Checkforupdates_CheckedChanged); + // // toolStripSeparator4 // this.toolStripSeparator4.Name = "toolStripSeparator4"; @@ -411,14 +428,6 @@ private void InitializeComponent() this.UseFixedSize.Text = "Fixed Size"; this.UseFixedSize.Visible = false; // - // Checkforupdates - // - this.Checkforupdates.CheckOnClick = true; - this.Checkforupdates.Name = "Checkforupdates"; - this.Checkforupdates.Size = new System.Drawing.Size(229, 22); - this.Checkforupdates.Text = "Check for Updates"; - this.Checkforupdates.CheckedChanged += new System.EventHandler(this.Checkforupdates_CheckedChanged); - // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -734,6 +743,7 @@ private void InitializeComponent() private System.Windows.Forms.DataGridViewTextBoxColumn TextValue; private System.Windows.Forms.DataGridViewTextBoxColumn Index; private System.Windows.Forms.ToolStripMenuItem Checkforupdates; + private System.Windows.Forms.ToolStripMenuItem csvFileToolStripMenuItem; } } diff --git a/UE4localizationsTool/Forms/FrmMain.cs b/UE4localizationsTool/Forms/FrmMain.cs index cede82c..e6121b4 100644 --- a/UE4localizationsTool/Forms/FrmMain.cs +++ b/UE4localizationsTool/Forms/FrmMain.cs @@ -12,10 +12,13 @@ using System.Threading.Tasks; using System.Windows.Forms; using UE4localizationsTool.Controls; +using UE4localizationsTool.Helper; namespace UE4localizationsTool { + + public partial class FrmMain : NForm { struct DataRow @@ -119,8 +122,8 @@ public async void LoadFile(string filePath) } else if (filePath.ToLower().EndsWith(".uasset") || filePath.ToLower().EndsWith(".umap")) { - Uasset Uasset = await Task.Run(() => new Uasset(filePath)); - Uasset.UseMethod2 = Method2.Checked; + IUasset Uasset = await Task.Run(() => Uexp.GetUasset(filePath)); + Uasset.UseMethod2 = Uasset.UseMethod2? Uasset.UseMethod2 : Method2.Checked; Asset = await Task.Run(() => new Uexp(Uasset)); CreateBackupList(); if (!Asset.IsGood) @@ -179,6 +182,7 @@ private void ControlsMode(bool Enabled) noNamesToolStripMenuItem.Enabled = Enabled; withNamesToolStripMenuItem.Enabled = Enabled; clearFilterToolStripMenuItem.Enabled = Enabled; + csvFileToolStripMenuItem.Enabled = Enabled; } enum ExportType { @@ -236,12 +240,32 @@ private void ExportAll(ExportType exportType) private void importAllTextToolStripMenuItem_Click(object sender, EventArgs e) { + OpenFileDialog ofd = new OpenFileDialog(); - ofd.Filter = "Text File|*.txt"; + ofd.Filter = "Text File|*.txt;*.csv"; ofd.Title = "Import All Text"; if (ofd.ShowDialog() == DialogResult.OK) { + if (this.SortApply) SortDataGrid(2, true); + + if (ofd.FileName.EndsWith(".csv",StringComparison.InvariantCulture)) + { + try + { + CSVFile.Instance.Load(this.dataGridView1, ofd.FileName); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, ToolName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + MessageBox.Show("Successful import!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + + string[] DataGridStrings; try { @@ -279,8 +303,6 @@ private void importAllTextToolStripMenuItem_Click(object sender, EventArgs e) } - - if (this.SortApply) SortDataGrid(2, true); for (int n = 0; n < dataGridView1.Rows.Count; n++) { dataGridView1.Rows[n].Cells[1].Value = DataGridStrings[n]; @@ -791,7 +813,7 @@ private string ObjectToString(object Value) private void FrmMain_Load(object sender, EventArgs e) { if (Properties.Settings.Default.CheckForUpdates) - { + { this.Invoke(new Action(() => { float ToolVer = 0; @@ -843,7 +865,7 @@ private void FrmMain_Load(object sender, EventArgs e) }) ); - } + } } @@ -1004,5 +1026,35 @@ private void Checkforupdates_CheckedChanged(object sender, EventArgs e) Properties.Settings.Default.CheckForUpdates = Checkforupdates.Checked; Properties.Settings.Default.Save(); } + + private void csvFileToolStripMenuItem_Click(object sender, EventArgs e) + { + SaveFileDialog sfd = new SaveFileDialog(); + sfd.Filter = "CSV File|*.csv"; + sfd.Title = "Export All Text"; + sfd.FileName = Path.GetFileName(FilePath) + ".csv"; + + + if (sfd.ShowDialog() == DialogResult.OK) + { + try + { + CSVFile.Instance.Save(this.dataGridView1, sfd.FileName); + + if (Filter) + { + MessageBox.Show("Successful export!\n Remember to apply the same filter you using right now before 'import'.", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("Successful export!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + catch + { + MessageBox.Show("Can't write export file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); + } + } + } } } diff --git a/UE4localizationsTool/Helper/CSVFile.cs b/UE4localizationsTool/Helper/CSVFile.cs new file mode 100644 index 0000000..1e0d96d --- /dev/null +++ b/UE4localizationsTool/Helper/CSVFile.cs @@ -0,0 +1,62 @@ +using Microsoft.VisualBasic.FileIO; +using System.IO; +using System.Windows.Forms; + +namespace UE4localizationsTool.Helper +{ + public class CSVFile + { + public static CSVFile Instance { get; } = new CSVFile(); + + public char Delimiter { get; set; } = ','; + public bool HasHeader { get; set; } = true; + + public void Load(DataGridView dataGrid, string filePath) + { + + using (TextFieldParser parser = new TextFieldParser(filePath)) + { + parser.TextFieldType = FieldType.Delimited; + parser.SetDelimiters(Delimiter.ToString()); + + int i = -1; + if (!HasHeader) i++; + + while (!parser.EndOfData) + { + + string[] fields = parser.ReadFields(); + + if (HasHeader && i == -1) + { + i++; + continue; + } + + if (fields.Length >= 3 && !string.IsNullOrEmpty(fields[2])) + dataGrid.Rows[i].Cells["TextValue"].Value = fields[2]; + + i++; + } + } + } + + public void Save(DataGridView dataGrid, string filePath) + { + using (var writer = new StreamWriter(filePath)) + { + writer.WriteLine("Key,Source,Translation"); + foreach (DataGridViewRow row in dataGrid.Rows) + { + writer.WriteLine("\"" + FixedString(row.Cells["TextName"].Value) + "\"" + Delimiter.ToString() + "\"" + FixedString(row.Cells["TextValue"].Value) + "\"" + Delimiter.ToString() + "\"" + "\""); + } + } + } + + private string FixedString(object str) + { + return str.ToString().Replace("\"", "\"\""); + } + } + +} diff --git a/UE4localizationsTool/Helper/MemoryList.cs b/UE4localizationsTool/Helper/MemoryList.cs index 4fdbf49..023db4f 100644 --- a/UE4localizationsTool/Helper/MemoryList.cs +++ b/UE4localizationsTool/Helper/MemoryList.cs @@ -1318,7 +1318,7 @@ public string GetStringValueN(bool SavePosition = true, int SeekAndRead = -1, En } - public void DeleteStringN(int SeekAndRead = -1, Encoding encoding = null) + public int DeleteStringN(int SeekAndRead = -1, Encoding encoding = null) { if (encoding == null) { @@ -1326,13 +1326,19 @@ public void DeleteStringN(int SeekAndRead = -1, Encoding encoding = null) } int ThisPosition = GetPosition(); + int StringLength; if (SeekAndRead != -1) { - DeleteBytes(GetString(encoding, false).Length, SeekAndRead); - return; + Seek(SeekAndRead); + StringLength = GetString(encoding, false).Length; + DeleteBytes(StringLength); + Seek(ThisPosition); + return StringLength; } - + + StringLength = GetString(encoding, false).Length; DeleteBytes(GetString(encoding, false).Length); + return StringLength; } diff --git a/UE4localizationsTool/Program.cs b/UE4localizationsTool/Program.cs index 34bdc2b..f981687 100644 --- a/UE4localizationsTool/Program.cs +++ b/UE4localizationsTool/Program.cs @@ -140,7 +140,7 @@ static void Main(string[] args) catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(ex.Message); + Console.WriteLine("\n"+ex.Message); Console.ForegroundColor = ConsoleColor.White; } return; diff --git a/UE4localizationsTool/Properties/AssemblyInfo.cs b/UE4localizationsTool/Properties/AssemblyInfo.cs index 7abc48f..3e222ac 100644 --- a/UE4localizationsTool/Properties/AssemblyInfo.cs +++ b/UE4localizationsTool/Properties/AssemblyInfo.cs @@ -1,37 +1,14 @@ using System.Reflection; -using System.Resources; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. + [assembly: AssemblyTitle("UE4 localizations Tool")] -[assembly: AssemblyDescription("Simple to to edit engine texts")] +[assembly: AssemblyDescription("Simple tool to edit engine texts")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Arabic Subtitles")] [assembly: AssemblyProduct("UE4 localizations Tool Beta")] [assembly: AssemblyCopyright("Copyright © 2022 - By Amr Shaheen")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. +[assembly: AssemblyTrademark("amr shaheen")] [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c8aa2127-04a4-400b-9ca3-1951639bb0a3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0")] -[assembly: AssemblyFileVersion("2.2")] -[assembly: NeutralResourcesLanguage("ar")] +[assembly: AssemblyFileVersion("2.3")] diff --git a/UE4localizationsTool/Properties/Resources.Designer.cs b/UE4localizationsTool/Properties/Resources.Designer.cs index 4a8150b..cbbc29f 100644 --- a/UE4localizationsTool/Properties/Resources.Designer.cs +++ b/UE4localizationsTool/Properties/Resources.Designer.cs @@ -28,7 +28,7 @@ internal class Resources { private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } diff --git a/UE4localizationsTool/UE4localizationsTool.csproj b/UE4localizationsTool/UE4localizationsTool.csproj index 669c971..603d600 100644 --- a/UE4localizationsTool/UE4localizationsTool.csproj +++ b/UE4localizationsTool/UE4localizationsTool.csproj @@ -11,9 +11,9 @@ v4.7.2 512 true - true false + false publish\ true Disk @@ -24,7 +24,7 @@ false false true - 28 + 30 1.0.0.%2a false true @@ -34,7 +34,7 @@ AnyCPU true full - false + true bin\Debug\ TRACE;DEBUG prompt @@ -78,22 +78,13 @@ LocalIntranet + + + + Properties\app.manifest - - - - - - - - - - - - - @@ -104,12 +95,16 @@ + + + + @@ -141,6 +136,7 @@ FrmState.cs + @@ -198,5 +194,11 @@ + + + + + + \ No newline at end of file diff --git a/UE4localizationsTool/UpdateInfo.txt b/UE4localizationsTool/UpdateInfo.txt index 9dc672b..fecdb8e 100644 --- a/UE4localizationsTool/UpdateInfo.txt +++ b/UE4localizationsTool/UpdateInfo.txt @@ -1,3 +1,3 @@ UpdateFile -Tool_UpdateVer = 2.2 -Tool_UpdateSite = https://github.com/amrshaheen61/UE4LocalizationsTool/releases/tag/v2.2 \ No newline at end of file +Tool_UpdateVer = 2.3 +Tool_UpdateSite = https://github.com/amrshaheen61/UE4LocalizationsTool/releases/tag/v2.3 \ No newline at end of file diff --git a/cso.dat b/cso.dat deleted file mode 100644 index 5ccafaa..0000000 --- a/cso.dat +++ /dev/null @@ -1,14 +0,0 @@ -V1 -2:AssetParser,m -2:s1389313363,u -2:t1389313363,G -1:1,UE4localizationsTool,m_,u_,G_ -2:ExportFolder,F -2:FolderPath,U -2:ConsoleText,h -2:LanguageFiles,e -2:x,P -2:i,v -2:ThisPosition,X -2:Souce,I -2:EX,UH