public static List <string> AssumedStructPattern(Program.RunData runData, ReadingContext readingContext, out HeuristicaStatus heuristicaStatus) { Int32 assumedEndOfStructOffset = readingContext.declaredSizeStartOffset + readingContext.declaredSize; Int32 assumedSize = readingContext.collectionElementCount > 0 ? readingContext.declaredSize / readingContext.collectionElementCount : readingContext.collectionElementCount; try { string assumedLastName = ExportParsingMachine.FullNameString(runData.uexp, assumedEndOfStructOffset - 8); if (assumedLastName == ExportParsingMachine.endOfStructConfigName) { heuristicaStatus = HeuristicaStatus.Success; return(new List <string>() { "NTPL" }); } } catch (Exception) { } heuristicaStatus = HeuristicaStatus.Failure; return(new List <string>()); }
private static void FloatPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); ExportParsingMachine.ReportExportContents($"Float Value: {BitConverter.ToSingle(uexp, readingContext.currentUexpOffset)}"); readingContext.currentUexpOffset += 4; }
private static void NamePatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); ExportParsingMachine.ReportExportContents($"Name: {ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset)}"); readingContext.currentUexpOffset += 8; }
private static void SkipContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); Int32 skipLength = Int32.Parse(readingContext.pattern.TakeArg()); readingContext.currentUexpOffset += skipLength; }
private static void SizePatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.declaredSize = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 4; readingContext.pattern.TakeArg(); ExportParsingMachine.ReportExportContents($"Size: {readingContext.declaredSize}"); }
private static void ElementCountContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); readingContext.collectionElementCount = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.contextCollectionElementCountOffset = readingContext.currentUexpOffset; readingContext.currentUexpOffset += 4; }
private static void SizeStartContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); readingContext.declaredSizeStartOffset = readingContext.currentUexpOffset; if (customRunDara.reportSearchSteps) { ExportParsingMachine.ReportExportContents($"Context Size start at {readingContext.currentUexpOffset}"); } }
private static void SkipContextContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { if (customRunDara.reportSearchSteps) { ExportParsingMachine.ReportExportContents("Skipping context"); } readingContext.pattern.Clear(); readingContext.currentUexpOffset = readingContext.declaredSizeStartOffset + readingContext.declaredSize; }
private static void SkipIfEndContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); if (readingContext.pattern.Count == 0) { readingContext.currentUexpOffset = readingContext.declaredSizeStartOffset + readingContext.declaredSize; ExportParsingMachine.ReportExportContents("Skipping structure due to lack of pattern"); } }
private static void ContextReturnProcesser(ReadingContext upperContext, ReadingContext finishedContext) { upperContext.sizeChange += finishedContext.sizeChange; if (finishedContext.contextDeclaredSizeOffset != 0) { DOLib.AddToInt32ByOffset(Program.runData.uexp, finishedContext.sizeChange, finishedContext.contextDeclaredSizeOffset); } if (customRunDara.taskComplete) { upperContext.targetContext.Clear(); upperContext.pattern.Clear(); } }
private static void SizeContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); readingContext.declaredSize = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.contextDeclaredSizeOffset = readingContext.currentUexpOffset; if (customRunDara.reportSearchSteps) { ExportParsingMachine.ReportExportContents($"Size is {readingContext.declaredSize}, stored at {readingContext.contextDeclaredSizeOffset}"); } readingContext.currentUexpOffset += 4; }
public static void ExecutePushedReadingContext(byte[] uasset, byte[] uexp, ReadingContext readingContext) { IncStructLevel(); StepsTilEndOfStruct(uasset, uexp); DecStructLevel(); ReadingContext finishedContext = machineState.Pop(); readingContext.currentUexpOffset = finishedContext.currentUexpOffset; if (finishedContext.contextReturnProcesser != null) { finishedContext.contextReturnProcesser(readingContext, finishedContext); } }
private static void ValueContextSearcher(byte[] uasset, byte[] uexp, ReadingContext readingContext) { string primitiveTypeName = readingContext.pattern.TakeArg(); PrimitiveTypeData primitiveType = primitiveTypes[primitiveTypeName]; if (readingContext.targetContext.Count == 2) { Int32 skipsLeft = Int32.Parse(readingContext.targetContext[1]); if (primitiveTypeName == readingContext.targetContext[0]) { if (skipsLeft == 0) { if (customRunDara.reportSearchSteps) { ExportParsingMachine.ReportExportContents($"Found replacement target at {readingContext.currentUexpOffset}"); } readingContext.pattern.Clear(); readingContext.targetContext.Clear(); primitiveType.writer(ref readingContext.currentUexpOffset, customRunDara.newValue); customRunDara.taskComplete = true; return; } else { skipsLeft--; readingContext.targetContext[1] = skipsLeft.ToString(); } } } primitiveType.skip(ref readingContext.currentUexpOffset); if (customRunDara.reportSearchSteps) { ExportParsingMachine.ReportExportContents($"Skipping {primitiveTypeName} value"); } }
private static bool Step(byte[] uasset, byte[] uexp) { ReadingContext readingContext = machineState.Peek(); if (readingContext.pattern.Count == 0) { return(false); } if (readingContext.patternAlphabet.ContainsKey(readingContext.pattern[0])) { readingContext.patternAlphabet[readingContext.pattern[0]](uasset, uexp, readingContext); } else { readingContext.currentUexpOffset += 4; readingContext.pattern.TakeArg(); } return(true); }
public static string ObjectByIndexFullNameString(byte[] uasset, byte[] uexp, ReadingContext readingContext) { Int32 index = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 4; string valueStr; if (index == 0) { valueStr = "null"; } else if (index < 0) { valueStr = $"Import:{ImportByIndexFullNameString(uasset, uexp, index)}"; } else { valueStr = $"Export:{ExportByIndexFullNameString(uasset, uexp, index)}"; } return(valueStr); }
private static void TextPropertyDirtyHackPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); //Epic Games probably like it when you have to f**k your brain with TexProperty having a body prefix which varies in SIZE between types. //I don't. I hope the author of that idea got a proper remedy. readingContext.currentUexpOffset = readingContext.declaredSizeStartOffset + readingContext.declaredSize; ExportParsingMachine.ReportExportContents("Text Property support is postponed. ETA depends on readability of UE shitcode."); }
private static void MapGeneratorTypesPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string tKey = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; string tVal = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; ExportParsingMachine.ReportExportContents($"<{tKey}, {tVal}>"); if (Program.PatternExists($"{Program.PatternFolders.body}/{tKey}") && Program.PatternExists($"{Program.PatternFolders.body}/{tVal}")) { List <string> keyPattern = Program.GetPattern($"{Program.PatternFolders.body}/{tKey}"); List <string> valPattern = Program.GetPattern($"{Program.PatternFolders.body}/{tVal}"); if (keyPattern.TakeArg() == ExportParsingMachine.arrayRepeatPatternElementName && valPattern.TakeArg() == ExportParsingMachine.arrayRepeatPatternElementName) { readingContext.pattern.Add(ExportParsingMachine.elementCountPatternElementName); readingContext.pattern.Add(ExportParsingMachine.arrayRepeatPatternElementName); readingContext.pattern.AddRange(keyPattern); readingContext.pattern.Add(ExportParsingMachine.arrayRepeatEndPatternElementName); readingContext.pattern.Add(ExportParsingMachine.elementCountPatternElementName); readingContext.pattern.Add(ExportParsingMachine.arrayRepeatPatternElementName); readingContext.pattern.AddRange(keyPattern); readingContext.pattern.AddRange(valPattern); } } }
private static void StructPropertyArrayTypePatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string typeName = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; ExportParsingMachine.ReportExportContents($"Element structure type: {typeName}"); if (Program.PatternExists($"{Program.PatternFolders.structure}/{typeName}")) { readingContext.pattern.Add(ExportParsingMachine.arrayRepeatPatternElementName); readingContext.pattern.AddRange(Program.GetPattern($"{Program.PatternFolders.structure}/{typeName}")); } else if (Program.config.enablePatternReadingHeuristica && readingContext.collectionElementCount != 0) { readingContext.pattern.Add(structTypeHeuristicaPatternElementName); readingContext.pattern.Add(ExportParsingMachine.skipIfPatternShorterThanPatternElemetnName); readingContext.pattern.Add("2"); readingContext.pattern.Add(ExportParsingMachine.arrayRepeatPatternElementName); } }
private static void ArrayRepeatPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); Int32 scaledElementSize; // Some element types have no context-free size determination apart from assumed elements total size and count. // Also ignore it if we have 0 elements because it is pointless and causes exception. if (readingContext.pattern[0] == ExportParsingMachine.scaledArrayElementsPatternElementName && readingContext.collectionElementCount != 0) { readingContext.pattern.TakeArg(); scaledElementSize = (readingContext.declaredSizeStartOffset + readingContext.declaredSize - readingContext.currentUexpOffset) / (readingContext.collectionElementCount); } else { scaledElementSize = -1; } List <string> repeatedPattern = new List <string>(); // Passing all the stuff to repeat in cycle which is all past ArrayRepeat and til ArrayRepeatEnd or end of pattern while (readingContext.pattern.Count > 0) { string element = readingContext.pattern.TakeArg(); if (element == ExportParsingMachine.arrayRepeatEndPatternElementName) { break; } repeatedPattern.Add(element); } for (int i = 0; i < readingContext.collectionElementCount; i++) { ExportParsingMachine.ReportExportContents($"Element {i}"); ExportParsingMachine.machineState.Push(new ReadingContext() { currentUexpOffset = readingContext.currentUexpOffset, pattern = new List <string>(repeatedPattern), patternAlphabet = readingContext.patternAlphabet, structCategory = ReadingContext.StructCategory.nonExport, declaredSize = scaledElementSize }); ExportParsingMachine.ExecutePushedReadingContext(uasset, uexp, readingContext); } }
private static void ElementCountPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); Int32 elementCount = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 4; readingContext.collectionElementCount = elementCount; ExportParsingMachine.ReportExportContents($"Elements Count: {elementCount}"); }
private static void NoneTerminatedPropListPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { string substructName = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; if (substructName == ExportParsingMachine.endOfStructConfigName) { readingContext.pattern.TakeArg(); return; } string typeName = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; ExportParsingMachine.ReportExportContents("------------------------------"); ExportParsingMachine.ReportExportContents($"{substructName} is {typeName}"); List <string> propertyPattern; try { propertyPattern = Program.GetPattern($"{Program.PatternFolders.property}/{typeName}"); } catch { ExportParsingMachine.ReportExportContents($"Failed to find a pattern for property type {typeName}"); Int32 assumedSize = BitConverter.ToInt32(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; ExportParsingMachine.ReportExportContents($"Assumed property size {assumedSize}"); ExportParsingMachine.ReportExportContents($"Assumed property body {BitConverter.ToString(uexp, readingContext.currentUexpOffset + 1, assumedSize)}"); throw; } ExportParsingMachine.machineState.Push(new ReadingContext() { currentUexpOffset = readingContext.currentUexpOffset, declaredSize = -1, declaredSizeStartOffset = -1, collectionElementCount = -1, pattern = propertyPattern, patternAlphabet = readingContext.patternAlphabet, structCategory = ReadingContext.StructCategory.nonExport }); ExportParsingMachine.ExecutePushedReadingContext(uasset, uexp, readingContext); }
private static void StructTypeNameIndexPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string typeName = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); ExportParsingMachine.ReportExportContents($"Structure Type: {typeName}"); readingContext.currentUexpOffset += 8; if (Program.PatternExists($"{Program.PatternFolders.structure}/{typeName}")) { readingContext.pattern.AddRange(Program.GetPattern($"{Program.PatternFolders.structure}/{typeName}")); } else if (Program.config.enablePatternReadingHeuristica) { readingContext.pattern.Add(structTypeHeuristicaPatternElementName); readingContext.pattern.Add(ExportParsingMachine.skipIfPatternEndsPatternElementName); } }
private static void UnknownBytesPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); Int32 count = Int32.Parse(readingContext.pattern.TakeArg()); ExportParsingMachine.ReportExportContents($"Unknown Bytes: {BitConverter.ToString(uexp, readingContext.currentUexpOffset, count)}"); readingContext.currentUexpOffset += count; }
private static void SizePrefixedNullTermStringPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string value = Program.SizePrefixedStringFromOffsetOffsetAdvance(uexp, ref readingContext.currentUexpOffset); ExportParsingMachine.ReportExportContents($"String: {value}"); }
private static void GUIDPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); ExportParsingMachine.ReportExportContents(ExportParsingMachine.GUIDFromUexpOffsetToString(ref readingContext.currentUexpOffset)); }
private static void SkipIfPatternShorterThanPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); Int32 minimalCountToProceed = Int32.Parse(readingContext.pattern.TakeArg()); if (readingContext.pattern.Count < minimalCountToProceed) { readingContext.currentUexpOffset = readingContext.declaredSizeStartOffset + readingContext.declaredSize; readingContext.pattern.Clear(); ExportParsingMachine.ReportExportContents("Skipping structure due to lack of pattern"); } }
private static void ObjectIndexPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string valueStr = ExportParsingMachine.ObjectByIndexFullNameString(uasset, uexp, readingContext); ExportParsingMachine.ReportExportContents($"Object: {valueStr}"); }
private static void StructTypeHeurisitcaPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); readingContext.pattern.AddRange(PatternHeuristica.AssumedStructPattern(Program.runData, readingContext, out PatternHeuristica.HeuristicaStatus heuristicaStatus)); switch (heuristicaStatus) { case PatternHeuristica.HeuristicaStatus.Failure: ExportParsingMachine.ReportExportContents("Heuristica failed to give assumed structure pattern"); break; case PatternHeuristica.HeuristicaStatus.NonCriticalFailure: ExportParsingMachine.ReportExportContents("Heuristica failed to find a meaningful pattern, boilerplate is provided"); break; case PatternHeuristica.HeuristicaStatus.Success: ExportParsingMachine.ReportExportContents("Heuristica proposed a structure pattern, applying it"); break; } }
private static void BytePropPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); ExportParsingMachine.ReportExportContents($"Bytes Value: {BitConverter.ToString(uexp, readingContext.currentUexpOffset, readingContext.declaredSize)}"); readingContext.currentUexpOffset += readingContext.declaredSize; }
private static void ArrayElementTypeNameIndexPatternElementProcesser(byte[] uasset, byte[] uexp, ReadingContext readingContext) { readingContext.pattern.TakeArg(); string typeName = ExportParsingMachine.FullNameString(uexp, readingContext.currentUexpOffset); readingContext.currentUexpOffset += 8; ExportParsingMachine.ReportExportContents($"Array Element Type: {typeName}"); if (Program.PatternExists($"{Program.PatternFolders.body}/{typeName}")) { readingContext.pattern.AddRange(Program.GetPattern($"{Program.PatternFolders.body}/{typeName}")); } }