Skip to content
This repository has been archived by the owner on Mar 3, 2024. It is now read-only.

Commit

Permalink
add mesh prop searching commands
Browse files Browse the repository at this point in the history
  • Loading branch information
parzivail committed Aug 3, 2021
1 parent 5207898 commit cebccbf
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 4 deletions.
4 changes: 2 additions & 2 deletions DumpTool/DumpMeshPropsCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public static void ProcessFlatArchive(ILiteDatabase db, Forge forge, Entry entry
return;
}

foreach (var meshProp in arc.Entries.Where(archiveEntry => MagicHelper.Equals(Magic.MeshProperties, archiveEntry.Meta.Magic)))
foreach (var meshProp in arc.Entries)
{
var unresolvedExterns = new List<ulong>();

var outputDir = Path.Combine(rootOutputDir, $"model_flatarchive_id{entry.Uid}", $"meshprop_{meshProp.Meta.Uid}");
var outputDir = Path.Combine(rootOutputDir, $"model_flatarchive_id{entry.Uid}", $"{(Magic) meshProp.Meta.Magic}_{meshProp.Meta.Uid}");
Directory.CreateDirectory(outputDir);

DumpHelper.DumpNonContainerChildren(outputDir, assetStream, arc, meshProp, unresolvedExterns);
Expand Down
65 changes: 65 additions & 0 deletions DumpTool/FindAllMeshPropsCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using CommandLine;
using RainbowForge;
using RainbowForge.Archive;
using RainbowForge.Dump;
using RainbowForge.Forge;
using RainbowForge.Forge.Container;

namespace DumpTool
{
[Verb("findallmeshprops", HelpText = "Find all MeshProperties containers which reference the given UID in all flat archives in the given forge file")]
public class FindAllMeshPropsCommand
{
[Value(0, HelpText = "The forge file to reference")]
public string ForgeFilename { get; set; }

[Value(1, HelpText = "The UID to search for")]
public ulong Uid { get; set; }

public static void Run(FindAllMeshPropsCommand args)
{
try
{
var forge = Program.GetForge(args.ForgeFilename);
foreach (var entry in forge.Entries)
if (SearchFlatArchive(forge, entry, args.Uid))
Console.WriteLine(entry.Uid);
}
catch (Exception e)
{
Console.Error.WriteLine($"Error while dumping: {e}");
}
}

public static bool SearchFlatArchive(Forge forge, Entry entry, ulong uid)
{
var container = forge.GetContainer(entry.Uid);
if (container is not ForgeAsset forgeAsset || MagicHelper.GetFiletype(entry.Name.FileType) != AssetType.FlatArchive)
return false;

var assetStream = forgeAsset.GetDataStream(forge);
var arc = FlatArchive.Read(assetStream);

foreach (var meshProp in arc.Entries)
{
var unresolvedExterns = new List<ulong>();

try
{
DumpHelper.SearchNonContainerChildren(assetStream, arc, meshProp, unresolvedExterns);
}
catch (NotSupportedException)
{
continue;
}

if (unresolvedExterns.Contains(uid))
return true;
}

return false;
}
}
}
38 changes: 38 additions & 0 deletions DumpTool/FindAllMeshPropsGlobalCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.IO;
using CommandLine;

namespace DumpTool
{
[Verb("findallmeshpropsglobal", HelpText = "Find all MeshProperties containers which reference the given UID in all flat archives in the given forge file")]
public class FindAllMeshPropsGlobalCommand
{
[Value(0, HelpText = "The directory of forge files to search")]
public string ForgeDirectory { get; set; }

[Value(1, HelpText = "The UID to search for")]
public ulong Uid { get; set; }

public static void Run(FindAllMeshPropsGlobalCommand args)
{
Program.AssertDirectoryExists(args.ForgeDirectory);

foreach (var file in Directory.GetFiles(args.ForgeDirectory, "*.forge"))
try
{
var forge = Program.GetForge(file);
for (var i = 0; i < forge.Entries.Length; i++)
{
var entry = forge.Entries[i];

if (FindAllMeshPropsCommand.SearchFlatArchive(forge, entry, args.Uid))
Console.WriteLine($"{Path.GetFileName(file)}: {entry.Uid}");
}
}
catch (Exception e)
{
Console.Error.WriteLine($"Error while dumping: {e}");
}
}
}
}
4 changes: 3 additions & 1 deletion DumpTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ public static Forge GetForge(string filename)
private static void Main(string[] args)
{
Parser.Default.ParseArguments<ListCommand, FindCommand, InspectCommand, DumpCommand, DumpMeshPropsCommand, IndexCommand,
DumpAllCommand, DumpAllMeshPropsCommand>(args)
DumpAllCommand, DumpAllMeshPropsCommand, FindAllMeshPropsCommand, FindAllMeshPropsGlobalCommand>(args)
.WithParsed<ListCommand>(ListCommand.Run)
.WithParsed<FindCommand>(FindCommand.Run)
.WithParsed<InspectCommand>(InspectCommand.Run)
.WithParsed<DumpCommand>(DumpCommand.Run)
.WithParsed<DumpAllCommand>(DumpAllCommand.Run)
.WithParsed<DumpMeshPropsCommand>(DumpMeshPropsCommand.Run)
.WithParsed<DumpAllMeshPropsCommand>(DumpAllMeshPropsCommand.Run)
.WithParsed<FindAllMeshPropsCommand>(FindAllMeshPropsCommand.Run)
.WithParsed<FindAllMeshPropsGlobalCommand>(FindAllMeshPropsGlobalCommand.Run)
.WithParsed<IndexCommand>(IndexCommand.Run);
}
}
Expand Down
2 changes: 1 addition & 1 deletion RainbowForge/BinaryReaderExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static Vector3 ReadVector3(this BinaryReader r)

