Skip to content

Commit

Permalink
Finish release-1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
EliotVU committed Mar 25, 2024
2 parents bcbb53e + 58b5022 commit cb45c2c
Show file tree
Hide file tree
Showing 35 changed files with 991 additions and 96 deletions.
55 changes: 52 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,62 @@
# [1.4.0](https://github.com/EliotVU/Unreal-Library/releases/tag/1.4.0)

Notable changes that affect UnrealScript output:

* Improved decompilation output of string and decimal literals.
* 5141285c Improved decompilation of delegate assignments (in a T3D context)
* 6d889c87 Added decompilation of optional parameter assignments e.g. `function MyFunction(option bool A = true);`.
* e55cfce0 Fixed decompilation with arrays of bools

Notable changes that affect support of games:

General deserialization fixes that affect all of UE1, UE2, and UE3 builds, as well as more specifically:

* 13460cca Support for Battleborn
* 4aff61fa Support for Duke Nukem Forever (2011)
* bce38c4f Support for Tom Clancy's Splinter Cell
* 809edaad Support for Harry Potter (UE1) data class {USound}
* b3e1489d Support for Devastation (UE2, 2003)
* 4780771a Support for Clive Barker's Undying (UE1) data classes {UClass, UTextBuffer, UPalette, USound}
* 01772a83 Support for Lemony Snicket's A Series of Unfortunate Events data class {UProperty}
* c4c1978d Fixed support for Dungeon Defenders 2 (versions 687-688/111-117)
* 86538e5d Fixed support for Vanguard: Saga of Heroes
* eb82dba5 Fixed support for Rocket League (version 868/003)
* 6ed6ed74 Fixed support for Hawken (version 860/002)
* b4b79773 Fixed ResizeStringToken for UE1 builds
* 3653f8e1 Fixed ReturnToken and BeginFunctionToken for UE1 builds (with a package version of 61)
* 9a659549 Fixed deserialization of Heritages for UE1 builds (with a package version older than 68)

Notable changes that affect various data structures:

* Improved detection of UComponent objects and class types.
* ea3c1aa5 Support for UE4 .uasset packages (earlier builds only)
* e37b8a12 Support for class {UTexture}, f1b74af1 {UPrimitive, UTexture2D and its derivatives} (UE3)
* aa5ca861 Support for classes: {UFont, UMultiFont}
* ab290b6c Support for types {UPolys, FPoly}
* 02bea77b Support for types {FUntypedBulkData} (UE3) and {TLazyArray} (UE1, UE2)
* 94e02927 Support for structures: {FPointRegion, FCoords, FPlane, FScale, FSphere, FRotator, FVector, FGuid, FBox, FLinearColor, FMatrix, FQuat, FRange, FRangeVector, FVector2D, FVector4}
* 09c76240 Support for class {USoundGroup} (UE2.5)

**Support for the data types listed above have only been implemented for the standard structure that Epic Games uses**

# [1.3.1](https://github.com/EliotVU/Unreal-Library/releases/tag/1.3.1)

Notable changes back-ported from 'develop' version 1.4.0:

* Added support for various data structures: FColor; and data class UBitmapMaterial (UE2)

* Improved support for Batman series
* Improved support for Transformers series
* Fixed the decompilation of UnrealScript casting byte-codes that were swapped i.e. `InterfaceToBool` with `InterfaceToObject`.
* Fixed a missing package version check in UStateFrame (this affected some object classes that are usually found in map package files).
* Added the capability to override the interpreted version for packages of builds that are auto-detected.
* e8308284 Fixed decompilation of primitive castings for UE1 builds
* ffaca763 Fixed decompilation of interface castings i.e. `InterfaceToBool` with `InterfaceToObject` (UE3).
* 3317e06a Fixed a missing package version check in UStateFrame (this affected some object classes that are usually found in map package files).

* 42783b16 Added the capability to override the interpreted version for packages of builds that are auto-detected.

# [1.3.0](https://github.com/EliotVU/Unreal-Library/releases/tag/1.3.0.0)

Notable changes:

* Support for Vengeance which includes BioShock 1 & 2, Swat4, and Tribes: Vengeance
* Support for Batman series (to the release branch, incomplete)
* Support for Thief: Deadly Shadows and Deus Ex: Invisible War
Expand Down
27 changes: 18 additions & 9 deletions src/BinaryMetaData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using UELib.Annotations;

