From 880245fea42b646dd54a3cec8537f30bddcec6f1 Mon Sep 17 00:00:00 2001 From: morkt Date: Sun, 19 Jun 2016 03:06:09 +0400 Subject: [PATCH] implemented EENC images and UM3 audio. --- ArcFormats/ArcFormats.csproj | 2 + ArcFormats/Bruns/AudioUM3.cs | 86 ++++++++++++++++++ ArcFormats/Bruns/ImageEENC.cs | 165 ++++++++++++++++++++++++++++++++++ supported.html | 15 ++++ 4 files changed, 268 insertions(+) create mode 100644 ArcFormats/Bruns/AudioUM3.cs create mode 100644 ArcFormats/Bruns/ImageEENC.cs diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index 6a4c6f12..02694a65 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -72,6 +72,8 @@ + + diff --git a/ArcFormats/Bruns/AudioUM3.cs b/ArcFormats/Bruns/AudioUM3.cs new file mode 100644 index 00000000..c1a2bea2 --- /dev/null +++ b/ArcFormats/Bruns/AudioUM3.cs @@ -0,0 +1,86 @@ +//! \file AudioUM3.cs +//! \date Sat Jun 18 11:11:29 2016 +//! \brief UltraMarine3 encrypted OGG vorbis audio. +// +// 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; + +namespace GameRes.Formats +{ + [Export(typeof(AudioFormat))] + public class Um3Audio : AudioFormat + { + public override string Tag { get { return "UM3"; } } + public override string Description { get { return "UltraMarine3 audio format (Ogg/Vorbis)"; } } + public override uint Signature { get { return 0xAC9898B0; } } // ~'OggS' + + public override SoundInput TryOpen (Stream file) + { + return new OggInput (new Um3Stream (file)); + } + } + + internal class Um3Stream : ProxyStream + { + public Um3Stream (Stream main, bool leave_open = false) + : base (main, leave_open) + { + } + + public override int Read (byte[] buffer, int offset, int count) + { + var pos = Position; + int read = BaseStream.Read (buffer, offset, count); + if (pos < 0x800 && read > 0) + { + int enc_count = Math.Min (0x800 - (int)pos, read); + for (int i = 0; i < enc_count; ++i) + { + buffer[offset+i] ^= 0xFF; + } + } + return read; + } + + public override int ReadByte () + { + var pos = Position; + int b = BaseStream.ReadByte(); + if (-1 != b && pos < 0x800) + b ^= 0xFF; + return b; + } + + public override void Write (byte[] buffer, int offset, int count) + { + throw new NotSupportedException ("Um3Stream.Write not supported"); + } + + public override void WriteByte (byte value) + { + throw new NotSupportedException ("Um3Stream.Write not supported"); + } + } +} diff --git a/ArcFormats/Bruns/ImageEENC.cs b/ArcFormats/Bruns/ImageEENC.cs new file mode 100644 index 00000000..72e53e31 --- /dev/null +++ b/ArcFormats/Bruns/ImageEENC.cs @@ -0,0 +1,165 @@ +//! \file ImageEENC.cs +//! \date Sat Jun 18 06:26:23 2016 +//! \brief SepterApp encrypted images. +// +// 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 GameRes.Compression; +using GameRes.Utility; + +namespace GameRes.Formats.Bruns +{ + internal class EencMetaData : ImageMetaData + { + public uint Key; + public ImageMetaData Info; + public ImageFormat Format; + public bool Compressed; + } + + [Export(typeof(ImageFormat))] + public class EencFormat : ImageFormat + { + public override string Tag { get { return "EENC"; } } + public override string Description { get { return "Bruns system encrypted image"; } } + public override uint Signature { get { return 0x434E4545; } } // 'EENC' + + static readonly uint EencKey = 0xDEADBEEF; + + public EencFormat () + { + Extensions = new string[] { "brs", "png", "bmp" }; + Signatures = new uint[] { 0x434E4545, 0x5A4E4545 }; // 'EENC', 'EENZ' + } + + public override ImageMetaData ReadMetaData (Stream stream) + { + var header = new byte[8]; + if (8 != stream.Read (header, 0, 8)) + return null; + bool compressed = 'Z' == header[3]; + uint key = LittleEndian.ToUInt32 (header, 4) ^ EencKey; + Stream input = new StreamRegion (stream, 8, true); + try + { + input = new EencStream (input, key); + if (compressed) + { + input = new ZLibStream (input, CompressionMode.Decompress); + input = new SeekableStream (input); + } + var format = FindFormat (input); + if (null == format) + return null; + return new EencMetaData + { + Width = format.Item2.Width, + Height = format.Item2.Height, + BPP = format.Item2.BPP, + Key = key, + Info = format.Item2, + Format = format.Item1, + Compressed = compressed, + }; + } + finally + { + input.Dispose(); + } + } + + public override ImageData Read (Stream stream, ImageMetaData info) + { + var meta = (EencMetaData)info; + meta.Info.FileName = info.FileName; + Stream input = new StreamRegion (stream, 8, true); + try + { + input = new EencStream (input, meta.Key); + if (meta.Compressed) + input = new ZLibStream (input, CompressionMode.Decompress); + return meta.Format.Read (input, meta.Info); + } + finally + { + input.Dispose(); + } + } + + public override void Write (Stream file, ImageData image) + { + throw new System.NotImplementedException ("EencFormat.Write not implemented"); + } + } + + internal class EencStream : ProxyStream + { + uint m_key; + + public EencStream (Stream main, uint key, bool leave_open = false) + : base (main, leave_open) + { + m_key = key; + } + + public override bool CanWrite { get { return false; } } + + public override int Read (byte[] buffer, int offset, int count) + { + int pos = (int)Position & 3; + int read = BaseStream.Read (buffer, offset, count); + for (int i = 0; i < read; ++i) + { + buffer[offset+i] ^= (byte)(m_key >> (pos << 3)); + pos = (pos + 1) & 3; + } + return read; + } + + public override int ReadByte () + { + int pos = (int)Position & 3; + int b = BaseStream.ReadByte(); + if (-1 != b) + b ^= (byte)(m_key >> (pos << 3)); + return b; + } + + public override void SetLength (long length) + { + throw new NotSupportedException ("EencStream.SetLength method is not supported"); + } + + public override void Write (byte[] buffer, int offset, int count) + { + throw new NotSupportedException ("EencStream.Write method is not supported"); + } + + public override void WriteByte (byte value) + { + throw new NotSupportedException ("EencStream.WriteByte method is not supported"); + } + } +} diff --git a/supported.html b/supported.html index c2bb2fb1..d92c451d 100644 --- a/supported.html +++ b/supported.html @@ -98,10 +98,12 @@ Okaa-san ga Ippai!
*.pakHyPackYesKogadoSymphonic Rain *+*.lst-NoNexton LikeC +Chikan Ou ~Inkoku no Souzousha~
Injoku Shinryuu Club
Moon.
Ryoujoku Famiresu Choukyou Menu
Ryoujoku Idol Mesu Dorei
+Sentoreido Gakuen
Yakuchu!
*.tgf-No @@ -216,6 +218,7 @@ Coμ
Crime Rhyme series
Damegane
Distance
+ExE
Fate/stay night
Fate/hollow ataraxia
G-senjou no Maou
@@ -249,6 +252,9 @@ Zecchou Spiral!!
*.tlgTLG0.0
TLG5.0
TLG6.0No *.ypfYPFYesYU-RIS Eroge! ~H mo Game mo Kaihatsu Zanmai~
+Mamono Musume-tachi to no Rakuen ~Slime & Scylla~
+Sei Monmusu Festival!!
+Shin Chikan Ou
Unionism Quartet
*.ycgYCGNo @@ -391,6 +397,7 @@ Shuffle! Essence+
*.arcARC\x1a
ARCNoAZ System Clover Heart's
Geki Tama! ~Seiryou Gakuen Engeki Bu~
+Maria ~Tenshi no Kiss to Akuma no Hanayome~
Triptych
Tsurugi Otome Noah
@@ -540,6 +547,7 @@ Samurai Jupiter
Sora no Iro, Mizu no Iro
Thunder Claps!
Tokumei Kyoushi Hitomi
+Toshiue Lesson ~Mama to Oba-san to Sensei to~
*.iksNPSRNoX[iks]Shikkan ~Hazukashimerareta Karada, Oreta Kokoro~ *.wbpARCFORM3 WBUGNoWild Bug @@ -753,6 +761,7 @@ AstralAir no Shiroki Towa
*.binESC-ARC1
ESC-ARC2NoEscu:de Otome Renshin Prister
Suisei Tenshi Primaveil Zwei
+Verdia Gensoukyoku
Wondering Repair!
*.pac-NoTmr-Hiro ADV System @@ -834,6 +843,7 @@ Angenehm Platz -Kleiner Garten Sie Erstellen-
Ase Nure Shoujo Misaki "Anata no Nioi de Icchau!"
D-spray Biyaku de Motemote Kachou Dairi Hosa
Hitomi no Rakuin ~Inbaku no Mesu Dorei~
+Jokujima
*.grp-NoAnkh Mozu
@@ -883,6 +893,11 @@ Grope ~Yami no Naka no Kotori-tachi~
Ryoujoku Seifuku Jogakuen ~Chimitsu ni Nureta Seifuku~
*.galGale105
Gale106No +*.png
*.bmpEENC
EENZNoBruns +Majiyome
+Uchi no Tsuma Dakimasenka?
+ +*.um3\xB0\x98\x98\xACNo

1 Non-encrypted only