diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index 4d9a5af7..5e24aaa3 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -63,6 +63,8 @@ + + diff --git a/ArcFormats/Emic/ArcPACK.cs b/ArcFormats/Emic/ArcPACK.cs new file mode 100644 index 00000000..8f3372cd --- /dev/null +++ b/ArcFormats/Emic/ArcPACK.cs @@ -0,0 +1,147 @@ +//! \file ArcPACK.cs +//! \date Sun Aug 30 01:11:18 2015 +//! \brief Emic engine archive implementation. +// +// Copyright (C) 2015 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using GameRes.Utility; + +namespace GameRes.Formats.Emic +{ + internal class EmicArchive : ArcFile + { + public readonly byte[] Key; + + public EmicArchive (ArcView arc, ArchiveFormat impl, ICollection dir, byte[] key) + : base (arc, impl, dir) + { + Key = key; + } + } + + [Export(typeof(ArchiveFormat))] + public class PacOpener : ArchiveFormat + { + public override string Tag { get { return "PAC/EMIC"; } } + public override string Description { get { return "Emic engine resource archive"; } } + public override uint Signature { get { return 0x4B434150; } } + public override bool IsHierarchic { get { return true; } } + public override bool CanCreate { get { return false; } } + + public override ArcFile TryOpen (ArcView file) + { + int count = file.View.ReadInt32 (0x28); + if (!IsSaneCount (count)) + return null; + + var reader = new PacReader (file, count); + var dir = reader.ReadIndex(); + if (null == dir) + return null; + if (reader.Encrypted) + return new EmicArchive (file, this, dir, reader.Key); + else + return new ArcFile (file, this, dir); + } + + public override Stream OpenEntry (ArcFile arc, Entry entry) + { + var emic = arc as EmicArchive; + if (null == emic) + return arc.File.CreateStream (entry.Offset, entry.Size); + var reader = new PacReader (emic.File, emic.Key); + var data = new byte[entry.Size]; + reader.Read (entry.Offset, data, 0, data.Length); + return new MemoryStream (data); + } + } + + internal class PacReader + { + ArcView m_file; + int m_count; + + public bool Encrypted { get; private set; } + public byte[] Key { get; private set; } + + public PacReader (ArcView file, int count) + { + m_file = file; + m_count = count; + Key = new byte[0x20]; + Encrypted = 1 == m_file.View.ReadInt32 (4); + file.View.Read (8, Key, 0, (uint)Key.Length); + for (int i = 0; i < Key.Length; ++i) + Key[i] ^= 0xAA; + } + + public PacReader (ArcView file, byte[] key) + { + m_file = file; + Encrypted = true; + Key = key; + } + + public List ReadIndex () + { + var index_buf = new byte[0x110]; + var dir = new List (m_count); + uint index_offset = 0x2C; + for (int i = 0; i < m_count; ++i) + { + Read (index_offset, index_buf, 0, 4); + int name_len = LittleEndian.ToInt32 (index_buf, 0); + if (name_len > index_buf.Length-8) // file name is too long + return null; + index_offset += 4; + Read (index_offset, index_buf, 0, name_len+8); + string name = Binary.GetCString (index_buf, 0, name_len); + var entry = FormatCatalog.Instance.CreateEntry (name); + entry.Offset = LittleEndian.ToUInt32 (index_buf, name_len+4); + entry.Size = LittleEndian.ToUInt32 (index_buf, name_len); + if (!entry.CheckPlacement (m_file.MaxOffset)) + return null; + dir.Add (entry); + index_offset += (uint)name_len + 8; + } + return dir; + } + + public int Read (long offset, byte[] buf, int index, int count) + { + int read = m_file.View.Read (offset, buf, index, (uint)count); + if (Encrypted) + { + int key_offset = (int)offset; + for (int i = 0; i < read; ++i) + { + buf[i] ^= Key[key_offset++ & 0x1F]; + } + } + return read; + } + } +} diff --git a/ArcFormats/Emic/ImageMWP.cs b/ArcFormats/Emic/ImageMWP.cs new file mode 100644 index 00000000..94d87da1 --- /dev/null +++ b/ArcFormats/Emic/ImageMWP.cs @@ -0,0 +1,72 @@ +//! \file ImageMWP.cs +//! \date Sun Aug 30 02:15:38 2015 +//! \brief Emic engine RGBA bitmap. +// +// Copyright (C) 2015 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System.ComponentModel.Composition; +using System.IO; +using System.Windows.Media; +using GameRes.Utility; + +namespace GameRes.Formats.Emic +{ + [Export(typeof(ImageFormat))] + public class MwpFormat : ImageFormat + { + public override string Tag { get { return "MWP"; } } + public override string Description { get { return "Emic engine bitmap"; } } + public override uint Signature { get { return 0x1050574D; } } // 'MWP\x10' + + public MwpFormat () + { + Extensions = new string[] { "bmp" }; + } + + public override ImageMetaData ReadMetaData (Stream stream) + { + var header = new byte[12]; + if (header.Length != stream.Read (header, 0, header.Length)) + return null; + return new ImageMetaData + { + Width = LittleEndian.ToUInt32 (header, 4), + Height = LittleEndian.ToUInt32 (header, 8), + BPP = 32, + }; + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + var pixels = new byte[info.Width*info.Height*4]; + stream.Position = 12; + if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) + throw new EndOfStreamException(); + return ImageData.Create (info, PixelFormats.Bgra32, null, pixels); + } + + public override void Write (Stream file, ImageData image) + { + throw new System.NotImplementedException ("MwpFormat.Write not implemented"); + } + } +} diff --git a/ArcFormats/Properties/AssemblyInfo.cs b/ArcFormats/Properties/AssemblyInfo.cs index a1fbacab..7b160fd3 100644 --- a/ArcFormats/Properties/AssemblyInfo.cs +++ b/ArcFormats/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion ("1.1.9.416")] -[assembly: AssemblyFileVersion ("1.1.9.416")] +[assembly: AssemblyVersion ("1.1.9.417")] +[assembly: AssemblyFileVersion ("1.1.9.417")] diff --git a/supported.html b/supported.html index 0263f269..887594eb 100644 --- a/supported.html +++ b/supported.html @@ -71,6 +71,7 @@ Yakuchu!
*.tgf-No *.arcMajiroArcV1.000
MajiroArcV2.000
MajiroArcV3.000YesMajiro +Amber Quartz
Chikan Kizoku
Reconquista
White ~blanche comme la lune~
@@ -356,9 +357,14 @@ _summer
*.ykgYKG000No *.pakGCEXNoG2 Aster
+Kimi to Koishite Musubarete
Majiresu!! ~Omatase Little Wing~
*.arg
*.argbBGRANo +*.pacPACKNoEmic +Futamajo
+ +*.bmpMWPNo

1 Non-encrypted only