fix FS#8969 - rockbox info screen is now redrawn every half second
[Rockbox.git] / tools / descramble.c
blob5d4975be26a0b078ff865236a68671b2fa59c80d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "iriver.h"
25 #include "gigabeat.h"
27 int iaudio_decode(char *iname, char *oname);
29 unsigned int le2int(unsigned char* buf)
31 unsigned int res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
33 return res;
36 void int2le(unsigned int val, unsigned char* addr)
38 addr[0] = val & 0xFF;
39 addr[1] = (val >> 8) & 0xff;
40 addr[2] = (val >> 16) & 0xff;
41 addr[3] = (val >> 24) & 0xff;
44 void usage(void)
46 printf("usage: descramble [options] <input file> <output file>\n");
47 printf("options:\n"
48 "\t-fm Archos FM recorder format\n"
49 "\t-v2 Archos V2 recorder format\n"
50 "\t-mm Archos Multimedia format\n"
51 "\t-iriver iRiver format\n"
52 "\t-gigabeat Toshiba Gigabeat format\n"
53 "\t-iaudio iAudio format\n"
54 "\nNo option assumes Archos standard player/recorder format.\n");
55 exit(1);
58 int main (int argc, char** argv)
60 unsigned long length,i,slen;
61 unsigned char *inbuf,*outbuf;
62 char *iname = argv[1];
63 char *oname = argv[2];
64 unsigned char header[32];
65 int headerlen = 6;
66 int descramble = 1;
67 FILE* file;
69 if (argc < 3) {
70 usage();
73 if (!strcmp(argv[1], "-fm") || !strcmp(argv[1], "-v2")) {
74 headerlen = 24;
75 iname = argv[2];
76 oname = argv[3];
79 if (!strcmp(argv[1], "-mm")) {
80 headerlen = 16;
81 iname = argv[2];
82 oname = argv[3];
83 descramble = 0;
86 if(!strcmp(argv[1], "-iriver")) {
87 /* iRiver code dealt with in the iriver.c code */
88 iname = argv[2];
89 oname = argv[3];
90 return iriver_decode(iname, oname, FALSE, STRIP_NONE) ? -1 : 0;
92 if(!strcmp(argv[1], "-gigabeat")) {
93 iname = argv[2];
94 oname = argv[3];
95 gigabeat_code(iname, oname);
96 return 0;
99 if(!strcmp(argv[1], "-iaudio")) {
100 iname = argv[2];
101 oname = argv[3];
102 return iaudio_decode(iname, oname);
105 /* open file and check size */
106 file = fopen(iname,"rb");
107 if (!file) {
108 perror(iname);
109 return -1;
111 fseek(file,0,SEEK_END);
112 length = ftell(file) - headerlen; /* skip header */
113 fseek(file,0,SEEK_SET);
114 i = fread(header, 1, headerlen, file);
115 if ( !i ) {
116 perror(iname);
117 return -1;
120 inbuf = malloc(length);
121 outbuf = malloc(length);
122 if ( !inbuf || !outbuf ) {
123 printf("out of memory!\n");
124 return -1;
127 /* read file */
128 i=fread(inbuf,1,length,file);
129 if ( !i ) {
130 perror(iname);
131 return -1;
133 fclose(file);
135 if (descramble) {
136 /* descramble */
137 slen = length/4;
138 for (i = 0; i < length; i++) {
139 unsigned long addr = ((i % slen) << 2) + i/slen;
140 unsigned char data = inbuf[i];
141 data = ~((data >> 1) | ((data << 7) & 0x80)); /* poor man's ROR */
142 outbuf[addr] = data;
145 else {
146 void* tmpptr;
147 unsigned int j=0;
148 int stringlen = 32;
149 int unpackedsize;
150 unsigned char xorstring[32];
152 unpackedsize = header[4] | header[5] << 8;
153 unpackedsize |= header[6] << 16 | header[7] << 24;
155 length = header[8] | header[9] << 8;
156 length |= header[10] << 16 | header[11] << 24;
158 /* calculate the xor string used */
159 for (i=0; i<(unsigned long)stringlen; i++) {
160 int top=0, topchar=0, c;
161 int bytecount[256];
162 memset(bytecount, 0, sizeof(bytecount));
164 /* gather byte frequency statistics */
165 for (c=i; c<(int)length; c+=stringlen)
166 bytecount[inbuf[c]]++;
168 /* find the most frequent byte */
169 for (c=0; c<256; c++) {
170 if (bytecount[c] > top) {
171 top = bytecount[c];
172 topchar = c;
175 xorstring[i] = topchar;
177 printf("XOR string: %.*s\n", stringlen, xorstring);
179 /* xor the buffer */
180 for (i=0; i<length; i++)
181 outbuf[i] = inbuf[i] ^ xorstring[i & (stringlen-1)];
183 /* unpack */
184 tmpptr = realloc(inbuf, unpackedsize);
185 memset(tmpptr, 0, unpackedsize);
186 inbuf = outbuf;
187 outbuf = tmpptr;
189 for (i=0; i<length;) {
190 int bit;
191 int head = inbuf[i++];
193 for (bit=0; bit<8 && i<length; bit++) {
194 if (head & (1 << (bit))) {
195 outbuf[j++] = inbuf[i++];
197 else {
198 int x;
199 int byte1 = inbuf[i];
200 int byte2 = inbuf[i+1];
201 int count = (byte2 & 0x0f) + 3;
202 int src =
203 (j & 0xfffff000) + (byte1 | ((byte2 & 0xf0)<<4)) + 18;
204 if (src > (int)j)
205 src -= 0x1000;
207 for (x=0; x<count; x++)
208 outbuf[j++] = outbuf[src+x];
209 i += 2;
213 length = j;
216 /* write file */
217 file = fopen(oname,"wb");
218 if ( !file ) {
219 perror(argv[2]);
220 return -1;
222 if ( !fwrite(outbuf,length,1,file) ) {
223 perror(argv[2]);
224 return -1;
226 fclose(file);
228 free(inbuf);
229 free(outbuf);
231 return 0;
234 int iaudio_decode(char *iname, char *oname)
236 size_t len;
237 int length;
238 FILE *file;
239 char *outbuf;
240 int i;
241 unsigned char sum = 0;
242 unsigned char filesum;
244 file = fopen(iname, "rb");
245 if (!file) {
246 perror(iname);
247 return -1;
249 fseek(file,0,SEEK_END);
250 length = ftell(file);
252 fseek(file,0,SEEK_SET);
253 outbuf = malloc(length);
255 if ( !outbuf ) {
256 printf("out of memory!\n");
257 return -1;
260 len = fread(outbuf, 1, length, file);
261 if(len < (size_t)length) {
262 perror(iname);
263 return -2;
266 fclose(file);
268 for(i = 0; i < length-0x1030;i++)
269 sum += outbuf[0x1030 + i];
271 filesum = outbuf[0x102b];
273 if(filesum != sum) {
274 printf("Checksum mismatch!\n");
275 return -1;
278 file = fopen(oname, "wb");
279 if (!file) {
280 perror(oname);
281 return -3;
284 len = fwrite(outbuf+0x1030, 1, length-0x1030, file);
285 if(len < (size_t)length-0x1030) {
286 perror(oname);
287 return -4;
290 fclose(file);
291 return 0;