EFFN ptcl fixes and add saving back

This commit is contained in:
KillzXGaming 2019-08-17 09:58:17 -04:00
parent 31ec93411f
commit 3769cc12c2
10 changed files with 331 additions and 213 deletions

Binary file not shown.

View file

@ -6,12 +6,14 @@ using System.Threading.Tasks;
using System.Runtime.InteropServices;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Forms;
using System.IO;
using System.Windows.Forms;
using FirstPlugin.Forms;
namespace DKCTF
{
public class MSBT : TreeNodeFile, IFileFormat
public class MSBT : TreeNodeFile, IFileFormat, ILeaveOpenOnLoad
{
public FileType FileType { get; set; } = FileType.Layout;
@ -42,13 +44,17 @@ namespace DKCTF
}
}
private Stream _stream;
public void Load(System.IO.Stream stream)
{
using (var reader = new Toolbox.Library.IO.FileReader(stream))
_stream = stream;
using (var reader = new Toolbox.Library.IO.FileReader(stream, true))
{
reader.SetByteOrder(true);
var header = reader.ReadStruct<MSBTHeader>();
Text = FileName;
//parse the data
int index = 0;
while (!reader.EndOfStream)
@ -57,8 +63,10 @@ namespace DKCTF
long startPos = reader.Position;
reader.SeekBegin(startPos + (int)chunk.DataOffset);
byte[] chunkData = reader.ReadBytes((int)chunk.DataSize);
Nodes.Add(new MessageEntry(chunkData, index++, chunk.ChunkType));
var subStream = new SubStream(_stream, reader.Position, (long)chunk.DataSize);
Nodes.Add(new MessageEntry(subStream, index++, chunk.ChunkType));
reader.SeekBegin(startPos + (int)chunk.DataOffset + (int)chunk.DataSize);
}
}
}
@ -67,19 +75,40 @@ namespace DKCTF
}
public class MessageEntry : TreeNodeCustom
public class MessageEntry : TreeNodeCustom, IContextMenuNode
{
FirstPlugin.MSBT msbt;
public MessageEntry(byte[] data, int index, string type)
private Stream stream;
public MessageEntry(Stream data, int index, string type)
{
Text = $"Message Entry ({type}) {index}";
stream = data;
var chunkFile = STFileLoader.OpenFileFormat(Text, data);
Text = $"{type}.msbt";
var chunkFile = STFileLoader.OpenFileFormat(data, Text);
if (chunkFile != null && chunkFile is FirstPlugin.MSBT)
msbt = (FirstPlugin.MSBT)chunkFile;
}
public ToolStripItem[] GetContextMenuItems()
{
List<ToolStripItem> Items = new List<ToolStripItem>();
Items.Add(new STToolStipMenuItem("Export", null, ExportAction, Keys.Control | Keys.E));
return Items.ToArray();
}
private void ExportAction(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(typeof(MSBT));
sfd.FileName = Text;
if (sfd.ShowDialog() == DialogResult.OK)
{
stream.ExportToFile(sfd.FileName);
}
}
public override void OnClick(TreeView treeview)
{
if (msbt != null)

View file

@ -5,10 +5,11 @@ using System.Text;
using System.Threading.Tasks;
using Toolbox.Library.IO;
using Toolbox.Library;
using System.Windows.Forms;
namespace FirstPlugin
{
public class EFF : TreeNodeFile,IFileFormat
public class EFF : TreeNodeFile,IFileFormat, IContextMenuNode
{
public FileType FileType { get; set; } = FileType.Effect;
@ -36,19 +37,54 @@ namespace FirstPlugin
}
}
private PTCL ptcl;
private byte[] DataStart;
public void Load(System.IO.Stream stream)
{
Text = FileName;
CanSave = true;
FileReader reader = new FileReader(stream);
reader.Seek(4096, System.IO.SeekOrigin.Begin);
int SectionSize = 0;
while (true)
{
string magicCheck = reader.ReadString(4, Encoding.ASCII);
if (magicCheck == "VFXB")
{
reader.Seek(-4);
break;
}
PTCL pctl = new PTCL();
pctl.Text = "Output.pctl";
Nodes.Add(pctl);
SectionSize += 4;
}
PTCL.Header Header = new PTCL.Header();
Header.Read(reader, pctl);
DataStart = reader.getSection(0, SectionSize);
Text = FileName;
ptcl = new PTCL();
ptcl.IFileInfo = new IFileInfo();
ptcl.FileName = "Output.pctl";
Nodes.Add(ptcl);
ptcl.Load(new SubStream(stream, reader.Position));
}
public ToolStripItem[] GetContextMenuItems()
{
return new ToolStripItem[]
{
new ToolStripMenuItem("Save", null, SaveAction, Keys.Control | Keys.S),
};
}
private void SaveAction(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(typeof(EFF));
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
public void Unload()
@ -58,6 +94,13 @@ namespace FirstPlugin
public void Save(System.IO.Stream stream)
{
using (var writer = new FileWriter(stream))
{
writer.Write(DataStart);
var mem = new System.IO.MemoryStream();
ptcl.Save(mem);
writer.Write(mem.ToArray());
}
}
}
}

View file

@ -64,38 +64,39 @@ namespace FirstPlugin
Text = FileName;
CanSave = true;
FileReader reader = new FileReader(new MemoryStream(data));
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
string Signature = reader.ReadString(4, Encoding.ASCII);
byte VersionNum = reader.ReadByte();
if (VersionNum != 0 && Signature == "SPBD")
Is3DS = true;
reader.Position = 0;
if (Is3DS)
using (var reader = new FileReader(stream))
{
reader.ByteOrder = ByteOrder.LittleEndian;
header3DS = new PTCL_3DS.Header();
header3DS.Read(reader, this);
}
else if (Signature == "EFTF" || Signature == "SPBD")
{
IsWiiU = true;
headerU = new PTCL_WiiU.Header();
headerU.Read(reader, this);
}
else
{
header = new Header();
header.Read(reader, this);
}
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
string Signature = reader.ReadString(4, Encoding.ASCII);
reader.Close();
reader.Dispose();
stream.Close();
stream.Dispose();
byte VersionNum = reader.ReadByte();
if (VersionNum != 0 && Signature == "SPBD")
Is3DS = true;
reader.Position = 0;
if (Is3DS)
{
reader.ByteOrder = ByteOrder.LittleEndian;
header3DS = new PTCL_3DS.Header();
header3DS.Read(reader, this);
}
else if (Signature == "EFTF" || Signature == "SPBD")
{
IsWiiU = true;
headerU = new PTCL_WiiU.Header();
headerU.Read(reader, this);
}
else
{
header = new Header();
header.Read(reader, this);
}
reader.Close();
reader.Dispose();
stream.Close();
stream.Dispose();
}
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Save", null, Save, Keys.Control | Keys.S));
@ -116,11 +117,8 @@ namespace FirstPlugin
}
private void Save(object sender, EventArgs args)
{
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.Filter = Utils.GetAllFilters(typeof(PTCL));
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace Toolbox.Library.IO
{
public static class StreamExport
{
public static void ExportToFile(this Stream stream, string fileName)
{
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
{
stream.CopyTo(fileStream);
}
}
}
}

View file

@ -133,190 +133,201 @@ namespace Toolbox.Library.IO
public static IFileFormat OpenFileFormat(string FileName, byte[] data = null, bool LeaveStreamOpen = false, bool InArchive = false,
TreeNode archiveNode = null, bool Compressed = false, CompressionType CompType = 0, uint DecompressedSize = 0, uint CompressedSize = 0)
{
uint DecompressedFileSize = 0;
uint CompressedFileSize = 0;
FileReader fileReader;
if (data != null)
fileReader = new FileReader(data);
else
fileReader = new FileReader(FileName);
if (CompType == CompressionType.None)
DecompressedFileSize = (uint)fileReader.BaseStream.Length;
if (CompType != CompressionType.None)
CompressedFileSize = (uint)fileReader.BaseStream.Length;
if (fileReader.BaseStream.Length <= 4)
{
fileReader.Close();
fileReader.Dispose();
return null;
}
Cursor.Current = Cursors.WaitCursor;
fileReader.ByteOrder = ByteOrder.BigEndian;
uint MagicHex = fileReader.ReadUInt32();
string Magic = fileReader.ReadMagic(0, 4);
fileReader.Position = 0;
ushort MagicHex2 = fileReader.ReadUInt16();
//Another hacky magic check if decomp size is first
fileReader.Position = 4;
ushort MagicHex3 = fileReader.ReadUInt16();
Stream stream;
if (data != null)
stream = new MemoryStream(data);
else
stream = File.OpenRead(FileName);
//Note this method will soon be how all compression formats are handled rather than being checked here
foreach (ICompressionFormat compressionFormat in FileManager.GetCompressionFormats())
return OpenFileFormat(stream, FileName, data, LeaveStreamOpen, InArchive,
archiveNode, Compressed, CompType, DecompressedSize, CompressedSize);
}
/// <summary>
/// Gets the <see cref="IFileFormat"/> from a file or byte array.
/// </summary>
/// <param name="FileName">The name of the file</param>
/// <param name="data">The byte array of the data</param>
/// <param name="InArchive">If the file is in an archive so it can be saved back</param>
/// <param name="archiveNode">The node being replaced from an archive</param>
/// <param name="Compressed">If the file is being compressed or not</param>
/// <param name="CompType">The type of <see cref="CompressionType"/> being used</param>
/// <returns></returns>
public static IFileFormat OpenFileFormat(Stream stream, string FileName, byte[] data = null, bool LeaveStreamOpen = false, bool InArchive = false,
TreeNode archiveNode = null, bool Compressed = false, CompressionType CompType = 0, uint DecompressedSize = 0, uint CompressedSize = 0)
{
uint DecompressedFileSize = 0;
uint CompressedFileSize = 0;
using (var fileReader = new FileReader(stream, true))
{
if (compressionFormat.Identify(stream))
if (CompType == CompressionType.None)
DecompressedFileSize = (uint)fileReader.BaseStream.Length;
if (CompType != CompressionType.None)
CompressedFileSize = (uint)fileReader.BaseStream.Length;
if (fileReader.BaseStream.Length <= 4)
{
stream = compressionFormat.Decompress(stream);
fileReader.Close();
fileReader.Dispose();
return null;
}
}
if (Magic == "Yaz0")
{
if (data != null)
data = EveryFileExplorer.YAZ0.Decompress(data);
else
data = EveryFileExplorer.YAZ0.Decompress(FileName);
Cursor.Current = Cursors.WaitCursor;
fileReader.ByteOrder = ByteOrder.BigEndian;
uint MagicHex = fileReader.ReadUInt32();
string Magic = fileReader.ReadMagic(0, 4);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Yaz0, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".cbtex")
{
fileReader.Position = 0;
byte compType = fileReader.ReadByte();
if (compType == 0x50)
ushort MagicHex2 = fileReader.ReadUInt16();
//Another hacky magic check if decomp size is first
fileReader.Position = 4;
ushort MagicHex3 = fileReader.ReadUInt16();
//Note this method will soon be how all compression formats are handled rather than being checked here
foreach (ICompressionFormat compressionFormat in FileManager.GetCompressionFormats())
{
if (compressionFormat.Identify(stream))
{
stream = compressionFormat.Decompress(stream);
}
}
if (Magic == "Yaz0")
{
if (data != null)
data = EveryFileExplorer.YAZ0.Decompress(data);
else
data = EveryFileExplorer.YAZ0.Decompress(FileName);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Yaz0, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".cbtex")
{
fileReader.Position = 0;
byte compType = fileReader.ReadByte();
if (compType == 0x50)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
fileReader.Seek(4, System.IO.SeekOrigin.Begin);
uint decompSize = fileReader.ReadUInt32();
uint compSize = (uint)fileReader.BaseStream.Length - 8;
var comp = new STLibraryCompression.MTA_CUSTOM();
data = comp.Decompress(data, decompSize);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.MarioTennisCustom, DecompressedFileSize, CompressedFileSize);
}
fileReader.Position = 0;
}
if (Path.GetExtension(FileName) == ".lz")
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
fileReader.Seek(4, System.IO.SeekOrigin.Begin);
uint decompSize = fileReader.ReadUInt32();
uint compSize = (uint)fileReader.BaseStream.Length - 8;
var comp = new STLibraryCompression.MTA_CUSTOM();
data = comp.Decompress(data, decompSize);
data = LZ77_WII.Decompress(fileReader.getSection(16, data.Length - 16));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.MarioTennisCustom, DecompressedFileSize, CompressedFileSize);
CompressionType.Yaz0, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x28B52FFD || MagicHex == 0xFD2FB528)
{
if (data != null)
data = STLibraryCompression.ZSTD.Decompress(fileReader.getSection(0, data.Length));
else
data = STLibraryCompression.ZSTD.Decompress(File.ReadAllBytes(FileName));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zstb, DecompressedFileSize, CompressedFileSize);
}
if (Magic == "ZCMP" || MagicHex2 == 0x789C || MagicHex2 == 0x78DA || Path.GetExtension(FileName) == ".z" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.ZLIB.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex3 == 0x789C || MagicHex3 == 0x78DA && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.Position = 0;
int OuSize = fileReader.ReadInt32();
int InSize = data.Length - 4;
data = STLibraryCompression.ZLIB.Decompress(fileReader.getSection(4, InSize));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".carc" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.ZLIB.Decompress(fileReader.getSection(0x10, data.Length - 0x10));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Magic == "ZLIB")
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.GZIP.Decompress(fileReader.getSection(64, data.Length - 64));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x1f8b0808 || MagicHex2 == 0x1f8b && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.GZIP.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Gzip, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x184D2204)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.Type_LZ4.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Lz4, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".lz" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.LZ77.Decompress(fileReader.getSection(16, data.Length - 16));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".cmp" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.Position = 0;
int OuSize = fileReader.ReadInt32();
int InSize = data.Length - 4;
data = STLibraryCompression.Type_LZ4F.Decompress(fileReader.getSection(4, InSize));
return OpenFileFormat(FileName, data, InArchive, LeaveStreamOpen, archiveNode, true,
CompressionType.Lz4f, DecompressedFileSize, CompressedFileSize);
}
fileReader.Position = 0;
}
if (Path.GetExtension(FileName) == ".lz")
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = LZ77_WII.Decompress(fileReader.getSection(16, data.Length - 16));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Yaz0, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x28B52FFD || MagicHex == 0xFD2FB528)
{
if (data != null)
data = STLibraryCompression.ZSTD.Decompress(fileReader.getSection(0, data.Length));
else
data = STLibraryCompression.ZSTD.Decompress(File.ReadAllBytes(FileName));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zstb, DecompressedFileSize, CompressedFileSize);
}
if (Magic == "ZCMP" || MagicHex2 == 0x789C || MagicHex2 == 0x78DA || Path.GetExtension(FileName) == ".z" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.ZLIB.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex3 == 0x789C || MagicHex3 == 0x78DA && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.Position = 0;
int OuSize = fileReader.ReadInt32();
int InSize = data.Length - 4;
data = STLibraryCompression.ZLIB.Decompress(fileReader.getSection(4, InSize));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".carc" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.ZLIB.Decompress(fileReader.getSection(0x10, data.Length - 0x10));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Magic == "ZLIB")
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.GZIP.Decompress(fileReader.getSection(64, data.Length - 64));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x1f8b0808 || MagicHex2 == 0x1f8b && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.GZIP.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Gzip, DecompressedFileSize, CompressedFileSize);
}
if (MagicHex == 0x184D2204)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.Type_LZ4.Decompress(data);
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Lz4, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".lz" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
data = STLibraryCompression.LZ77.Decompress(fileReader.getSection(16, data.Length - 16));
return OpenFileFormat(FileName, data, LeaveStreamOpen, InArchive, archiveNode, true,
CompressionType.Zlib, DecompressedFileSize, CompressedFileSize);
}
if (Path.GetExtension(FileName) == ".cmp" && CompType == CompressionType.None)
{
if (data == null)
data = File.ReadAllBytes(FileName);
fileReader.Position = 0;
int OuSize = fileReader.ReadInt32();
int InSize = data.Length - 4;
data = STLibraryCompression.Type_LZ4F.Decompress(fileReader.getSection(4, InSize));
return OpenFileFormat(FileName, data, InArchive, LeaveStreamOpen, archiveNode, true,
CompressionType.Lz4f, DecompressedFileSize, CompressedFileSize);
}
fileReader.Close();
fileReader.Dispose();
foreach (IFileFormat fileFormat in FileManager.GetFileFormats())
{

View file

@ -27,6 +27,22 @@ namespace Toolbox.Library.IO
this.length = length;
baseOffset = offset;
}
public SubStream(Stream baseStream, long offset)
{
long length = baseStream.Length - offset;
if (baseStream == null) throw new ArgumentNullException("baseStream");
if (!baseStream.CanRead) throw new ArgumentException("baseStream.CanRead is false");
if (!baseStream.CanSeek) throw new ArgumentException("baseStream.CanSeek is false");
if (offset < 0) throw new ArgumentOutOfRangeException("offset");
if (offset + length > baseStream.Length) throw new ArgumentOutOfRangeException("length");
this.baseStream = baseStream;
this.length = length;
baseOffset = offset;
}
public override int Read(byte[] buffer, int offset, int count)
{
baseStream.Position = baseOffset + offset + Position;

View file

@ -291,6 +291,7 @@
<Compile Include="Interfaces\ModelData\IMeshContainer.cs" />
<Compile Include="Interfaces\Textures\ITextureContainer.cs" />
<Compile Include="Interfaces\Forms\IUpdateForm.cs" />
<Compile Include="IO\Extensions\StreamExport.cs" />
<Compile Include="IO\Extensions\UintExtension.cs" />
<Compile Include="IO\FileStreamStorage.cs" />
<Compile Include="IO\IOComoon.cs" />