Minor tweaks to compile on win32.
[kugel-rb.git] / tools / scramble.c
blob4e3addfc26c420207858e13a7f46f3e849f90477
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>
23 void int2le(unsigned int val, unsigned char* addr)
25 addr[0] = val & 0xFF;
26 addr[1] = (val >> 8) & 0xff;
27 addr[2] = (val >> 16) & 0xff;
28 addr[3] = (val >> 24) & 0xff;
31 void int2be(unsigned int val, unsigned char* addr)
33 addr[0] = (val >> 24) & 0xff;
34 addr[1] = (val >> 16) & 0xff;
35 addr[2] = (val >> 8) & 0xff;
36 addr[3] = val & 0xFF;
39 int main (int argc, char** argv)
41 unsigned long length,i,slen;
42 unsigned char *inbuf,*outbuf;
43 unsigned short crc=0;
44 unsigned char header[24];
45 unsigned char *iname = argv[1];
46 unsigned char *oname = argv[2];
47 unsigned char *xorstring;
48 int headerlen = 6;
49 FILE* file;
50 int version;
51 enum { none, scramble, xor } method = scramble;
53 if (argc < 3) {
54 printf("usage: %s [options] <input file> <output file> [xor string]\n",argv[0]);
55 printf("options:\n");
56 printf("\t-fm Archos FM recorder format\n");
57 printf("\t-v2 Archos V2 recorder format\n");
58 printf("\t-ofm Archos Ondio FM recorder format\n");
59 printf("\t-osp Archos Ondio SP format\n");
60 printf("\t-neo SSI Neo format\n");
61 printf("\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n");
62 printf("\nNo option results in Archos standard player/recorder format.\n");
63 return -1;
66 if(!strcmp(argv[1], "-fm")) {
67 headerlen = 24;
68 iname = argv[2];
69 oname = argv[3];
70 version = 4;
73 else if(!strcmp(argv[1], "-v2")) {
74 headerlen = 24;
75 iname = argv[2];
76 oname = argv[3];
77 version = 2;
80 else if(!strcmp(argv[1], "-ofm")) {
81 headerlen = 24;
82 iname = argv[2];
83 oname = argv[3];
84 version = 8;
87 else if(!strcmp(argv[1], "-osp")) {
88 headerlen = 24;
89 iname = argv[2];
90 oname = argv[3];
91 version = 16;
94 else if(!strcmp(argv[1], "-neo")) {
95 headerlen = 17;
96 iname = argv[2];
97 oname = argv[3];
98 method = none;
100 else if(!strncmp(argv[1], "-mm=", 4)) {
101 headerlen = 16;
102 iname = argv[2];
103 oname = argv[3];
104 method = xor;
105 version = argv[1][4];
106 if (argc > 4)
107 xorstring = argv[4];
108 else {
109 printf("Multimedia needs an xor string\n");
110 return -1;
114 /* open file */
115 file = fopen(iname,"rb");
116 if (!file) {
117 perror(iname);
118 return -1;
120 fseek(file,0,SEEK_END);
121 length = ftell(file);
122 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
124 if ((method == scramble) && ((length + headerlen) >= 0x32000)) {
125 printf("error: max firmware size is 200KB!\n");
126 fclose(file);
127 return -1;
130 fseek(file,0,SEEK_SET);
131 inbuf = malloc(length);
132 if (method == xor)
133 outbuf = malloc(length*2);
134 else
135 outbuf = malloc(length);
136 if ( !inbuf || !outbuf ) {
137 printf("out of memory!\n");
138 return -1;
141 /* read file */
142 i=fread(inbuf,1,length,file);
143 if ( !i ) {
144 perror(iname);
145 return -1;
147 fclose(file);
149 switch (method)
151 case scramble:
152 slen = length/4;
153 for (i = 0; i < length; i++) {
154 unsigned long addr = (i >> 2) + ((i % 4) * slen);
155 unsigned char data = inbuf[i];
156 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
157 outbuf[addr] = data;
159 break;
161 case xor:
162 /* "compress" */
163 slen = 0;
164 for (i=0; i<length; i++) {
165 if (!(i&7))
166 outbuf[slen++] = 0xff; /* all data is uncompressed */
167 outbuf[slen++] = inbuf[i];
169 break;
172 /* calculate checksum */
173 for (i=0;i<length;i++)
174 crc += inbuf[i];
176 memset(header, 0, sizeof header);
177 switch (method)
179 case scramble:
180 if (headerlen == 6) {
181 int2be(length, header);
182 header[4] = (crc >> 8) & 0xff;
183 header[5] = crc & 0xff;
185 else {
186 header[0] =
187 header[1] =
188 header[2] =
189 header[3] = 0xff; /* ??? */
191 header[6] = (crc >> 8) & 0xff;
192 header[7] = crc & 0xff;
194 header[11] = version;
196 header[15] = headerlen; /* really? */
198 int2be(length, &header[20]);
200 break;
202 case xor:
204 int xorlen = strlen(xorstring);
206 /* xor data */
207 for (i=0; i<slen; i++)
208 outbuf[i] ^= xorstring[i & (xorlen-1)];
210 /* calculate checksum */
211 for (i=0; i<slen; i++)
212 crc += outbuf[i];
214 header[0] = header[2] = 'Z';
215 header[1] = header[3] = version;
216 int2le(length, &header[4]);
217 int2le(slen, &header[8]);
218 int2le(crc, &header[12]);
219 length = slen;
220 break;
223 #define MY_FIRMWARE_TYPE "Rockbox"
224 #define MY_HEADER_VERSION 1
225 default:
226 strncpy(header,MY_FIRMWARE_TYPE,9);
227 header[9]='\0'; /*shouldn't have to, but to be SURE */
228 header[10]=MY_HEADER_VERSION&0xFF;
229 header[11]=(crc>>8)&0xFF;
230 header[12]=crc&0xFF;
231 int2be(sizeof(header), &header[12]);
232 break;
235 /* write file */
236 file = fopen(oname,"wb");
237 if ( !file ) {
238 perror(oname);
239 return -1;
241 if ( !fwrite(header,headerlen,1,file) ) {
242 perror(oname);
243 return -1;
245 if ( !fwrite(outbuf,length,1,file) ) {
246 perror(oname);
247 return -1;
249 fclose(file);
251 free(inbuf);
252 free(outbuf);
254 return 0;