diff --git a/Legacy/Legacy.csproj b/Legacy/Legacy.csproj
index 334f51c9..8993bbdd 100644
--- a/Legacy/Legacy.csproj
+++ b/Legacy/Legacy.csproj
@@ -70,11 +70,16 @@
+
+
+
+
+
@@ -115,6 +120,7 @@
+
diff --git a/Legacy/Sviu/ArcPKZ.cs b/Legacy/Sviu/ArcPKZ.cs
new file mode 100644
index 00000000..f1f227fb
--- /dev/null
+++ b/Legacy/Sviu/ArcPKZ.cs
@@ -0,0 +1,186 @@
+//! \file ArcPKZ.cs
+//! \date 2018 Aug 26
+//! \brief SVIU System resource archive.
+//
+// Copyright (C) 2018 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 System.Linq;
+using GameRes.Utility;
+
+// [030725][Hayashigumi] Fall in Love
+
+namespace GameRes.Formats.Sviu
+{
+ [Serializable]
+ public class PkzScheme : ResourceScheme
+ {
+ public Dictionary KnownSchemes;
+ }
+
+ internal class PkzArchive : ArcFile
+ {
+ public readonly byte[] Key;
+
+ public PkzArchive (ArcView arc, ArchiveFormat impl, ICollection dir, byte[] key)
+ : base (arc, impl, dir)
+ {
+ Key = key;
+ }
+ }
+
+ [Export(typeof(ArchiveFormat))]
+ public class PkzOpener : ArchiveFormat
+ {
+ public override string Tag { get { return "PKZ"; } }
+ public override string Description { get { return "SVIU System resource archive"; } }
+ public override uint Signature { get { return 0x305A4B50; } } // 'PKZ0'
+ public override bool IsHierarchic { get { return false; } }
+ public override bool CanWrite { get { return false; } }
+
+ PkzScheme DefaultScheme = new PkzScheme { KnownSchemes = new Dictionary() };
+
+ public override ResourceScheme Scheme
+ {
+ get { return DefaultScheme; }
+ set { DefaultScheme = (PkzScheme)value; }
+ }
+
+ public override ArcFile TryOpen (ArcView file)
+ {
+ int count = file.View.ReadInt32 (4);
+ if (!IsSaneCount (count))
+ return null;
+ var key = QueryKey();
+ if (null == key)
+ return null;
+ uint data_offset = (uint)count * 0x2Cu + 0x14u;
+ var index = file.View.ReadBytes (8, data_offset - 8);
+ DecryptData (index, key);
+ var dir = new List (count);
+ int index_offset = 0xC;
+ for (int i = 0; i < count; ++i)
+ {
+ var name = Binary.GetCString (index, index_offset, 0x20);
+ var entry = FormatCatalog.Instance.Create (name);
+ entry.Size = index.ToUInt32 (index_offset+0x20);
+ entry.Offset = index.ToUInt32 (index_offset+0x24) + data_offset;
+ if (!entry.CheckPlacement (file.MaxOffset))
+ return null;
+ dir.Add (entry);
+ index_offset += 0x2C;
+ }
+ return new PkzArchive (file, this, dir, key);
+ }
+
+ public override Stream OpenEntry (ArcFile arc, Entry entry)
+ {
+ var parc = (PkzArchive)arc;
+ var data = arc.File.View.ReadBytes (entry.Offset, entry.Size);
+ DecryptData (data, parc.Key);
+ if (data.AsciiEqual (0, "SVS18"))
+ data = UnpackScript (data);
+ return new BinMemoryStream (data, entry.Name);
+ }
+
+ byte[] UnpackScript (byte[] data)
+ {
+ if (data.ToInt32 (0x10) == 0)
+ return data;
+ int unpacked_size = data.ToInt32 (0xC);
+ int header_size = data.ToInt32 (0x14);
+ int packed_size = data.ToInt32 (0x1C);
+ var output = new byte[unpacked_size];
+ Buffer.BlockCopy (data, 0, output, 0, header_size);
+ LittleEndian.Pack (0, output, 0x10);
+ using (var input = new BinMemoryStream (data, header_size, packed_size))
+ LzUnpack (input, output, header_size);
+ return output;
+ }
+
+ void LzUnpack (IBinaryStream input, byte[] output, int dst)
+ {
+ var frame = new byte[0x800];
+ int frame_pos = 0x7E8;
+ int ctl = 1;
+ while (dst < output.Length)
+ {
+ if (1 == ctl)
+ {
+ ctl = input.ReadByte();
+ if (-1 == ctl)
+ break;
+ ctl |= 0x100;
+ }
+ if (0 != (ctl & 1))
+ {
+ byte b = input.ReadUInt8();
+ output[dst++] = b;
+ frame[frame_pos++ & 0x7FF] = b;
+ }
+ else
+ {
+ byte lo = input.ReadUInt8();
+ byte hi = input.ReadUInt8();
+ int offset = lo | (hi & 0xE0) << 3;
+ int count = (hi & 0x1F) + 2;
+ for (int i = 0; i < count; ++i)
+ {
+ byte b = frame[(offset + i) & 0x7FF];
+ output[dst++] = b;
+ frame[frame_pos++ & 0x7FF] = b;
+ }
+ }
+ ctl >>= 1;
+ }
+ }
+
+ public static byte[] CreateKey (string key)
+ {
+ var bkey = Encodings.cp932.GetBytes (key);
+ for (int i = 0; i < bkey.Length; ++i)
+ {
+ bkey[i] += 6;
+ }
+ return bkey;
+ }
+
+ void DecryptData (byte[] data, byte[] key)
+ {
+ for (int i = 0; i < data.Length; ++i)
+ {
+ data[i] ^= key[i % key.Length];
+ data[i] += 0x80;
+ }
+ }
+
+ byte[] QueryKey ()
+ {
+ if (DefaultScheme.KnownSchemes.Count == 0)
+ return null;
+ return DefaultScheme.KnownSchemes.Values.First();
+ }
+ }
+}
diff --git a/Legacy/Sviu/AudioKOG.cs b/Legacy/Sviu/AudioKOG.cs
new file mode 100644
index 00000000..a98feeb3
--- /dev/null
+++ b/Legacy/Sviu/AudioKOG.cs
@@ -0,0 +1,55 @@
+//! \file AudioKOG.cs
+//! \date 2018 Aug 27
+//! \brief SVIU System audio (OGG)
+//
+// Copyright (C) 2018 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;
+
+namespace GameRes.Formats.Sviu
+{
+ [Export(typeof(AudioFormat))]
+ public class KogAudio : AudioFormat
+ {
+ public override string Tag { get { return "KOG"; } }
+ public override string Description { get { return "SVIU System audio format (Ogg/Vorbis)"; } }
+ public override uint Signature { get { return 0; } }
+ public override bool CanWrite { get { return false; } }
+
+ public override SoundInput TryOpen (IBinaryStream file)
+ {
+ if (file.Signature != 0)
+ return null;
+ var header = file.ReadHeader (8);
+ int header_size = header.ToInt32 (4);
+ file.Position = header_size;
+ uint signature = file.ReadUInt32();
+ if (signature != OggAudio.Instance.Signature)
+ return null;
+ var input = new StreamRegion (file.AsStream, header_size);
+ var ogg = new BinaryStream (input, file.Name);
+ return new OggInput (ogg);
+ }
+ }
+}
diff --git a/Legacy/Sviu/ImageGBP.cs b/Legacy/Sviu/ImageGBP.cs
new file mode 100644
index 00000000..cba7d15f
--- /dev/null
+++ b/Legacy/Sviu/ImageGBP.cs
@@ -0,0 +1,116 @@
+//! \file ImageGBP.cs
+//! \date 2018 Aug 27
+//! \brief SVIU System image format.
+//
+// Copyright (C) 2018 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.Media;
+
+namespace GameRes.Formats.Sviu
+{
+ internal class GbpMetaData : ImageMetaData
+ {
+ public int HeaderSize;
+ public int Method;
+ }
+
+ [Export(typeof(ImageFormat))]
+ public class GbpFormat : ImageFormat
+ {
+ public override string Tag { get { return "GBP"; } }
+ public override string Description { get { return "SVIU system image format"; } }
+ public override uint Signature { get { return 0x50425947; } }
+
+ public override ImageMetaData ReadMetaData (IBinaryStream file)
+ {
+ var header = file.ReadHeader (0x14);
+ file.Seek (-0x13, SeekOrigin.End);
+ var key = file.ReadBytes (0x13);
+ for (int i = 4; i < 0x14; i += 2)
+ {
+ header[i] ^= key[0x10];
+ header[i+1] ^= key[0x11];
+ }
+ for (int i = 0; i < 0x10; ++i)
+ {
+ header[i+4] -= key[i];
+ }
+ return new GbpMetaData {
+ Width = header.ToUInt16 (0xE),
+ Height = header.ToUInt16 (0x10),
+ BPP = header.ToUInt16 (0x12),
+ HeaderSize = header.ToInt32 (4),
+ Method = header.ToUInt16 (0xC),
+ };
+ }
+
+ public override ImageData Read (IBinaryStream file, ImageMetaData info)
+ {
+ var reader = new GbpReader (file, (GbpMetaData)info);
+ var pixels = reader.Unpack();
+ return ImageData.Create (info, reader.Format, null, pixels);
+ }
+
+ public override void Write (Stream file, ImageData image)
+ {
+ throw new System.NotImplementedException ("GbpFormat.Write not implemented");
+ }
+ }
+
+ internal class GbpReader
+ {
+ IBinaryStream m_input;
+ GbpMetaData m_info;
+ byte[] m_output;
+
+ public PixelFormat Format { get; private set; }
+
+ public GbpReader (IBinaryStream input, GbpMetaData info)
+ {
+ m_input = input;
+ m_info = info;
+ if (32 == info.BPP)
+ Format = PixelFormats.Bgra32;
+ else
+ Format = PixelFormats.Bgr32;
+ m_output = new byte[4 * (int)m_info.Width * (int)m_info.Height];
+ }
+
+ public byte[] Unpack ()
+ {
+ m_input.Position = m_info.HeaderSize;
+ if (3 == m_info.Method)
+ UnpackV3();
+ else
+ throw new NotImplementedException();
+ return m_output;
+ }
+
+ void UnpackV3 ()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Legacy/Sviu/ImageJBP.cs b/Legacy/Sviu/ImageJBP.cs
new file mode 100644
index 00000000..3179a00a
--- /dev/null
+++ b/Legacy/Sviu/ImageJBP.cs
@@ -0,0 +1,62 @@
+//! \file ImageJBP.cs
+//! \date 2018 Aug 27
+//! \brief SVIU System image format.
+//
+// Copyright (C) 2018 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;
+
+namespace GameRes.Formats.Sviu
+{
+ [Export(typeof(ImageFormat))]
+ public class JbpFormat : ImageFormat
+ {
+ public override string Tag { get { return "JBP"; } }
+ public override string Description { get { return "SVIU System image format"; } }
+ public override uint Signature { get { return 0x3150424A; } } // 'JBP1'
+
+ public override ImageMetaData ReadMetaData (IBinaryStream file)
+ {
+ var header = file.ReadHeader (0x20);
+ return new ImageMetaData {
+ Width = header.ToUInt16 (0x10),
+ Height = header.ToUInt16 (0x12),
+ BPP = 24,
+ };
+ }
+
+ public override ImageData Read (IBinaryStream file, ImageMetaData info)
+ {
+ var input = file.ReadBytes ((int)file.Length);
+ var reader = new Purple.JbpReader (input, 0);
+ var pixels = reader.Unpack();
+ return ImageData.Create (info, PixelFormats.Bgr32, null, pixels, reader.Stride);
+ }
+
+ public override void Write (Stream file, ImageData image)
+ {
+ throw new System.NotImplementedException ("JbpFormat.Write not implemented");
+ }
+ }
+}