11 * The Cochran file format is designed to be annoying to read. It's roughly:
13 * 0x00000: room for 65534 4-byte words, giving the starting offsets
14 * of the dives themselves.
16 * 0x3fff8: the size of the file + 1
17 * 0x3ffff: 0 (high 32 bits of filesize? Bogus: the offsets into the file
18 * are 32-bit, so it can't be a large file anyway)
20 * 0x40000: "block 0": the decoding block. The first byte is some random
21 * value (0x46 in the files I have access to), the next 200+ bytes or so
22 * are the "scrambling array" that needs to be added into the file
23 * contents to make sense of them.
25 * The descrambling array seems to be of some random size which is likely
26 * determinable from the array somehow, the two test files I have it as
27 * 230 bytes and 234 bytes respectively.
29 static unsigned int partial_decode(unsigned int start, unsigned int end,
30 const unsigned char *decode, unsigned offset, unsigned mod,
31 const unsigned char *buf, unsigned int size, unsigned char *dst)
35 for (i = start ; i < end; i++) {
36 unsigned char d = decode[offset++];
50 * The decode buffer size can be figured out by simply trying our the
51 * decode: we expect that the scrambled contents are largely random, and
52 * thus tend to have half the bits set. Summing over the bytes is going
53 * to give an average of 0x80 per byte.
55 * The decoded array is mostly full of zeroes, so the sum is lower.
59 static int figure_out_modulus(const unsigned char *decode, const unsigned char *dive, unsigned int size)
62 unsigned int min = ~0u;
67 for (mod = 50; mod < 300; mod++) {
70 sum = partial_decode(0, 0x0fff, decode, 1, mod, dive, size, NULL);
79 static void cochran_debug_write(int dive, const unsigned char *data, unsigned size)
84 snprintf(buffer, sizeof(buffer), "cochran.%d.out", dive);
85 fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0666);
87 write(fd, data, size);
92 static void parse_cochran_dive(int dive, const unsigned char *decode, unsigned mod,
93 const unsigned char *in, unsigned size)
95 char *buf = malloc(size);
98 * The scrambling has odd boundaries. I think the boundaries
99 * match some data structure size, but I don't know. They were
100 * discovered the same way we dynamically discover the decode
101 * size: automatically looking for least random output.
103 * The boundaries are also this confused "off-by-one" thing,
104 * the same way the file size is off by one. It's as if the
105 * cochran software forgot to write one byte at the beginning.
107 partial_decode(0 , 0x0fff, decode, 1, mod, in, size, buf);
108 partial_decode(0x0fff, 0x1fff, decode, 0, mod, in, size, buf);
109 partial_decode(0x1fff, 0x2fff, decode, 0, mod, in, size, buf);
110 partial_decode(0x2fff, 0x48ff, decode, 0, mod, in, size, buf);
113 * This is not all the descrambling you need - the above are just
114 * what appears to be the fixed-size blocks. The rest is also
115 * scrambled, but there seems to be size differences in the data,
116 * so this just descrambles part of it:
118 partial_decode(0x48ff, size, decode, 0, mod, in, size, buf);
120 cochran_debug_write(dive, buf, size);
125 int try_to_open_cochran(const char *filename, struct memblock *mem, GError **error)
129 unsigned int *offsets, dive1, dive2;
130 unsigned char *decode = mem->buffer + 0x40001;
132 if (mem->size < 0x40000)
134 offsets = mem->buffer;
137 if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
140 mod = figure_out_modulus(decode, mem->buffer + dive1, dive2 - dive1);
142 for (i = 0; i < 65534; i++) {
144 dive2 = offsets[i+1];
147 if (dive2 > mem->size)
149 parse_cochran_dive(i, decode, mod, mem->buffer + dive1, dive2 - dive1);