From 69382f33b91a0c7060220e76cc8b01939ca24679 Mon Sep 17 00:00:00 2001 From: morkt Date: Wed, 9 Dec 2015 18:30:17 +0400 Subject: [PATCH] implemented Favorite BIN archives and HZC1 images. --- ArcFormats/ArcFormats.csproj | 3 + ArcFormats/Favorite/ArcBIN.cs | 104 +++++++++++++++++++++++++++++ ArcFormats/Favorite/ArcHZC.cs | 113 ++++++++++++++++++++++++++++++++ ArcFormats/Favorite/ImageHZC.cs | 107 ++++++++++++++++++++++++++++++ supported.html | 4 ++ 5 files changed, 331 insertions(+) create mode 100644 ArcFormats/Favorite/ArcBIN.cs create mode 100644 ArcFormats/Favorite/ArcHZC.cs create mode 100644 ArcFormats/Favorite/ImageHZC.cs diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index c72e6282..321ea11d 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -77,6 +77,9 @@ + + + diff --git a/ArcFormats/Favorite/ArcBIN.cs b/ArcFormats/Favorite/ArcBIN.cs new file mode 100644 index 00000000..ab6caa0a --- /dev/null +++ b/ArcFormats/Favorite/ArcBIN.cs @@ -0,0 +1,104 @@ +//! \file ArcBIN.cs +//! \date Tue Dec 08 21:45:54 2015 +//! \brief Favorite View Point v2 resource archive. +// +// 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.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; + +namespace GameRes.Formats.FVP +{ + [Export(typeof(ArchiveFormat))] + public class Bin2Opener : ArchiveFormat + { + public override string Tag { get { return "BIN/FVP"; } } + public override string Description { get { return "Favorite View Point resource archive"; } } + public override uint Signature { get { return 0; } } + public override bool IsHierarchic { get { return false; } } + public override bool CanCreate { get { return false; } } + + public Bin2Opener () + { + Extensions = new string[] { "bin" }; + } + + public override ArcFile TryOpen (ArcView file) + { + int count = file.View.ReadInt32 (0); + if (!IsSaneCount (count)) + return null; + uint index_size = (uint)count * 12; + uint name_index_size = file.View.ReadUInt32 (4); + if (8L + index_size + name_index_size >= file.MaxOffset) + return null; + + uint index_offset = 8; + file.View.Reserve (index_offset, index_size + name_index_size); + uint names_base = index_offset + index_size; + var dir = new List (count); + string entry_type = null; + string arc_name = Path.GetFileNameWithoutExtension (file.Name).ToLowerInvariant(); + if ("voice" == arc_name || "bgm" == arc_name) + entry_type = "audio"; + for (int i = 0; i < count; ++i) + { + uint filename_offset = file.View.ReadUInt32 (index_offset); + if (filename_offset >= name_index_size) + return null; + var name = file.View.ReadString (names_base+filename_offset, name_index_size-filename_offset); + if (0 == name.Length) + return null; + var entry = new Entry { + Name = name, + Offset = file.View.ReadUInt32 (index_offset+4), + Size = file.View.ReadUInt32 (index_offset+8), + }; + if (!entry.CheckPlacement (file.MaxOffset)) + return null; + if (entry_type != null) + entry.Type = entry_type; + dir.Add (entry); + index_offset += 12; + } + if (null == entry_type) + { + foreach (var entry in dir) + { + var signature = file.View.ReadUInt32 (entry.Offset); + if (0 == signature) + continue; + var res = FormatCatalog.Instance.LookupSignature (signature).FirstOrDefault(); + if (null == res) + continue; + entry.Type = res.Type; + var ext = res.Extensions.FirstOrDefault(); + if (!string.IsNullOrEmpty (ext)) + entry.Name += '.'+ext; + } + } + return new ArcFile (file, this, dir); + } + } +} diff --git a/ArcFormats/Favorite/ArcHZC.cs b/ArcFormats/Favorite/ArcHZC.cs new file mode 100644 index 00000000..9f79a2dd --- /dev/null +++ b/ArcFormats/Favorite/ArcHZC.cs @@ -0,0 +1,113 @@ +//! \file ArcHZC.cs +//! \date Wed Dec 09 17:04:23 2015 +//! \brief Favorite View Point multi-frame image format. +// +// 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; +using GameRes.Compression; + +namespace GameRes.Formats.FVP +{ + internal class HzcArchive : ArcFile + { + public readonly HzcMetaData ImageInfo; + + public HzcArchive (ArcView arc, ArchiveFormat impl, ICollection dir, HzcMetaData info) + : base (arc, impl, dir) + { + ImageInfo = info; + } + } + + [Export(typeof(ArchiveFormat))] + public class HzcOpener : ArchiveFormat + { + public override string Tag { get { return "HZC/MULTI"; } } + public override string Description { get { return "Favorite View Point multi-frame image"; } } + public override uint Signature { get { return 0x31637A68; } } // 'HZC1' + public override bool IsHierarchic { get { return false; } } + public override bool CanCreate { get { return false; } } + + static readonly Lazy Hzc = new Lazy (() => ImageFormat.FindByTag ("HZC")); + + public override ArcFile TryOpen (ArcView file) + { + uint header_size = file.View.ReadUInt32 (8); + HzcMetaData image_info; + using (var header = file.CreateStream (0, 0xC+header_size)) + { + image_info = Hzc.Value.ReadMetaData (header) as HzcMetaData; + if (null == image_info) + return null; + } + int count = file.View.ReadInt32 (0x20); + if (0 == count) + count = 1; + string base_name = Path.GetFileNameWithoutExtension (file.Name); + int frame_size = image_info.UnpackedSize / count; + var dir = new List (count); + for (int i = 0; i < count; ++i) + { + var entry = new Entry { + Name = string.Format ("{0}#{1:D3}.tga", base_name, i), + Type = "image", + Offset = frame_size * i, + Size = 0x12 + (uint)frame_size, + }; + dir.Add (entry); + } + return new HzcArchive (file, this, dir, image_info); + } + + public override Stream OpenEntry (ArcFile arc, Entry entry) + { + var hzc = (HzcArchive)arc; + using (var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize)) + using (var z = new ZLibStream (input, CompressionMode.Decompress)) + { + uint frame_size = entry.Size - 0x12; + var pixels = new byte[frame_size]; + uint offset = 0; + for (;;) + { + if (pixels.Length != z.Read (pixels, 0, pixels.Length)) + break; + if (offset >= entry.Offset) + break; + offset += frame_size; + } + if (4 == hzc.ImageInfo.Type) + { + for (int i = 0; i < pixels.Length; ++i) + if (1 == pixels[i]) + pixels[i] = 0xFF; + } + return TgaStream.Create (hzc.ImageInfo, pixels); + } + } + } +} diff --git a/ArcFormats/Favorite/ImageHZC.cs b/ArcFormats/Favorite/ImageHZC.cs new file mode 100644 index 00000000..2d911654 --- /dev/null +++ b/ArcFormats/Favorite/ImageHZC.cs @@ -0,0 +1,107 @@ +//! \file ImageHZC.cs +//! \date Tue Dec 08 22:54:11 2015 +//! \brief Favorite View Point image format. +// +// 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 GameRes.Compression; +using GameRes.Utility; +using System; +using System.ComponentModel.Composition; +using System.IO; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace GameRes.Formats.FVP +{ + internal class HzcMetaData : ImageMetaData + { + public int Type; + public int UnpackedSize; + public int HeaderSize; + } + + [Export(typeof(ImageFormat))] + public class HzcFormat : ImageFormat + { + public override string Tag { get { return "HZC"; } } + public override string Description { get { return "Favorite View Point image format"; } } + public override uint Signature { get { return 0x31637A68; } } // 'HZC1' + + public override ImageMetaData ReadMetaData (Stream stream) + { + var header = new byte[0x2C]; + if (header.Length != stream.Read (header, 0, header.Length)) + return null; + if (!Binary.AsciiEqual (header, 0xC, "NVSG")) + return null; + int type = LittleEndian.ToUInt16 (header, 0x12); + return new HzcMetaData + { + Width = LittleEndian.ToUInt16 (header, 0x14), + Height = LittleEndian.ToUInt16 (header, 0x16), + OffsetX = LittleEndian.ToInt16 (header, 0x18), + OffsetY = LittleEndian.ToInt16 (header, 0x1A), + BPP = 0 == type ? 24 : type > 2 ? 8 : 32, + Type = type, + UnpackedSize = LittleEndian.ToInt32 (header, 4), + HeaderSize = LittleEndian.ToInt32 (header, 8), + }; + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + var meta = (HzcMetaData)info; + BitmapPalette palette = null; + int stride = (int)meta.Width * meta.BPP / 8; + PixelFormat format; + switch (meta.Type) + { + default: throw new NotSupportedException(); + case 0: format = PixelFormats.Bgr24; break; + case 1: + case 2: format = PixelFormats.Bgra32; break; + case 3: format = PixelFormats.Gray8; break; + case 4: + { + format = PixelFormats.Indexed8; + var colors = new Color[2] { Color.FromRgb (0,0,0), Color.FromRgb (0xFF,0xFF,0xFF) }; + palette = new BitmapPalette (colors); + break; + } + } + stream.Position = 12 + meta.HeaderSize; + using (var z = new ZLibStream (stream, CompressionMode.Decompress, true)) + { + var pixels = new byte[stride * (int)meta.Height]; + if (pixels.Length != z.Read (pixels, 0, pixels.Length)) + throw new EndOfStreamException(); + return ImageData.Create (info, format, palette, pixels, stride); + } + } + + public override void Write (Stream file, ImageData image) + { + throw new System.NotImplementedException ("HzcFormat.Write not implemented"); + } + } +} diff --git a/supported.html b/supported.html index a48e10a0..53a92f59 100644 --- a/supported.html +++ b/supported.html @@ -552,6 +552,10 @@ Hapymaher
Hitozuma Net Auction
*.pgxPGXNo +*.bin-NoFavorite +AstralAir no Shiroki Towa
+ +*.hzchzc1No

1 Non-encrypted only