public static Vector3 ReadUInt64AsPos(this BinaryReader r)
{
const float bias = 0x777F;
const float bias = 0x7FFF;

var x = r.ReadUInt16();
var y = r.ReadUInt16();
Expand Down
83 changes: 83 additions & 0 deletions RainbowForge/Dump/DumpHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,5 +242,88 @@ void TryRecurseChildren(string dir, ulong uid)
}
}
}

public static void SearchNonContainerChildren(BinaryReader assetStream, FlatArchive arc, FlatArchiveEntry entry, List<ulong> referencedExterns)
{
if (!referencedExterns.Contains(entry.Meta.Uid))
referencedExterns.Add(entry.Meta.Uid);

void TryRecurseChildren(ulong uid)
{
if (uid == 0)
return;

if (!referencedExterns.Contains(uid))
referencedExterns.Add(uid);

var arcEntry = arc.Entries.FirstOrDefault(archiveEntry => archiveEntry.Meta.Uid == uid);
if (arcEntry != null)
SearchNonContainerChildren(assetStream, arc, arcEntry, referencedExterns);
}

assetStream.BaseStream.Seek(entry.PayloadOffset, SeekOrigin.Begin);
switch ((Magic) entry.Meta.Magic)
{
case Magic.MaterialContainer:
{
var mat = MaterialContainer.Read(assetStream);
foreach (var mipContainerReference in mat.BaseMipContainers)
TryRecurseChildren(mipContainerReference.MipContainerUid);
foreach (var mipContainerReference in mat.SecondaryMipContainers)
TryRecurseChildren(mipContainerReference.MipContainerUid);
foreach (var mipContainerReference in mat.TertiaryMipContainers)
TryRecurseChildren(mipContainerReference.MipContainerUid);

break;
}
case Magic.MipContainer:
{
var mipContainer = MipContainer.Read(assetStream);
TryRecurseChildren(mipContainer.MipUid);
break;
}
case Magic.MeshProperties:
{
var meshProps = MeshProperties.Read(assetStream);
TryRecurseChildren(meshProps.MeshUid);

foreach (var materialContainer in meshProps.MaterialContainers)
TryRecurseChildren(materialContainer);
break;
}
case Magic.MipSet:
{
var mipSet = MipSet.Read(assetStream);
foreach (var uid in mipSet.TexUidMipSet1.Where(arg => arg != 0 && !referencedExterns.Contains(arg)))
referencedExterns.Add(uid);
foreach (var uid in mipSet.TexUidMipSet2.Where(arg => arg != 0 && !referencedExterns.Contains(arg)))
referencedExterns.Add(uid);
break;
}
// The root entry is a UidLinkContainer
case Magic.FlatArchive1:
case Magic.FlatArchive2:
case Magic.FlatArchive3:
{
var linkContainer = UidLinkContainer.Read(assetStream, entry.Meta.Var1);
foreach (var linkEntry in linkContainer.UidLinkEntries)
{
if (linkEntry.UidLinkNode1 != null)
{
var uid = linkEntry.UidLinkNode1.LinkedUid;
TryRecurseChildren(uid);
}

if (linkEntry.UidLinkNode2 != null)
{
var uid = linkEntry.UidLinkNode2.LinkedUid;
TryRecurseChildren(uid);
}
}

break;
}
}
}
}
}

0 comments on commit cebccbf

Please sign in to comment.