Major W32 beastpatcher rework (FS#10220).
[kugel-rb.git] / tools / telechips.c
blob8eefffcb98d58cf8ebfba175d8048786891af56c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Telechips firmware checksum support for scramble
12 * Copyright (C) 2007 Dave Chapman
14 * Thanks to Hein-Pieter van Braam for his work in identifying the
15 * CRC algorithm used.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <stdint.h>
33 #include <stdlib.h>
35 static uint32_t crctable[256];
37 /* Simple implementation of a function to reverse the bottom n bits in x */
38 static uint32_t bitreverse(uint32_t x,int n)
40 int i;
41 uint32_t mask = 1<<(n-1);
42 uint32_t res = 0;
44 for (i=0; i<n; i++)
46 if (x & 1)
47 res |= mask;
49 x >>= 1;
50 mask >>= 1;
52 return res;
55 /* Generate a lookup table for a reverse CRC32 */
56 static void gentable(uint32_t poly)
58 int i;
59 uint32_t r;
60 uint32_t index;
62 for (index = 0; index < 256; index++)
64 r = bitreverse(index,8) << 24;
65 for (i=0; i<8; i++)
67 if (r & (1 << 31))
68 r = (r << 1) ^ poly;
69 else
70 r<<=1;
72 crctable[index] = bitreverse(r,32);
76 /* Perform a reverse CRC32 */
77 static uint32_t calc_crc(unsigned char *message, int size)
79 uint32_t crc = 0;
80 int i;
82 for (i=0; i < size; i++){
83 if ((i < 0x10) || (i >= 0x18)) {
84 crc = crctable[((crc ^ (message[i])) & 0xff)] ^ (crc >> 8);
88 return crc;
91 /* Endian-safe functions to read/write a 32-bit little-endian integer */
93 static uint32_t get_uint32le(unsigned char* p)
95 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
98 static void put_uint32le(unsigned char* p, uint32_t x)
100 p[0] = x & 0xff;
101 p[1] = (x >> 8) & 0xff;
102 p[2] = (x >> 16) & 0xff;
103 p[3] = (x >> 24) & 0xff;
106 /* A simple checksum - seems to be used by the TCC76x firmwares */
107 void telechips_encode_sum(unsigned char* buf, int length)
109 uint32_t sum;
110 int i;
112 /* Set checksum field to 0 */
113 put_uint32le(buf + 0x10, 0);
115 /* Perform a simple sum, treating the file as a series of 32-bit
116 little-endian integers */
117 sum = 0;
118 for (i=0; i < length; i+=4) {
119 sum += get_uint32le(buf + i);
121 /* Negate the sum - this means that the sum of the whole file
122 (including this value) will be equal to zero */
123 sum = -sum;
125 /* Set the checksum field */
126 put_uint32le(buf + 0x10, sum);
130 /* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */
131 void telechips_encode_crc(unsigned char* buf, int length)
133 uint32_t crc1,crc2;
135 /* Generate the CRC table */
136 gentable(0x8001801BL);
138 /* Clear the existing CRC values */
139 put_uint32le(buf+0x10, 0);
140 put_uint32le(buf+0x18, 0);
142 /* Write the length */
143 put_uint32le(buf+0x1c, length);
145 /* Calculate the first CRC - over the entire file */
146 crc1 = calc_crc(buf, length);
148 /* What happens next depends on the filesize */
149 if (length >= 128*1024)
151 put_uint32le(buf+0x18, crc1);
153 crc2 = calc_crc(buf, 128*1024);
154 put_uint32le(buf+0x10, crc2);
155 } else {
156 put_uint32le(buf+0x10, crc1);