blob: 712f8ff728fcca55777b42b76094b3f335914ce1 [file] [log] [blame]
Björn Stenberge1715c22002-03-28 14:34:13 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <stdlib.h>
22
Björn Stenberg123ae832004-01-08 21:34:52 +000023void int2le(unsigned int val, unsigned char* addr)
24{
25 addr[0] = val & 0xFF;
26 addr[1] = (val >> 8) & 0xff;
27 addr[2] = (val >> 16) & 0xff;
28 addr[3] = (val >> 24) & 0xff;
29}
30
31void int2be(unsigned int val, unsigned char* addr)
32{
33 addr[0] = (val >> 24) & 0xff;
34 addr[1] = (val >> 16) & 0xff;
35 addr[2] = (val >> 8) & 0xff;
36 addr[3] = val & 0xFF;
37}
38
Björn Stenberge1715c22002-03-28 14:34:13 +000039int main (int argc, char** argv)
40{
41 unsigned long length,i,slen;
42 unsigned char *inbuf,*outbuf;
43 unsigned short crc=0;
Björn Stenberg323f2972002-12-19 15:00:40 +000044 unsigned char header[24];
45 unsigned char *iname = argv[1];
46 unsigned char *oname = argv[2];
Björn Stenberg123ae832004-01-08 21:34:52 +000047 unsigned char *xorstring;
Björn Stenberg323f2972002-12-19 15:00:40 +000048 int headerlen = 6;
Björn Stenberge1715c22002-03-28 14:34:13 +000049 FILE* file;
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000050 int version;
Björn Stenberg123ae832004-01-08 21:34:52 +000051 enum { none, scramble, xor } method = scramble;
Björn Stenberge1715c22002-03-28 14:34:13 +000052
53 if (argc < 3) {
Björn Stenberg123ae832004-01-08 21:34:52 +000054 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-neo SSI Neo format\n");
59 printf("\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n");
60 printf("\nNo option results in Archos standard player/recorder format.\n");
Björn Stenberge1715c22002-03-28 14:34:13 +000061 return -1;
62 }
Björn Stenberg323f2972002-12-19 15:00:40 +000063
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000064 if(!strcmp(argv[1], "-fm")) {
Björn Stenberg323f2972002-12-19 15:00:40 +000065 headerlen = 24;
66 iname = argv[2];
67 oname = argv[3];
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000068 version = 4;
69 }
70
Daniel Stenberg0115af22003-12-12 14:07:28 +000071 else if(!strcmp(argv[1], "-v2")) {
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000072 headerlen = 24;
73 iname = argv[2];
74 oname = argv[3];
75 version = 2;
Björn Stenberg323f2972002-12-19 15:00:40 +000076 }
Daniel Stenberg0115af22003-12-12 14:07:28 +000077
78 else if(!strcmp(argv[1], "-neo")) {
79 headerlen = 17;
80 iname = argv[2];
81 oname = argv[3];
Björn Stenberg123ae832004-01-08 21:34:52 +000082 method = none;
83 }
84 else if(!strncmp(argv[1], "-mm=", 4)) {
85 headerlen = 16;
86 iname = argv[2];
87 oname = argv[3];
88 method = xor;
89 version = argv[1][4];
90 if (argc > 4)
91 xorstring = argv[4];
92 else {
93 printf("Multimedia needs an xor string\n");
94 return -1;
95 }
Daniel Stenberg0115af22003-12-12 14:07:28 +000096 }
97
Björn Stenberge1715c22002-03-28 14:34:13 +000098 /* open file */
Björn Stenberg323f2972002-12-19 15:00:40 +000099 file = fopen(iname,"rb");
Björn Stenberge1715c22002-03-28 14:34:13 +0000100 if (!file) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000101 perror(iname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000102 return -1;
103 }
104 fseek(file,0,SEEK_END);
105 length = ftell(file);
Linus Nielsen Feltzing1326f662003-04-12 21:17:47 +0000106 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
107
Björn Stenberg123ae832004-01-08 21:34:52 +0000108 if ((method == scramble) && ((length + headerlen) >= 0x32000)) {
Linus Nielsen Feltzing6a429972003-04-14 09:59:47 +0000109 printf("error: max firmware size is 200KB!\n");
110 fclose(file);
111 return -1;
112 }
113
Björn Stenberge1715c22002-03-28 14:34:13 +0000114 fseek(file,0,SEEK_SET);
115 inbuf = malloc(length);
Björn Stenberg123ae832004-01-08 21:34:52 +0000116 if (method == xor)
117 outbuf = malloc(length*2);
118 else
119 outbuf = malloc(length);
Björn Stenberge1715c22002-03-28 14:34:13 +0000120 if ( !inbuf || !outbuf ) {
121 printf("out of memory!\n");
122 return -1;
123 }
124
125 /* read file */
126 i=fread(inbuf,1,length,file);
127 if ( !i ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000128 perror(iname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000129 return -1;
130 }
131 fclose(file);
132
Björn Stenberg123ae832004-01-08 21:34:52 +0000133 switch (method)
134 {
135 case scramble:
136 slen = length/4;
137 for (i = 0; i < length; i++) {
138 unsigned long addr = (i >> 2) + ((i % 4) * slen);
139 unsigned char data = inbuf[i];
140 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
141 outbuf[addr] = data;
142 }
143 break;
144
145 case xor:
146 /* "compress" */
147 slen = 0;
148 for (i=0; i<length; i++) {
149 if (!(i&7))
150 outbuf[slen++] = 0xff; /* all data is uncompressed */
151 outbuf[slen++] = inbuf[i];
152 }
153 break;
Björn Stenberge1715c22002-03-28 14:34:13 +0000154 }
155
156 /* calculate checksum */
157 for (i=0;i<length;i++)
158 crc += inbuf[i];
159
Björn Stenberg323f2972002-12-19 15:00:40 +0000160 memset(header, 0, sizeof header);
Björn Stenberg123ae832004-01-08 21:34:52 +0000161 switch (method)
162 {
163 case scramble:
164 if (headerlen == 6) {
165 int2be(length, header);
166 header[4] = (crc >> 8) & 0xff;
167 header[5] = crc & 0xff;
168 }
169 else {
170 header[0] =
171 header[1] =
172 header[2] =
173 header[3] = 0xff; /* ??? */
174
175 header[6] = (crc >> 8) & 0xff;
176 header[7] = crc & 0xff;
177
178 header[11] = version;
179
180 header[15] = headerlen; /* really? */
181
182 int2be(length, &header[20]);
183 }
184 break;
185
186 case xor:
187 {
188 int xorlen = strlen(xorstring);
189
Björn Stenberg123ae832004-01-08 21:34:52 +0000190 /* xor data */
191 for (i=0; i<slen; i++)
192 outbuf[i] ^= xorstring[i & (xorlen-1)];
Daniel Stenberg0115af22003-12-12 14:07:28 +0000193
Björn Stenberg452702d2004-03-17 23:43:42 +0000194 /* calculate checksum */
195 for (i=0; i<slen; i++)
196 crc += outbuf[i];
197
Björn Stenberg123ae832004-01-08 21:34:52 +0000198 header[0] = header[2] = 'Z';
199 header[1] = header[3] = version;
200 int2le(length, &header[4]);
201 int2le(slen, &header[8]);
202 int2le(crc, &header[12]);
203 length = slen;
204 break;
Daniel Stenberg0115af22003-12-12 14:07:28 +0000205 }
Björn Stenberg123ae832004-01-08 21:34:52 +0000206
Daniel Stenberg0115af22003-12-12 14:07:28 +0000207#define MY_FIRMWARE_TYPE "Rockbox"
208#define MY_HEADER_VERSION 1
Björn Stenberg123ae832004-01-08 21:34:52 +0000209 default:
210 strncpy(header,MY_FIRMWARE_TYPE,9);
211 header[9]='\0'; /*shouldn't have to, but to be SURE */
212 header[10]=MY_HEADER_VERSION&0xFF;
213 header[11]=(crc>>8)&0xFF;
214 header[12]=crc&0xFF;
215 int2be(sizeof(header), &header[12]);
216 break;
Björn Stenberg323f2972002-12-19 15:00:40 +0000217 }
Björn Stenberge1715c22002-03-28 14:34:13 +0000218
219 /* write file */
Björn Stenberg323f2972002-12-19 15:00:40 +0000220 file = fopen(oname,"wb");
Björn Stenberge1715c22002-03-28 14:34:13 +0000221 if ( !file ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000222 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000223 return -1;
224 }
Björn Stenberg323f2972002-12-19 15:00:40 +0000225 if ( !fwrite(header,headerlen,1,file) ) {
226 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000227 return -1;
228 }
229 if ( !fwrite(outbuf,length,1,file) ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000230 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000231 return -1;
232 }
233 fclose(file);
234
235 free(inbuf);
236 free(outbuf);
237
Linus Nielsen Feltzing6a429972003-04-14 09:59:47 +0000238 return 0;
Björn Stenberge1715c22002-03-28 14:34:13 +0000239}