FS#8916 - updated chinese translations by harry tu
[Rockbox.git] / tools / scramble.c
bloba17b16efaa03605805bfcc82f681685a6226c717
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 - 2007 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 <stdbool.h>
23 #include <string.h>
24 #include "iriver.h"
25 #include "gigabeat.h"
26 #include "gigabeats.h"
27 #include "mi4.h"
28 #include "telechips.h"
29 #include "creative.h"
30 #include "iaudio_bl_flash.h"
32 int iaudio_encode(char *iname, char *oname, char *idstring);
33 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc);
35 enum
37 ARCHOS_PLAYER, /* and V1 recorder */
38 ARCHOS_V2RECORDER,
39 ARCHOS_FMRECORDER,
40 ARCHOS_ONDIO_SP,
41 ARCHOS_ONDIO_FM
44 static unsigned int size_limit[] =
46 0x32000, /* ARCHOS_PLAYER */
47 0x64000, /* ARCHOS_V2RECORDER */
48 0x64000, /* ARCHOS_FMRECORDER */
49 0x64000, /* ARCHOS_ONDIO_SP */
50 0x64000 /* ARCHOS_ONDIO_FM */
53 void short2le(unsigned short val, unsigned char* addr)
55 addr[0] = val & 0xFF;
56 addr[1] = (val >> 8) & 0xff;
59 unsigned int le2int(unsigned char* buf)
61 unsigned int res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
63 return res;
66 void int2le(unsigned int val, unsigned char* addr)
68 addr[0] = val & 0xFF;
69 addr[1] = (val >> 8) & 0xff;
70 addr[2] = (val >> 16) & 0xff;
71 addr[3] = (val >> 24) & 0xff;
74 void int2be(unsigned int val, unsigned char* addr)
76 addr[0] = (val >> 24) & 0xff;
77 addr[1] = (val >> 16) & 0xff;
78 addr[2] = (val >> 8) & 0xff;
79 addr[3] = val & 0xFF;
82 void short2be(unsigned short val, unsigned char* addr)
84 addr[0] = (val >> 8) & 0xff;
85 addr[1] = val & 0xFF;
88 void usage(void)
90 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
91 printf("options:\n"
92 "\t-fm Archos FM recorder format\n"
93 "\t-v2 Archos V2 recorder format\n"
94 "\t-ofm Archos Ondio FM recorder format\n"
95 "\t-osp Archos Ondio SP format\n"
96 "\t-neo SSI Neo format\n"
97 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
98 "\t-iriver iRiver format\n"
99 "\t-iaudiox5 iAudio X5 format\n"
100 "\t-iaudiox5v iAudio X5V format\n"
101 "\t-iaudiom5 iAudio M5 format\n"
102 "\t-iaudiom3 iAudio M3 format\n");
103 printf("\t-ipod3g ipod firmware partition format (3rd Gen)\n"
104 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
105 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
106 "\t-creative=X Creative firmware structure format\n"
107 "\t-gigabeat Toshiba Gigabeat F/X format\n"
108 "\t-gigabeats Toshiba Gigabeat S format\n"
109 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
110 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
111 "\t-mi4r Sandisk Rhapsody .mi4 format\n"
112 "\t All mi4 options take two optional arguments:\n");
113 printf("\t -model=XXXX where XXXX is the model id string\n"
114 "\t -type=XXXX where XXXX is a string indicating the \n"
115 "\t type of binary, eg. RBOS, RBBL\n"
116 "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n"
117 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
118 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n"
119 "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"
120 "\t tpj2, c200, e200, giga, gigs, m100, m500, d2, zvm)\n");
121 printf("\nNo option results in Archos standard player/recorder format.\n");
123 exit(1);
126 int main (int argc, char** argv)
128 unsigned long length,i,slen=0;
129 unsigned char *inbuf,*outbuf;
130 unsigned short crc=0;
131 unsigned long chksum=0; /* 32 bit checksum */
132 unsigned char header[24];
133 char *iname = argv[1];
134 char *oname = argv[2];
135 char *xorstring=NULL;
136 int headerlen = 6;
137 FILE* file;
138 int version=0;
139 unsigned long modelnum;
140 char modelname[5];
141 int model_id;
142 enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble;
144 model_id = ARCHOS_PLAYER;
146 if (argc < 3) {
147 usage();
150 if(!strcmp(argv[1], "-fm")) {
151 headerlen = 24;
152 iname = argv[2];
153 oname = argv[3];
154 version = 4;
155 model_id = ARCHOS_FMRECORDER;
158 else if(!strcmp(argv[1], "-v2")) {
159 headerlen = 24;
160 iname = argv[2];
161 oname = argv[3];
162 version = 2;
163 model_id = ARCHOS_V2RECORDER;
166 else if(!strcmp(argv[1], "-ofm")) {
167 headerlen = 24;
168 iname = argv[2];
169 oname = argv[3];
170 version = 8;
171 model_id = ARCHOS_ONDIO_FM;
174 else if(!strcmp(argv[1], "-osp")) {
175 headerlen = 24;
176 iname = argv[2];
177 oname = argv[3];
178 version = 16;
179 model_id = ARCHOS_ONDIO_SP;
182 else if(!strcmp(argv[1], "-neo")) {
183 headerlen = 17;
184 iname = argv[2];
185 oname = argv[3];
186 method = none;
188 else if(!strncmp(argv[1], "-mm=", 4)) {
189 headerlen = 16;
190 iname = argv[2];
191 oname = argv[3];
192 method = xor;
193 version = argv[1][4];
194 if (argc > 4)
195 xorstring = argv[4];
196 else {
197 printf("Multimedia needs an xor string\n");
198 return -1;
201 else if(!strncmp(argv[1], "-tcc=", 4)) {
202 headerlen = 0;
203 iname = argv[2];
204 oname = argv[3];
206 if(!strcmp(&argv[1][5], "sum"))
207 method = tcc_sum;
208 else if(!strcmp(&argv[1][5], "crc"))
209 method = tcc_crc;
210 else {
211 fprintf(stderr, "unsupported TCC method: %s\n", &argv[1][5]);
212 return 2;
215 else if(!strncmp(argv[1], "-add=", 5)) {
216 iname = argv[2];
217 oname = argv[3];
218 method = add;
220 if(!strcmp(&argv[1][5], "h120"))
221 modelnum = 0;
222 else if(!strcmp(&argv[1][5], "h140"))
223 modelnum = 0; /* the same as the h120 */
224 else if(!strcmp(&argv[1][5], "h100"))
225 modelnum = 1;
226 else if(!strcmp(&argv[1][5], "h300"))
227 modelnum = 2;
228 else if(!strcmp(&argv[1][5], "ipco"))
229 modelnum = 3;
230 else if(!strcmp(&argv[1][5], "nano"))
231 modelnum = 4;
232 else if(!strcmp(&argv[1][5], "ipvd"))
233 modelnum = 5;
234 else if(!strcmp(&argv[1][5], "fp7x"))
235 modelnum = 6;
236 else if(!strcmp(&argv[1][5], "ip3g"))
237 modelnum = 7;
238 else if(!strcmp(&argv[1][5], "ip4g"))
239 modelnum = 8;
240 else if(!strcmp(&argv[1][5], "mini"))
241 modelnum = 9;
242 else if(!strcmp(&argv[1][5], "iax5"))
243 modelnum = 10;
244 else if(!strcmp(&argv[1][5], "mn2g"))
245 modelnum = 11;
246 else if(!strcmp(&argv[1][5], "h10"))
247 modelnum = 13;
248 else if(!strcmp(&argv[1][5], "h10_5gb"))
249 modelnum = 14;
250 else if(!strcmp(&argv[1][5], "tpj2"))
251 modelnum = 15;
252 else if(!strcmp(&argv[1][5], "e200"))
253 modelnum = 16;
254 else if(!strcmp(&argv[1][5], "iam5"))
255 modelnum = 17;
256 else if(!strcmp(&argv[1][5], "giga"))
257 modelnum = 18;
258 else if(!strcmp(&argv[1][5], "1g2g"))
259 modelnum = 19;
260 else if(!strcmp(&argv[1][5], "c200"))
261 modelnum = 20;
262 else if(!strcmp(&argv[1][5], "gigs"))
263 modelnum = 21;
264 else if(!strcmp(&argv[1][5], "m500"))
265 modelnum = 22;
266 else if(!strcmp(&argv[1][5], "m100"))
267 modelnum = 23;
268 else if(!strcmp(&argv[1][5], "d2"))
269 modelnum = 24;
270 else if(!strcmp(&argv[1][5], "iam3"))
271 modelnum = 25;
272 else if(!strcmp(&argv[1][5], "zvm"))
273 modelnum = 26;
274 else {
275 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
276 return 2;
278 /* we store a 4-letter model name too, for humans */
279 strcpy(modelname, &argv[1][5]);
280 chksum = modelnum; /* start checksum calcs with this */
283 else if(!strcmp(argv[1], "-iriver")) {
284 /* iRiver code dealt with in the iriver.c code */
285 iname = argv[2];
286 oname = argv[3];
287 iriver_encode(iname, oname, FALSE);
288 return 0;
290 else if(!strcmp(argv[1], "-gigabeat")) {
291 /* iRiver code dealt with in the iriver.c code */
292 iname = argv[2];
293 oname = argv[3];
294 gigabeat_code(iname, oname);
295 return 0;
297 else if(!strcmp(argv[1], "-gigabeats")) {
298 iname = argv[2];
299 oname = argv[3];
300 gigabeat_s_code(iname, oname);
301 return 0;
303 else if(!strcmp(argv[1], "-iaudiox5")) {
304 iname = argv[2];
305 oname = argv[3];
306 return iaudio_encode(iname, oname, "COWON_X5_FW");
308 else if(!strcmp(argv[1], "-iaudiox5v")) {
309 iname = argv[2];
310 oname = argv[3];
311 return iaudio_encode(iname, oname, "COWON_X5V_FW");
313 else if(!strcmp(argv[1], "-iaudiom5")) {
314 iname = argv[2];
315 oname = argv[3];
316 return iaudio_encode(iname, oname, "COWON_M5_FW");
318 else if(!strcmp(argv[1], "-iaudiom3")) {
319 iname = argv[2];
320 oname = argv[3];
321 return iaudio_encode(iname, oname, "COWON_M3_FW");
323 else if(!strcmp(argv[1], "-ipod3g")) {
324 iname = argv[2];
325 oname = argv[3];
326 return ipod_encode(iname, oname, 2, false); /* Firmware image v2 */
328 else if(!strcmp(argv[1], "-ipod4g")) {
329 iname = argv[2];
330 oname = argv[3];
331 return ipod_encode(iname, oname, 3, false); /* Firmware image v3 */
333 else if(!strcmp(argv[1], "-ipod5g")) {
334 iname = argv[2];
335 oname = argv[3];
336 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
338 else if(!strncmp(argv[1], "-creative=", 10)) {
339 iname = argv[2];
340 oname = argv[3];
341 if(!strcmp(&argv[1][10], "zvm"))
342 return zvm_encode(iname, oname, ZENVISIONM);
343 else if(!strcmp(&argv[1][10], "zvm60"))
344 return zvm_encode(iname, oname, ZENVISIONM60);
345 else if(!strcmp(&argv[1][10], "zenvision"))
346 return zvm_encode(iname, oname, ZENVISION);
347 else if(!strcmp(&argv[1][10], "zenv"))
348 return zvm_encode(iname, oname, ZENV);
349 else if(!strcmp(&argv[1][10], "zen"))
350 return zvm_encode(iname, oname, ZEN);
351 else {
352 fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
353 return 2;
356 else if(!strncmp(argv[1], "-mi4", 4)) {
357 int mi4magic;
358 char model[4] = "";
359 char type[4] = "";
361 if(!strcmp(&argv[1][4], "v2")) {
362 mi4magic = MI4_MAGIC_DEFAULT;
363 version = 0x00010201;
365 else if(!strcmp(&argv[1][4], "v3")) {
366 mi4magic = MI4_MAGIC_DEFAULT;
367 version = 0x00010301;
369 else if(!strcmp(&argv[1][4], "r")) {
370 mi4magic = MI4_MAGIC_R;
371 version = 0x00010301;
373 else {
374 printf( "Invalid mi4 version: %s\n", &argv[1][4]);
375 return -1;
378 iname = argv[2];
379 oname = argv[3];
381 if(!strncmp(argv[2], "-model=", 7)) {
382 iname = argv[3];
383 oname = argv[4];
384 strncpy(model, &argv[2][7], 4);
386 if(!strncmp(argv[3], "-type=", 6)) {
387 iname = argv[4];
388 oname = argv[5];
389 strncpy(type, &argv[3][6], 4);
393 return mi4_encode(iname, oname, version, mi4magic, model, type);
396 /* open file */
397 file = fopen(iname,"rb");
398 if (!file) {
399 perror(iname);
400 return -1;
402 fseek(file,0,SEEK_END);
403 length = ftell(file);
404 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
406 if ((method == scramble) &&
407 ((length + headerlen) >= size_limit[model_id])) {
408 printf("error: firmware image is %ld bytes while max size is %u!\n",
409 length + headerlen,
410 size_limit[model_id]);
411 fclose(file);
412 return -1;
415 fseek(file,0,SEEK_SET);
416 inbuf = malloc(length);
417 if (method == xor)
418 outbuf = malloc(length*2);
419 else if(method == add)
420 outbuf = malloc(length + 8);
421 else
422 outbuf = malloc(length);
423 if ( !inbuf || !outbuf ) {
424 printf("out of memory!\n");
425 return -1;
427 if(length> 4) {
428 /* zero-fill the last 4 bytes to make sure there's no rubbish there
429 when we write the size-aligned file later */
430 memset(outbuf+length-4, 0, 4);
433 /* read file */
434 i=fread(inbuf,1,length,file);
435 if ( !i ) {
436 perror(iname);
437 return -1;
439 fclose(file);
441 switch (method)
443 case add:
444 for (i = 0; i < length; i++) {
445 /* add 8 unsigned bits but keep a 32 bit sum */
446 chksum += inbuf[i];
448 break;
449 case scramble:
450 slen = length/4;
451 for (i = 0; i < length; i++) {
452 unsigned long addr = (i >> 2) + ((i % 4) * slen);
453 unsigned char data = inbuf[i];
454 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
455 outbuf[addr] = data;
457 break;
459 case xor:
460 /* "compress" */
461 slen = 0;
462 for (i=0; i<length; i++) {
463 if (!(i&7))
464 outbuf[slen++] = 0xff; /* all data is uncompressed */
465 outbuf[slen++] = inbuf[i];
467 break;
468 case none:
469 default:
470 /* dummy case just to silence picky compilers */
471 break;
474 if((method == none) || (method == scramble) || (method == xor)) {
475 /* calculate checksum */
476 for (i=0;i<length;i++)
477 crc += inbuf[i];
480 memset(header, 0, sizeof header);
481 switch (method)
483 case add:
485 int2be(chksum, header); /* checksum, big-endian */
486 memcpy(&header[4], modelname, 4); /* 4 bytes model name */
487 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
488 headerlen = 8;
490 break;
492 case tcc_sum:
493 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
494 telechips_encode_sum(outbuf, length);
495 break;
497 case tcc_crc:
498 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
499 telechips_encode_crc(outbuf, length);
500 break;
502 case scramble:
503 if (headerlen == 6) {
504 int2be(length, header);
505 header[4] = (crc >> 8) & 0xff;
506 header[5] = crc & 0xff;
508 else {
509 header[0] =
510 header[1] =
511 header[2] =
512 header[3] = 0xff; /* ??? */
514 header[6] = (crc >> 8) & 0xff;
515 header[7] = crc & 0xff;
517 header[11] = version;
519 header[15] = headerlen; /* really? */
521 int2be(length, &header[20]);
523 break;
525 case xor:
527 int xorlen = strlen(xorstring);
529 /* xor data */
530 for (i=0; i<slen; i++)
531 outbuf[i] ^= xorstring[i & (xorlen-1)];
533 /* calculate checksum */
534 for (i=0; i<slen; i++)
535 crc += outbuf[i];
537 header[0] = header[2] = 'Z';
538 header[1] = header[3] = version;
539 int2le(length, &header[4]);
540 int2le(slen, &header[8]);
541 int2le(crc, &header[12]);
542 length = slen;
543 break;
546 #define MY_FIRMWARE_TYPE "Rockbox"
547 #define MY_HEADER_VERSION 1
548 default:
549 strncpy((char *)header, MY_FIRMWARE_TYPE,9);
550 header[9]='\0'; /*shouldn't have to, but to be SURE */
551 header[10]=MY_HEADER_VERSION&0xFF;
552 header[11]=(crc>>8)&0xFF;
553 header[12]=crc&0xFF;
554 int2be(sizeof(header), &header[12]);
555 break;
558 /* write file */
559 file = fopen(oname,"wb");
560 if ( !file ) {
561 perror(oname);
562 return -1;
564 if (headerlen > 0) {
565 if ( !fwrite(header,headerlen,1,file) ) {
566 perror(oname);
567 return -1;
570 if ( !fwrite(outbuf,length,1,file) ) {
571 perror(oname);
572 return -1;
574 fclose(file);
576 free(inbuf);
577 free(outbuf);
579 return 0;
582 int iaudio_encode(char *iname, char *oname, char *idstring)
584 size_t len;
585 int length;
586 FILE *file;
587 unsigned char *outbuf;
588 int i;
589 unsigned char sum = 0;
591 file = fopen(iname, "rb");
592 if (!file) {
593 perror(iname);
594 return -1;
596 fseek(file,0,SEEK_END);
597 length = ftell(file);
599 fseek(file,0,SEEK_SET);
600 outbuf = malloc(length+0x1030);
602 if ( !outbuf ) {
603 printf("out of memory!\n");
604 return -1;
607 len = fread(outbuf+0x1030, 1, length, file);
608 if(len < (size_t) length) {
609 perror(iname);
610 return -2;
613 memset(outbuf, 0, 0x1030);
614 strcpy((char *)outbuf, idstring);
615 memcpy(outbuf+0x20, iaudio_bl_flash,
616 BMPWIDTH_iaudio_bl_flash * (BMPHEIGHT_iaudio_bl_flash/8) * 2);
617 short2be(BMPWIDTH_iaudio_bl_flash, &outbuf[0x10]);
618 short2be((BMPHEIGHT_iaudio_bl_flash/8), &outbuf[0x12]);
619 outbuf[0x19] = 2;
621 for(i = 0; i < length;i++)
622 sum += outbuf[0x1030 + i];
624 int2be(length, &outbuf[0x1024]);
625 outbuf[0x102b] = sum;
627 fclose(file);
629 file = fopen(oname, "wb");
630 if (!file) {
631 perror(oname);
632 return -3;
635 len = fwrite(outbuf, 1, length+0x1030, file);
636 if(len < (size_t)length) {
637 perror(oname);
638 return -4;
641 fclose(file);
642 return 0;
646 /* Create an ipod firmware partition image
648 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
650 This function doesn't yet handle the Broadcom resource image for the 5g,
651 so the resulting images won't be usable.
653 This has also only been tested on an ipod Photo
656 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
658 static const char *apple_stop_sign = "{{~~ /-----\\ "\
659 "{{~~ / \\ "\
660 "{{~~| | "\
661 "{{~~| S T O P | "\
662 "{{~~| | "\
663 "{{~~ \\ / "\
664 "{{~~ \\-----/ "\
665 "Copyright(C) 200"\
666 "1 Apple Computer"\
667 ", Inc.----------"\
668 "----------------"\
669 "----------------"\
670 "----------------"\
671 "----------------"\
672 "----------------"\
673 "---------------";
674 size_t len;
675 int length;
676 int rsrclength;
677 int rsrcoffset;
678 FILE *file;
679 unsigned int sum = 0;
680 unsigned int rsrcsum = 0;
681 unsigned char *outbuf;
682 int bufsize;
683 int i;
685 file = fopen(iname, "rb");
686 if (!file) {
687 perror(iname);
688 return -1;
690 fseek(file,0,SEEK_END);
691 length = ftell(file);
693 fseek(file,0,SEEK_SET);
695 bufsize=(length+0x4600);
696 if (fake_rsrc) {
697 bufsize = (bufsize + 0x400) & ~0x200;
700 outbuf = malloc(bufsize);
702 if ( !outbuf ) {
703 printf("out of memory!\n");
704 return -1;
707 len = fread(outbuf+0x4600, 1, length, file);
708 if(len < (size_t)length) {
709 perror(iname);
710 return -2;
712 fclose(file);
714 /* Calculate checksum for later use in header */
715 for(i = 0x4600; i < 0x4600+length;i++)
716 sum += outbuf[i];
718 /* Clear the header area to zero */
719 memset(outbuf, 0, 0x4600);
721 /* APPLE STOP SIGN */
722 strcpy((char *)outbuf, apple_stop_sign);
724 /* VOLUME HEADER */
725 memcpy(&outbuf[0x100],"]ih[",4); /* Magic */
726 int2le(0x4000, &outbuf[0x104]); /* Firmware offset relative to 0x200 */
727 short2le(0x10c, &outbuf[0x108]); /* Location of extended header */
728 short2le(fw_ver, &outbuf[0x10a]);
730 /* Firmware Directory - "osos" entry */
731 memcpy(&outbuf[0x4200],"!ATAsoso",8); /* dev and type */
732 int2le(0, &outbuf[0x4208]); /* id */
733 int2le(0x4400, &outbuf[0x420c]); /* devOffset */
734 int2le(length, &outbuf[0x4210]); /* Length of firmware */
735 int2le(0x10000000, &outbuf[0x4214]); /* Addr */
736 int2le(0, &outbuf[0x4218]); /* Entry Offset */
737 int2le(sum, &outbuf[0x421c]); /* Checksum */
738 int2le(0x00006012, &outbuf[0x4220]); /* vers - 0x6012 is a guess */
739 int2le(0xffffffff, &outbuf[0x4224]); /* LoadAddr - for flash images */
741 /* "rsrc" entry (if applicable) */
742 if (fake_rsrc) {
743 rsrcoffset=(length+0x4600+0x200) & ~0x200;
744 rsrclength=0x200;
745 rsrcsum=0;
747 memcpy(&outbuf[0x4228],"!ATAcrsr",8); /* dev and type */
748 int2le(0, &outbuf[0x4230]); /* id */
749 int2le(rsrcoffset, &outbuf[0x4234]); /* devOffset */
750 int2le(rsrclength, &outbuf[0x4238]); /* Length of firmware */
751 int2le(0x10000000, &outbuf[0x423c]); /* Addr */
752 int2le(0, &outbuf[0x4240]); /* Entry Offset */
753 int2le(rsrcsum, &outbuf[0x4244]); /* Checksum */
754 int2le(0x0000b000, &outbuf[0x4248]); /* vers */
755 int2le(0xffffffff, &outbuf[0x424c]); /* LoadAddr - for flash images */
758 file = fopen(oname, "wb");
759 if (!file) {
760 perror(oname);
761 return -3;
764 len = fwrite(outbuf, 1, length+0x4600, file);
765 if(len < (size_t)length) {
766 perror(oname);
767 return -4;
770 fclose(file);
772 return 0;