blob: 4e3addfc26c420207858e13a7f46f3e849f90477 [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");
Jörg Hohensohn4f52bf42004-09-08 21:21:22 +000058 printf("\t-ofm Archos Ondio FM recorder format\n");
59 printf("\t-osp Archos Ondio SP format\n");
Björn Stenberg123ae832004-01-08 21:34:52 +000060 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");
Björn Stenberge1715c22002-03-28 14:34:13 +000063 return -1;
64 }
Björn Stenberg323f2972002-12-19 15:00:40 +000065
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000066 if(!strcmp(argv[1], "-fm")) {
Björn Stenberg323f2972002-12-19 15:00:40 +000067 headerlen = 24;
68 iname = argv[2];
69 oname = argv[3];
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000070 version = 4;
71 }
72
Daniel Stenberg0115af22003-12-12 14:07:28 +000073 else if(!strcmp(argv[1], "-v2")) {
Linus Nielsen Feltzinged11bd32003-10-27 18:04:28 +000074 headerlen = 24;
75 iname = argv[2];
76 oname = argv[3];
77 version = 2;
Björn Stenberg323f2972002-12-19 15:00:40 +000078 }
Daniel Stenberg0115af22003-12-12 14:07:28 +000079
Jörg Hohensohn4f52bf42004-09-08 21:21:22 +000080 else if(!strcmp(argv[1], "-ofm")) {
81 headerlen = 24;
82 iname = argv[2];
83 oname = argv[3];
84 version = 8;
85 }
86
87 else if(!strcmp(argv[1], "-osp")) {
88 headerlen = 24;
89 iname = argv[2];
90 oname = argv[3];
91 version = 16;
92 }
93
Daniel Stenberg0115af22003-12-12 14:07:28 +000094 else if(!strcmp(argv[1], "-neo")) {
95 headerlen = 17;
96 iname = argv[2];
97 oname = argv[3];
Björn Stenberg123ae832004-01-08 21:34:52 +000098 method = none;
99 }
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;
111 }
Daniel Stenberg0115af22003-12-12 14:07:28 +0000112 }
113
Björn Stenberge1715c22002-03-28 14:34:13 +0000114 /* open file */
Björn Stenberg323f2972002-12-19 15:00:40 +0000115 file = fopen(iname,"rb");
Björn Stenberge1715c22002-03-28 14:34:13 +0000116 if (!file) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000117 perror(iname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000118 return -1;
119 }
120 fseek(file,0,SEEK_END);
121 length = ftell(file);
Linus Nielsen Feltzing1326f662003-04-12 21:17:47 +0000122 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
123
Björn Stenberg123ae832004-01-08 21:34:52 +0000124 if ((method == scramble) && ((length + headerlen) >= 0x32000)) {
Linus Nielsen Feltzing6a429972003-04-14 09:59:47 +0000125 printf("error: max firmware size is 200KB!\n");
126 fclose(file);
127 return -1;
128 }
129
Björn Stenberge1715c22002-03-28 14:34:13 +0000130 fseek(file,0,SEEK_SET);
131 inbuf = malloc(length);
Björn Stenberg123ae832004-01-08 21:34:52 +0000132 if (method == xor)
133 outbuf = malloc(length*2);
134 else
135 outbuf = malloc(length);
Björn Stenberge1715c22002-03-28 14:34:13 +0000136 if ( !inbuf || !outbuf ) {
137 printf("out of memory!\n");
138 return -1;
139 }
140
141 /* read file */
142 i=fread(inbuf,1,length,file);
143 if ( !i ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000144 perror(iname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000145 return -1;
146 }
147 fclose(file);
148
Björn Stenberg123ae832004-01-08 21:34:52 +0000149 switch (method)
150 {
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;
158 }
159 break;
160
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];
168 }
169 break;
Björn Stenberge1715c22002-03-28 14:34:13 +0000170 }
171
172 /* calculate checksum */
173 for (i=0;i<length;i++)
174 crc += inbuf[i];
175
Björn Stenberg323f2972002-12-19 15:00:40 +0000176 memset(header, 0, sizeof header);
Björn Stenberg123ae832004-01-08 21:34:52 +0000177 switch (method)
178 {
179 case scramble:
180 if (headerlen == 6) {
181 int2be(length, header);
182 header[4] = (crc >> 8) & 0xff;
183 header[5] = crc & 0xff;
184 }
185 else {
186 header[0] =
187 header[1] =
188 header[2] =
189 header[3] = 0xff; /* ??? */
190
191 header[6] = (crc >> 8) & 0xff;
192 header[7] = crc & 0xff;
193
194 header[11] = version;
195
196 header[15] = headerlen; /* really? */
197
198 int2be(length, &header[20]);
199 }
200 break;
201
202 case xor:
203 {
204 int xorlen = strlen(xorstring);
205
Björn Stenberg123ae832004-01-08 21:34:52 +0000206 /* xor data */
207 for (i=0; i<slen; i++)
208 outbuf[i] ^= xorstring[i & (xorlen-1)];
Daniel Stenberg0115af22003-12-12 14:07:28 +0000209
Björn Stenberg452702d2004-03-17 23:43:42 +0000210 /* calculate checksum */
211 for (i=0; i<slen; i++)
212 crc += outbuf[i];
213
Björn Stenberg123ae832004-01-08 21:34:52 +0000214 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;
Daniel Stenberg0115af22003-12-12 14:07:28 +0000221 }
Björn Stenberg123ae832004-01-08 21:34:52 +0000222
Daniel Stenberg0115af22003-12-12 14:07:28 +0000223#define MY_FIRMWARE_TYPE "Rockbox"
224#define MY_HEADER_VERSION 1
Björn Stenberg123ae832004-01-08 21:34:52 +0000225 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;
Björn Stenberg323f2972002-12-19 15:00:40 +0000233 }
Björn Stenberge1715c22002-03-28 14:34:13 +0000234
235 /* write file */
Björn Stenberg323f2972002-12-19 15:00:40 +0000236 file = fopen(oname,"wb");
Björn Stenberge1715c22002-03-28 14:34:13 +0000237 if ( !file ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000238 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000239 return -1;
240 }
Björn Stenberg323f2972002-12-19 15:00:40 +0000241 if ( !fwrite(header,headerlen,1,file) ) {
242 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000243 return -1;
244 }
245 if ( !fwrite(outbuf,length,1,file) ) {
Björn Stenberg323f2972002-12-19 15:00:40 +0000246 perror(oname);
Björn Stenberge1715c22002-03-28 14:34:13 +0000247 return -1;
248 }
249 fclose(file);
250
251 free(inbuf);
252 free(outbuf);
253
Linus Nielsen Feltzing6a429972003-04-14 09:59:47 +0000254 return 0;
Björn Stenberge1715c22002-03-28 14:34:13 +0000255}