From 303a8551b0956a222b2357be40a6c0a53cda4491 Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 19 Aug 2016 09:29:06 +0400 Subject: [PATCH] Crc32 implementation moved to separate file. this implementation uses 'normal' polynomial representation unlike Crc32 defined in GameRes. --- ArcFormats/CatSystem/ArcINT.cs | 12 +--- ArcFormats/Crc32.cs | 77 ++++++++++++++++++++++++++ ArcFormats/ShiinaRio/WarcEncryption.cs | 14 +---- ArcFormats/TopCat/ArcTCD3.cs | 47 ++++------------ 4 files changed, 91 insertions(+), 59 deletions(-) create mode 100644 ArcFormats/Crc32.cs diff --git a/ArcFormats/CatSystem/ArcINT.cs b/ArcFormats/CatSystem/ArcINT.cs index 32a7891c..8da3103d 100644 --- a/ArcFormats/CatSystem/ArcINT.cs +++ b/ArcFormats/CatSystem/ArcINT.cs @@ -35,6 +35,7 @@ using System.Runtime.InteropServices; using GameRes.Formats.Strings; using GameRes.Formats.Properties; using GameRes.Cryptography; +using GameRes.Utility; namespace GameRes.Formats.CatSystem { @@ -67,16 +68,7 @@ namespace GameRes.Formats.CatSystem uint key = 0xffffffff; foreach (var c in pass_bytes) { - uint val = (uint)c << 24; - key ^= val; - for (int i = 0; i < 8; ++i) - { - bool carry = 0 != (key & 0x80000000); - key <<= 1; - if (carry) - key ^= 0x4C11DB7; - } - key = ~key; + key = ~Crc32Normal.Table[(key >> 24) ^ c] ^ (key << 8); } return key; } diff --git a/ArcFormats/Crc32.cs b/ArcFormats/Crc32.cs new file mode 100644 index 00000000..7449c466 --- /dev/null +++ b/ArcFormats/Crc32.cs @@ -0,0 +1,77 @@ +//! \file Crc32.cs +//! \date Fri Aug 19 09:18:42 2016 +//! \brief Crc32 with normal polynomial representation. +// +// 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. +// + +namespace GameRes.Utility +{ + /// + /// Crc32 with normal polynomial representation. + /// + public sealed class Crc32Normal : ICheckSum + { + private static readonly uint[] crc_table = InitializeTable(); + + public static uint[] Table { get { return crc_table; } } + + private static uint[] InitializeTable () + { + const uint polynomial = 0x04C11DB7; + var table = new uint[256]; + for (uint n = 0; n < 256; n++) + { + uint c = n << 24; + for (int k = 0; k < 8; k++) + { + if (0 != (c & 0x80000000u)) + c = polynomial ^ (c << 1); + else + c <<= 1; + } + table[n] = c; + } + return table; + } + + public static uint UpdateCrc (uint init_crc, byte[] data, int pos, int length) + { + uint c = init_crc; + for (int n = 0; n < length; n++) + c = crc_table[(c >> 24) ^ data[pos+n]] ^ (c << 8); + return c; + } + + public static uint Compute (byte[] buf, int pos, int len) + { + return ~UpdateCrc (0xffffffff, buf, pos, len); + } + + private uint m_crc = 0xffffffff; + public uint Value { get { return ~m_crc; } } + + public void Update (byte[] buf, int pos, int len) + { + m_crc = UpdateCrc (m_crc, buf, pos, len); + } + } +} diff --git a/ArcFormats/ShiinaRio/WarcEncryption.cs b/ArcFormats/ShiinaRio/WarcEncryption.cs index d17400f8..a24b925c 100644 --- a/ArcFormats/ShiinaRio/WarcEncryption.cs +++ b/ArcFormats/ShiinaRio/WarcEncryption.cs @@ -172,18 +172,8 @@ namespace GameRes.Formats.ShiinaRio { if (length < 0x400 || null == m_scheme.DecodeBin) return; - uint crc = 0xffffffff; - for (int i = 0; i < 0x100; ++i) - { - crc ^= (uint)data[index++] << 24; - for (int j = 0; j < 8; ++j) - { - uint bit = crc & 0x80000000u; - crc <<= 1; - if (0 != bit) - crc ^= 0x04c11db7; - } - } + uint crc = Crc32Normal.UpdateCrc (0xFFFFFFFF, data, index, 0x100); + index += 0x100; for (int i = 0; i < 0x40; ++i) { uint src = LittleEndian.ToUInt32 (data, index) & 0x1ffcu; diff --git a/ArcFormats/TopCat/ArcTCD3.cs b/ArcFormats/TopCat/ArcTCD3.cs index 3652cb9b..fa4a1b72 100644 --- a/ArcFormats/TopCat/ArcTCD3.cs +++ b/ArcFormats/TopCat/ArcTCD3.cs @@ -305,26 +305,6 @@ namespace GameRes.Formats.TopCat data[i] = Binary.RotByteR (data[i], 1); } - static Lazy OggCrcTable = new Lazy (InitOggCrcTable); - - static uint[] InitOggCrcTable () - { - var table = new uint[0x100]; - for (uint i = 0; i < 0x100; ++i) - { - uint a = i << 24; - for (int j = 0; j < 8; ++j) - { - bool carry = 0 != (a & 0x80000000); - a <<= 1; - if (carry) - a ^= 0x04C11DB7; - } - table[i] = a; - } - return table; - } - Stream RestoreOggStream (ArcFile arc, Entry entry) { var data = arc.File.View.ReadBytes (entry.Offset, entry.Size); @@ -332,32 +312,25 @@ namespace GameRes.Formats.TopCat int src = 0; while (remaining > 0x1B && Binary.AsciiEqual (data, src, "OggS")) { - int d = data[src+0x1A]; + int segment_count = data[src+0x1A]; data[src+0x16] = 0; data[src+0x17] = 0; data[src+0x18] = 0; data[src+0x19] = 0; - int dst = src + 0x1B; - int count = d + 0x1B; - if (d != 0) + int page_size = segment_count + 0x1B; + if (segment_count != 0) { - if (remaining < count) + if (remaining < page_size) break; - for (int i = 0; i < d; ++i) - count += data[dst++]; + int segment_table = src + 0x1B; + for (int i = 0; i < segment_count; ++i) + page_size += data[segment_table++]; } - remaining -= count; + remaining -= page_size; if (remaining < 0) break; - dst = src + 0x16; - uint crc = 0; - for (int i = 0; i < count; ++i) - { - uint x = (crc >> 24) ^ data[src++]; - crc <<= 8; - crc ^= OggCrcTable.Value[x]; - } - LittleEndian.Pack (crc, data, dst); + uint crc = Crc32Normal.UpdateCrc (0, data, src, page_size); + LittleEndian.Pack (crc, data, src+0x16); } return new MemoryStream (data); }