14 * The Cochran file format is designed to be annoying to read. It's roughly:
16 * 0x00000: room for 65534 4-byte words, giving the starting offsets
17 * of the dives themselves.
19 * 0x3fff8: the size of the file + 1
20 * 0x3ffff: 0 (high 32 bits of filesize? Bogus: the offsets into the file
21 * are 32-bit, so it can't be a large file anyway)
23 * 0x40000: "block 0": the decoding block. The first byte is some random
24 * value (0x46 in the files I have access to), the next 200+ bytes or so
25 * are the "scrambling array" that needs to be added into the file
26 * contents to make sense of them.
28 * The descrambling array seems to be of some random size which is likely
29 * determinable from the array somehow, the two test files I have it as
30 * 230 bytes and 234 bytes respectively.
32 static unsigned int partial_decode(unsigned int start, unsigned int end,
33 const unsigned char *decode, unsigned offset, unsigned mod,
34 const unsigned char *buf, unsigned int size, unsigned char *dst)
38 for (i = start ; i < end; i++) {
39 unsigned char d = decode[offset++];
53 * The decode buffer size can be figured out by simply trying our the
54 * decode: we expect that the scrambled contents are largely random, and
55 * thus tend to have half the bits set. Summing over the bytes is going
56 * to give an average of 0x80 per byte.
58 * The decoded array is mostly full of zeroes, so the sum is lower.
62 static int figure_out_modulus(const unsigned char *decode, const unsigned char *dive, unsigned int size)
65 unsigned int min = ~0u;
70 for (mod = 50; mod < 300; mod++) {
73 sum = partial_decode(0, 0x0fff, decode, 1, mod, dive, size, NULL);
82 #define hexchar(n) ("0123456789abcdef"[(n)&15])
84 static int show_line(unsigned offset, const unsigned char *data, unsigned size, int show_empty)
94 memset(buffer, ' ', sizeof(buffer));
95 off = sprintf(buffer, "%06x ", offset);
96 for (i = 0; i < size; i++) {
97 char *hex = buffer + off + 3*i;
98 char *asc = buffer + off + 50 + i;
99 unsigned char byte = data[i];
101 hex[0] = hexchar(byte>>4);
102 hex[1] = hexchar(byte);
104 if (byte < 32 || byte > 126)
119 static void cochran_debug_write(const char *filename, const unsigned char *data, unsigned size)
123 for (i = 0; i < size; i += 16)
124 show = show_line(i, data + i, size - i, show);
127 static void parse_cochran_header(const char *filename,
128 const unsigned char *decode, unsigned mod,
129 const unsigned char *in, unsigned size)
131 char *buf = malloc(size);
133 /* Do the "null decode" using a one-byte decode array of '\0' */
134 partial_decode(0 , 0x0b14, "", 0, 1, in, size, buf);
137 * The header scrambling is different form the dive
138 * scrambling. Oh yay!
140 partial_decode(0x010e, 0x0b14, decode, 0, mod, in, size, buf);
141 partial_decode(0x0b14, 0x1b14, decode, 0, mod, in, size, buf);
142 partial_decode(0x1b14, 0x2b14, decode, 0, mod, in, size, buf);
143 partial_decode(0x2b14, 0x3b14, decode, 0, mod, in, size, buf);
144 partial_decode(0x3b14, 0x5414, decode, 0, mod, in, size, buf);
145 partial_decode(0x5414, size, decode, 0, mod, in, size, buf);
147 printf("\n%s, header\n\n", filename);
148 cochran_debug_write(filename, buf, size);
154 * Cochran export files show that depths seem to be in
155 * quarter feet (rounded up to tenths).
157 * Temperature seems to be exported in Fahrenheit.
159 * Cylinder pressure seems to be in multiples of 4 psi.
161 * The data seems to be some byte-stream where the pattern
162 * appears to be that the two high bits indicate type of
165 * For '00', the low six bits seem to be positive
166 * values with a distribution towards zero, probably depth
167 * deltas. '0 0' exists, but is very rare ("surface"?). 63
168 * exists, but is rare.
170 * For '01', the low six bits seem to be a signed binary value,
171 * with the most common being 0, and 1 and -1 (63) being the
172 * next most common values.
174 * NOTE! Don's CAN data is different. It shows the reverse pattern
175 * for 00 and 01 above: 00 looks like signed data, with 01 looking
176 * like unsigned data.
178 * For '10', there seems to be another positive value distribution,
179 * but unlike '00' the value 0 is common, and I see examples of 63
180 * too ("overflow"?) and a spike at '7'.
182 * Again, Don's data is different.
184 * The values for '11' seem to be some exception case. Possibly
185 * overflow handling, possibly warning events. It doesn't have
186 * any clear distribution: values 0, 1, 16, 33, 35, 48, 51, 55
189 * For David and Don's data, '01' is the most common, with '00'
190 * and '10' not uncommon. '11' is two orders of magnitude less
193 * For Alex, '00' is the most common, with 01 about a third as
194 * common, and 02 a third of that. 11 is least common.
196 * There clearly are variations in the format here. And Alex has
197 * a different data offset than Don/David too (see the #ifdef DON).
198 * Christ. Maybe I've misread the patterns entirely.
200 static void cochran_profile_write(const unsigned char *buf, int size)
204 for (i = 0; i < size; i++) {
205 unsigned char c = buf[i];
211 static void parse_cochran_dive(const char *filename, int dive,
212 const unsigned char *decode, unsigned mod,
213 const unsigned char *in, unsigned size)
215 char *buf = malloc(size);
217 unsigned int offset = 0x4a14;
219 unsigned int offset = 0x4b14;
223 * The scrambling has odd boundaries. I think the boundaries
224 * match some data structure size, but I don't know. They were
225 * discovered the same way we dynamically discover the decode
226 * size: automatically looking for least random output.
228 * The boundaries are also this confused "off-by-one" thing,
229 * the same way the file size is off by one. It's as if the
230 * cochran software forgot to write one byte at the beginning.
232 partial_decode(0 , 0x0fff, decode, 1, mod, in, size, buf);
233 partial_decode(0x0fff, 0x1fff, decode, 0, mod, in, size, buf);
234 partial_decode(0x1fff, 0x2fff, decode, 0, mod, in, size, buf);
235 partial_decode(0x2fff, 0x48ff, decode, 0, mod, in, size, buf);
238 * This is not all the descrambling you need - the above are just
239 * what appears to be the fixed-size blocks. The rest is also
240 * scrambled, but there seems to be size differences in the data,
241 * so this just descrambles part of it:
243 partial_decode(0x48ff, offset, decode, 0, mod, in, size, buf);
244 partial_decode(offset, size, decode, 0, mod, in, size, buf);
246 printf("\n%s, dive %d\n\n", filename, dive);
247 cochran_debug_write(filename, buf, size);
248 cochran_profile_write(buf + offset, size - offset);
253 int try_to_open_cochran(const char *filename, struct memblock *mem, GError **error)
257 unsigned int *offsets, dive1, dive2;
258 unsigned char *decode = mem->buffer + 0x40001;
260 if (mem->size < 0x40000)
262 offsets = mem->buffer;
265 if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
268 mod = figure_out_modulus(decode, mem->buffer + dive1, dive2 - dive1);
270 parse_cochran_header(filename, decode, mod, mem->buffer + 0x40000, dive1 - 0x40000);
272 for (i = 0; i < 65534; i++) {
274 dive2 = offsets[i+1];
277 if (dive2 > mem->size)
279 parse_cochran_dive(filename, i+1, decode, mod, mem->buffer + dive1, dive2 - dive1);