1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
25 void int2le(unsigned int val
, unsigned char* addr
)
28 addr
[1] = (val
>> 8) & 0xff;
29 addr
[2] = (val
>> 16) & 0xff;
30 addr
[3] = (val
>> 24) & 0xff;
33 void int2be(unsigned int val
, unsigned char* addr
)
35 addr
[0] = (val
>> 24) & 0xff;
36 addr
[1] = (val
>> 16) & 0xff;
37 addr
[2] = (val
>> 8) & 0xff;
43 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
45 "\t-fm Archos FM recorder format\n"
46 "\t-v2 Archos V2 recorder format\n"
47 "\t-ofm Archos Ondio FM recorder format\n"
48 "\t-osp Archos Ondio SP format\n"
49 "\t-neo SSI Neo format\n"
50 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
51 "\t-iriver iRiver format\n"
52 "\t-add=X Rockbox iRiver \"add-up\" checksum format\n"
53 "\t (X values: h100, h120, h140, h300)\n"
54 "\nNo option results in Archos standard player/recorder format.\n");
59 int main (int argc
, char** argv
)
61 unsigned long length
,i
,slen
;
62 unsigned char *inbuf
,*outbuf
;
64 unsigned long crc32
=0; /* 32 bit checksum */
65 unsigned char header
[24];
66 unsigned char *iname
= argv
[1];
67 unsigned char *oname
= argv
[2];
68 unsigned char *xorstring
;
72 unsigned long irivernum
;
74 enum { none
, scramble
, xor, add
} method
= scramble
;
80 if(!strcmp(argv
[1], "-fm")) {
87 else if(!strcmp(argv
[1], "-v2")) {
94 else if(!strcmp(argv
[1], "-ofm")) {
101 else if(!strcmp(argv
[1], "-osp")) {
108 else if(!strcmp(argv
[1], "-neo")) {
114 else if(!strncmp(argv
[1], "-mm=", 4)) {
119 version
= argv
[1][4];
123 printf("Multimedia needs an xor string\n");
127 else if(!strncmp(argv
[1], "-add=", 5)) {
132 if(!strcmp(&argv
[1][5], "h120"))
134 else if(!strcmp(&argv
[1][5], "h140"))
135 irivernum
= 0; /* the same as the h120 */
136 else if(!strcmp(&argv
[1][5], "h100"))
138 else if(!strcmp(&argv
[1][5], "h300"))
141 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
144 /* we store a 4-letter model name too, for humans */
145 strcpy(irivermodel
, &argv
[1][5]);
146 crc32
= irivernum
; /* start checksum calcs with this */
149 else if(!strcmp(argv
[1], "-iriver")) {
150 /* iRiver code dealt with in the iriver.c code */
153 iriver_encode(iname
, oname
, FALSE
);
158 file
= fopen(iname
,"rb");
163 fseek(file
,0,SEEK_END
);
164 length
= ftell(file
);
165 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
167 if ((method
== scramble
) && ((length
+ headerlen
) >= 0x32000)) {
168 printf("error: max firmware size is 200KB!\n");
173 fseek(file
,0,SEEK_SET
);
174 inbuf
= malloc(length
);
176 outbuf
= malloc(length
*2);
177 else if(method
== add
)
178 outbuf
= malloc(length
+ 8);
180 outbuf
= malloc(length
);
181 if ( !inbuf
|| !outbuf
) {
182 printf("out of memory!\n");
186 /* zero-fill the last 4 bytes to make sure there's no rubbish there
187 when we write the size-aligned file later */
188 memset(outbuf
+length
-4, 0, 4);
192 i
=fread(inbuf
,1,length
,file
);
202 for (i
= 0; i
< length
/2; i
++) {
203 unsigned short *inbuf16
= (unsigned short *)inbuf
;
204 /* add 16 unsigned bits but keep a 32 bit sum */
210 for (i
= 0; i
< length
; i
++) {
211 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
212 unsigned char data
= inbuf
[i
];
213 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
221 for (i
=0; i
<length
; i
++) {
223 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
224 outbuf
[slen
++] = inbuf
[i
];
230 /* calculate checksum */
231 for (i
=0;i
<length
;i
++)
235 memset(header
, 0, sizeof header
);
240 int2be(crc32
, header
); /* checksum, big-endian */
241 memcpy(&header
[4], irivermodel
, 4); /* 4 bytes model name */
242 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
247 if (headerlen
== 6) {
248 int2be(length
, header
);
249 header
[4] = (crc
>> 8) & 0xff;
250 header
[5] = crc
& 0xff;
256 header
[3] = 0xff; /* ??? */
258 header
[6] = (crc
>> 8) & 0xff;
259 header
[7] = crc
& 0xff;
261 header
[11] = version
;
263 header
[15] = headerlen
; /* really? */
265 int2be(length
, &header
[20]);
271 int xorlen
= strlen(xorstring
);
274 for (i
=0; i
<slen
; i
++)
275 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
277 /* calculate checksum */
278 for (i
=0; i
<slen
; i
++)
281 header
[0] = header
[2] = 'Z';
282 header
[1] = header
[3] = version
;
283 int2le(length
, &header
[4]);
284 int2le(slen
, &header
[8]);
285 int2le(crc
, &header
[12]);
290 #define MY_FIRMWARE_TYPE "Rockbox"
291 #define MY_HEADER_VERSION 1
293 strncpy(header
,MY_FIRMWARE_TYPE
,9);
294 header
[9]='\0'; /*shouldn't have to, but to be SURE */
295 header
[10]=MY_HEADER_VERSION
&0xFF;
296 header
[11]=(crc
>>8)&0xFF;
298 int2be(sizeof(header
), &header
[12]);
303 file
= fopen(oname
,"wb");
308 if ( !fwrite(header
,headerlen
,1,file
) ) {
312 if ( !fwrite(outbuf
,length
,1,file
) ) {