From 459468ff68fb15bb7b2582f75ad9143282b51b8b Mon Sep 17 00:00:00 2001 From: alcexhim Date: Tue, 7 Oct 2014 23:24:51 -0400 Subject: [PATCH] Added Eighting FPK archive format (without compression) --- .../FileSystem/Eighting/FPK/FPKDataFormat.cs | 142 ++++++++++++++++++ .../UniversalEditor.Plugins.FileSystem.csproj | 1 + 2 files changed, 143 insertions(+) create mode 100644 CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/Eighting/FPK/FPKDataFormat.cs diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/Eighting/FPK/FPKDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/Eighting/FPK/FPKDataFormat.cs new file mode 100644 index 00000000..83d4bd87 --- /dev/null +++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/Eighting/FPK/FPKDataFormat.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.FileSystem; + +namespace UniversalEditor.DataFormats.FileSystem.Eighting.FPK +{ + public class FPKDataFormat : DataFormat + { + private static DataFormatReference _dfr = null; + public override DataFormatReference MakeReference() + { + if (_dfr == null) + { + _dfr = base.MakeReference(); + _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All); + _dfr.ExportOptions.Add(new CustomOptionNumber("DataAlignment", "Data &alignment (in bytes): ", 16, 0, UInt32.MaxValue)); + _dfr.Filters.Add("Eighting (Bleach PSP) FPK archive", new byte?[][] { new byte?[] { (byte)'x', (byte)'J', (byte)0, (byte)0 } }, new string[] { "*.fpk" }); + _dfr.Sources.Add("http://wiki.xentax.com/index.php?title=Bleach_%28PSP%29"); + } + return _dfr; + } + + private uint mvarDataAlignment = 16; + public uint DataAlignment { get { return mvarDataAlignment; } set { mvarDataAlignment = value; } } + + protected override void LoadInternal(ref ObjectModel objectModel) + { + FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); + if (fsom == null) throw new ObjectModelNotSupportedException(); + + Reader reader = base.Accessor.Reader; + string header1 = reader.ReadFixedLengthString(2); + ushort header2 = reader.ReadUInt16(); + if (!(header1 == "xJ" && header2 == 0)) throw new InvalidDataFormatException("File does not begin with 'xJ', 0x00, 0x00"); + + uint fileCount = reader.ReadUInt32(); + mvarDataAlignment = reader.ReadUInt32(); + uint archiveSize = reader.ReadUInt32(); + + for (uint i = 0; i < fileCount; i++) + { + string fileName = reader.ReadFixedLengthString(36).TrimNull(); + uint offset = reader.ReadUInt32(); + uint compressedLength = reader.ReadUInt32(); + uint decompressedLength = reader.ReadUInt32(); + + File file = fsom.AddFile(fileName); + file.Size = decompressedLength; + file.Properties.Add("reader", reader); + file.Properties.Add("offset", offset); + file.Properties.Add("CompressedLength", compressedLength); + file.Properties.Add("DecompressedLength", decompressedLength); + file.DataRequest += file_DataRequest; + } + } + + private void file_DataRequest(object sender, DataRequestEventArgs e) + { + File file = (sender as File); + Reader reader = (Reader)file.Properties["reader"]; + uint offset = (uint)file.Properties["offset"]; + uint CompressedLength = (uint)file.Properties["CompressedLength"]; + uint DecompressedLength = (uint)file.Properties["DecompressedLength"]; + + reader.Seek(offset, SeekOrigin.Begin); + byte flag = reader.ReadByte(); + bool compressed = (flag == 255); + + byte[] compressedData = reader.ReadBytes(CompressedLength); + byte[] decompressedData = compressedData; + if (compressed) + { + + } + e.Data = decompressedData; + } + + protected override void SaveInternal(ObjectModel objectModel) + { + FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel); + if (fsom == null) throw new ObjectModelNotSupportedException(); + + Writer writer = base.Accessor.Writer; + writer.WriteFixedLengthString("xJ"); + writer.WriteUInt16(0); + + File[] files = fsom.GetAllFiles(); + writer.WriteUInt32((uint)files.Length); + writer.WriteUInt32(mvarDataAlignment); + + uint archiveSize = 16; + long archiveSizePosition = base.Accessor.Position; + writer.WriteUInt32(archiveSize); + + uint offset = (uint)(base.Accessor.Position + (48 * files.Length)); + + byte[][] compressedDatas = new byte[files.Length][]; + bool[] compressed = new bool[files.Length]; + for (int i = 0; i < files.Length; i++) + { + File file = files[i]; + writer.WriteFixedLengthString(file.Name, 36); + writer.WriteUInt32(offset); + + byte[] decompressedData = file.GetDataAsByteArray(); + byte[] compressedData = decompressedData; + + compressedDatas[i] = compressedData; + compressed[i] = false; + + writer.WriteUInt32((uint)compressedData.Length); + writer.WriteUInt32((uint)decompressedData.Length); + + offset += (uint)(compressedData.Length + 1); + + long count = (offset % mvarDataAlignment); + offset += (uint)count; + } + for (int i = 0; i < files.Length; i++) + { + if (compressed[i]) + { + writer.WriteByte(255); + } + else + { + writer.WriteByte(0); + } + writer.WriteBytes(compressedDatas[i]); + writer.Align((int)mvarDataAlignment); + } + + base.Accessor.Seek(archiveSizePosition, SeekOrigin.Begin); + writer.WriteUInt32((uint)base.Accessor.Length); + + writer.Flush(); + } + } +} diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj index ff390d2c..d2d67315 100644 --- a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj +++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj @@ -78,6 +78,7 @@ +