diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index f8c8904b..3e0deeb0 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -37,6 +37,15 @@
true
6291456
+
+ bin\Prerelease\
+ 6291456
+ true
+ true
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
False
@@ -88,6 +97,10 @@
WidgetBELL.xaml
+
+
+
+
diff --git a/ArcFormats/Ipac/ArcIPAC.cs b/ArcFormats/Ipac/ArcIPAC.cs
new file mode 100644
index 00000000..1a064d8d
--- /dev/null
+++ b/ArcFormats/Ipac/ArcIPAC.cs
@@ -0,0 +1,72 @@
+//! \file ArcIPAC.cs
+//! \date Sat Jul 23 14:03:35 2016
+//! \brief IPAC resource archive.
+//
+// Copyright (C) 2016 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 GameRes.Compression;
+
+namespace GameRes.Formats.BaseUnit
+{
+ [Export(typeof(ArchiveFormat))]
+ public class PakOpener : ArchiveFormat
+ {
+ public override string Tag { get { return "IPAC"; } }
+ public override string Description { get { return "IPAC resource archive"; } }
+ public override uint Signature { get { return 0x43415049; } } // 'IPAC'
+ public override bool IsHierarchic { get { return false; } }
+ public override bool CanCreate { get { return false; } }
+
+ public override ArcFile TryOpen (ArcView file)
+ {
+ int count = file.View.ReadInt16 (4);
+ if (!IsSaneCount (count))
+ return null;
+
+ uint index_offset = 8;
+ var dir = new List (count);
+ for (int i = 0; i < count; ++i)
+ {
+ var name = file.View.ReadString (index_offset, 0x20);
+ var entry = FormatCatalog.Instance.Create (name);
+ entry.Offset = file.View.ReadUInt32 (index_offset+0x24);
+ entry.Size = file.View.ReadUInt32 (index_offset+0x28);
+ if (!entry.CheckPlacement (file.MaxOffset))
+ return null;
+ dir.Add (entry);
+ index_offset += 0x2C;
+ }
+ return new ArcFile (file, this, dir);
+ }
+
+ public override Stream OpenEntry (ArcFile arc, Entry entry)
+ {
+ if (!arc.File.View.AsciiEqual (entry.Offset, "IEL1"))
+ return base.OpenEntry (arc, entry);
+ var input = arc.File.CreateStream (entry.Offset+8, entry.Size-8);
+ return new LzssStream (input);
+ }
+ }
+}
diff --git a/ArcFormats/Ipac/AudioWST.cs b/ArcFormats/Ipac/AudioWST.cs
new file mode 100644
index 00000000..be9272ab
--- /dev/null
+++ b/ArcFormats/Ipac/AudioWST.cs
@@ -0,0 +1,85 @@
+//! \file AudioWST.cs
+//! \date Sat Jul 23 14:19:31 2016
+//! \brief IPAC audio format.
+//
+// Copyright (C) 2016 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.Text;
+
+namespace GameRes.Formats.BaseUnit
+{
+ [Export(typeof(AudioFormat))]
+ public class WstAudio : AudioFormat
+ {
+ public override string Tag { get { return "WST"; } }
+ public override string Description { get { return "IPAC ADPCM audio format"; } }
+ public override uint Signature { get { return 0x32545357; } } // 'WST2'
+
+ public override SoundInput TryOpen (Stream file)
+ {
+ var adpcm_data = new byte[0x20];
+ file.Position = 12;
+ if (0x1C != file.Read (adpcm_data, 4, 0x1C))
+ return null;
+ adpcm_data[0] = 0xF4;
+ adpcm_data[1] = 7;
+ adpcm_data[2] = 7;
+ int data_length = (int)(file.Length - file.Position);
+ int total_size = 0x4E - 8 + data_length;
+ var wav_file = new MemoryStream (total_size+4);
+ try
+ {
+ using (var wav = new BinaryWriter (wav_file, Encoding.Default, true))
+ {
+ wav.Write (Wav.Signature);
+ wav.Write (total_size);
+ wav.Write (0x45564157); // 'WAVE'
+ wav.Write (0x20746d66); // 'fmt '
+ wav.Write (0x32);
+ wav.Write ((ushort)2); // ADPCM
+ wav.Write ((ushort)2); // channels
+ wav.Write ((uint)0xAC44);
+ wav.Write ((uint)0xAC44);
+ wav.Write ((ushort)0x800);
+ wav.Write ((ushort)4);
+ wav.Write ((ushort)0x20);
+ wav.Write (adpcm_data, 0, adpcm_data.Length);
+ wav.Write (0x61746164); // 'data'
+ wav.Write (data_length);
+ file.CopyTo (wav_file);
+ }
+ wav_file.Position = 0;
+ var sound = new WaveInput (wav_file);
+ file.Dispose();
+ return sound;
+ }
+ catch
+ {
+ wav_file.Dispose();
+ throw;
+ }
+ }
+ }
+}
diff --git a/ArcFormats/Ipac/ImageIES.cs b/ArcFormats/Ipac/ImageIES.cs
new file mode 100644
index 00000000..b9d9749d
--- /dev/null
+++ b/ArcFormats/Ipac/ImageIES.cs
@@ -0,0 +1,110 @@
+//! \file ImageIES.cs
+//! \date Sat Jul 23 16:04:34 2016
+//! \brief IPAC image format.
+//
+// Copyright (C) 2016 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 System.Windows.Media.Imaging;
+using GameRes.Utility;
+
+namespace GameRes.Formats.BaseUnit
+{
+ [Export(typeof(ImageFormat))]
+ public class IesFormat : ImageFormat
+ {
+ public override string Tag { get { return "IES"; } }
+ public override string Description { get { return "IPAC image format"; } }
+ public override uint Signature { get { return 0x32534549; } } // 'IES2'
+
+ public override ImageMetaData ReadMetaData (Stream stream)
+ {
+ var header = new byte[0x14];
+ if (header.Length != stream.Read (header, 0, header.Length))
+ return null;
+ return new ImageMetaData
+ {
+ Width = LittleEndian.ToUInt32 (header, 0x08),
+ Height = LittleEndian.ToUInt32 (header, 0x0C),
+ BPP = LittleEndian.ToInt32 (header, 0x10),
+ };
+ }
+
+ public override ImageData Read (Stream stream, ImageMetaData info)
+ {
+ if (24 == info.BPP)
+ {
+ stream.Position = 0x420;
+ var rgb = new byte[info.Width * info.Height * 3];
+ if (rgb.Length != stream.Read (rgb, 0, rgb.Length))
+ throw new EndOfStreamException();
+ var alpha = new byte[info.Width * info.Height];
+ if (alpha.Length != stream.Read (alpha, 0, alpha.Length))
+ throw new EndOfStreamException();
+ var pixels = new byte[info.Width * info.Height * 4];
+ int dst = 0;
+ int src_alpha = 0;
+ for (int src = 0; src < rgb.Length; )
+ {
+ byte a = alpha[src_alpha++];
+ pixels[dst++] = rgb[src++];
+ pixels[dst++] = rgb[src++];
+ pixels[dst++] = rgb[src++];
+ pixels[dst++] = a;
+ }
+ return ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
+ }
+ else if (8 == info.BPP)
+ {
+ stream.Position = 0x20;
+ var palette = ReadPalette (stream);
+ var pixels = new byte[info.Width * info.Height];
+ if (pixels.Length != stream.Read (pixels, 0, pixels.Length))
+ throw new EndOfStreamException();
+ return ImageData.Create (info, PixelFormats.Indexed8, palette, pixels);
+ }
+ else
+ throw new InvalidFormatException ("[IES] Invalid color depth");
+ }
+
+ public override void Write (Stream file, ImageData image)
+ {
+ throw new System.NotImplementedException ("IesFormat.Write not implemented");
+ }
+
+ BitmapPalette ReadPalette (Stream input)
+ {
+ var palette_data = new byte[0x400];
+ if (palette_data.Length != input.Read (palette_data, 0, palette_data.Length))
+ throw new EndOfStreamException();
+ var palette = new Color[0x100];
+ for (int i = 0; i < 0x100; ++i)
+ {
+ int c = i * 4;
+ palette[i] = Color.FromRgb (palette_data[c], palette_data[c+1], palette_data[c+2]);
+ }
+ return new BitmapPalette (palette);
+ }
+ }
+}