static int test_pha(const uint8 *data, char *t, int s) { int i; int ptr, ssize; PW_REQUEST_DATA(s, 451 + 128 * 4); if (data[10] != 0x03 || data[11] != 0xc0) return -1; /* test #2 (volumes,sample addresses and whole sample size) */ ssize = 0; for (i = 0; i < 31; i++) { const uint8 *d = data + i * 14; /* sample size */ ssize += readmem16b(d) << 1; if (d[3] > 0x40) return -1; /* loop start */ if ((readmem16b(d + 4) << 1) > ssize) return -1; /* address of sample data */ if (readmem32b(d + 8) < 0x3c0) return -1; } if (ssize <= 2 || ssize > 31 * 65535) return -1; /* test #3 (addresses of pattern in file ... ptk_tableible ?) */ /* l is the whole sample size */ /* ssize is used here as a variable ... set to 0 afterward */ for (i = 0; i < 128; i++) { ptr = readmem32b(data + 448 + i * 4); if (ptr + 2 - 960 < ssize) return -1; } pw_read_title(NULL, t, 0); return 0; }
/* get nbits from the compressed stream */ static int getb(struct bitstream *bs, int nbits) { bs->word &= 0x0000ffff; /* If not enough bits in the bit buffer, get more */ if (bs->left < nbits) { bs->word <<= bs->left; /* assert((bs->word & 0x0000ffffU) == 0); */ /* Check that we don't go out of bounds */ /*assert((uint8 *)bs->src >= bs->orgsrc);*/ if (bs->orgsrc > (uint8 *)bs->src) { return -1; } bs->word |= readmem16b((uint8 *)bs->src); bs->src--; nbits -= bs->left; bs->left = 16; /* 16 unused (and some used) bits left in the word */ } /* Shift nbits off the word and return them */ bs->left -= nbits; bs->word <<= nbits; return bs->word >> 16; }
static int test_fuzz (uint8 *data, int s) { int j, k; int start = 0, ssize = 0; if (readmem32b(data) != MAGIC4('M','1','.','0')) return -1; /* test finetune */ for (k = 0; k < 31; k++) { if (data[start + 72 + k * 68] > 0x0f) return -1; } /* test volumes */ for (k = 0; k < 31; k++) { if (data[start + 73 + k * 68] > 0x40) return -1; } /* test sample sizes */ for (k = 0; k < 31; k++) { j = readmem16b(data + start + k * 68 + 66); if (j > 0x8000) return -1; ssize += j * 2; } /* test size of pattern list */ if (data[start + 2114] == 0x00) return -1; return 0; }
static int test_ntp(uint8 *data, int s) { int j, k; int start = 0; PW_REQUEST_DATA(s, 64); if (readmem32b(data + start) != MAGIC4('M','O','D','U')) return -1; j = readmem16b(data + start + 20) + 4; /* "BODY" tag */ k = readmem16b(data + start + 28) + j + 4; /* "SAMP" tag */ PW_REQUEST_DATA(s, j + 4); if (readmem32b(data + start + j) != MAGIC4('B','O','D','Y')) return -1; PW_REQUEST_DATA(s, k + 4); if (readmem32b(data + start + k) != MAGIC4('S','A','M','P')) return -1; return 0; }
static int initGetb(struct bitstream *bs, uint8 *src, uint32 src_length) { int eff; bs->src = (uint16 *) (src + src_length); bs->orgsrc = src; bs->left = readmem16b((uint8 *)bs->src); /* bit counter */ /*if (bs->left & (~0xf)) fprintf(stderr, "Workarounded an ancient stc bug\n");*/ /* mask off any corrupt bits */ bs->left &= 0x000f; bs->src--; /* get the first 16-bits of the compressed stream */ bs->word = readmem16b((uint8 *)bs->src); bs->src--; eff = readmem16b((uint8 *)bs->src); /* efficiency */ bs->src--; return eff; }
uint16 hio_read16b(HIO_HANDLE *h) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return read16b(h->f); } else { ptrdiff_t can_read = CAN_READ(h); if (can_read >= 2) { uint16 n = readmem16b(h->start + h->pos); h->pos += 2; return n; } else { h->pos += can_read; return EOF; } } }
static int mfp_test(HIO_HANDLE *f, char *t, const int start) { uint8 buf[384]; int i, len, lps, lsz; if (HIO_HANDLE_TYPE(f) != HIO_HANDLE_TYPE_FILE) return -1; if (hio_read(buf, 1, 384, f) < 384) return -1; /* check restart byte */ if (buf[249] != 0x7f) return -1; for (i = 0; i < 31; i++) { /* check size */ len = readmem16b(buf + i * 8); if (len > 0x7fff) return -1; /* check finetune */ if (buf[i * 8 + 2] & 0xf0) return -1; /* check volume */ if (buf[i * 8 + 3] > 0x40) return -1; /* check loop start */ lps = readmem16b(buf + i * 8 + 4); if (lps > len) return -1; /* check loop size */ lsz = readmem16b(buf + i * 8 + 6); if (lps + lsz - 1 > len) return -1; if (len > 0 && lsz == 0) return -1; } if (buf[248] != readmem16b(buf + 378)) return -1; if (readmem16b(buf + 378) != readmem16b(buf + 380)) return -1; read_title(f, t, 0); return 0; }
static int depack_hrt(HIO_HANDLE *in, FILE *out) { uint8 buf[1024]; uint8 c1, c2, c3, c4; int len, npat; int ssize = 0; int i, j; memset(buf, 0, 950); hio_read(buf, 950, 1, in); /* read header */ for (i = 0; i < 31; i++) /* erase addresses */ *(uint32 *)(buf + 38 + 30 * i) = 0; fwrite(buf, 950, 1, out); /* write header */ for (i = 0; i < 31; i++) /* samples size */ ssize += readmem16b(buf + 42 + 30 * i) * 2; write8(out, len = hio_read8(in)); /* song length */ write8(out, hio_read8(in)); /* nst byte */ hio_read(buf, 1, 128, in); /* pattern list */ npat = 0; /* number of patterns */ for (i = 0; i < 128; i++) { if (buf[i] > npat) npat = buf[i]; } npat++; write32b(out, PW_MOD_MAGIC); /* write ptk ID */ /* pattern data */ hio_seek(in, 1084, SEEK_SET); for (i = 0; i < npat; i++) { for (j = 0; j < 256; j++) { buf[0] = hio_read8(in); buf[1] = hio_read8(in); buf[2] = hio_read8(in); buf[3] = hio_read8(in); buf[0] /= 2; c1 = buf[0] & 0xf0; if (buf[1] == 0) c2 = 0; else { c1 |= ptk_table[buf[1] / 2][0]; c2 = ptk_table[buf[1] / 2][1]; } c3 = ((buf[0] << 4) & 0xf0) | buf[2]; c4 = buf[3]; write8(out, c1); write8(out, c2); write8(out, c3); write8(out, c4); } } /* sample data */ pw_move_data(out, in, ssize); return 0; }
static int test_pp21(uint8 *data, char *t, int s) { int i; int ssize, tsize, npat, max_ref; ssize = 0; for (i = 0; i < 31; i++) { uint8 *d = data + i * 8; int len = readmem16b(d) << 1; int start = readmem16b(d + 4) << 1; ssize += len; /* finetune > 0x0f ? */ if (d[2] > 0x0f) return -1; /* loop start > size ? */ if (start > len) return -1; } if (ssize <= 2) return -1; /* test #3 about size of pattern list */ npat = data[248]; if (npat == 0 || npat > 127) return -1; /* get the highest track value */ tsize = 0; for (i = 0; i < 512; i++) { int trk = data[250 + i]; if (trk > tsize) tsize = trk; } tsize++; tsize <<= 6; /* test #4 track data value > $4000 ? */ max_ref = 0; for (i = 0; i < tsize; i++) { int ref = readmem16b(data + i * 2 + 762); if (ref > 0x4000) return -1; if (ref > max_ref) max_ref = ref; } /* test #5 reference table size *4 ? */ if (readmem32b(data + (tsize << 1) + 762) != (max_ref + 1) * 4) return -1; pw_read_title(NULL, t, 0); return 0; }
static int test_mp_noid(uint8 *data, int s) { int start, ssize; int j, k, l, m, n; start = 0; #if 0 if (i < 3) { Test = BAD; return; } #endif /* test #2 */ l = 0; for (j = 0; j < 31; j++) { int x = start + 8 * j; k = readmem16b(data + x) * 2; /* size */ m = readmem16b(data + x + 4) * 2; /* loop start */ n = readmem16b(data + x + 6) * 2; /* loop size */ l += k; /* finetune > 0x0f ? */ if (data[x + 2] > 0x0f) return -1; /* loop start+replen > size ? */ if (n != 2 && (m + n) > k) return -1; /* loop size > size ? */ if (n > (k + 2)) return -1; /* loop start != 0 and loop size = 0 */ if (m != 0 && n <= 2) return -1; /* when size!=0 loopsize==0 ? */ if (k != 0 && n == 0) return -1; } if (l <= 2) return -1; /* test #3 */ l = data[start + 248]; if (l > 0x7f || l == 0x00) return -1; /* test #4 */ /* l contains the size of the pattern list */ k = 0; for (j = 0; j < 128; j++) { if (data[start + 250 + j] > k) k = data[start + 250 + j]; if (data[start + 250 + j] > 0x7f) return -1; if (j > l + 3) { if (data[start + 250 + j] != 0x00) return -1; } } k++; /* test #5 ptk notes .. gosh ! (testing all patterns !) */ /* k contains the number of pattern saved */ for (j = 0; j < (256 * k); j++) { int x = start + j * 4; l = data[x + 378]; if (l > 19 && l != 74) /* MadeInCroatia has l == 74 */ return -1; ssize = data[x + 378] & 0x0f; ssize *= 256; ssize += data[x + 379]; if (ssize > 0 && ssize < 0x71) return -1; } /* test #6 (loopStart+LoopSize > Sample ? ) */ for (j = 0; j < 31; j++) { int x = start + j * 8; k = readmem16b(data + x) * 2; l = (readmem16b(data + x + 4) + readmem16b(data + x + 6)) * 2; if (l > (k + 2)) return -1; } return 0; }
static int depack_eu(FILE *in, FILE *out) { uint8 tmp[1080]; uint8 c1; int npat, smp_addr; int ssize = 0; int trk_addr[128][4]; int i, j, k; /* read header ... same as ptk */ fread(tmp, 1080, 1, in); fwrite(tmp, 1080, 1, out); /* now, let's sort out that a bit :) */ /* first, the whole sample size */ for (i = 0; i < 31; i++) ssize += 2 * readmem16b(tmp + i * 30 + 42); /* now, the pattern list .. and the max */ for (npat = i = 0; i < 128; i++) { if (tmp[952 + i] > npat) npat = tmp[952 + i]; } npat++; write32b(out, PW_MOD_MAGIC); /* write ptk ID */ smp_addr = read32b(in); /* read sample data address */ /* read tracks addresses */ for (i = 0; i < npat; i++) { for (j = 0; j < 4; j++) trk_addr[i][j] = read16b(in); } /* the track data now ... */ for (i = 0; i < npat; i++) { memset(tmp, 0, 1024); for (j = 0; j < 4; j++) { fseek(in, trk_addr[i][j], SEEK_SET); for (k = 0; k < 64; k++) { uint8 *x = &tmp[k * 16 + j * 4]; c1 = read8(in); if ((c1 & 0xc0) == 0x00) { *x++ = c1; *x++ = read8(in); *x++ = read8(in); *x++ = read8(in); continue; } if ((c1 & 0xc0) == 0xc0) { k += (c1 & 0x3f); continue; } if ((c1 & 0xc0) == 0x40) { x += 2; *x++ = c1 & 0x0f; *x++ = read8(in); continue; } if ((c1 & 0xc0) == 0x80) { *x++ = read8(in); *x++ = read8(in); *x++ = (c1 << 4) & 0xf0; continue; } } } fwrite(tmp, 1024, 1, out); } fseek(in, smp_addr, SEEK_SET); pw_move_data(out, in, ssize); return 0; }
static int test_tdd(uint8 *data, char *t, int s) { int i; int ssize, psize, pdata_ofs; PW_REQUEST_DATA(s, 564); /* test #2 (volumes,sample addresses and whole sample size) */ ssize = 0; for (i = 0; i < 31; i++) { uint8 *d = data + i * 14; int addr = readmem32b(d + 130); /* sample address */ int size = readmem16b(d + 134); /* sample size */ int sadr = readmem32b(d + 138); /* loop start address */ int lsiz = readmem16b(d + 142); /* loop size (replen) */ /* volume > 40h ? */ if (d[137] > 0x40) return -1; /* loop start addy < sampl addy ? */ if (sadr < addr) return -1; /* addy < 564 ? */ if (addr < 564 || sadr < 564) return -1; /* loop start > size ? */ if (sadr - addr > size) return -1; /* loop start+replen > size ? */ if (sadr - addr + lsiz > size + 2) return -1; ssize += size; } if (ssize <= 2 || ssize > 31 * 65535) return -1; #if 0 /* test #3 (addresses of pattern in file ... ptk_tableible ?) */ /* ssize is the whole sample size :) */ if ((ssize + 564) > in_size) { Test = BAD; return; } #endif /* test size of pattern list */ if (data[0] == 0 || data[0] > 0x7f) return -1; /* test pattern list */ psize = 0; for (i = 0; i < 128; i++) { int pat = data[i + 2]; if (pat > 0x7f) return -1; if (pat > psize) psize = pat; } psize++; psize <<= 10; /* test end of pattern list */ for (i = data[0] + 2; i < 128; i++) { if (data[i + 2] != 0) return -1; } #if 0 /* test if not out of file range */ if ((ssize + 564 + k) > in_size) return -1; #endif /* ssize is the whole sample data size */ /* test pattern data now ... */ pdata_ofs = 564 + ssize; PW_REQUEST_DATA(s, 564 + ssize + psize); for (i = 0; i < psize; i += 4) { uint8 *d = data + pdata_ofs + i; /* sample number > 31 ? */ if (d[0] > 0x1f) return -1; /* note > 0x48 (36*2) */ if (d[1] > 0x48 || (d[1] & 0x01) == 0x01) return -1; /* fx=C and fxtArg > 64 ? */ if ((d[2] & 0x0f) == 0x0c && d[3] > 0x40) return -1; /* fx=D and fxtArg > 64 ? */ if ((d[2] & 0x0f) == 0x0d && d[3] > 0x40) return -1; /* fx=B and fxtArg > 127 ? */ if ((d[2] & 0x0f) == 0x0b) return -1; } pw_read_title(NULL, t, 0); return -1; }
static int depack_pru1 (HIO_HANDLE *in, FILE *out) { uint8 header[2048]; uint8 c1, c2, c3, c4; uint8 npat, max; uint8 ptable[128]; int ssize = 0; int i, j; memset(header, 0, 2048); memset(ptable, 0, 128); /* read and write whole header */ hio_read(header, 950, 1, in); fwrite(header, 950, 1, out); /* get whole sample size */ for (i = 0; i < 31; i++) { ssize += readmem16b(header + i * 30 + 42) * 2; } /* read and write size of pattern list */ write8(out, npat = hio_read8(in)); memset(header, 0, 2048); /* read and write ntk byte and pattern list */ hio_read(header, 129, 1, in); fwrite(header, 129, 1, out); /* write ID */ write32b(out, PW_MOD_MAGIC); /* get number of pattern */ max = 0; for (i = 1; i < 129; i++) { if (header[i] > max) max = header[i]; } /* pattern data */ hio_seek(in, 1084, SEEK_SET); for (i = 0; i <= max; i++) { for (j = 0; j < 256; j++) { header[0] = hio_read8(in); header[1] = hio_read8(in); header[2] = hio_read8(in); header[3] = hio_read8(in); c1 = header[0] & 0xf0; c3 = (header[0] & 0x0f) << 4; c3 |= header[2]; c4 = header[3]; c1 |= ptk_table[header[1]][0]; c2 = ptk_table[header[1]][1]; write8(out, c1); write8(out, c2); write8(out, c3); write8(out, c4); } } /* sample data */ pw_move_data(out, in, ssize); return 0; }
static int test_tdd (uint8 *data, int s) { int j, k, l, m, n; int start = 0, ssize; PW_REQUEST_DATA (s, 564); /* test #2 (volumes,sample addresses and whole sample size) */ ssize = 0; for (j = 0; j < 31; j++) { uint8 *d = data + start + j * 14; k = readmem32b(d + 130); /* sample address */ l = readmem16b(d + 134); /* sample size */ m = readmem32b(d + 138); /* loop start address */ n = readmem16b(d + 142); /* loop size (replen) */ /* volume > 40h ? */ if (data[start + j * 14 + 137] > 0x40) return -1; /* loop start addy < sampl addy ? */ if (m < k) return -1; /* addy < 564 ? */ if (k < 564 || m < 564) return -1; /* loop start > size ? */ if (m - k > l) return -1; /* loop start+replen > size ? */ if (m - k + n > l + 2) return -1; ssize += l; } if (ssize <= 2 || ssize > (31 * 65535)) return -1; #if 0 /* test #3 (addresses of pattern in file ... ptk_tableible ?) */ /* ssize is the whole sample size :) */ if ((ssize + 564) > in_size) { /*printf ( "#3 (start:%ld)\n" , start );*/ Test = BAD; return; } #endif /* test size of pattern list */ if (data[start] > 0x7f || data[start] == 0x00) return -1; /* test pattern list */ k = 0; for (j = 0; j < 128; j++) { if (data[start + j + 2] > 0x7f) return -1; if (data[start + j + 2] > k) k = data[start + j + 2]; } k += 1; k *= 1024; /* test end of pattern list */ for (j = data[start] + 2; j < 128; j++) { if (data[start + j + 2] != 0) return -1; } #if 0 /* test if not out of file range */ if ((start + ssize + 564 + k) > in_size) return -1; #endif /* ssize is the whole sample data size */ /* k is the whole pattern data size */ /* test pattern data now ... */ l = start + 564 + ssize; /* l points on pattern data */ for (j = 0; j < k; j += 4) { /* sample number > 31 ? */ if (data[l + j] > 0x1f) return -1; /* note > 0x48 (36*2) */ if (data[l + j + 1] > 0x48 || (data[l + j + 1] & 0x01) == 0x01) return -1; /* fx=C and fxtArg > 64 ? */ if ((data[l + j + 2] & 0x0f) == 0x0c && data[l + j + 3] > 0x40) return -1; /* fx=D and fxtArg > 64 ? */ if ((data[l + j + 2] & 0x0f) == 0x0d && data[l + j + 3] > 0x40) return -1; /* fx=B and fxtArg > 127 ? */ if ((data[l + j + 2] & 0x0f) == 0x0b) return -1; } return -1; }