Expand Down Expand Up @@ -37,6 +38,14 @@ public struct BinaryField : IUnrealDecompilable
/// </summary>
public long Size { get; set; }

[Obsolete("Use Field")]
public string Name => Field;

[Obsolete("Use Value")]
public object Tag => Value;

[Obsolete("Use Offset")] public int Position => (int)Offset;

/// <summary>
/// Decompiles and returns the output of @Tag.
/// </summary>
Expand All @@ -57,20 +66,20 @@ public string Decompile()
/// <summary>
/// Adds a new field to the @Fields stack.
/// </summary>
/// <param name="name">Name of the field</param>
/// <param name="tag">Value of the field</param>
/// <param name="position">Position in bytes where the field is read from</param>
/// <param name="field">Name of the field</param>
/// <param name="value">Value of the field</param>
/// <param name="offset">Position in bytes where the field is read from</param>
/// <param name="size">Size in bytes of the field</param>
public void AddField(string name, object tag, long position, long size)
public void AddField(string field, object value, long offset, long size)
{
Debug.Assert(size > 0, $"Size of field {name} at {position} cannot be less than 1");
//Debug.Assert(size > 0, $"Size of field {field} at {offset} cannot be less than 1");
Fields.Push
(
new BinaryField
{
Field = name,
Value = tag,
Offset = position,
Field = field,
Value = value,
Offset = offset,
Size = size
}
);
Expand Down
22 changes: 11 additions & 11 deletions src/Branch/DefaultEngineBranch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,34 +128,34 @@ public DefaultEngineBranch(BuildGeneration generation) : base(generation)
public override void Setup(UnrealPackage linker)
{
SetupEnumPackageFlags(linker);
EnumFlagsMap.Add(typeof(PackageFlags), PackageFlags);
EnumFlagsMap.Add(typeof(PackageFlag), PackageFlags);
}

protected virtual void SetupEnumPackageFlags(UnrealPackage linker)
{
PackageFlags[(int)Flags.PackageFlags.AllowDownload] = (uint)PackageFlagsDefault.AllowDownload;
PackageFlags[(int)Flags.PackageFlags.ClientOptional] = (uint)PackageFlagsDefault.ClientOptional;
PackageFlags[(int)Flags.PackageFlags.ServerSideOnly] = (uint)PackageFlagsDefault.ServerSideOnly;
PackageFlags[(int)Flags.PackageFlag.AllowDownload] = (uint)PackageFlagsDefault.AllowDownload;
PackageFlags[(int)Flags.PackageFlag.ClientOptional] = (uint)PackageFlagsDefault.ClientOptional;
PackageFlags[(int)Flags.PackageFlag.ServerSideOnly] = (uint)PackageFlagsDefault.ServerSideOnly;
#if UE1
// FIXME: Version
if (linker.Version > 61 && linker.Version <= 69) // <= UT99
PackageFlags[(int)Flags.PackageFlags.Encrypted] = (uint)PackageFlagsUE1.Encrypted;
PackageFlags[(int)Flags.PackageFlag.Encrypted] = (uint)PackageFlagsUE1.Encrypted;
#endif
#if UE2
if (linker.Build == BuildGeneration.UE2_5)
PackageFlags[(int)Flags.PackageFlags.Official] = (uint)PackageFlagsUE2.Official;
PackageFlags[(int)Flags.PackageFlag.Official] = (uint)PackageFlagsUE2.Official;
#endif
#if UE3
// Map the new PackageFlags, but the version is nothing but a guess!
if (linker.Version >= 180)
{
if (linker.Version >= UnrealPackage.PackageFileSummary.VCookerVersion)
PackageFlags[(int)Flags.PackageFlags.Cooked] = (uint)PackageFlagsUE3.Cooked;
PackageFlags[(int)Flags.PackageFlag.Cooked] = (uint)PackageFlagsUE3.Cooked;

PackageFlags[(int)Flags.PackageFlags.ContainsMap] = (uint)PackageFlagsUE3.ContainsMap;
PackageFlags[(int)Flags.PackageFlags.ContainsDebugData] = (uint)PackageFlagsUE3.ContainsDebugData;
PackageFlags[(int)Flags.PackageFlags.ContainsScript] = (uint)PackageFlagsUE3.ContainsScript;
PackageFlags[(int)Flags.PackageFlags.StrippedSource] = (uint)PackageFlagsUE3.StrippedSource;
PackageFlags[(int)Flags.PackageFlag.ContainsMap] = (uint)PackageFlagsUE3.ContainsMap;
PackageFlags[(int)Flags.PackageFlag.ContainsDebugData] = (uint)PackageFlagsUE3.ContainsDebugData;
PackageFlags[(int)Flags.PackageFlag.ContainsScript] = (uint)PackageFlagsUE3.ContainsScript;
PackageFlags[(int)Flags.PackageFlag.StrippedSource] = (uint)PackageFlagsUE3.StrippedSource;
}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion src/Branch/EngineBranch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public abstract class EngineBranch
/// </summary>
public readonly Dictionary<Type, ulong[]> EnumFlagsMap = new Dictionary<Type, ulong[]>();

protected readonly ulong[] PackageFlags = new ulong[(int)Flags.PackageFlags.Max];
protected readonly ulong[] PackageFlags = new ulong[(int)Flags.PackageFlag.Max];

public EngineBranch()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Branch/UE2/AA2/CryptoDecoder.AA2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace UELib.Branch.UE2.AA2
{
// TODO: Re-implement as a BaseStream wrapper (in UELib 2.0)
// TODO: Re-implement as a BaseStream wrapper
public class CryptoDecoderAA2 : IBufferDecoder
{
public void PreDecode(IUnrealStream stream)
Expand Down
16 changes: 8 additions & 8 deletions src/Branch/UE4/EngineBranch.UE4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,20 @@ public EngineBranchUE4() : base(BuildGeneration.UE4)
public override void Setup(UnrealPackage linker)
{
SetupEnumPackageFlags(linker);
EnumFlagsMap.Add(typeof(PackageFlags), PackageFlags);
EnumFlagsMap.Add(typeof(PackageFlag), PackageFlags);
}

protected virtual void SetupEnumPackageFlags(UnrealPackage linker)
{
PackageFlags[(int)Flags.PackageFlags.ClientOptional] =
PackageFlags[(int)Flags.PackageFlag.ClientOptional] =
(uint)DefaultEngineBranch.PackageFlagsDefault.ClientOptional;
PackageFlags[(int)Flags.PackageFlags.ServerSideOnly] =
PackageFlags[(int)Flags.PackageFlag.ServerSideOnly] =
(uint)DefaultEngineBranch.PackageFlagsDefault.ServerSideOnly;
PackageFlags[(int)Flags.PackageFlags.EditorOnly] = (uint)PackageFlagsUE4.EditorOnly;
PackageFlags[(int)Flags.PackageFlags.Cooked] = (uint)PackageFlagsUE4.Cooked;
PackageFlags[(int)Flags.PackageFlags.UnversionedProperties] = (uint)PackageFlagsUE4.UnversionedProperties;
PackageFlags[(int)Flags.PackageFlags.ReloadingForCooker] = (uint)PackageFlagsUE4.ReloadingForCooker;
PackageFlags[(int)Flags.PackageFlags.FilterEditorOnly] = (uint)PackageFlagsUE4.FilterEditorOnly;
PackageFlags[(int)Flags.PackageFlag.EditorOnly] = (uint)PackageFlagsUE4.EditorOnly;
PackageFlags[(int)Flags.PackageFlag.Cooked] = (uint)PackageFlagsUE4.Cooked;
PackageFlags[(int)Flags.PackageFlag.UnversionedProperties] = (uint)PackageFlagsUE4.UnversionedProperties;
PackageFlags[(int)Flags.PackageFlag.ReloadingForCooker] = (uint)PackageFlagsUE4.ReloadingForCooker;
PackageFlags[(int)Flags.PackageFlag.FilterEditorOnly] = (uint)PackageFlagsUE4.FilterEditorOnly;
}

protected override void SetupSerializer(UnrealPackage linker)
Expand Down
4 changes: 3 additions & 1 deletion src/Core/Classes/Props/UPropertyDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,9 @@ public string FormatFlags()
return string.Empty;
}

return output;
// alright...
//return "/*" + UnrealMethods.FlagToString( PropertyFlags ) + "*/ " + output;
return copyFlags != 0 ? "/*" + UnrealMethods.FlagToString(copyFlags) + "*/ " + output : output;
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/Core/Classes/UClassDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,25 @@ public override string Decompile()
return content;
}

[Obsolete]
[Obsolete("Deprecated", true)]
public string GetDependencies()
{
throw new NotImplementedException();
}

[Obsolete]
[Obsolete("Deprecated", true)]
private string GetImports()
{
throw new NotImplementedException();
}

[Obsolete]
[Obsolete("Deprecated", true)]
public string GetStats()
{
throw new NotImplementedException();
}

protected override string FormatHeader()
public override string FormatHeader()
{
string output = (IsClassInterface() ? "interface " : "class ") + Name;
string metaData = DecompileMeta();
Expand Down
42 changes: 42 additions & 0 deletions src/Core/Classes/UClassNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#if Forms
using System.Windows.Forms;

namespace UELib.Core
{
public partial class UClass
{
protected override void InitNodes(TreeNode node)
{
_ParentNode = AddSectionNode(node, nameof(UClass));
AddSimpleObjectNode(_ParentNode, Within, "Within", Within != null ? Within.GetImageName() : "");

var classFlagsNode = AddTextNode(_ParentNode, $"Class Flags:{UnrealMethods.FlagToString(ClassFlags)}");
classFlagsNode.ToolTipText = UnrealMethods.FlagsListToString(
UnrealMethods.FlagsToList(typeof(Flags.ClassFlags), ClassFlags)
);

base.InitNodes(_ParentNode);
}

protected override void AddChildren(TreeNode node)
{
base.AddChildren(node);
AddObjectListNode(node, "States", States, nameof(UState));
}

public override string GetImageName()
{
if (IsClassInterface())
{
return "Interface";
}
if (IsClassWithin())
{
return "UClass-Within";
}

return base.GetImageName();
}
}
}
#endif
2 changes: 1 addition & 1 deletion src/Core/Classes/UEnumDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public override string Decompile()
UnrealConfig.PrintEndBracket() + ";";
}

protected virtual string FormatHeader()
public override string FormatHeader()
{
return $"enum {Name}{DecompileMeta()}";
}
Expand Down
17 changes: 17 additions & 0 deletions src/Core/Classes/UFieldNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#if Forms
using System.Windows.Forms;

namespace UELib.Core
{
public partial class UField
{
protected override void InitNodes(TreeNode node)
{
_ParentNode = AddSectionNode(node, nameof(UField));
AddSimpleObjectNode(_ParentNode, Super, "SuperField", Super != null ? Super.GetImageName() : "");
AddSimpleObjectNode(_ParentNode, NextField, "NextField", NextField != null ? NextField.GetImageName() : "");
base.InitNodes(_ParentNode);
}
}
}
#endif
2 changes: 1 addition & 1 deletion src/Core/Classes/UFunctionDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ private string FormatFlags()
return output;
}

protected override string FormatHeader()
public override string FormatHeader()
{
var output = string.Empty;
// static function (string?:) Name(Parms)...
Expand Down
65 changes: 65 additions & 0 deletions src/Core/Classes/UFunctionNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#if Forms
using System.Windows.Forms;

namespace UELib.Core
{
public partial class UFunction
{
protected override void InitNodes(TreeNode node)
{
node.ToolTipText = FormatHeader();
_ParentNode = AddSectionNode(node, nameof(UFunction));

var funcFlagsNode = AddTextNode(_ParentNode, $"FunctionFlags:{UnrealMethods.FlagToString(FunctionFlags)}");
funcFlagsNode.ToolTipText =
UnrealMethods.FlagsListToString(UnrealMethods.FlagsToList(typeof(Flags.FunctionFlags), FunctionFlags));

if (RepOffset > 0)
{
AddTextNode(_ParentNode, $"Replication Offset:{RepOffset}");
}

base.InitNodes(_ParentNode);
}

protected override void AddChildren(TreeNode node)
{
base.AddChildren(node);
AddObjectListNode(node, "Parameters", Params, nameof(UProperty));
AddObjectListNode(node, "Locals", Locals, nameof(UProperty));
}

public override string GetImageName()
{
var name = string.Empty;
if (HasFunctionFlag(Flags.FunctionFlags.Event))
{
name = "Event";
}
else if (HasFunctionFlag(Flags.FunctionFlags.Delegate))
{
name = "Delegate";
}
else if (HasFunctionFlag(Flags.FunctionFlags.Operator))
{
name = "Operator";
}

if (name != string.Empty)
{
if (IsProtected())
{
return $"{name}-Protected";
}
if (IsPrivate())
{
return $"{name}-Private";
}
return name;
}

return base.GetImageName();
}
}
}
#endif
Loading

0 comments on commit cb45c2c

Please sign in to comment.