From ebbac01c402548a29c8ba0a6836280c20d7acf4b Mon Sep 17 00:00:00 2001 From: morkt Date: Tue, 30 Jan 2018 09:30:34 +0400 Subject: [PATCH] (OGG): added fix checksums setting. --- ArcFormats/AudioOGG.cs | 93 +++++++++++++++++++++- ArcFormats/Properties/Settings.Designer.cs | 12 +++ ArcFormats/Properties/Settings.settings | 3 + ArcFormats/Strings/arcStrings.Designer.cs | 9 +++ ArcFormats/Strings/arcStrings.ja-JP.resx | 4 + ArcFormats/Strings/arcStrings.ko-KR.resx | 4 + ArcFormats/Strings/arcStrings.resx | 3 + ArcFormats/Strings/arcStrings.ru-RU.resx | 3 + ArcFormats/Strings/arcStrings.zh-Hans.resx | 4 + ArcFormats/app.config | 3 + 10 files changed, 137 insertions(+), 1 deletion(-) diff --git a/ArcFormats/AudioOGG.cs b/ArcFormats/AudioOGG.cs index 1d9c98e1..ab83c652 100644 --- a/ArcFormats/AudioOGG.cs +++ b/ArcFormats/AudioOGG.cs @@ -27,6 +27,7 @@ using System; using System.ComponentModel.Composition; using System.IO; using System.Linq; +using GameRes.Utility; using NVorbis; namespace GameRes.Formats @@ -124,16 +125,19 @@ namespace GameRes.Formats } [Export(typeof(AudioFormat))] - public class OggAudio : AudioFormat + public sealed class OggAudio : AudioFormat { public override string Tag { get { return "OGG"; } } public override string Description { get { return "Ogg/Vorbis audio format"; } } public override uint Signature { get { return 0x5367674f; } } // 'OggS' public override bool CanWrite { get { return false; } } + LocalResourceSetting FixCrc = new LocalResourceSetting ("OGGFixCrc"); + public OggAudio () { Signatures = new uint[] { 0x5367674F, 0 }; + Settings = new[] { FixCrc }; } public override SoundInput TryOpen (IBinaryStream file) @@ -169,6 +173,8 @@ namespace GameRes.Formats } else if (file.Signature != this.Signature) return null; + if (FixCrc.Get()) + input = new SeekableStream (new OggRestoreStream (input)); return new OggInput (input); } @@ -176,4 +182,89 @@ namespace GameRes.Formats static readonly ResourceInstance s_OggFormat = new ResourceInstance ("OGG"); } + + /// + /// Restore CRC checksums of the OGG stream pages. + /// + internal class OggRestoreStream : InputProxyStream + { + bool m_eof; + bool m_ogg_ended; + + byte[] m_page = new byte[0x10000]; + int m_page_pos = 0; + int m_page_length = 0; + + public override bool CanSeek { get { return false; } } + + public OggRestoreStream (Stream input) : base (input) + { + } + + public override int Read (byte[] buffer, int offset, int count) + { + int total_read = 0; + while (count > 0 && !m_eof) + { + if (m_page_pos == m_page_length) + { + if (m_ogg_ended) + { + int read = BaseStream.Read (buffer, offset, count); + total_read += read; + m_eof = 0 == read; + break; + } + NextPage(); + } + if (m_eof) + break; + int available = Math.Min (m_page_length - m_page_pos, count); + Buffer.BlockCopy (m_page, m_page_pos, buffer, offset, available); + m_page_pos += available; + offset += available; + count -= available; + total_read += available; + } + return total_read; + } + + void NextPage () + { + m_page_pos = 0; + m_page_length = BaseStream.Read (m_page, 0, 0x1B); + if (0 == m_page_length) + { + m_eof = true; + return; + } + if (m_page_length < 0x1B || !m_page.AsciiEqual ("OggS")) + { + m_ogg_ended = true; + return; + } + int segment_count = m_page[0x1A]; + m_page[0x16] = 0; + m_page[0x17] = 0; + m_page[0x18] = 0; + m_page[0x19] = 0; + if (segment_count != 0) + { + int table_length = BaseStream.Read (m_page, 0x1B, segment_count); + m_page_length += table_length; + if (table_length != segment_count) + { + m_ogg_ended = true; + return; + } + int segments_length = 0; + int segment_table = 0x1B; + for (int i = 0; i < segment_count; ++i) + segments_length += m_page[segment_table++]; + m_page_length += BaseStream.Read (m_page, 0x1B+segment_count, segments_length); + } + uint crc = Crc32Normal.UpdateCrc (0, m_page, 0, m_page_length); + LittleEndian.Pack (crc, m_page, 0x16); + } + } } diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs index 1ed014a5..0610cb60 100644 --- a/ArcFormats/Properties/Settings.Designer.cs +++ b/ArcFormats/Properties/Settings.Designer.cs @@ -729,5 +729,17 @@ namespace GameRes.Formats.Properties { this["ZIPPassword"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool OGGFixCrc { + get { + return ((bool)(this["OGGFixCrc"])); + } + set { + this["OGGFixCrc"] = value; + } + } } } diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings index 512a0bd6..db7c27c8 100644 --- a/ArcFormats/Properties/Settings.settings +++ b/ArcFormats/Properties/Settings.settings @@ -179,5 +179,8 @@ + + False + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs index a2571e9d..c8be97dc 100644 --- a/ArcFormats/Strings/arcStrings.Designer.cs +++ b/ArcFormats/Strings/arcStrings.Designer.cs @@ -606,6 +606,15 @@ namespace GameRes.Formats.Strings { } } + /// + /// Looks up a localized string similar to Fix Ogg files checksums. + /// + public static string OGGFixCrc { + get { + return ResourceManager.GetString("OGGFixCrc", resourceCulture); + } + } + /// /// Looks up a localized string similar to Archive type. /// diff --git a/ArcFormats/Strings/arcStrings.ja-JP.resx b/ArcFormats/Strings/arcStrings.ja-JP.resx index 3c84a92b..e804ada7 100644 --- a/ArcFormats/Strings/arcStrings.ja-JP.resx +++ b/ArcFormats/Strings/arcStrings.ja-JP.resx @@ -491,4 +491,8 @@ Choose encryption scheme or enter a passphrase. アーカイブコンテンツは暗号化されています。 Archive content is encrypted. + + Fix Ogg files checksums + Translation pending + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.ko-KR.resx b/ArcFormats/Strings/arcStrings.ko-KR.resx index 1ed0516d..3f1598e9 100644 --- a/ArcFormats/Strings/arcStrings.ko-KR.resx +++ b/ArcFormats/Strings/arcStrings.ko-KR.resx @@ -391,4 +391,8 @@ 아카이브 내용이 암호화됨. + + Fix Ogg files checksums + Translation pending + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx index 9a58891a..c1fb8ddf 100644 --- a/ArcFormats/Strings/arcStrings.resx +++ b/ArcFormats/Strings/arcStrings.resx @@ -392,4 +392,7 @@ Choose encryption scheme or enter a passphrase. Archive content is encrypted. + + Fix Ogg files checksums + \ No newline at end of file diff --git a/ArcFormats/Strings/arcStrings.ru-RU.resx b/ArcFormats/Strings/arcStrings.ru-RU.resx index 6335c133..227e2966 100644 --- a/ArcFormats/Strings/arcStrings.ru-RU.resx +++ b/ArcFormats/Strings/arcStrings.ru-RU.resx @@ -276,6 +276,9 @@ Ключи шифрования (требуются даже если содержимое не шифруется) + + Исправлять контрольные суммы в Ogg аудио файлах + Тип архива diff --git a/ArcFormats/Strings/arcStrings.zh-Hans.resx b/ArcFormats/Strings/arcStrings.zh-Hans.resx index 8bf60e2f..1116c9fd 100644 --- a/ArcFormats/Strings/arcStrings.zh-Hans.resx +++ b/ArcFormats/Strings/arcStrings.zh-Hans.resx @@ -392,4 +392,8 @@ 压缩文件的内容已被加密。 + + Fix Ogg files checksums + Translation pending + \ No newline at end of file diff --git a/ArcFormats/app.config b/ArcFormats/app.config index a101ec1e..4572b883 100644 --- a/ArcFormats/app.config +++ b/ArcFormats/app.config @@ -181,6 +181,9 @@ + + False +