From d7030ecbdc706b3afda1604d2444345709c003fc Mon Sep 17 00:00:00 2001 From: morkt Date: Sat, 13 Jun 2015 12:54:23 +0400 Subject: [PATCH] implemented Crowd CWL images. --- ArcFormats/ArcFormats.csproj | 1 + ArcFormats/ImageCWL.cs | 123 +++++++++++++++++++++++++++++++++++ supported.html | 6 +- 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 ArcFormats/ImageCWL.cs diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index a8ade86c..4e556f3e 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -166,6 +166,7 @@ + diff --git a/ArcFormats/ImageCWL.cs b/ArcFormats/ImageCWL.cs new file mode 100644 index 00000000..5cca16bc --- /dev/null +++ b/ArcFormats/ImageCWL.cs @@ -0,0 +1,123 @@ +//! \file ImageCWL.cs +//! \date Sat Jun 13 09:36:33 2015 +//! \brief Crowd compressed 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.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Media; +using GameRes.Utility; + +namespace GameRes.Formats.Crowd +{ + [Export(typeof(ImageFormat))] + public class CwdFormat : ImageFormat + { + public override string Tag { get { return "CWD"; } } + public override string Description { get { return "Crowd hi-color bitmap"; } } + public override uint Signature { get { return 0x20647763u; } } // 'cwd ' + + static readonly byte[] SignatureText = Encoding.ASCII.GetBytes ("cwd format - version 1.00 -"); + + public override ImageMetaData ReadMetaData (Stream stream) + { + var header = new byte[0x38]; + if (header.Length != stream.Read (header, 0, header.Length)) + return null; + if (!header.Take (SignatureText.Length).SequenceEqual (SignatureText)) + return null; + uint key = header[0x34] + 0x259Au; + return new ImageMetaData + { + Width = LittleEndian.ToUInt32 (header, 0x2c) + key, + Height = LittleEndian.ToUInt32 (header, 0x30) + key, + BPP = 15, + }; + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + stream.Position = 0x38; + int size = (int)info.Width * (int)info.Height * 2; + var pixels = new byte[size]; + if (pixels.Length != stream.Read (pixels, 0, pixels.Length)) + throw new InvalidFormatException ("Unexpected end of file"); + return ImageData.Create (info, PixelFormats.Bgr555, null, pixels); + } + + public override void Write (Stream file, ImageData image) + { + throw new NotImplementedException ("CwdFormat.Write not implemented"); + } + } + + [Export(typeof(ImageFormat))] + public class CwlFormat : CwdFormat + { + public override string Tag { get { return "CWL"; } } + public override string Description { get { return "LZ-compressed Crowd bitmap"; } } + public override uint Signature { get { return 0x44445A53u; } } // 'SZDD' + + public override ImageMetaData ReadMetaData (Stream stream) + { + stream.Position = 0x0e; + using (var lz = new LzssReader (stream, 100, 0x38)) // extract CWD header + { + lz.FrameSize = 0x1000; + lz.FrameFill = 0x20; + lz.FrameInitPos = 0x1000 - 0x10; + lz.Unpack(); + using (var cwd = new MemoryStream (lz.Data)) + return base.ReadMetaData (cwd); + } + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + if (stream.Length > int.MaxValue) + throw new FileSizeException(); + var header = new byte[14]; + if (header.Length != stream.Read (header, 0, header.Length)) + throw new InvalidFormatException(); + int data_length = LittleEndian.ToInt32 (header, 10); + int input_length = (int)(stream.Length-stream.Position); + using (var lz = new LzssReader (stream, input_length, data_length)) + { + lz.FrameSize = 0x1000; + lz.FrameFill = 0x20; + lz.FrameInitPos = 0x1000 - 0x10; + lz.Unpack(); + using (var cwd = new MemoryStream (lz.Data)) + return base.Read (cwd, info); + } + } + + public override void Write (Stream file, ImageData image) + { + throw new NotImplementedException ("CwlFormat.Write not implemented"); + } + } +} diff --git a/supported.html b/supported.html index 342bfbb9..4f637840 100644 --- a/supported.html +++ b/supported.html @@ -187,13 +187,15 @@ Onna Kyoushi *.bg_
*.cg_APYes *.dpkDPKNoDACYumemiru Tsuki no Lunalutia *.dgcDGCNo -*.pck-NoCrowd +*.pck-NoCrowd X Change R
X Change
+X Change 2
*.cwpCWDPYes +*.cwdcwdNo *.eogCRMNo -*.zbmSZDDNo +*.zbm
*.cwlSZDDNo

[1] Non-encrypted only