From 3a4a3901fc1d40fb4aed22ed51812fca7a61eba0 Mon Sep 17 00:00:00 2001 From: morkt Date: Wed, 22 Apr 2015 22:39:16 +0400 Subject: [PATCH] AZ system engine resources implementation. --- ArcFormats/ArcAZSys.cs | 145 ++++++++++++++++++++++++++ ArcFormats/ArcFormats.csproj | 2 + ArcFormats/ImageCPB.cs | 145 ++++++++++++++++++++++++++ ArcFormats/Properties/AssemblyInfo.cs | 4 +- supported.html | 2 + 5 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 ArcFormats/ArcAZSys.cs create mode 100644 ArcFormats/ImageCPB.cs diff --git a/ArcFormats/ArcAZSys.cs b/ArcFormats/ArcAZSys.cs new file mode 100644 index 00000000..2af6f0e4 --- /dev/null +++ b/ArcFormats/ArcAZSys.cs @@ -0,0 +1,145 @@ +//! \file ArcAZSys.cs +//! \date Wed Apr 22 09:52:23 2015 +//! \brief AZ system 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.Formats.Strings; +using GameRes.Utility; + +namespace GameRes.Formats.AZSys +{ + [Export(typeof(ArchiveFormat))] + public class ArcOpener : ArchiveFormat + { + public override string Tag { get { return "ARC/AZ"; } } + public override string Description { get { return "AZ system resource archive"; } } + public override uint Signature { get { return 0x1a435241; } } // 'ARC\x1a' + public override bool IsHierarchic { get { return false; } } + public override bool CanCreate { get { return false; } } + + public ArcOpener () + { + Extensions = new string[] { "arc" }; + } + + public override ArcFile TryOpen (ArcView file) + { + int ext_count = file.View.ReadInt32 (4); + int count = file.View.ReadInt32 (8); + uint index_length = file.View.ReadUInt32 (12); + if (ext_count < 1 || ext_count > 8 || count <= 0 || count > 0xfffff + || index_length <= 0x14 || index_length >= file.MaxOffset) + return null; + var packed_index = new byte[index_length]; + if ((int)index_length != file.View.Read (0x30, packed_index, 0, index_length)) + return null; + uint base_offset = 0x30 + index_length; + uint crc = LittleEndian.ToUInt32 (packed_index, 0); + if (crc != Crc32.Compute (packed_index, 0x14, packed_index.Length-0x14)) + throw new InvalidFormatException ("CRC32 mismatch"); + var reader = new IndexReader (packed_index, count); + var index = reader.Unpack(); + int index_offset = 0; + var dir = new List (count); + for (int i = 0; i < count; ++i) + { + var name = Binary.GetCString (index, index_offset + 0x10, 0x30); + if (name.Length > 0) + { + var entry = FormatCatalog.Instance.CreateEntry (name); + entry.Offset = base_offset + LittleEndian.ToUInt32 (index, index_offset); + entry.Size = LittleEndian.ToUInt32 (index, index_offset + 4); + if (entry.CheckPlacement (file.MaxOffset)) + dir.Add (entry); + } + index_offset += 0x40; + } + if (0 == dir.Count) + return null; + return new ArcFile (file, this, dir); + } + + internal class IndexReader + { + byte[] m_input; + byte[] m_output; + int m_control_len; + int m_compr1_len; + int m_compr2_len; + int m_output_len; + + public byte[] Index { get { return m_output; } } + + public IndexReader (byte[] packed, int count) + { + m_input = packed; + m_output = new byte[count*0x40]; + m_control_len = LittleEndian.ToInt32 (packed, 4); + m_compr1_len = LittleEndian.ToInt32 (packed, 8); + m_compr2_len = LittleEndian.ToInt32 (packed, 12); + m_output_len = LittleEndian.ToInt32 (packed, 0x10); + } + + public byte[] Unpack () + { + int control = 0x14; + int compr1 = control + m_control_len; + int compr2 = compr1 + m_compr1_len; + int dst = 0; + byte mask = 0x80; + int copy_count; + while (dst < m_output.Length) + { + if (0 != (m_input[control] & mask)) + { + int offset = LittleEndian.ToUInt16 (m_input, compr1); + compr1 += 2; + copy_count = (offset >> 13) + 3; + offset &= 0x1fff; + offset++; + Binary.CopyOverlapped (m_output, dst-offset, dst, copy_count); + dst += copy_count; + } + else + { + copy_count = m_input[compr2++] + 1; + Buffer.BlockCopy (m_input, compr2, m_output, dst, copy_count); + compr2 += copy_count; + dst += copy_count; + } + mask >>= 1; + if (0 == mask) + { + ++control; + mask = 0x80; + } + } + return m_output; + } + } + } +} diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index ebe26580..e7f7b347 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -67,6 +67,7 @@ + @@ -139,6 +140,7 @@ + diff --git a/ArcFormats/ImageCPB.cs b/ArcFormats/ImageCPB.cs new file mode 100644 index 00000000..7f970484 --- /dev/null +++ b/ArcFormats/ImageCPB.cs @@ -0,0 +1,145 @@ +//! \file ImageCPB.cs +//! \date Wed Apr 22 11:08:13 2015 +//! \brief AZ system image format 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.ComponentModel.Composition; +using System.IO; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using ZLibNet; + +namespace GameRes.Formats.AZSys +{ + internal class CpbMetaData : ImageMetaData + { + public uint[] Channel = new uint[4]; + } + + [Export(typeof(ImageFormat))] + public class CpbFormat : ImageFormat + { + public override string Tag { get { return "CPB"; } } + public override string Description { get { return "AZ system image format"; } } + public override uint Signature { get { return 0x1a425043; } } // 'CPB\x1a' + + public override void Write (Stream file, ImageData image) + { + throw new System.NotImplementedException ("CpbFormat.Write not implemented"); + } + + public override ImageMetaData ReadMetaData (Stream stream) + { + stream.Seek (5, SeekOrigin.Current); + int bpp = stream.ReadByte(); + if (24 != bpp && 32 != bpp) + throw new NotSupportedException ("Not supported CPB image format"); + using (var input = new ArcView.Reader (stream)) + { + int version = input.ReadInt16 (); + if (1 != version) + throw new NotSupportedException ("Not supported CPB image version"); + var info = new CpbMetaData (); + info.BPP = bpp; + input.ReadUInt32(); + info.Width = input.ReadUInt16(); + info.Height = input.ReadUInt16(); + info.Channel[0] = input.ReadUInt32(); // Alpha + info.Channel[1] = input.ReadUInt32(); + info.Channel[2] = input.ReadUInt32(); + info.Channel[3] = input.ReadUInt32(); + return info; + } + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + var meta = info as CpbMetaData; + if (null == meta) + throw new ArgumentException ("CpbFormat.Read should be supplied with CpbMetaData", "info"); + + stream.Position = 0x20; + var reader = new Reader (stream, meta); + reader.Unpack(); + return ImageData.Create (meta, reader.Format, reader.Palette, reader.Data); + } + + internal class Reader + { + int m_width; + int m_height; + int m_bpp; + Stream m_input; + byte[] m_output; + uint[] m_channel; + + public PixelFormat Format { get; private set; } + public BitmapPalette Palette { get; private set; } + public byte[] Data { get { return m_output; } } + + public Reader (Stream input, CpbMetaData info) + { + m_width = (int)info.Width; + m_height = (int)info.Height; + m_bpp = info.BPP; + m_channel = info.Channel; + m_output = new byte[m_width * m_height * 4]; + if (8 == m_bpp) + Format = PixelFormats.Indexed8; + else if (24 == m_bpp) + Format = PixelFormats.Bgr32; + else + Format = PixelFormats.Bgra32; + m_input = input; + } + + static byte[] StreamMap = new byte[] { 0, 3, 1, 2 }; + static byte[] ChannelMap = new byte[] { 3, 0, 1, 2 }; + + public void Unpack () + { + byte[] channel = new byte[m_width*m_height]; + long start_pos = m_input.Position; + for (int i = 0; i < 4; ++i) + { + if (0 == m_channel[StreamMap[i]]) + continue; + m_input.Position = start_pos + 4; // skip crc32 + using (var input = new ZLibStream (m_input, CompressionMode.Decompress, true)) + { + int channel_size = input.Read (channel, 0, channel.Length); + int dst = ChannelMap[i]; + for (int j = 0; j < channel_size; ++j) + { + m_output[dst] = channel[j]; + dst += 4; + } + } + start_pos += m_channel[StreamMap[i]]; + } + } + } + } +} diff --git a/ArcFormats/Properties/AssemblyInfo.cs b/ArcFormats/Properties/AssemblyInfo.cs index d917e655..e1f40468 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.0.4.41")] -[assembly: AssemblyFileVersion ("1.0.4.41")] +[assembly: AssemblyVersion ("1.0.4.42")] +[assembly: AssemblyFileVersion ("1.0.4.42")] diff --git a/supported.html b/supported.html index ddbf97a7..9f8a285d 100644 --- a/supported.html +++ b/supported.html @@ -137,6 +137,8 @@ Nikutai Ten'i
*.dat-NoAilRagna☆彡Science *.lpkLPK1NoLucifenDoki Doki Rooming *.elgELGNo +*.arcARC\x1aNoAZ SystemTriptych +*.cpbCPB\x1aNo

[1] Non-encrypted only