Created
January 4, 2017 18:27
-
-
Save camden-smallwood-zz/53da0b19a7981f135fadac89fee5483d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using TagTool.Cache; | |
using TagTool.Serialization; | |
using TagTool.TagDefinitions; | |
using TagTool.TagGroups; | |
using static TagTool.Commands.ArgumentParser; | |
namespace TagTool.Commands.Tags | |
{ | |
class NullTagCommand : Command | |
{ | |
public OpenTagCache Info { get; } | |
public NullTagCommand(OpenTagCache info) | |
: base(CommandFlags.None, | |
"nulltag", | |
"Nulls a tag in the current tag cache.", | |
"nulltag <tag index>", | |
"Nulls a tag in the current tag index. The tag's data will be removed from cache.") | |
{ | |
Info = info; | |
} | |
private void LoadTagDependencies(int index, ref HashSet<int> tags) | |
{ | |
var queue = new List<int> { index }; | |
while (queue.Count != 0) | |
{ | |
var nextQueue = new List<int>(); | |
foreach (var entry in queue) | |
{ | |
if (!tags.Contains(entry)) | |
{ | |
if (Info.Cache.Tags[entry] == null) | |
continue; | |
tags.Add(entry); | |
foreach (var dependency in Info.Cache.Tags[entry].Dependencies) | |
if (!nextQueue.Contains(dependency)) | |
nextQueue.Add(dependency); | |
} | |
} | |
queue = nextQueue; | |
} | |
} | |
public override bool Execute(List<string> args) | |
{ | |
var globalTags = new HashSet<int>(); | |
LoadTagDependencies(0x0000, ref globalTags); | |
LoadTagDependencies(0x27C3, ref globalTags); | |
var tagCount = Info.Cache.Tags.Count; | |
var currentTag = 0; | |
var resources = new ResourceDataManager(); | |
resources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName); | |
var tagQueue = new List<int>(); | |
var resourceQueue = new List<int>(); | |
Info.Cache.Tags.FindAllInGroup("bink").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.FindAllInGroup("bitm").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.FindAllInGroup("mode").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.FindAllInGroup("jmad").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.FindAllInGroup("snd!").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.FindAllInGroup("sbsp").ToList().ForEach(tag => { if (tag != null && !resourceQueue.Contains(tag.Index)) resourceQueue.Add(tag.Index); }); | |
Info.Cache.Tags.ForEach(tag => { if (tag != null && (!globalTags.Contains(tag.Index)) && (!resourceQueue.Contains(tag.Index)) && (!tagQueue.Contains(tag.Index))) tagQueue.Add(tag.Index); }); | |
tagQueue.AddRange(resourceQueue); | |
resourceQueue.Clear(); | |
resourceQueue = null; | |
foreach (var tagIndex in tagQueue) | |
{ | |
var tag = Info.Cache.Tags[tagIndex]; | |
if (tag == null) | |
continue; | |
if (globalTags.Contains(tag.Index)) | |
continue; | |
using (var stream = Info.OpenCacheReadWrite()) | |
{ | |
var tagName = $"{Info.TagNames[tag.Index]}.{Info.StringIDs.GetString(tag.Group.Name)}"; | |
Console.Write($"[{currentTag++}/{tagCount - globalTags.Count}] {tagName} (tag 0x{tag.Index:X4}): "); | |
var context = new TagSerializationContext(stream, Info.Cache, Info.StringIDs, tag); | |
if (tag.IsInGroup("bitm")) | |
{ | |
Console.Write("nulling bitmap resources..."); | |
var bitm = Info.Deserializer.Deserialize<Bitmap>(context); | |
foreach (var resource in bitm.Resources) | |
{ | |
var location = resource.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(resource.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
} | |
else if (tag.IsInGroup("bink")) | |
{ | |
Console.Write("nulling bink resource..."); | |
var bink = Info.Deserializer.Deserialize<Bink>(context); | |
var location = bink.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(bink.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
else if (tag.IsInGroup("mode")) | |
{ | |
Console.Write("nulling render model resource..."); | |
var mode = Info.Deserializer.Deserialize<RenderModel>(context); | |
var location = mode.Geometry.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(mode.Geometry.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
else if (tag.IsInGroup("jmad")) | |
{ | |
Console.Write("nulling model animation graph resources..."); | |
var jmad = Info.Deserializer.Deserialize<ModelAnimationGraph>(context); | |
foreach (var resourceGroup in jmad.ResourceGroups) | |
{ | |
var location = resourceGroup.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(resourceGroup.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
} | |
else if (tag.IsInGroup("snd!")) | |
{ | |
Console.Write("nulling sound resource..."); | |
var snd_ = Info.Deserializer.Deserialize<Sound>(context); | |
var location = snd_.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(snd_.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
else if (tag.IsInGroup("sbsp")) | |
{ | |
Console.Write("null scenario structure bsp resources..."); | |
var sbsp = Info.Deserializer.Deserialize<ScenarioStructureBsp>(context); | |
{ | |
var location = sbsp.Geometry.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(sbsp.Geometry.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
{ | |
var location = sbsp.Geometry2.Resource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(sbsp.Geometry2.Resource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
{ | |
var location = sbsp.CollisionBSPResource.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(sbsp.CollisionBSPResource, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
{ | |
var location = sbsp.Resource4.GetLocation(); | |
var cache = resources.GetCache(location); | |
resources.ReplaceRaw(sbsp.Resource4, new byte[] { }); | |
using (var resourceStream = resources.OpenCacheReadWrite(location)) | |
using (var writer = new BinaryWriter(resourceStream)) | |
{ | |
cache.UpdateResourceTable(writer); | |
} | |
} | |
} | |
Console.Write("nulling tag data..."); | |
Info.Cache.SetTagDataRaw(stream, tag, new byte[] { }); | |
Info.Cache.Tags[tag.Index] = null; | |
using (var writer = new BinaryWriter(stream)) | |
Info.Cache.UpdateTagOffsets(writer); | |
Console.WriteLine("done."); | |
} | |
} | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment