diff options
| author | Björn Stenberg <bjorn@haxx.se> | 2004-01-08 00:22:27 +0000 |
|---|---|---|
| committer | Björn Stenberg <bjorn@haxx.se> | 2004-01-08 00:22:27 +0000 |
| commit | 7f749b4689dfb212580abbd568818e95a922fe49 (patch) | |
| tree | 63b816528108964514178e49d7e188c87094743a | |
| parent | a55bfd920468f26a8e97e4387c73d69375f58676 (diff) | |
| download | rockbox-7f749b4689dfb212580abbd568818e95a922fe49.zip rockbox-7f749b4689dfb212580abbd568818e95a922fe49.tar.gz rockbox-7f749b4689dfb212580abbd568818e95a922fe49.tar.bz2 rockbox-7f749b4689dfb212580abbd568818e95a922fe49.tar.xz | |
Added support for multimedia .ajz files
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4199 a1c6a512-1295-4272-9138-f99709370657
| -rw-r--r-- | tools/descramble.c | 105 |
1 files changed, 95 insertions, 10 deletions
diff --git a/tools/descramble.c b/tools/descramble.c index d28e18a..8ba8d4a 100644 --- a/tools/descramble.c +++ b/tools/descramble.c @@ -26,11 +26,14 @@ int main (int argc, char** argv) unsigned char *inbuf,*outbuf; unsigned char *iname = argv[1]; unsigned char *oname = argv[2]; + unsigned char header[32]; int headerlen = 6; + int descramble = 1; FILE* file; if (argc < 3) { - printf("usage: %s [-fm] [-v2] <input file> <output file>\n",argv[0]); + printf("usage: %s [-fm] [-v2] [-mm] <input file> <output file>\n", + argv[0]); return -1; } @@ -39,6 +42,13 @@ int main (int argc, char** argv) iname = argv[2]; oname = argv[3]; } + + if (!strcmp(argv[1], "-mm")) { + headerlen = 16; + iname = argv[2]; + oname = argv[3]; + descramble = 0; + } /* open file and check size */ file = fopen(iname,"rb"); @@ -48,7 +58,13 @@ int main (int argc, char** argv) } fseek(file,0,SEEK_END); length = ftell(file) - headerlen; /* skip header */ - fseek(file,headerlen,SEEK_SET); + fseek(file,0,SEEK_SET); + i = fread(header, 1, headerlen, file); + if ( !i ) { + perror(iname); + return -1; + } + inbuf = malloc(length); outbuf = malloc(length); if ( !inbuf || !outbuf ) { @@ -64,15 +80,84 @@ int main (int argc, char** argv) } fclose(file); - /* descramble */ - slen = length/4; - for (i = 0; i < length; i++) { - unsigned long addr = ((i % slen) << 2) + i/slen; - unsigned char data = inbuf[i]; - data = ~((data >> 1) | ((data << 7) & 0x80)); /* poor man's ROR */ - outbuf[addr] = data; + if (descramble) { + /* descramble */ + slen = length/4; + for (i = 0; i < length; i++) { + unsigned long addr = ((i % slen) << 2) + i/slen; + unsigned char data = inbuf[i]; + data = ~((data >> 1) | ((data << 7) & 0x80)); /* poor man's ROR */ + outbuf[addr] = data; + } } - + else { + void* tmpptr; + unsigned int j=0; + int stringlen = 32; + int unpackedsize; + unsigned char xorstring[32]; + + unpackedsize = ((unsigned int*)header)[1]; + length = ((unsigned int*)header)[2]; + + /* calculate the xor string used */ + for (i=0; i<stringlen; i++) { + int top=0, topchar=0, c; + int bytecount[256]; + memset(bytecount, 0, sizeof(bytecount)); + + /* gather byte frequency statistics */ + for (c=i; c<length; c+=stringlen) + bytecount[inbuf[c]]++; + + /* find the most frequent byte */ + for (c=0; c<256; c++) { + if (bytecount[c] > top) { + top = bytecount[c]; + topchar = c; + } + } + xorstring[i] = topchar; + } + printf("XOR string: %.*s\n", stringlen, xorstring); + + /* xor the buffer */ + for (i=0; i<length; i++) + outbuf[i] = inbuf[i] ^ xorstring[i & (stringlen-1)]; + + /* unpack */ + tmpptr = realloc(inbuf, unpackedsize); + memset(tmpptr, 0, unpackedsize); + inbuf = outbuf; + outbuf = tmpptr; + + for (i=0; i<length;) { + int bit; + int head = inbuf[i++]; + + for (bit=0; bit<8 && i<length; bit++) { + if (head & (1 << (bit))) { + outbuf[j++] = inbuf[i++]; + } + else { + int x; + int byte1 = inbuf[i]; + int byte2 = inbuf[i+1]; + int count = (byte2 & 0x0f) + 3; + int src = + (j & 0xfffff000) + (byte1 | ((byte2 & 0xf0)<<4)) + 18; + if (src > j) + src -= 0x1000; + + for (x=0; x<count; x++) + outbuf[j++] = outbuf[src+x]; + i += 2; + } + } + } + length = j; + } + /* write file */ file = fopen(oname,"wb"); if ( !file ) { |