From 1e26ef9cd49e3c1a85d915cfc19b722d3e217b6d Mon Sep 17 00:00:00 2001 From: hbeham Date: Sat, 20 Jul 2019 02:08:51 +0200 Subject: [PATCH] Generalized Crc32 implementation so it can be used for LG (TLL), Panasonic (.bin and .db) and Sony (sdb.xml) --- source/ChanSort.Api/Utils/Crc32.cs | 77 ++++- .../ChanSort.Loader.LG/TllFileSerializer.cs | 4 +- .../ChanSort.Loader.Panasonic/Serializer.cs | 277 +----------------- source/ChanSort.Loader.Sony/Serializer.cs | 30 +- 4 files changed, 68 insertions(+), 320 deletions(-) diff --git a/source/ChanSort.Api/Utils/Crc32.cs b/source/ChanSort.Api/Utils/Crc32.cs index f9643a1..dcadd1c 100644 --- a/source/ChanSort.Api/Utils/Crc32.cs +++ b/source/ChanSort.Api/Utils/Crc32.cs @@ -1,45 +1,92 @@ namespace ChanSort.Api { - public static class Crc32 + public class Crc32 { - private const uint CrcMask = 0xFFFFFFFF; - private const uint CrcPoly = 0xEDB88320; + // This implementation is MSB-first based, using left-shift operators and a polynomial of 0x04C11DB7 + // To get the same CRC32 values that an LSB-first implementation with polynomial 0xEDB88320 would produce, + // all bits in the input bytes and the resulting crc need to be reversed (msb to lsb) - private static readonly uint[] crc32Table; + private const uint CrcMask = 0xFFFFFFFF; + private const uint CrcPoly = 0x04C11DB7; + + public static Crc32 Normal = new Crc32(true); + public static Crc32 Reversed = new Crc32(false); + private static readonly byte[] BitReversedBytes = new byte[256]; + + private readonly uint[] crc32Table; + private readonly bool msbFirst; + + #region static initializers static Crc32() { - crc32Table = InitCrc32Table(); + InitCrc32Table(); + InitReversedBitOrderTable(); + } + + private static void InitReversedBitOrderTable() + { + for (int i = 0; i < 256; i++) + { + byte v = 0; + for (int j = 0, m = i; j < 8; j++, m >>= 1) + { + v <<= 1; + if ((m & 1) != 0) + v |= 0x01; + } + + BitReversedBytes[i] = v; + } } - #region InitCrc32Table() private static uint[] InitCrc32Table() { var crcTable = new uint[256]; + var poly = CrcPoly; for (uint i = 0; i < 256; i++) { - uint r = i; - for (uint j = 8; j > 0; j--) + uint r = i << 24; + for (uint j = 0; j < 8; j++) { - if ((r & 1) == 1) - r = ((r >> 1) ^ CrcPoly); + if ((r & 0x80000000) != 0) + r = (r << 1) ^ poly; else - r >>= 1; + r <<= 1; } + crcTable[i] = r; } + return crcTable; } #endregion + /// true for using the "left shift" MSB-first algorithm with polynomial 0x04C11Db7. false to use "right shift" with polynomial 0xEDB883320 + public Crc32(bool msbFirst = true) + { + this.msbFirst = msbFirst; + crc32Table = InitCrc32Table(); + } + #region CalcCrc32() - public static uint CalcCrc32(byte[] block, int start, int length) + public uint CalcCrc32(byte[] data, int start, int length) { uint crc32 = CrcMask; for (int i = 0; i < length; i++) - crc32 = crc32Table[(crc32 & 0xff) ^ block[start + i]] ^ (crc32 >> 8); - return crc32; + { + var b = data[start + i]; + if (!this.msbFirst) + b = BitReversedBytes[b]; + crc32 = (crc32 << 8) ^ crc32Table[((crc32 >> 24) ^ b) & 0xFF]; + } + + if (this.msbFirst) + return crc32; + + // reverse all bits to make MSB <-> LSB + return (uint) BitReversedBytes[crc32 >> 24] | ((uint) BitReversedBytes[(crc32 >> 16) & 0xFF] << 8) | ((uint) BitReversedBytes[(crc32 >> 8) & 0xFF] << 16) | ((uint) BitReversedBytes[crc32 & 0xFF] << 24); } #endregion @@ -52,7 +99,7 @@ { if (crc32 == checksum) return i; - crc32 = crc32Table[(crc32 & 0xff) ^ block[i]] ^ (crc32 >> 8); + crc32 = (crc32 >> 8) ^ crc32Table[(crc32 >> 24) ^ block[i]]; } return 0; } diff --git a/source/ChanSort.Loader.LG/TllFileSerializer.cs b/source/ChanSort.Loader.LG/TllFileSerializer.cs index 78c364f..89b0bf0 100644 --- a/source/ChanSort.Loader.LG/TllFileSerializer.cs +++ b/source/ChanSort.Loader.LG/TllFileSerializer.cs @@ -426,7 +426,7 @@ namespace ChanSort.Loader.LG this.dvbsSubblockCrcOffset[i] = off; int subblockLength = satConfig.dvbsSubblockLength[i]; uint fileCrc = BitConverter.ToUInt32(fileContent, off); - uint calcCrc = Crc32.CalcCrc32(fileContent, off + 4, subblockLength); + uint calcCrc = Crc32.Reversed.CalcCrc32(fileContent, off + 4, subblockLength); if (fileCrc != calcCrc) throw new FileLoadException(string.Format(ERR_wrongChecksum, fileCrc, calcCrc)); off += 4 + subblockLength; @@ -1008,7 +1008,7 @@ namespace ChanSort.Loader.LG { for (int i = 0; i < this.dvbsSubblockCrcOffset.Length; i++) { - uint crc32 = Crc32.CalcCrc32(fileContent, this.dvbsSubblockCrcOffset[i] + 4, satConfig.dvbsSubblockLength[i]); + uint crc32 = Crc32.Reversed.CalcCrc32(fileContent, this.dvbsSubblockCrcOffset[i] + 4, satConfig.dvbsSubblockLength[i]); var bytes = BitConverter.GetBytes(crc32); for (int j = 0; j < bytes.Length; j++) fileContent[this.dvbsSubblockCrcOffset[i] + j] = bytes[j]; diff --git a/source/ChanSort.Loader.Panasonic/Serializer.cs b/source/ChanSort.Loader.Panasonic/Serializer.cs index 252b874..9ab3d2f 100644 --- a/source/ChanSort.Loader.Panasonic/Serializer.cs +++ b/source/ChanSort.Loader.Panasonic/Serializer.cs @@ -12,7 +12,6 @@ namespace ChanSort.Loader.Panasonic class Serializer : SerializerBase { private const string ERR_FileFormatOrEncryption = "File uses an unknown format or encryption"; - private static readonly int[] headerCypherTable; private readonly ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT | SignalSource.Tv | SignalSource.Radio, "Analog Antenna"); private readonly ChannelList avbcChannels = new ChannelList(SignalSource.AnalogC | SignalSource.Tv | SignalSource.Radio, "Analog Cable"); private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Radio, "DVB-T"); @@ -36,272 +35,6 @@ namespace ChanSort.Loader.Panasonic Unknown } - - #region static ctor / headerCypherTable - static Serializer() - { - headerCypherTable = new[] - { - 0, - 79764919, - 159529838, - 222504665, - 319059676, - 398814059, - 445009330, - 507990021, - 638119352, - 583659535, - 797628118, - 726387553, - 890018660, - 835552979, - 1015980042, - 944750013, - 1276238704, - 1221641927, - 1167319070, - 1095957929, - 1595256236, - 1540665371, - 1452775106, - 1381403509, - 1780037320, - 1859660671, - 1671105958, - 1733955601, - 2031960084, - 2111593891, - 1889500026, - 1952343757, - -1742489888, - -1662866601, - -1851683442, - -1788833735, - -1960329156, - -1880695413, - -2103051438, - -2040207643, - -1104454824, - -1159051537, - -1213636554, - -1284997759, - -1389417084, - -1444007885, - -1532160278, - -1603531939, - -734892656, - -789352409, - -575645954, - -646886583, - -952755380, - -1007220997, - -827056094, - -898286187, - -231047128, - -151282273, - -71779514, - -8804623, - -515967244, - -436212925, - -390279782, - -327299027, - 881225847, - 809987520, - 1023691545, - 969234094, - 662832811, - 591600412, - 771767749, - 717299826, - 311336399, - 374308984, - 453813921, - 533576470, - 25881363, - 88864420, - 134795389, - 214552010, - 2023205639, - 2086057648, - 1897238633, - 1976864222, - 1804852699, - 1867694188, - 1645340341, - 1724971778, - 1587496639, - 1516133128, - 1461550545, - 1406951526, - 1302016099, - 1230646740, - 1142491917, - 1087903418, - -1398421865, - -1469785312, - -1524105735, - -1578704818, - -1079922613, - -1151291908, - -1239184603, - -1293773166, - -1968362705, - -1905510760, - -2094067647, - -2014441994, - -1716953613, - -1654112188, - -1876203875, - -1796572374, - -525066777, - -462094256, - -382327159, - -302564546, - -206542021, - -143559028, - -97365931, - -17609246, - -960696225, - -1031934488, - -817968335, - -872425850, - -709327229, - -780559564, - -600130067, - -654598054, - 1762451694, - 1842216281, - 1619975040, - 1682949687, - 2047383090, - 2127137669, - 1938468188, - 2001449195, - 1325665622, - 1271206113, - 1183200824, - 1111960463, - 1543535498, - 1489069629, - 1434599652, - 1363369299, - 622672798, - 568075817, - 748617968, - 677256519, - 907627842, - 853037301, - 1067152940, - 995781531, - 51762726, - 131386257, - 177728840, - 240578815, - 269590778, - 349224269, - 429104020, - 491947555, - -248556018, - -168932423, - -122852000, - -60002089, - -500490030, - -420856475, - -341238852, - -278395381, - -685261898, - -739858943, - -559578920, - -630940305, - -1004286614, - -1058877219, - -845023740, - -916395085, - -1119974018, - -1174433591, - -1262701040, - -1333941337, - -1371866206, - -1426332139, - -1481064244, - -1552294533, - -1690935098, - -1611170447, - -1833673816, - -1770699233, - -2009983462, - -1930228819, - -2119160460, - -2056179517, - 1569362073, - 1498123566, - 1409854455, - 1355396672, - 1317987909, - 1246755826, - 1192025387, - 1137557660, - 2072149281, - 2135122070, - 1912620623, - 1992383480, - 1753615357, - 1816598090, - 1627664531, - 1707420964, - 295390185, - 358241886, - 404320391, - 483945776, - 43990325, - 106832002, - 186451547, - 266083308, - 932423249, - 861060070, - 1041341759, - 986742920, - 613929101, - 542559546, - 756411363, - 701822548, - -978770311, - -1050133554, - -869589737, - -924188512, - -693284699, - -764654318, - -550540341, - -605129092, - -475935807, - -413084042, - -366743377, - -287118056, - -257573603, - -194731862, - -114850189, - -35218492, - -1984365303, - -1921392450, - -2143631769, - -2063868976, - -1698919467, - -1635936670, - -1824608069, - -1744851700, - -1347415887, - -1418654458, - -1506661409, - -1561119128, - -1129027987, - -1200260134, - -1254728445, - -1309196108 - }; - } - #endregion - #region ctor() public Serializer(string inputFile) : base(inputFile) { @@ -461,16 +194,12 @@ namespace ChanSort.Loader.Panasonic #endregion #region CalcChecksum() + private uint CalcChecksum(byte[] data, int length) { - uint v = 0xffffffff; - for (int i = 0; i < length; i++) - { - byte b = data[i]; - v = (v << 8) ^ (uint)headerCypherTable[((v >> 24) ^ b) & 0xFF]; - } - return v; + return Crc32.Normal.CalcCrc32(data, 0, length); } + #endregion #region CleanTempFile() diff --git a/source/ChanSort.Loader.Sony/Serializer.cs b/source/ChanSort.Loader.Sony/Serializer.cs index 57ed096..3faf3e3 100644 --- a/source/ChanSort.Loader.Sony/Serializer.cs +++ b/source/ChanSort.Loader.Sony/Serializer.cs @@ -38,28 +38,6 @@ namespace ChanSort.Loader.Sony private readonly Dictionary channeListNodes = new Dictionary(); - #region Crc32Table - private static readonly uint[] Crc32Table = - { - 0, 79764919, 159529838, 222504665, 319059676, 398814059, 445009330, 507990021, 638119352, 583659535, 797628118, 726387553, 890018660, 835552979, 1015980042, 944750013, - 1276238704, 1221641927, 1167319070, 1095957929, 1595256236, 1540665371, 1452775106, 1381403509, 1780037320, 1859660671, 1671105958, 1733955601, 2031960084, 2111593891, 1889500026, 1952343757, - 2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653, 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357, - 3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109, 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269, - 881225847, 809987520, 1023691545, 969234094, 662832811, 591600412, 771767749, 717299826, 311336399, 374308984, 453813921, 533576470, 25881363, 88864420, 134795389, 214552010, - 2023205639, 2086057648, 1897238633, 1976864222, 1804852699, 1867694188, 1645340341, 1724971778, 1587496639, 1516133128, 1461550545, 1406951526, 1302016099, 1230646740, 1142491917, 1087903418, - 2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130, 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922, - 3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050, 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242, - 1762451694, 1842216281, 1619975040, 1682949687, 2047383090, 2127137669, 1938468188, 2001449195, 1325665622, 1271206113, 1183200824, 1111960463, 1543535498, 1489069629, 1434599652, 1363369299, - 622672798, 568075817, 748617968, 677256519, 907627842, 853037301, 1067152940, 995781531, 51762726, 131386257, 177728840, 240578815, 269590778, 349224269, 429104020, 491947555, - 4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915, 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211, - 3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763, 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779, - 1569362073, 1498123566, 1409854455, 1355396672, 1317987909, 1246755826, 1192025387, 1137557660, 2072149281, 2135122070, 1912620623, 1992383480, 1753615357, 1816598090, 1627664531, 1707420964, - 295390185, 358241886, 404320391, 483945776, 43990325, 106832002, 186451547, 266083308, 932423249, 861060070, 1041341759, 986742920, 613929101, 542559546, 756411363, 701822548, - 3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204, 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804, - 2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596, 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188 - }; - #endregion - #region ctor() public Serializer(string inputFile) : base(inputFile) @@ -483,13 +461,7 @@ namespace ChanSort.Loader.Sony end = data.Length; } - uint crc = 0xFFFFFFFF; - for (int i = start; i < end; i++) - { - var b = data[i]; - crc = (crc << 8) ^ Crc32Table[b ^ (crc >> 24)]; - } - return ~crc; + return ~Crc32.Normal.CalcCrc32(data, start, end - start); } #endregion