From 1290385eae5dca858fb23fc144ec2f733eef4065 Mon Sep 17 00:00:00 2001 From: Amr Shaheen Date: Mon, 27 Jun 2022 03:49:49 +0200 Subject: [PATCH] Changes for v1.7 --- UE4localizationsTool/Commads.cs | 49 +- UE4localizationsTool/Core/AssetHelper.cs | 93 +- UE4localizationsTool/Core/Enum.cs | 116 +++ UE4localizationsTool/Core/Function.cs | 797 ++++++++++++++++++ UE4localizationsTool/Core/REDAdvTextData.cs | 157 ++++ .../Core/REDLocalizeTextData.cs | 68 ++ UE4localizationsTool/Core/StructProperty.cs | 208 ++--- UE4localizationsTool/Core/Uasset.cs | 9 +- UE4localizationsTool/Core/Uexp.cs | 21 +- UE4localizationsTool/Helper/MemoryList.cs | 111 ++- UE4localizationsTool/Program.cs | 96 ++- .../Properties/AssemblyInfo.cs | 2 +- .../UE4localizationsTool.csproj | 3 + UE4localizationsTool/UpdateInfo.txt | 4 +- 14 files changed, 1560 insertions(+), 174 deletions(-) create mode 100644 UE4localizationsTool/Core/Function.cs create mode 100644 UE4localizationsTool/Core/REDAdvTextData.cs create mode 100644 UE4localizationsTool/Core/REDLocalizeTextData.cs diff --git a/UE4localizationsTool/Commads.cs b/UE4localizationsTool/Commads.cs index e229ccd..2437d20 100644 --- a/UE4localizationsTool/Commads.cs +++ b/UE4localizationsTool/Commads.cs @@ -11,14 +11,15 @@ public class Commads { private List> Strings; private bool usefilter = false; + private bool nonames = false; private bool UseMatching = false; private bool RegularExpression = false; private bool ReverseMode = false; private List ArrayValues; - public Commads(string Options, string SourcePath, bool UseFilter = false) + public Commads(string Options, string SourcePath, bool UseFilter = false, bool NoNames = false) { usefilter = UseFilter; - + nonames = NoNames; if (usefilter) { GetFilterValues(); @@ -116,7 +117,14 @@ private void SaveTextFile(string FilePath) } else { - stringsArray[i] = item[0] + "=" + item[1]; + if (!nonames) + { + stringsArray[i] = item[0] + "=" + item[1]; + } + else + { + stringsArray[i] = item[1]; + } } i++; } @@ -238,12 +246,20 @@ void EditList(List> Strings, string[] StringValues) { try { - Strings[i][1] = StringValues[i].Split(new char[] { '=' }, 2)[1]; + if (!nonames) + { + Strings[i][1] = StringValues[i].Split(new char[] { '=' }, 2)[1]; + } + else + { + Strings[i][1] = StringValues[i]; + } } catch { throw new Exception("Can't parse this line from text file: " + StringValues[i]); } + } } @@ -518,10 +534,19 @@ private void ApplyFilter(List> Strings, string[] Array) { if (!ReverseMode) { + try { - Strings[x][1] = Array[i].Split(new char[] { '=' }, 2)[1]; - i++; + if (!nonames) + { + Strings[x][1] = Array[i].Split(new char[] { '=' }, 2)[1]; + i++; + } + else + { + Strings[x][1] = Array[i]; + i++; + } } catch { @@ -533,8 +558,16 @@ private void ApplyFilter(List> Strings, string[] Array) { try { - Strings[x][1] = Array[i].Split(new char[] { '=' }, 2)[1]; - i++; + if (!nonames) + { + Strings[x][1] = Array[i].Split(new char[] { '=' }, 2)[1]; + i++; + } + else + { + Strings[x][1] = Array[i]; + i++; + } } catch { diff --git a/UE4localizationsTool/Core/AssetHelper.cs b/UE4localizationsTool/Core/AssetHelper.cs index 0db3b65..89785d1 100644 --- a/UE4localizationsTool/Core/AssetHelper.cs +++ b/UE4localizationsTool/Core/AssetHelper.cs @@ -1,4 +1,7 @@ using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.IO; using System.Text; namespace AssetParser @@ -59,7 +62,75 @@ public static string GetStringUE(this MemoryList memoryList) return Stringvalue.TrimEnd('\0'); } - public static bool IsASCII(string StringValue) + + public static string GetStringUE(this MemoryList memoryList,Encoding encoding) + { + string Stringvalue = memoryList.GetStringValueN(true,-1, encoding); + Stringvalue = Stringvalue.Replace("\r\n", ""); + Stringvalue = Stringvalue.Replace("\r", ""); + Stringvalue = Stringvalue.Replace("\n", ""); + return Stringvalue.TrimEnd('\0'); + } + + public static string GetStringUE(this MemoryList memoryList,int Lenght, bool SavePosition = true, int SeekAndRead = -1, Encoding encoding = null) + { + string Stringvalue = memoryList.GetStringValue(Lenght, SavePosition, SeekAndRead, encoding); + Stringvalue = Stringvalue.Replace("\r\n", ""); + Stringvalue = Stringvalue.Replace("\r", ""); + Stringvalue = Stringvalue.Replace("\n", ""); + return Stringvalue.TrimEnd('\0'); + } + + + public static string ReplaceString(string Str) + { + Str = Str.Replace("", "\r\n"); + Str = Str.Replace("", "\r"); + return Str.Replace("", "\n"); + } + + + public static void ReplaceStringUE_Func(this MemoryList memoryList, string StringValue) + { + + StringValue = StringValue.Replace("", "\r\n"); + StringValue = StringValue.Replace("", "\r"); + StringValue = StringValue.Replace("", "\n"); + + memoryList.Skip(-1); + ExprToken eExpr = (ExprToken)memoryList.GetByteValue(); + if (eExpr == ExprToken.EX_StringConst) + { + memoryList.DeleteStringN(-1, Encoding.ASCII); + } + else if (eExpr == ExprToken.EX_UnicodeStringConst) + { + memoryList.DeleteStringN(-1, Encoding.Unicode); + } + memoryList.Skip(-1); + + + Encoding encoding = Encoding.Unicode; + if (IsASCII(StringValue)) + { + encoding = Encoding.ASCII; + } + + if (encoding == Encoding.ASCII) + { + memoryList.SetByteValue((byte)ExprToken.EX_StringConst); + memoryList.InsertStringValueN(StringValue,true,-1, encoding); + } + else + { + memoryList.SetByteValue((byte)ExprToken.EX_UnicodeStringConst); + memoryList.InsertStringValueN(StringValue, true, -1, encoding); + } + } + + + + public static bool IsASCII(string StringValue) { for (int n = 0; n < StringValue.Length; n++) { @@ -135,4 +206,24 @@ public static void ReplaceStringUE(this MemoryList memoryList, string StringValu } } + + + public class ReadStringProperty + { + public ReadStringProperty(MemoryList memoryList, Uexp uexp, string PropertyName, bool Modify = false) + { + if (!Modify) + { + uexp.Strings.Add(new List() { PropertyName, memoryList.GetStringUE() }); + ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 1][1], ConsoleColor.Magenta); + } + else + { + memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); + uexp.CurrentIndex++; + } + } + } + + } diff --git a/UE4localizationsTool/Core/Enum.cs b/UE4localizationsTool/Core/Enum.cs index e6ff2fc..3db0b32 100644 --- a/UE4localizationsTool/Core/Enum.cs +++ b/UE4localizationsTool/Core/Enum.cs @@ -343,4 +343,120 @@ public enum UE4Version VER_UE4_26 = 519, VER_UE4_27 = 522, }; + + public enum ExprToken + { + EX_LocalVariable = 0x00, + EX_InstanceVariable = 0x01, + EX_DefaultVariable = 0x02, + EX_Return = 0x04, + EX_Jump = 0x06, + EX_JumpIfNot = 0x07, + EX_Assert = 0x09, + EX_Nothing = 0x0B, + EX_Let = 0x0F, + EX_ClassContext = 0x12, + EX_MetaCast = 0x13, + EX_LetBool = 0x14, + EX_EndParmValue = 0x15, + EX_EndFunctionParms = 0x16, + EX_Self = 0x17, + EX_Skip = 0x18, + EX_Context = 0x19, + EX_Context_FailSilent = 0x1A, + EX_VirtualFunction = 0x1B, + EX_FinalFunction = 0x1C, + EX_IntConst = 0x1D, + EX_FloatConst = 0x1E, + EX_StringConst = 0x1F, + EX_ObjectConst = 0x20, + EX_NameConst = 0x21, + EX_RotationConst = 0x22, + EX_VectorConst = 0x23, + EX_ByteConst = 0x24, + EX_IntZero = 0x25, + EX_IntOne = 0x26, + EX_True = 0x27, + EX_False = 0x28, + EX_TextConst = 0x29, + EX_NoObject = 0x2A, + EX_TransformConst = 0x2B, + EX_IntConstByte = 0x2C, + EX_NoInterface = 0x2D, + EX_DynamicCast = 0x2E, + EX_StructConst = 0x2F, + EX_EndStructConst = 0x30, + EX_SetArray = 0x31, + EX_EndArray = 0x32, + EX_PropertyConst = 0x33, + EX_UnicodeStringConst = 0x34, + EX_Int64Const = 0x35, + EX_UInt64Const = 0x36, + EX_PrimitiveCast = 0x38, + EX_SetSet = 0x39, + EX_EndSet = 0x3A, + EX_SetMap = 0x3B, + EX_EndMap = 0x3C, + EX_SetConst = 0x3D, + EX_EndSetConst = 0x3E, + EX_MapConst = 0x3F, + EX_EndMapConst = 0x40, + EX_StructMemberContext = 0x42, + EX_LetMulticastDelegate = 0x43, + EX_LetDelegate = 0x44, + EX_LocalVirtualFunction = 0x45, + EX_LocalFinalFunction = 0x46, + EX_LocalOutVariable = 0x48, + EX_DeprecatedOp4A = 0x4A, + EX_InstanceDelegate = 0x4B, + EX_PushExecutionFlow = 0x4C, + EX_PopExecutionFlow = 0x4D, + EX_ComputedJump = 0x4E, + EX_PopExecutionFlowIfNot = 0x4F, + EX_Breakpoint = 0x50, + EX_InterfaceContext = 0x51, + EX_ObjToInterfaceCast = 0x52, + EX_EndOfScript = 0x53, + EX_CrossInterfaceCast = 0x54, + EX_InterfaceToObjCast = 0x55, + EX_WireTracepoint = 0x5A, + EX_SkipOffsetConst = 0x5B, + EX_AddMulticastDelegate = 0x5C, + EX_ClearMulticastDelegate = 0x5D, + EX_Tracepoint = 0x5E, + EX_LetObj = 0x5F, + EX_LetWeakObjPtr = 0x60, + EX_BindDelegate = 0x61, + EX_RemoveMulticastDelegate = 0x62, + EX_CallMulticastDelegate = 0x63, + EX_LetValueOnPersistentFrame = 0x64, + EX_ArrayConst = 0x65, + EX_EndArrayConst = 0x66, + EX_SoftObjectConst = 0x67, + EX_CallMath = 0x68, + EX_SwitchValue = 0x69, + EX_InstrumentationEvent = 0x6A, + EX_ArrayGetByRef = 0x6B, + EX_ClassSparseDataVariable = 0x6C, + EX_FieldPathConst = 0x6D, + EX_Max = 0x100, + }; + public enum TextHistoryType + { + None = -1, + Base = 0, + NamedFormat, + OrderedFormat, + ArgumentFormat, + AsNumber, + AsPercent, + AsCurrency, + AsDate, + AsTime, + AsDateTime, + Transform, + StringTableEntry, + TextGenerator + } + } diff --git a/UE4localizationsTool/Core/Function.cs b/UE4localizationsTool/Core/Function.cs new file mode 100644 index 0000000..6c575df --- /dev/null +++ b/UE4localizationsTool/Core/Function.cs @@ -0,0 +1,797 @@ +using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.Text; + +namespace AssetParser +{ + public class Function + { + MemoryList FuncBlock; + Uexp uexp; + bool Modify; + int ScriptBytecodeSize; + int scriptStorageSize; + List offsetList; + List> stringOffset; + int Index; + int NewSize; + public Function(MemoryList memoryList, Uexp Uexp, int index, bool modify = false) + { + uexp = Uexp; + Modify = modify; + offsetList = new List(); + stringOffset = new List>(); + Index = index; + NewSize = 0; + if (uexp.UassetData.EngineVersion < UE4Version.VER_UE4_16) + { + return; + } + + memoryList.Skip(4 * 2); + + int numIndexEntries = memoryList.GetIntValue(); + + for (int i = 0; i < numIndexEntries; i++) + { + memoryList.Skip(4); + } + + //TODO :( + if (uexp.UassetData.Exports_Directory[index].Value >= 4 || uexp.UassetData.EngineVersion >= UE4Version.VER_UE4_ADDED_PACKAGE_OWNER) + { + if (uexp.UassetData.AutoVersion) + { + uexp.UassetData.EngineVersion = UE4Version.VER_UE4_26; + } + + int num = memoryList.GetIntValue(); + + for (int i = 0; i < num; i++) + { + ReadFProperty(memoryList); + } + + } + int StartPosition = memoryList.GetPosition(); + ScriptBytecodeSize = memoryList.GetIntValue(); + scriptStorageSize = memoryList.GetIntValue(); + ConsoleMode.Print("-\n" + ScriptBytecodeSize + "\n" + scriptStorageSize + "\n-", ConsoleColor.Gray); + + FuncBlock = new MemoryList(memoryList.GetBytes(scriptStorageSize)); + + while (FuncBlock.GetPosition() < FuncBlock.GetSize()) + { + ExprToken ss = ReadExpression(); + ConsoleMode.Print(Convert.ToString(ss), ConsoleColor.Yellow); + } + + + for (int i = 0; i < offsetList.Count; i++) + { + ConsoleMode.Print("offset: " + offsetList[i] + " - " + FuncBlock.GetIntValue(false, offsetList[i]) + " - " + (FuncBlock.GetIntValue(false, offsetList[i]) - (ScriptBytecodeSize - scriptStorageSize)), ConsoleColor.Green); + } + + for (int i = 0; i < stringOffset.Count; i++) + { + ConsoleMode.Print("stringOffset: " + stringOffset[i][0] + " , " + stringOffset[i][1] + " , " + stringOffset[i][2], ConsoleColor.Green); + + } + + + + if (Modify) + { + + for (int i = 0; i < stringOffset.Count; i++) + { + // [old] [new] [size] + + offsetList.ForEach(x => + { + + int OldOffet = FuncBlock.GetIntValue(false, x); + + + if (OldOffet > stringOffset[i][0]) + { + ConsoleMode.Print("offset: " + x, ConsoleColor.DarkYellow); + int NewOffset = OldOffet + stringOffset[i][2]; + + FuncBlock.SetIntValue(NewOffset, false, x); + + ConsoleMode.Print("OldVal: " + OldOffet, ConsoleColor.DarkYellow); + ConsoleMode.Print("NewVal: " + NewOffset, ConsoleColor.DarkYellow); + ConsoleMode.Print("TotalSize: " + stringOffset[i][2], ConsoleColor.DarkYellow); + ConsoleMode.Print("- - - - - - - - ", ConsoleColor.Green); + + } + + }); + ConsoleMode.Print("-------------------------", ConsoleColor.Red); + } + + int NewSize = FuncBlock.GetSize() - scriptStorageSize; + + memoryList.Seek(StartPosition); + + memoryList.SetIntValue(memoryList.GetIntValue(false) + NewSize); + memoryList.SetIntValue(memoryList.GetIntValue(false) + NewSize); + + memoryList.ReplaceBytes(scriptStorageSize, FuncBlock.ToArray()); + + } + + + + + } + + + + + void ReadFProperty(MemoryList memoryList) + { + string Property = uexp.UassetData.GetPropertyName(memoryList.GetIntValue()); + memoryList.Skip(4); + string NameProperty = uexp.UassetData.GetPropertyName(memoryList.GetIntValue()); + memoryList.Skip(4); + int Flags = memoryList.GetIntValue(); + int ArrayDim = memoryList.GetIntValue(); + int ElementSize = memoryList.GetIntValue(); + long PropertyFlags = memoryList.GetInt64Value(); + ushort RepIndex = memoryList.GetUShortValue(); + long RepNotifyFunc = memoryList.GetInt64Value(); + byte BlueprintReplicationCondition = memoryList.GetByteValue(); + + + //ConsoleMode.Print(NameProperty + "=" + Property, ConsoleColor.Yellow); + + if (Property == "BoolProperty") + { + memoryList.Skip(6); + } + else if (Property == "ObjectProperty") + { + memoryList.Skip(4); + } + else if (Property == "DelegateProperty") + { + memoryList.Skip(4); + } + else if (Property == "StructProperty") + { + memoryList.Skip(4); + } + else if (Property == "EnumProperty") + { + memoryList.Skip(4); + ReadFProperty(memoryList); + } + else if (Property == "ByteProperty") + { + memoryList.Skip(4); + } + else if (Property == "ArrayProperty") + { + ReadFProperty(memoryList); + } + else if (Property == "SetProperty") + { + ReadFProperty(memoryList); + } + else if (Property == "ClassProperty") + { + memoryList.Skip(8); //[+4] + } + else if (Property == "SoftClassProperty") + { + memoryList.Skip(4); + } + else if (Property == "InterfaceProperty") + { + memoryList.Skip(4); + } + else if (Property == "MapProperty") + { + ReadFProperty(memoryList); + ReadFProperty(memoryList); + } + else if (Property == "ByteProperty") + { + memoryList.Skip(4); + } + } + + + + + + void ReadPPOINTER() + { + if (uexp.UassetData.EngineVersion >= UE4Version.VER_UE4_25) + { + int num = FuncBlock.GetIntValue(); + for (int i = 0; i < num; i++) + { + FuncBlock.Skip(4);//name + FuncBlock.Skip(4); + } + FuncBlock.Skip(4); + } + else + { + + FuncBlock.Skip(4); + } + } + + + + void ReadExpressionArray(ExprToken eExpr) + { + + while (true) + { + if (ReadExpression() == eExpr) + { + break; + } + } + + } + + + ExprToken ReadExpression() + { + ExprToken token = (ExprToken)FuncBlock.GetByteValue(); + ConsoleMode.Print(Convert.ToString(token), ConsoleColor.Blue); + int offset; + string NameProperty; + switch (token) + { + + case ExprToken.EX_LocalVariable: + ReadPPOINTER(); + break; + case ExprToken.EX_InstanceVariable: + ReadPPOINTER(); + break; + case ExprToken.EX_DefaultVariable: + ReadPPOINTER(); + break; + case ExprToken.EX_Return: + ReadExpression(); + break; + case ExprToken.EX_Jump: + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); + + break; + case ExprToken.EX_JumpIfNot: + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); //CodeOffset + ReadExpression(); + break; + case ExprToken.EX_Assert: + FuncBlock.Skip(3); + ReadExpression(); + break; + case ExprToken.EX_Nothing: + break; + + case ExprToken.EX_Let: + ReadPPOINTER(); + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_ClassContext: + ReadExpression(); + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); + ReadPPOINTER(); + ReadExpression(); + break; + + case ExprToken.EX_MetaCast: + FuncBlock.Skip(4); + ReadExpression(); + break; + + + case ExprToken.EX_LetBool: + ReadExpression(); + ReadExpression(); + break; + + + case ExprToken.EX_EndParmValue: + break; + + case ExprToken.EX_EndFunctionParms: + break; + + case ExprToken.EX_Self: + break; + + case ExprToken.EX_Skip: + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); //CodeOffset + ReadExpression(); + break; + + case ExprToken.EX_Context: + ReadExpression(); + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); + ReadPPOINTER(); + ReadExpression(); + break; + + case ExprToken.EX_Context_FailSilent: + ReadExpression(); + offsetList.Add(FuncBlock.GetPosition()); + offset = FuncBlock.GetIntValue(); + ReadPPOINTER(); + ReadExpression(); + break; + + case ExprToken.EX_VirtualFunction: + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + ReadExpressionArray(ExprToken.EX_EndFunctionParms); + break; + + case ExprToken.EX_FinalFunction: + FuncBlock.Skip(4); //pointer + ReadExpressionArray(ExprToken.EX_EndFunctionParms); + break; + + case ExprToken.EX_IntConst: + FuncBlock.Skip(4); //value + break; + + case ExprToken.EX_FloatConst: + FuncBlock.Skip(4); //value + break; + + case ExprToken.EX_StringConst: + int thisoffset = FuncBlock.GetPosition(); + if (!Modify) + { + string StringConst = FuncBlock.GetStringUE(Encoding.ASCII); + ConsoleMode.Print(StringConst, ConsoleColor.Blue); + uexp.Strings.Add(new List() { "FuncText" + Index, StringConst }); + } + else + { + FuncBlock.ReplaceStringUE_Func(uexp.Strings[uexp.CurrentIndex][1]); + uexp.CurrentIndex++; + } + stringOffset.Add(new List() { thisoffset + NewSize, thisoffset, (FuncBlock.GetSize() - scriptStorageSize) - NewSize }); + NewSize = FuncBlock.GetSize() - scriptStorageSize; + break; + + case ExprToken.EX_ObjectConst: + FuncBlock.Skip(4); + break; + + case ExprToken.EX_NameConst: + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + break; + + case ExprToken.EX_RotationConst: + FuncBlock.Skip(4 * 3); + break; + + case ExprToken.EX_VectorConst: + FuncBlock.Skip(4 * 3); ; + break; + + case ExprToken.EX_ByteConst: + FuncBlock.Skip(1); + break; + + case ExprToken.EX_IntZero: + break; + + case ExprToken.EX_IntOne: + break; + + case ExprToken.EX_True: + break; + + case ExprToken.EX_False: + break; + + case ExprToken.EX_TextConst: + byte TextLiteralType = FuncBlock.GetByteValue(); + switch (TextLiteralType) + { + case 0: //Empty + break; + case 1: //LocalizedText + ReadExpression(); + ReadExpression(); + ReadExpression(); + break; + case 2: // InvariantText IsCultureInvariant + ReadExpression(); + break; + case 3: //LiteralString + ReadExpression(); + break; + case 4: //StringTableEntry + FuncBlock.Skip(4); + ReadExpression(); + ReadExpression(); + break; + } + break; + + case ExprToken.EX_NoObject: + break; + + case ExprToken.EX_TransformConst: + + FuncBlock.Skip(4 * 4); + FuncBlock.Skip(4 * 3); + FuncBlock.Skip(4 * 3); + break; + + case ExprToken.EX_IntConstByte: + + FuncBlock.Skip(1); + break; + + case ExprToken.EX_NoInterface: + break; + + case ExprToken.EX_DynamicCast: + + FuncBlock.Skip(4); + ReadExpression(); + break; + + case ExprToken.EX_StructConst: + FuncBlock.Skip(4); + int StructSize = FuncBlock.GetIntValue(); + ReadExpressionArray(ExprToken.EX_EndStructConst); + break; + + case ExprToken.EX_EndStructConst: + break; + + case ExprToken.EX_SetArray: + + if (uexp.UassetData.EngineVersion >= UE4Version.VER_UE4_CHANGE_SETARRAY_BYTECODE) + { + ReadExpression(); + } + else + { + FuncBlock.Skip(4); + }; + + ReadExpressionArray(ExprToken.EX_EndArray); + break; + + case ExprToken.EX_EndArray: + break; + + case ExprToken.EX_PropertyConst: + + ReadPPOINTER(); + break; + + case ExprToken.EX_UnicodeStringConst: + int ThisOffset = FuncBlock.GetPosition(); + if (!Modify) + { + string UnicodeStringConst = FuncBlock.GetStringUE(Encoding.Unicode); + ConsoleMode.Print(UnicodeStringConst, ConsoleColor.Blue); + uexp.Strings.Add(new List() { "FuncText" + Index, UnicodeStringConst }); + // Console.WriteLine(UnicodeStringConst.Length); + // Console.ReadLine(); + } + else + { + FuncBlock.ReplaceStringUE_Func(uexp.Strings[uexp.CurrentIndex][1]); + uexp.CurrentIndex++; + } + stringOffset.Add(new List() { ThisOffset + NewSize, ThisOffset, (FuncBlock.GetSize() - scriptStorageSize) - NewSize }); + NewSize = FuncBlock.GetSize() - scriptStorageSize; + break; + + case ExprToken.EX_Int64Const: + + FuncBlock.Skip(8); //value + break; + + case ExprToken.EX_UInt64Const: + + FuncBlock.Skip(8); //value; + break; + + case ExprToken.EX_PrimitiveCast: + FuncBlock.Skip(1);//ConversionType + ReadExpression(); + break; + + case ExprToken.EX_SetSet: + + ReadExpression(); + FuncBlock.Skip(4);//Entrie num + ReadExpressionArray(ExprToken.EX_EndSet); + break; + + case ExprToken.EX_EndSet: + break; + + case ExprToken.EX_SetMap: + ReadExpression(); + FuncBlock.Skip(4);//Entrie num + ReadExpressionArray(ExprToken.EX_EndMap); + break; + + case ExprToken.EX_EndMap: + break; + + case ExprToken.EX_SetConst: + + ReadPPOINTER(); + FuncBlock.Skip(4);//Entrie num + ReadExpressionArray(ExprToken.EX_EndSetConst); + break; + + case ExprToken.EX_EndSetConst: + break; + + case ExprToken.EX_MapConst: + + ReadPPOINTER(); + ReadPPOINTER(); + FuncBlock.Skip(4);//Entrie num + ReadExpressionArray(ExprToken.EX_EndMapConst); + break; + + case ExprToken.EX_EndMapConst: + break; + + + case ExprToken.EX_StructMemberContext: + + ReadPPOINTER(); + ReadExpression(); + break; + + case ExprToken.EX_LetMulticastDelegate: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_LetDelegate: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_LocalVirtualFunction: + + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + ReadExpressionArray(ExprToken.EX_EndFunctionParms); + break; + + case ExprToken.EX_LocalFinalFunction: + + FuncBlock.Skip(4); //pointer + ReadExpressionArray(ExprToken.EX_EndFunctionParms); + break; + + case ExprToken.EX_LocalOutVariable: + + ReadPPOINTER(); + break; + + case ExprToken.EX_DeprecatedOp4A: + break; + + case ExprToken.EX_InstanceDelegate: + + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + break; + + case ExprToken.EX_PushExecutionFlow: + offsetList.Add(FuncBlock.GetPosition()); + uint PushingAddress = FuncBlock.GetUIntValue(); + break; + + + case ExprToken.EX_PopExecutionFlow: + break; + + case ExprToken.EX_ComputedJump: + + ReadExpression(); + break; + + case ExprToken.EX_PopExecutionFlowIfNot: + + ReadExpression(); + break; + + case ExprToken.EX_Breakpoint: + break; + + case ExprToken.EX_InterfaceContext: + + ReadExpression(); + break; + + case ExprToken.EX_ObjToInterfaceCast: + + FuncBlock.Skip(4); + ReadExpression(); + break; + + case ExprToken.EX_EndOfScript: + break; + + case ExprToken.EX_CrossInterfaceCast: + + FuncBlock.Skip(4); + ReadExpression(); + break; + + case ExprToken.EX_InterfaceToObjCast: + + FuncBlock.Skip(4); + ReadExpression(); + break; + + case ExprToken.EX_WireTracepoint: + break; + + case ExprToken.EX_SkipOffsetConst: + + FuncBlock.Skip(4); //value + break; + + case ExprToken.EX_AddMulticastDelegate: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_ClearMulticastDelegate: + + ReadExpression(); + break; + + case ExprToken.EX_Tracepoint: + break; + + case ExprToken.EX_LetObj: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_LetWeakObjPtr: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_BindDelegate: + + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_RemoveMulticastDelegate: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_CallMulticastDelegate: + + FuncBlock.Skip(4); //pointer + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_LetValueOnPersistentFrame: + + ReadPPOINTER(); + ReadExpression(); + break; + + case ExprToken.EX_ArrayConst: + + ReadPPOINTER(); + FuncBlock.Skip(4);//Entrie num + ReadExpression(); + break; + + case ExprToken.EX_EndArrayConst: + break; + + case ExprToken.EX_SoftObjectConst: + + ReadExpression(); + break; + + case ExprToken.EX_CallMath: + + FuncBlock.Skip(4); //pointer + ReadExpressionArray(ExprToken.EX_EndFunctionParms); + break; + + case ExprToken.EX_SwitchValue: + + + ushort numCases = FuncBlock.GetUShortValue(); + offsetList.Add(FuncBlock.GetPosition()); + int EndGotoOffset = FuncBlock.GetIntValue(); + ReadExpression(); + for (int i = 0; i < numCases; i++) + { + ReadExpression(); + FuncBlock.Skip(4); + ReadExpression(); + } + ReadExpression(); + break; + + + case ExprToken.EX_InstrumentationEvent: + + byte EventType = FuncBlock.GetByteValue(); + + if (EventType == 4) + { + NameProperty = uexp.UassetData.GetPropertyName(FuncBlock.GetIntValue()); + FuncBlock.Skip(4); + } + + break; + + case ExprToken.EX_ArrayGetByRef: + + ReadExpression(); + ReadExpression(); + break; + + case ExprToken.EX_ClassSparseDataVariable: + + ReadPPOINTER(); + break; + + case ExprToken.EX_FieldPathConst: + + ReadExpression(); + break; + default: + throw new Exception("Invalid token type: " + token.ToString("X2")); + + } + return token; + } + + + } + + + +} + diff --git a/UE4localizationsTool/Core/REDAdvTextData.cs b/UE4localizationsTool/Core/REDAdvTextData.cs new file mode 100644 index 0000000..7ff4d92 --- /dev/null +++ b/UE4localizationsTool/Core/REDAdvTextData.cs @@ -0,0 +1,157 @@ +using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.Text; + +namespace AssetParser +{ + public class REDAdvTextData + { + + int StartOffset; + int ATFBlockHeaderSize; + int UncompressedSize; + int CompressedSize; + string MagicId; + int StringCount; + + public REDAdvTextData(MemoryList memoryList, Uexp uexp, bool Modify = false) + { + memoryList.GetIntValue();//Null + + memoryList.Skip(12); //Unknown + memoryList.GetIntValue(); //Start Data offset + memoryList.Skip(8); //Unknown2 + UncompressedSize = memoryList.GetIntValue(); + CompressedSize = memoryList.GetIntValue(); + if (UncompressedSize != CompressedSize) + { + throw new Exception("Can't Parse this file."); + } + memoryList.Skip(4); //Unknown3 + + memoryList.GetIntValue();//Null + + StartOffset = memoryList.GetPosition(); + + MemoryList ATFBlock = new MemoryList(memoryList.GetBytes(UncompressedSize)); + + MagicId = ATFBlock.GetStringValueN(); + + if (MagicId != "ATF") + { + throw new Exception("Can't Parse this file.\nSend this file to author."); + } + + StringCount = ATFBlock.GetIntValue(); + ATFBlock.Skip(8); //Null + + int StringsIdPosition = ATFBlock.GetPosition(); + int StringsIdOffset = ATFBlock.GetIntValue(); + int StringsIdCount = ATFBlock.GetIntValue(); + int StringsIdSize = ATFBlock.GetIntValue(); + ATFBlock.Skip(4); //Null + byte[] IdBlock = ATFBlock.GetBytes(StringsIdSize, false, StringsIdOffset); + + int StringsInfoPosition = ATFBlock.GetPosition(); + int StringsInfoOffset = ATFBlock.GetIntValue(); + int StringsInfoCount = ATFBlock.GetIntValue(); + int StringsInfoSize = ATFBlock.GetIntValue(); + ATFBlock.Skip(4); //Null + MemoryList StringsInfo = new MemoryList(ATFBlock.GetBytes(StringsInfoSize, false, StringsInfoOffset)); + + int StringsTagsPosition = ATFBlock.GetPosition(); + int StringsTagsOffset = ATFBlock.GetIntValue(); + int StringsTagsSize = ATFBlock.GetIntValue(); + _ = ATFBlock.GetIntValue();//StringsTagsSize + ATFBlock.Skip(4); //Null + MemoryList StringsTags = new MemoryList(ATFBlock.GetBytes(StringsTagsSize, false, StringsTagsOffset)); + + int StringsBlockPosition = ATFBlock.GetPosition(); + int StringsBlockOffset = ATFBlock.GetIntValue(); + int StringLenght = ATFBlock.GetIntValue(); + int StringsBlockSize = ATFBlock.GetIntValue(); + ATFBlock.Skip(4); //Null + MemoryList StringsBlock = new MemoryList(ATFBlock.GetBytes(StringsBlockSize, false, StringsBlockOffset)); + + ATFBlockHeaderSize = ATFBlock.GetPosition(); + + if (!Modify) + { + for (int n = 0; n < StringCount; n++) + { + int tagsOffsets = StringsInfo.GetIntValue(); + int tagsLength = StringsInfo.GetIntValue(); + StringsInfo.Skip(8);//Null + int stringOffsets = StringsInfo.GetIntValue(); + int stringLength = StringsInfo.GetIntValue(); + StringsInfo.Skip(8);//Null + + // Console.WriteLine(n+": " + tagsOffsets +" - "+ tagsLength + " - "+ stringOffsets + " - "+ stringLength); + uexp.Strings.Add(new List() { StringsTags.GetStringUE(tagsLength, false, tagsOffsets), StringsBlock.GetStringUE(stringLength * 2, false, stringOffsets * 2, System.Text.Encoding.Unicode) }); + + } + } + else + { + StringsBlock.Clear(); + for (int n = 0; n < StringCount; n++) + { + + byte[] StrBytes = Encoding.Unicode.GetBytes(AssetHelper.ReplaceString(uexp.Strings[uexp.CurrentIndex][1] + '\0')); + uexp.CurrentIndex++; + + StringsInfo.GetIntValue(); //tagsOffsets + StringsInfo.GetIntValue();//tagsLength + StringsInfo.Skip(8);//Null + StringsInfo.SetIntValue(StringsBlock.GetSize() / 2); //stringOffsets + StringsInfo.SetIntValue((StrBytes.Length - 2) / 2); + StringsInfo.Skip(8);//Null + StringsBlock.Add(StrBytes); + } + + + + ATFBlock.SetSize(ATFBlockHeaderSize); + + + ATFBlock.Seek(StringsIdPosition); + ATFBlock.SetIntValue(ATFBlock.GetSize()); + ATFBlock.Skip(4); + ATFBlock.SetIntValue(IdBlock.Length); + ATFBlock.Add(IdBlock); + + + ATFBlock.Seek(StringsInfoPosition); + ATFBlock.SetIntValue(ATFBlock.GetSize()); + ATFBlock.Skip(4); + ATFBlock.SetIntValue(StringsInfo.GetSize()); + ATFBlock.Add(StringsInfo.ToArray()); + + + ATFBlock.Seek(StringsTagsPosition); + ATFBlock.SetIntValue(ATFBlock.GetSize()); + ATFBlock.SetIntValue(StringsTags.GetSize()); + ATFBlock.SetIntValue(StringsTags.GetSize()); + ATFBlock.Add(StringsTags.ToArray()); + + ATFBlock.Seek(StringsBlockPosition); + ATFBlock.SetIntValue(ATFBlock.GetSize()); + ATFBlock.SetIntValue(StringsBlock.GetSize() / 2); + ATFBlock.SetIntValue(StringsBlock.GetSize()); + ATFBlock.Add(StringsBlock.ToArray()); + + + + memoryList.SetSize(StartOffset); + memoryList.Add(ATFBlock.ToArray()); + } + + + } + + + + + } +} diff --git a/UE4localizationsTool/Core/REDLocalizeTextData.cs b/UE4localizationsTool/Core/REDLocalizeTextData.cs new file mode 100644 index 0000000..255d998 --- /dev/null +++ b/UE4localizationsTool/Core/REDLocalizeTextData.cs @@ -0,0 +1,68 @@ +using Helper.MemoryList; +using System; +using System.Collections.Generic; +using System.Text; + +namespace AssetParser +{ + public class REDLocalizeTextData + { + public REDLocalizeTextData(MemoryList memoryList, Uexp uexp, bool Modify = false) + { + + memoryList.GetIntValue();//null + memoryList.Skip(4 + 8 + 4 /*uexp position*/ + 4 + 4);//Unkown + int ValuesPosition = memoryList.GetPosition(); + int UncompressedSize = memoryList.GetIntValue(); + int CompressedSize = memoryList.GetIntValue(); + int StartPosition = memoryList.GetIntValue();// Uasset+Position + memoryList.Skip(4); + StartPosition = memoryList.GetPosition(); + short Value = memoryList.GetShortValue(); + string[] String = memoryList.GetStringValue(UncompressedSize - 2, false, -1, Encoding.Unicode).Split(new string[] { "\r\n" }, StringSplitOptions.None); + + + for (int n = 0; n < String.Length - 1; n = n + 2) + { + if (!Modify) + { + uexp.Strings.Add(new List() { String[n], String[n + 1] }); + } + else + { + String[n + 1] = uexp.Strings[uexp.CurrentIndex][1]; + uexp.CurrentIndex++; + } + } + + if (Modify) + { + MemoryList memory = new MemoryList(); + + memory.SetShortValue(Value); + + for (int n = 0; n < String.Length - 1; n++) + { + memory.SetStringValue(String[n] + "\r\n", true, -1, Encoding.Unicode); + } + + memoryList.SetSize(StartPosition); + memoryList.Seek(StartPosition); + memoryList.SetBytes(memory.ToArray()); + + memoryList.Seek(ValuesPosition); + memoryList.SetIntValue(memory.GetSize()); + memoryList.SetIntValue(memory.GetSize()); + } + + + + } + + + + + + + } +} diff --git a/UE4localizationsTool/Core/StructProperty.cs b/UE4localizationsTool/Core/StructProperty.cs index a903487..9ac3420 100644 --- a/UE4localizationsTool/Core/StructProperty.cs +++ b/UE4localizationsTool/Core/StructProperty.cs @@ -12,13 +12,13 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, while (memoryList.GetPosition() < memoryList.GetSize()) { - long GetPropertyName; + ulong GetPropertyName; if (FromProperty) { - GetPropertyName = memoryList.GetInt64Value(); + GetPropertyName = memoryList.GetUInt64Value(); ConsoleMode.Print($"PropertyNameMoving- {GetPropertyName} > " + memoryList.GetPosition(), ConsoleColor.DarkBlue); - if (GetPropertyName > uexp.UassetData.Number_of_Names) + if (GetPropertyName > (uint)uexp.UassetData.Number_of_Names) { memoryList.Skip(-4); continue; @@ -26,7 +26,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, } else { - GetPropertyName = memoryList.GetIntValue(); + GetPropertyName = (uint)memoryList.GetIntValue(); memoryList.Skip(4); } string PropertyName = uexp.UassetData.GetPropertyName((int)GetPropertyName); @@ -85,6 +85,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } ConsoleMode.Print("EndMapProperty", ConsoleColor.Blue); @@ -157,7 +158,9 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } + if (Modify) { memoryList.ReplaceBytes(PropertyLength, ArrayData.ToArray(), false, ArrayPosition); @@ -274,6 +277,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } } @@ -311,65 +315,67 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { memoryList.Skip(1); //null For "Struct" } - memoryList.Skip(4); //unkown - byte ContainText = memoryList.GetByteValue(); - MemoryList TextData; int TextDataPosition = memoryList.GetPosition(); - if (ContainText == 0xff) + MemoryList TextData = new MemoryList(memoryList.GetBytes(PropertyLength)); + + if (TextData.GetSize() == 5) { + continue; + } - try + try + { + if (uexp.UassetData.EngineVersion < UE4Version.VER_UE4_FTEXT_HISTORY) { - TextData = new MemoryList(memoryList.GetBytes(PropertyLength - 5)); - if (TextData.GetSize() == 0) + + new ReadStringProperty(TextData, uexp, PropertyName + "_0", Modify); + if (uexp.UassetData.EngineVersion >= UE4Version.VER_UE4_ADDED_NAMESPACE_AND_KEY_DATA_TO_FTEXT) { - continue; + new ReadStringProperty(TextData, uexp, PropertyName + "_1", Modify); + new ReadStringProperty(TextData, uexp, PropertyName + "_2", Modify); } - int TextLinesCount = TextData.GetIntValue(); - for (int i = 0; i < TextLinesCount; i++) + else { - if (!Modify) - { - uexp.Strings.Add(new List() { PropertyName+"_"+i, TextData.GetStringUE() }); - - } - else - { - TextData.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - memoryList.ReplaceBytes(PropertyLength - 5, TextData.ToArray(), false, TextDataPosition); - memoryList.Seek(TextDataPosition + TextData.GetSize()); - memoryList.SetIntValue(TextData.GetSize() + 5, false, ThisPosition); - } + new ReadStringProperty(TextData, uexp, PropertyName + "_2", Modify); } + } - catch - { - uexp.IsGood = false; - ConsoleMode.Print("Bug here.", ConsoleColor.Red); - } - continue; - } - try - { - TextData = new MemoryList(memoryList.GetBytes(PropertyLength - 5)); - if (!Modify) + + if (uexp.UassetData.EngineVersion > UE4Version.VER_UE4_FTEXT_HISTORY) { - uexp.Strings.Add(new List() { PropertyName + "_1", TextData.GetStringUE() }); - uexp.Strings.Add(new List() { PropertyName + "_2", TextData.GetStringUE() }); - uexp.Strings.Add(new List() { PropertyName + "_3", TextData.GetStringUE() }); + TextData.Skip(4); //unkown + TextHistoryType ContainText = (TextHistoryType)TextData.GetByteValue(); + + switch (ContainText) + { + case TextHistoryType.None: + int TextLinesCount = TextData.GetIntValue(); + for (int i = 0; i < TextLinesCount; i++) + { + new ReadStringProperty(TextData, uexp, PropertyName + "_" + (i + 1), Modify); + } + break; + + case TextHistoryType.Base: + new ReadStringProperty(TextData, uexp, PropertyName + "_1", Modify); + new ReadStringProperty(TextData, uexp, PropertyName + "_2", Modify); + new ReadStringProperty(TextData, uexp, PropertyName + "_3", Modify); + break; + case TextHistoryType.StringTableEntry: + TextData.Skip(8); //Id + new ReadStringProperty(TextData, uexp, PropertyName + "_1", Modify); + break; + + default: + throw new Exception("UnKnown 'TextProperty' type: " + ContainText.ToString()); + } } - else + + if (Modify) { - TextData.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - TextData.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - TextData.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - memoryList.ReplaceBytes(PropertyLength - 5, TextData.ToArray(), false, TextDataPosition); + memoryList.ReplaceBytes(PropertyLength, TextData.ToArray(), false, TextDataPosition); memoryList.Seek(TextDataPosition + TextData.GetSize()); - memoryList.SetIntValue(TextData.GetSize() + 5, false, ThisPosition); + memoryList.SetIntValue(TextData.GetSize(), false, ThisPosition); } } catch @@ -445,6 +451,7 @@ public StructProperty(MemoryList memoryList, Uexp uexp, bool FromStruct = true, { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } } @@ -544,15 +551,7 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe else if (Property == "ActorReference") { memoryList.Skip(4); - if (!Modify) - { - uexp.Strings.Add(new List() { PropertyName, memoryList.GetStringUE() }); - } - else - { - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - } + new ReadStringProperty(memoryList, uexp, PropertyName, Modify); memoryList.Skip(2); } else if (Property == "MapProperty") @@ -587,6 +586,7 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } ConsoleMode.Print("EndMap", ConsoleColor.DarkBlue); } @@ -601,15 +601,7 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe } else if (Property == "AssetObjectProperty") { - if (!Modify) - { - uexp.Strings.Add(new List() { PropertyName, memoryList.GetStringUE() }); - } - else - { - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - } + new ReadStringProperty(memoryList, uexp, PropertyName, Modify); } else if (Property == "BoolProperty") { @@ -657,6 +649,7 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } if (Modify) @@ -677,48 +670,62 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe } else if (Property == "StrProperty") { - if (!Modify) - { - uexp.Strings.Add(new List() { PropertyName, memoryList.GetStringUE() }); - ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 1][1], ConsoleColor.Magenta); - } - else - { - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - } + new ReadStringProperty(memoryList, uexp, PropertyName, Modify); } else if (Property == "TextProperty") { - memoryList.Skip(4); //unkown - byte ContainText = memoryList.GetByteValue(); - if (ContainText == 0xff) + if (uexp.UassetData.EngineVersion < UE4Version.VER_UE4_FTEXT_HISTORY) { - return; - } - if (!Modify) - { - uexp.Strings.Add(new List() { PropertyName + "_1", memoryList.GetStringUE() }); - uexp.Strings.Add(new List() { PropertyName + "_2", memoryList.GetStringUE() }); - uexp.Strings.Add(new List() { PropertyName + "_3", memoryList.GetStringUE() }); - ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 3][1], ConsoleColor.Magenta); - ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 2][1], ConsoleColor.Magenta); - ConsoleMode.Print(uexp.Strings[uexp.Strings.Count - 1][1], ConsoleColor.Magenta); + new ReadStringProperty(memoryList, uexp, PropertyName + "_0", Modify); + if (uexp.UassetData.EngineVersion >= UE4Version.VER_UE4_ADDED_NAMESPACE_AND_KEY_DATA_TO_FTEXT) + { + new ReadStringProperty(memoryList, uexp, PropertyName + "_1", Modify); + new ReadStringProperty(memoryList, uexp, PropertyName + "_2", Modify); + } + else + { + new ReadStringProperty(memoryList, uexp, PropertyName + "_2", Modify); + } + } - else + + if (uexp.UassetData.EngineVersion > UE4Version.VER_UE4_FTEXT_HISTORY) { - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; - memoryList.ReplaceStringUE(uexp.Strings[uexp.CurrentIndex][1]); - uexp.CurrentIndex++; + memoryList.Skip(4); //Flag + TextHistoryType ContainText = (TextHistoryType)memoryList.GetByteValue(); + + switch (ContainText) + { + case TextHistoryType.None: + int TextLinesCount = memoryList.GetIntValue(); + for (int i = 0; i < TextLinesCount; i++) + { + new ReadStringProperty(memoryList, uexp, PropertyName + "_" + (i + 1), Modify); + } + break; + + case TextHistoryType.Base: + new ReadStringProperty(memoryList, uexp, PropertyName + "_1", Modify); + new ReadStringProperty(memoryList, uexp, PropertyName + "_2", Modify); + new ReadStringProperty(memoryList, uexp, PropertyName + "_3", Modify); + break; + case TextHistoryType.StringTableEntry: + new ReadStringProperty(memoryList, uexp, PropertyName + "_1", Modify); + new ReadStringProperty(memoryList, uexp, PropertyName + "_2", Modify); + break; + + default: + throw new Exception("UnKnown 'TextProperty' type: " + ContainText.ToString()); + } } } else if (Property == "StructProperty") { + + + ConsoleMode.Print("Struct->" + memoryList.GetPosition(), ConsoleColor.DarkCyan); new StructProperty(memoryList, uexp, uexp.UassetData.UseFromStruct, true, Modify); ConsoleMode.Print("EndStruct->" + memoryList.GetPosition(), ConsoleColor.DarkCyan); @@ -759,6 +766,7 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } } } @@ -779,13 +787,12 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe { uexp.IsGood = false; ConsoleMode.Print("Bug here.", ConsoleColor.Red); + //Console.ReadLine(); } memoryList.Skip(4); //ImplementationPtr Index ConsoleMode.Print("EndMovieSceneEvalTemplatePtr", ConsoleColor.Yellow); } } - - else { new StructProperty(memoryList, uexp, uexp.UassetData.UseFromStruct, true, Modify); @@ -793,4 +800,5 @@ private void PropertyParser(string PropertyName, string Property, int PropertyLe } } + } diff --git a/UE4localizationsTool/Core/Uasset.cs b/UE4localizationsTool/Core/Uasset.cs index e20cfaf..112dd6b 100644 --- a/UE4localizationsTool/Core/Uasset.cs +++ b/UE4localizationsTool/Core/Uasset.cs @@ -30,6 +30,7 @@ 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; } @@ -82,7 +83,7 @@ public struct ExportsDirectory public MemoryList UexpFile; public bool IsNotUseUexp; public bool UseFromStruct = true; - + public bool AutoVersion=false; public Uasset(string FilePath) { @@ -162,14 +163,17 @@ public Uasset(string FilePath) if (Name_Directory_Offset - (numCustomVersions * 20) == 189) { EngineVersion = UE4Version.VER_UE4_15; + AutoVersion = true; } else if (Name_Directory_Offset - (numCustomVersions * 20) > 185) { EngineVersion = UE4Version.VER_UE4_16; + AutoVersion = true; } else if (Name_Directory_Offset - (numCustomVersions * 20) == 185) { EngineVersion = UE4Version.VER_UE4_6; + AutoVersion = true; } } if (EngineVersion >= UE4Version.VER_UE4_NAME_HASHES_SERIALIZED) @@ -187,6 +191,7 @@ public Uasset(string FilePath) if (EngineVersion >= UE4Version.VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { GatherableTextDataCount = UassetFile.GetIntValue(); + FGatherableTextDataOffset = UassetFile.GetPosition(); GatherableTextDataOffset = UassetFile.GetIntValue(); } @@ -451,7 +456,7 @@ public void ExportReadOrEdit(bool Modify = false) ExportsDirectory.ExportParent_2 = UassetFile.GetIntValue(); } - _ = UassetFile.GetIntValue(); + ExportsDirectory.Value = UassetFile.GetIntValue(); ExportsDirectory.ExportName = UassetFile.GetIntValue(); _ = UassetFile.GetIntValue(); diff --git a/UE4localizationsTool/Core/Uexp.cs b/UE4localizationsTool/Core/Uexp.cs index a504104..31977a9 100644 --- a/UE4localizationsTool/Core/Uexp.cs +++ b/UE4localizationsTool/Core/Uexp.cs @@ -53,6 +53,12 @@ private void ReadOrEdit(bool Modify = false) _ = new StructProperty(memoryList, this, UassetData.UseFromStruct, false, Modify); ConsoleMode.Print($"-----------End------------", ConsoleColor.Red); + + ConsoleMode.Print($"-----------{n}------------", ConsoleColor.DarkRed); + if (memoryList.EndofFile()) + { + continue; + } switch (UassetData.GetExportPropertyName(UassetData.Exports_Directory[n].ExportClass)) { case "StringTable": @@ -67,13 +73,22 @@ private void ReadOrEdit(bool Modify = false) _ = new Spreadsheet(memoryList, this, Modify); break; case "Function": - // _ = new Function(memoryList, this, Modify); + // _ = new Function(memoryList, this, n, Modify); + break; + case "REDLocalizeTextData": + _ = new REDLocalizeTextData(memoryList, this, Modify); + break; + case "REDAdvTextData": + _ = new REDAdvTextData(memoryList, this, Modify); break; } + ConsoleMode.Print($"-----------End------------", ConsoleColor.DarkRed); + } - catch + catch(Exception ex) { - //Skip this export + ConsoleMode.Print("Skip this export:\n"+ ex.ToString(),ConsoleColor.Red); + // Skip this export } } diff --git a/UE4localizationsTool/Helper/MemoryList.cs b/UE4localizationsTool/Helper/MemoryList.cs index 16dff9c..0ce10ab 100644 --- a/UE4localizationsTool/Helper/MemoryList.cs +++ b/UE4localizationsTool/Helper/MemoryList.cs @@ -243,6 +243,10 @@ public void Add(object Value) { MemoryListData.Add(Convert.ToByte(Value)); } + else if (Value.GetType().IsArray) + { + MemoryListData.AddRange((byte[])Value); + } else { throw new Exception("Unknown type"); @@ -300,13 +304,22 @@ public void Write(object Value, bool SavePosition = true, int SeekAndRead = -1, { SetBoolValue((bool)Value, SavePosition, SeekAndRead); } + else if (Value.GetType().IsArray) + { + SetBytes((byte[])Value, SavePosition, SeekAndRead); + } else { throw new Exception("Unknown type"); } } - + void IDisposable.Dispose() { } + public void Dispose() + { + Clear(); + GC.SuppressFinalize(this); + } #endregion @@ -330,13 +343,6 @@ public void DeleteBoolValue(int SeekAndWrite = -1) DeleteByteValue(SeekAndWrite); } - void IDisposable.Dispose() { } - public void Dispose() - { - Clear(); - GC.SuppressFinalize(this); - } - #endregion @@ -1248,6 +1254,45 @@ public void InsertStringValue(string String, bool SavePosition = true, int SeekA InsertBytes(encoding.GetBytes(String), SavePosition, SeekAndRead); } + + private byte[] GetString(Encoding encoding, bool SavePosition = true) + { + int ThisPosition = GetPosition(); + List StringValues = new List(); + if (encoding != Encoding.Unicode) + { + while (true) + { + StringValues.Add(GetByteValue()); + if (StringValues[StringValues.Count - 1] == 0) + { + break; + } + + } + } + else + { + while (true) + { + StringValues.Add(GetByteValue()); + StringValues.Add(GetByteValue()); + if (StringValues[StringValues.Count - 1] == 0 && StringValues[StringValues.Count - 2] == 0) + { + break; + } + } + + } + + if (!SavePosition) + { + Seek(ThisPosition); + } + + return StringValues.ToArray(); + } + public string GetStringValueN(bool SavePosition = true, int SeekAndRead = -1, Encoding encoding = null) { if (encoding == null) @@ -1255,40 +1300,46 @@ public string GetStringValueN(bool SavePosition = true, int SeekAndRead = -1, En encoding = Encoding.ASCII; } - List StringValues = new List(); - int StringLenght = 0; + int ThisPosition = GetPosition(); + string Value; if (SeekAndRead != -1) { - do - { - StringValues.Add(GetByteValue(false, SeekAndRead + StringLenght)); - StringLenght++; - } while (StringValues[StringValues.Count - 1] != 0); - return encoding.GetString(StringValues.ToArray()); + Seek(SeekAndRead); + Value = encoding.GetString(GetString(encoding)).TrimEnd('\0'); + Seek(ThisPosition); + return Value; } - if (SavePosition) { - do - { - StringValues.Add(GetByteValue(false, MemoryListIndex + StringLenght)); - StringLenght++; - } while (StringValues[StringValues.Count - 1] != 0); - MemoryListIndex += StringLenght; - return encoding.GetString(StringValues.ToArray()); + return encoding.GetString(GetString(encoding)).TrimEnd('\0'); } - do - { - StringValues.Add(GetByteValue(false, MemoryListIndex + StringLenght)); - StringLenght++; - } while (StringValues[StringValues.Count - 1] != 0); - return encoding.GetString(StringValues.ToArray()); + Seek(MemoryListIndex); + Value = encoding.GetString(GetString(encoding)).TrimEnd('\0'); + Seek(ThisPosition); + return Value; } + public void DeleteStringN(int SeekAndRead = -1, Encoding encoding = null) + { + if (encoding == null) + { + encoding = Encoding.ASCII; + } + + int ThisPosition = GetPosition(); + if (SeekAndRead != -1) + { + DeleteBytes(GetString(encoding, false).Length, SeekAndRead); + return; + } + + DeleteBytes(GetString(encoding, false).Length); + } + public void SetStringValueN(string String, bool SavePosition = true, int SeekAndRead = -1, Encoding encoding = null) { diff --git a/UE4localizationsTool/Program.cs b/UE4localizationsTool/Program.cs index e5c8664..d5396ac 100644 --- a/UE4localizationsTool/Program.cs +++ b/UE4localizationsTool/Program.cs @@ -12,23 +12,71 @@ internal static class Program public static string commandlines = - $"{AppDomain.CurrentDomain.FriendlyName} export <(Locres/Uasset) FilePath>\n" + - $"{AppDomain.CurrentDomain.FriendlyName} import <(txt) FilePath>\n" + - $"{AppDomain.CurrentDomain.FriendlyName} -import <(txt) FilePath>\n" + - $"{AppDomain.CurrentDomain.FriendlyName} exportall \n" + - $"{AppDomain.CurrentDomain.FriendlyName} importall \n" + - $"{AppDomain.CurrentDomain.FriendlyName} -importall \n\n" + + $"{AppDomain.CurrentDomain.FriendlyName} export <(Locres/Uasset) FilePath> \n" + + $"{AppDomain.CurrentDomain.FriendlyName} import <(txt) FilePath> \n" + + $"{AppDomain.CurrentDomain.FriendlyName} -import <(txt) FilePath> \n" + + $"{AppDomain.CurrentDomain.FriendlyName} exportall \n" + + $"{AppDomain.CurrentDomain.FriendlyName} importall \n" + + $"{AppDomain.CurrentDomain.FriendlyName} -importall \n\n" + "- for import without rename file be careful with this command.\n\n" + - "To use last filter you applied before in GUI, add (TRUE) after command line\n" + + "Options:\n" + + "To use last filter you applied before in GUI, add (-f \\ -filter) after command line\n" + "filter will apply only in name table (Remember to apply the same filter when importing)\n\n" + + + "To export file without including the names use (-nn \\ -NoName)" + + "\n(Remember to use this command when importing)\n\n" + + "Examples:\n" + $"{AppDomain.CurrentDomain.FriendlyName} export Actions.uasset\n" + $"{AppDomain.CurrentDomain.FriendlyName} import Actions.uasset.txt\n" + - $"{AppDomain.CurrentDomain.FriendlyName} exportall Actions\n" + - $"{AppDomain.CurrentDomain.FriendlyName} exportall Actions True\n" + - $"{AppDomain.CurrentDomain.FriendlyName} importall Actions\n" + - $"{AppDomain.CurrentDomain.FriendlyName} importall Actions True"; + $"{AppDomain.CurrentDomain.FriendlyName} exportall Actions text.txt\n" + + $"{AppDomain.CurrentDomain.FriendlyName} importall Actions text.txt\n"; + + public static (bool UseFilter, bool NoName) GetArgs(int Index, string[] args) + { + bool usefilter = false; + bool noname = false; + + for (int n = Index; n < args.Length; n++) + { + switch (args[n].ToLower()) + { + case "-f": + case "-filter": + usefilter = true; + break; + case "-nn": + case "-noname": + noname = true; + break; + default: + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("Invalid command: " + args[n]); + Console.ForegroundColor = ConsoleColor.White; + break; + } + } + return (usefilter, noname); + } + + + public static void CheckArges(int Index, string[] args) + { + for (int n = 0; n < Index; n++) + { + switch (args[n].ToLower()) + { + case "-f": + case "-filter": + throw new Exception("Invalid number of arguments.\n\n" + commandlines); + case "-nn": + case "-noname": + throw new Exception("Invalid number of arguments.\n\n" + commandlines); + } + } + } + [STAThread] @@ -41,10 +89,11 @@ static void Main(string[] args) AttachConsole(ATTACH_PARENT_PROCESS); Console.SetCursorPosition(0, Console.CursorTop + 1); bool UseFilter = false; + bool NoName = false; if (args.Length < 2) { Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("Invalid number of arguments.\n" + commandlines); + Console.WriteLine("Invalid number of arguments.\n\n" + commandlines); Console.ForegroundColor = ConsoleColor.White; return; } @@ -55,25 +104,18 @@ static void Main(string[] args) { if (args.Length < 3) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("Invalid number of arguments.\n" + commandlines); - Console.ForegroundColor = ConsoleColor.White; - - return; - } - if (args.Length > 3) - { - bool.TryParse(args[3], out UseFilter); + throw new Exception("Invalid number of arguments.\n\n" + commandlines); } - new Commads(args[0], args[1] + "*" + args[2], UseFilter); + + CheckArges(3, args); + (UseFilter, NoName) = GetArgs(3, args); + new Commads(args[0], args[1] + "*" + args[2], UseFilter, NoName); } else { - if (args.Length > 2) - { - bool.TryParse(args[2], out UseFilter); - } - new Commads(args[0], args[1], UseFilter); + CheckArges(2, args); + (UseFilter, NoName) = GetArgs(2, args); + new Commads(args[0], args[1], UseFilter, NoName); } } diff --git a/UE4localizationsTool/Properties/AssemblyInfo.cs b/UE4localizationsTool/Properties/AssemblyInfo.cs index cc4c9fb..adc2b4c 100644 --- a/UE4localizationsTool/Properties/AssemblyInfo.cs +++ b/UE4localizationsTool/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0")] -[assembly: AssemblyFileVersion("1.6")] +[assembly: AssemblyFileVersion("1.7")] diff --git a/UE4localizationsTool/UE4localizationsTool.csproj b/UE4localizationsTool/UE4localizationsTool.csproj index b8b2687..b34aded 100644 --- a/UE4localizationsTool/UE4localizationsTool.csproj +++ b/UE4localizationsTool/UE4localizationsTool.csproj @@ -92,6 +92,9 @@ + + + diff --git a/UE4localizationsTool/UpdateInfo.txt b/UE4localizationsTool/UpdateInfo.txt index fbc60a1..a868181 100644 --- a/UE4localizationsTool/UpdateInfo.txt +++ b/UE4localizationsTool/UpdateInfo.txt @@ -1,3 +1,3 @@ UpdateFile -Tool_UpdateVer = 1.6 -Tool_UpdateSite = https://github.com/amrshaheen61/UE4LocalizationsTool/releases/tag/v1.6 \ No newline at end of file +Tool_UpdateVer = 1.7 +Tool_UpdateSite = https://github.com/amrshaheen61/UE4LocalizationsTool/releases/tag/v1.7 \ No newline at end of file