diff options
Diffstat (limited to 'tools/scramble.c')
-rw-r--r-- | tools/scramble.c | 157 |
1 files changed, 6 insertions, 151 deletions
diff --git a/tools/scramble.c b/tools/scramble.c index 7aa468ebaa..3b9497186d 100644 --- a/tools/scramble.c +++ b/tools/scramble.c | |||
@@ -36,24 +36,6 @@ static int iaudio_encode(char *iname, char *oname, char *idstring); | |||
36 | static int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); | 36 | static int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); |
37 | static int ccpmp_encode(char *iname, char *oname); | 37 | static int ccpmp_encode(char *iname, char *oname); |
38 | 38 | ||
39 | enum | ||
40 | { | ||
41 | ARCHOS_PLAYER, /* and V1 recorder */ | ||
42 | ARCHOS_V2RECORDER, | ||
43 | ARCHOS_FMRECORDER, | ||
44 | ARCHOS_ONDIO_SP, | ||
45 | ARCHOS_ONDIO_FM | ||
46 | }; | ||
47 | |||
48 | static unsigned int size_limit[] = | ||
49 | { | ||
50 | 0x32000, /* ARCHOS_PLAYER */ | ||
51 | 0x64000, /* ARCHOS_V2RECORDER */ | ||
52 | 0x64000, /* ARCHOS_FMRECORDER */ | ||
53 | 0x64000, /* ARCHOS_ONDIO_SP */ | ||
54 | 0x64000 /* ARCHOS_ONDIO_FM */ | ||
55 | }; | ||
56 | |||
57 | void short2le(unsigned short val, unsigned char* addr) | 39 | void short2le(unsigned short val, unsigned char* addr) |
58 | { | 40 | { |
59 | addr[0] = val & 0xFF; | 41 | addr[0] = val & 0xFF; |
@@ -91,14 +73,9 @@ void short2be(unsigned short val, unsigned char* addr) | |||
91 | 73 | ||
92 | void usage(void) | 74 | void usage(void) |
93 | { | 75 | { |
94 | printf("usage: scramble [options] <input file> <output file> [xor string]\n"); | 76 | printf("usage: scramble [options] <input file> <output file>\n"); |
95 | printf("options:\n" | 77 | printf("options:\n" |
96 | "\t-fm Archos FM recorder format\n" | ||
97 | "\t-v2 Archos V2 recorder format\n" | ||
98 | "\t-ofm Archos Ondio FM recorder format\n" | ||
99 | "\t-osp Archos Ondio SP format\n" | ||
100 | "\t-neo SSI Neo format\n" | 78 | "\t-neo SSI Neo format\n" |
101 | "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n" | ||
102 | "\t-iriver iRiver format\n" | 79 | "\t-iriver iRiver format\n" |
103 | "\t-iaudiox5 iAudio X5 format\n" | 80 | "\t-iaudiox5 iAudio X5 format\n" |
104 | "\t-iaudiox5v iAudio X5V format\n" | 81 | "\t-iaudiox5v iAudio X5V format\n" |
@@ -131,87 +108,38 @@ void usage(void) | |||
131 | "\t ip6g, rk27, clzp, zxf2, zxf3, fuz+, e370, e360,\n" | 108 | "\t ip6g, rk27, clzp, zxf2, zxf3, fuz+, e370, e360,\n" |
132 | "\t zxfi, zmoz, zen, zenv, ypz5, zxfs, e450, e460,\n" | 109 | "\t zxfi, zmoz, zen, zenv, ypz5, zxfs, e450, e460,\n" |
133 | "\t e470, e580, a10, a20, a860, s750, e350, xdx3)\n"); | 110 | "\t e470, e580, a10, a20, a860, s750, e350, xdx3)\n"); |
134 | printf("\nNo option results in Archos standard player/recorder format.\n"); | 111 | printf("\nNo option results in nothing being done.\n"); |
135 | 112 | ||
136 | exit(1); | 113 | exit(1); |
137 | } | 114 | } |
138 | 115 | ||
139 | int main (int argc, char** argv) | 116 | int main (int argc, char** argv) |
140 | { | 117 | { |
141 | unsigned long length,i,slen=0; | 118 | unsigned long length,i; |
142 | unsigned char *inbuf,*outbuf; | 119 | unsigned char *inbuf,*outbuf; |
143 | unsigned short crc=0; | 120 | unsigned short crc=0; |
144 | unsigned long chksum=0; /* 32 bit checksum */ | 121 | unsigned long chksum=0; /* 32 bit checksum */ |
145 | unsigned char header[24]; | 122 | unsigned char header[24]; |
146 | char *iname = argv[1]; | 123 | char *iname = argv[1]; |
147 | char *oname = argv[2]; | 124 | char *oname = argv[2]; |
148 | char *xorstring=NULL; | ||
149 | int headerlen = 6; | 125 | int headerlen = 6; |
150 | FILE* file; | 126 | FILE* file; |
151 | int version=0; | 127 | int version=0; |
152 | unsigned long modelnum; | 128 | unsigned long modelnum; |
153 | char modelname[5]; | 129 | char modelname[5]; |
154 | int model_id; | 130 | enum { none, tcc_sum, tcc_crc, rkw, add } method = none; |
155 | enum { none, scramble, xor, tcc_sum, tcc_crc, rkw, add } method = scramble; | ||
156 | bool creative_enable_ciff; | 131 | bool creative_enable_ciff; |
157 | 132 | ||
158 | model_id = ARCHOS_PLAYER; | ||
159 | |||
160 | if (argc < 3) { | 133 | if (argc < 3) { |
161 | usage(); | 134 | usage(); |
162 | } | 135 | } |
163 | 136 | ||
164 | if(!strcmp(argv[1], "-fm")) { | ||
165 | headerlen = 24; | ||
166 | iname = argv[2]; | ||
167 | oname = argv[3]; | ||
168 | version = 4; | ||
169 | model_id = ARCHOS_FMRECORDER; | ||
170 | } | ||
171 | |||
172 | else if(!strcmp(argv[1], "-v2")) { | ||
173 | headerlen = 24; | ||
174 | iname = argv[2]; | ||
175 | oname = argv[3]; | ||
176 | version = 2; | ||
177 | model_id = ARCHOS_V2RECORDER; | ||
178 | } | ||
179 | |||
180 | else if(!strcmp(argv[1], "-ofm")) { | ||
181 | headerlen = 24; | ||
182 | iname = argv[2]; | ||
183 | oname = argv[3]; | ||
184 | version = 8; | ||
185 | model_id = ARCHOS_ONDIO_FM; | ||
186 | } | ||
187 | |||
188 | else if(!strcmp(argv[1], "-osp")) { | ||
189 | headerlen = 24; | ||
190 | iname = argv[2]; | ||
191 | oname = argv[3]; | ||
192 | version = 16; | ||
193 | model_id = ARCHOS_ONDIO_SP; | ||
194 | } | ||
195 | |||
196 | else if(!strcmp(argv[1], "-neo")) { | 137 | else if(!strcmp(argv[1], "-neo")) { |
197 | headerlen = 17; | 138 | headerlen = 17; |
198 | iname = argv[2]; | 139 | iname = argv[2]; |
199 | oname = argv[3]; | 140 | oname = argv[3]; |
200 | method = none; | 141 | method = none; |
201 | } | 142 | } |
202 | else if(!strncmp(argv[1], "-mm=", 4)) { | ||
203 | headerlen = 16; | ||
204 | iname = argv[2]; | ||
205 | oname = argv[3]; | ||
206 | method = xor; | ||
207 | version = argv[1][4]; | ||
208 | if (argc > 4) | ||
209 | xorstring = argv[4]; | ||
210 | else { | ||
211 | printf("Multimedia needs an xor string\n"); | ||
212 | return -1; | ||
213 | } | ||
214 | } | ||
215 | else if(!strncmp(argv[1], "-tcc=", 4)) { | 143 | else if(!strncmp(argv[1], "-tcc=", 4)) { |
216 | headerlen = 0; | 144 | headerlen = 0; |
217 | iname = argv[2]; | 145 | iname = argv[2]; |
@@ -554,20 +482,10 @@ int main (int argc, char** argv) | |||
554 | length = ftell(file); | 482 | length = ftell(file); |
555 | length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */ | 483 | length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */ |
556 | 484 | ||
557 | if ((method == scramble) && | ||
558 | ((length + headerlen) >= size_limit[model_id])) { | ||
559 | printf("error: firmware image is %ld bytes while max size is %u!\n", | ||
560 | length + headerlen, | ||
561 | size_limit[model_id]); | ||
562 | fclose(file); | ||
563 | return -1; | ||
564 | } | ||
565 | 485 | ||
566 | fseek(file,0,SEEK_SET); | 486 | fseek(file,0,SEEK_SET); |
567 | inbuf = malloc(length); | 487 | inbuf = malloc(length); |
568 | if (method == xor) | 488 | if(method == add) |
569 | outbuf = malloc(length*2); | ||
570 | else if(method == add) | ||
571 | outbuf = malloc(length + 8); | 489 | outbuf = malloc(length + 8); |
572 | else | 490 | else |
573 | outbuf = malloc(length); | 491 | outbuf = malloc(length); |
@@ -597,32 +515,13 @@ int main (int argc, char** argv) | |||
597 | chksum += inbuf[i]; | 515 | chksum += inbuf[i]; |
598 | } | 516 | } |
599 | break; | 517 | break; |
600 | case scramble: | ||
601 | slen = length/4; | ||
602 | for (i = 0; i < length; i++) { | ||
603 | unsigned long addr = (i >> 2) + ((i % 4) * slen); | ||
604 | unsigned char data = inbuf[i]; | ||
605 | data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */ | ||
606 | outbuf[addr] = data; | ||
607 | } | ||
608 | break; | ||
609 | |||
610 | case xor: | ||
611 | /* "compress" */ | ||
612 | slen = 0; | ||
613 | for (i=0; i<length; i++) { | ||
614 | if (!(i&7)) | ||
615 | outbuf[slen++] = 0xff; /* all data is uncompressed */ | ||
616 | outbuf[slen++] = inbuf[i]; | ||
617 | } | ||
618 | break; | ||
619 | case none: | 518 | case none: |
620 | default: | 519 | default: |
621 | /* dummy case just to silence picky compilers */ | 520 | /* dummy case just to silence picky compilers */ |
622 | break; | 521 | break; |
623 | } | 522 | } |
624 | 523 | ||
625 | if((method == none) || (method == scramble) || (method == xor)) { | 524 | if(method == none) { |
626 | /* calculate checksum */ | 525 | /* calculate checksum */ |
627 | for (i=0;i<length;i++) | 526 | for (i=0;i<length;i++) |
628 | crc += inbuf[i]; | 527 | crc += inbuf[i]; |
@@ -650,50 +549,6 @@ int main (int argc, char** argv) | |||
650 | telechips_encode_crc(outbuf, length); | 549 | telechips_encode_crc(outbuf, length); |
651 | break; | 550 | break; |
652 | 551 | ||
653 | case scramble: | ||
654 | if (headerlen == 6) { | ||
655 | int2be(length, header); | ||
656 | header[4] = (crc >> 8) & 0xff; | ||
657 | header[5] = crc & 0xff; | ||
658 | } | ||
659 | else { | ||
660 | header[0] = | ||
661 | header[1] = | ||
662 | header[2] = | ||
663 | header[3] = 0xff; /* ??? */ | ||
664 | |||
665 | header[6] = (crc >> 8) & 0xff; | ||
666 | header[7] = crc & 0xff; | ||
667 | |||
668 | header[11] = version; | ||
669 | |||
670 | header[15] = headerlen; /* really? */ | ||
671 | |||
672 | int2be(length, &header[20]); | ||
673 | } | ||
674 | break; | ||
675 | |||
676 | case xor: | ||
677 | { | ||
678 | int xorlen = strlen(xorstring); | ||
679 | |||
680 | /* xor data */ | ||
681 | for (i=0; i<slen; i++) | ||
682 | outbuf[i] ^= xorstring[i & (xorlen-1)]; | ||
683 | |||
684 | /* calculate checksum */ | ||
685 | for (i=0; i<slen; i++) | ||
686 | crc += outbuf[i]; | ||
687 | |||
688 | header[0] = header[2] = 'Z'; | ||
689 | header[1] = header[3] = version; | ||
690 | int2le(length, &header[4]); | ||
691 | int2le(slen, &header[8]); | ||
692 | int2le(crc, &header[12]); | ||
693 | length = slen; | ||
694 | break; | ||
695 | } | ||
696 | |||
697 | #define MY_FIRMWARE_TYPE "Rockbox" | 552 | #define MY_FIRMWARE_TYPE "Rockbox" |
698 | #define MY_HEADER_VERSION 1 | 553 | #define MY_HEADER_VERSION 1 |
699 | default: | 554 | default: |