the showlog script
[kugel-rb.git] / tools / descramble.c
blobbfcf7062f7b44de07a854c018c1a123a24ccb9c0
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 void usage(void)
31 printf("usage: descramble [options] <input file> <output file>\n");
32 printf("options:\n"
33 "\t-fm Archos FM recorder format\n"
34 "\t-v2 Archos V2 recorder format\n"
35 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
36 "\t-iriver iRiver format\n"
37 "\t-gigabeat Toshiba Gigabeat format\n"
38 "\t-iaudio iAudio format\n"
39 "\nNo option assumes Archos standard player/recorder format.\n");
40 exit(1);
43 int main (int argc, char** argv)
45 unsigned long length,i,slen;
46 unsigned char *inbuf,*outbuf;
47 char *iname = argv[1];
48 char *oname = argv[2];
49 unsigned char header[32];
50 int headerlen = 6;
51 int descramble = 1;
52 FILE* file;
54 if (argc < 3) {
55 usage();
58 if (!strcmp(argv[1], "-fm") || !strcmp(argv[1], "-v2")) {
59 headerlen = 24;
60 iname = argv[2];
61 oname = argv[3];
64 if (!strcmp(argv[1], "-mm")) {
65 headerlen = 16;
66 iname = argv[2];
67 oname = argv[3];
68 descramble = 0;
71 if(!strcmp(argv[1], "-iriver")) {
72 /* iRiver code dealt with in the iriver.c code */
73 iname = argv[2];
74 oname = argv[3];
75 iriver_decode(iname, oname, FALSE, STRIP_NONE);
76 return 0;
78 if(!strcmp(argv[1], "-gigabeat")) {
79 iname = argv[2];
80 oname = argv[3];
81 gigabeat_code(iname, oname);
82 return 0;
85 if(!strcmp(argv[1], "-iaudio")) {
86 iname = argv[2];
87 oname = argv[3];
88 return iaudio_decode(iname, oname);
91 /* open file and check size */
92 file = fopen(iname,"rb");
93 if (!file) {
94 perror(oname);
95 return -1;
97 fseek(file,0,SEEK_END);
98 length = ftell(file) - headerlen; /* skip header */
99 fseek(file,0,SEEK_SET);
100 i = fread(header, 1, headerlen, file);
101 if ( !i ) {
102 perror(iname);
103 return -1;
106 inbuf = malloc(length);
107 outbuf = malloc(length);
108 if ( !inbuf || !outbuf ) {
109 printf("out of memory!\n");
110 return -1;
113 /* read file */
114 i=fread(inbuf,1,length,file);
115 if ( !i ) {
116 perror(iname);
117 return -1;
119 fclose(file);
121 if (descramble) {
122 /* descramble */
123 slen = length/4;
124 for (i = 0; i < length; i++) {
125 unsigned long addr = ((i % slen) << 2) + i/slen;
126 unsigned char data = inbuf[i];
127 data = ~((data >> 1) | ((data << 7) & 0x80)); /* poor man's ROR */
128 outbuf[addr] = data;
131 else {
132 void* tmpptr;
133 unsigned int j=0;
134 int stringlen = 32;
135 int unpackedsize;
136 unsigned char xorstring[32];
138 unpackedsize = header[4] | header[5] << 8;
139 unpackedsize |= header[6] << 16 | header[7] << 24;
141 length = header[8] | header[9] << 8;
142 length |= header[10] << 16 | header[11] << 24;
144 /* calculate the xor string used */
145 for (i=0; i<stringlen; i++) {
146 int top=0, topchar=0, c;
147 int bytecount[256];
148 memset(bytecount, 0, sizeof(bytecount));
150 /* gather byte frequency statistics */
151 for (c=i; c<length; c+=stringlen)
152 bytecount[inbuf[c]]++;
154 /* find the most frequent byte */
155 for (c=0; c<256; c++) {
156 if (bytecount[c] > top) {
157 top = bytecount[c];
158 topchar = c;
161 xorstring[i] = topchar;
163 printf("XOR string: %.*s\n", stringlen, xorstring);
165 /* xor the buffer */
166 for (i=0; i<length; i++)
167 outbuf[i] = inbuf[i] ^ xorstring[i & (stringlen-1)];
169 /* unpack */
170 tmpptr = realloc(inbuf, unpackedsize);
171 memset(tmpptr, 0, unpackedsize);
172 inbuf = outbuf;
173 outbuf = tmpptr;
175 for (i=0; i<length;) {
176 int bit;
177 int head = inbuf[i++];
179 for (bit=0; bit<8 && i<length; bit++) {
180 if (head & (1 << (bit))) {
181 outbuf[j++] = inbuf[i++];
183 else {
184 int x;
185 int byte1 = inbuf[i];
186 int byte2 = inbuf[i+1];
187 int count = (byte2 & 0x0f) + 3;
188 int src =
189 (j & 0xfffff000) + (byte1 | ((byte2 & 0xf0)<<4)) + 18;
190 if (src > j)
191 src -= 0x1000;
193 for (x=0; x<count; x++)
194 outbuf[j++] = outbuf[src+x];
195 i += 2;
199 length = j;
202 /* write file */
203 file = fopen(oname,"wb");
204 if ( !file ) {
205 perror(argv[2]);
206 return -1;
208 if ( !fwrite(outbuf,length,1,file) ) {
209 perror(argv[2]);
210 return -1;
212 fclose(file);
214 free(inbuf);
215 free(outbuf);
217 return 0;
220 int iaudio_decode(char *iname, char *oname)
222 size_t len;
223 int length;
224 FILE *file;
225 char *outbuf;
226 int i;
227 unsigned char sum = 0;
228 unsigned char filesum;
230 file = fopen(iname, "rb");
231 if (!file) {
232 perror(iname);
233 return -1;
235 fseek(file,0,SEEK_END);
236 length = ftell(file);
238 fseek(file,0,SEEK_SET);
239 outbuf = malloc(length);
241 if ( !outbuf ) {
242 printf("out of memory!\n");
243 return -1;
246 len = fread(outbuf, 1, length, file);
247 if(len < length) {
248 perror(iname);
249 return -2;
252 fclose(file);
254 for(i = 0; i < length-0x1030;i++)
255 sum += outbuf[0x1030 + i];
257 filesum = outbuf[0x102b];
259 if(filesum != sum) {
260 printf("Checksum mismatch!\n");
261 return -1;
264 file = fopen(oname, "wb");
265 if (!file) {
266 perror(oname);
267 return -3;
270 len = fwrite(outbuf+0x1030, 1, length-0x1030, file);
271 if(len < length-0x1030) {
272 perror(oname);
273 return -4;
276 fclose(file);
277 return 0;