diff --git a/src/image/hfe.c b/src/image/hfe.c index 11c21562..d15982d6 100644 --- a/src/image/hfe.c +++ b/src/image/hfe.c @@ -338,6 +338,7 @@ static bool_t hfe_write_track(struct image *im) struct write *write = get_write(im, im->wr_cons); struct image_buf *wr = &im->bufs.write_bc; uint8_t *buf = wr->p; + uint8_t b; unsigned int bufmask = wr->len - 1; uint8_t *w, *wrbuf = im->bufs.write_data.p; uint32_t i, space, c = wr->cons / 8, p = wr->prod / 8; @@ -414,37 +415,49 @@ static bool_t hfe_write_track(struct image *im) } } - while (i < nr) { - if (is_v3 && (w[i] & 0xf) == 0xf) { - switch (w[i]) { - case OP_SkipBits: - /* Keep the write byte-aligned. This changes the length of - * the track by 8+skip bitcells, but overwriting OP_SkipBits - * should be rare. */ - w[i++] = OP_Nop; - continue; - - case OP_Bitrate: - /* Assume bitrate does not change significantly for the - * entire track, and write_bc_ticks already adjusted when - * reading. */ - i += 2; - continue; - - case OP_Nop: - case OP_Index: - default: - /* Preserve opcode. But making sure not to write past end of - * buffer. */ - i++; - continue; - - case OP_Rand: - /* Replace with data. */ - break; + if (!is_v3) { + while (i < nr) + w[i++] = _rbit32(buf[c++ & bufmask]) >> 24; + } else { + while (i < nr) { + if ((w[i] & 0xf) == 0xf) { + switch (w[i]) { + case OP_SkipBits: + /* Keep the write byte-aligned. This changes the length + * of the track by 8+skip bitcells, but overwriting + * OP_SkipBits should be rare. */ + w[i++] = OP_Nop; + continue; + + case OP_Bitrate: + /* Assume bitrate does not change significantly for the + * entire track, and write_bc_ticks already adjusted + * when reading. */ + i += 2; + continue; + + case OP_Nop: + case OP_Index: + default: + /* Preserve opcode. But making sure not to write past + * end of buffer. */ + i++; + continue; + + case OP_Rand: + /* Replace with data. */ + break; + } } + b = _rbit32(buf[c++ & bufmask]) >> 24; + /* HFEv3 can't handle a run of 1s as it will appear like an + * opcode. If we encounter such a run, then either it is + * garbage or the file needs twice the bitrate. Assume garbage; + * a bad bitrate would fail rapidly. */ + if ((b & 0xf) == 0xf) + b ^= 2; + w[i++] = b; } - w[i++] = _rbit32(buf[c++ & bufmask]) >> 24; } im->hfe.write_batch.dirty = TRUE;