int hio_seek(HIO_HANDLE *h, long offset, int whence) { switch (HIO_HANDLE_TYPE(h)) { case HIO_HANDLE_TYPE_FILE: return fseek(h->handle.file, offset, whence); case HIO_HANDLE_TYPE_MEMORY: return mseek(h->handle.mem, offset, whence); default: return -1; } }
size_t hio_read(void *buf, size_t size, size_t num, HIO_HANDLE *h) { switch (HIO_HANDLE_TYPE(h)) { case HIO_HANDLE_TYPE_FILE: return fread(buf, size, num, h->handle.file); case HIO_HANDLE_TYPE_MEMORY: return mread(buf, size, num, h->handle.mem); default: return 0; } }
uint32 hio_read32b(HIO_HANDLE *h) { switch (HIO_HANDLE_TYPE(h)) { case HIO_HANDLE_TYPE_FILE: return read32b(h->handle.file); case HIO_HANDLE_TYPE_MEMORY: return mread32b(h->handle.mem); default: return 0; } }
uint8 hio_read8(HIO_HANDLE *h) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return read8(h->f); } else { if (CAN_READ(h) >= 1) return *(uint8 *)(h->start + h->pos++); else return EOF; } }
int hio_eof(HIO_HANDLE *h) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return feof(h->f); } else { if (h->size <= 0) return 0; else return CAN_READ(h) <= 0; } }
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; }
int hio_close(HIO_HANDLE *h) { int ret; if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { ret = fclose(h->f); free(h); return ret; } else { free(h); return 0; } }
uint32 hio_read24b(HIO_HANDLE *h) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return read24b(h->f); } else { ptrdiff_t can_read = CAN_READ(h); if (can_read >= 3) { uint32 n = readmem24b(h->start + h->pos); h->pos += 3; return n; } else { h->pos += can_read; return EOF; } } }
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 alm_test(HIO_HANDLE *f, char *t, const int start) { char buf[7]; if (HIO_HANDLE_TYPE(f) != HIO_HANDLE_TYPE_FILE) return -1; if (hio_read(buf, 1, 7, f) < 7) return -1; if (memcmp(buf, "ALEYMOD", 7) && memcmp(buf, "ALEY MO", 7)) return -1; read_title(f, t, 0); return 0; }
int hio_close(HIO_HANDLE *h) { int ret; switch (HIO_HANDLE_TYPE(h)) { case HIO_HANDLE_TYPE_FILE: ret = fclose(h->handle.file); break; case HIO_HANDLE_TYPE_MEMORY: ret = mclose(h->handle.mem); break; default: ret = -1; } free(h); return ret; }
size_t hio_read(void *buf, size_t size, size_t num, HIO_HANDLE *h) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return fread(buf, size, num, h->f); } else { size_t should_read = size * num; ptrdiff_t can_read = CAN_READ(h); if (can_read <= 0) return 0; if (should_read > can_read) { should_read = can_read; } memcpy(buf, h->start + h->pos, should_read); h->pos += should_read; return should_read / size; } }
int hio_seek(HIO_HANDLE *h, long offset, int whence) { if (HIO_HANDLE_TYPE(h) == HIO_HANDLE_TYPE_FILE) { return fseek(h->f, offset, whence); } else { switch (whence) { default: case SEEK_SET: if (offset > h->size || offset < 0) return -1; h->pos = offset; return 0; case SEEK_CUR: if (offset > CAN_READ(h) || offset < -h->pos) return -1; h->pos += offset; return 0; case SEEK_END: h->pos = h->size + offset; return 0; } } }
static int mod_test(HIO_HANDLE *f, char *t, const int start) { int i; char buf[4]; struct stat st; int smp_size, num_pat; hio_seek(f, start + 1080, SEEK_SET); if (hio_read(buf, 1, 4, f) < 4) return -1; if (!strncmp(buf + 2, "CH", 2) && isdigit((int)buf[0]) && isdigit((int)buf[1])) { i = (buf[0] - '0') * 10 + buf[1] - '0'; if (i > 0 && i <= 32) { goto found; } } if (!strncmp(buf + 1, "CHN", 3) && isdigit((int)*buf)) { if (*buf - '0') { goto found; } } for (i = 0; mod_magic[i].ch; i++) { if (!memcmp(buf, mod_magic[i].magic, 4)) break; } if (mod_magic[i].ch == 0) return -1; /* * Sanity check to prevent loading NoiseRunner and other module * formats with valid magic at offset 1080 */ hio_seek(f, start + 20, SEEK_SET); for (i = 0; i < 31; i++) { hio_seek(f, 22, SEEK_CUR); /* Instrument name */ if (hio_read16b(f) & 0x8000) /* test length */ return -1; if (hio_read8(f) & 0xf0) /* test finetune */ return -1; if (hio_read8(f) > 0x40) /* test volume */ return -1; if (hio_read16b(f) & 0x8000) /* test loop start */ return -1; if (hio_read16b(f) & 0x8000) /* test loop size */ return -1; } if (HIO_HANDLE_TYPE(f) != HIO_HANDLE_TYPE_FILE) goto found; /* Test for UNIC tracker modules * * From Gryzor's Pro-Wizard PW_FORMATS-Engl.guide: * ``The UNIC format is very similar to Protracker... At least in the * heading... same length : 1084 bytes. Even the "M.K." is present, * sometimes !! Maybe to disturb the rippers.. hehe but Pro-Wizard * doesn't test this only!'' */ /* get file size */ hio_stat(f, &st); smp_size = 0; hio_seek(f, start + 20, SEEK_SET); /* get samples size */ for (i = 0; i < 31; i++) { hio_seek(f, 22, SEEK_CUR); smp_size += 2 * hio_read16b(f); /* Length in 16-bit words */ hio_seek(f, 6, SEEK_CUR); } /* get number of patterns */ num_pat = 0; hio_seek(f, start + 952, SEEK_SET); for (i = 0; i < 128; i++) { uint8 x = hio_read8(f); if (x > 0x7f) break; if (x > num_pat) num_pat = x; } num_pat++; if (start + 1084 + num_pat * 0x300 + smp_size == st.st_size) return -1; found: hio_seek(f, start + 0, SEEK_SET); read_title(f, t, 20); return 0; }