static int no_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j, k; int nsize; LOAD_INIT(); hio_read32b(f); /* NO 0x00 0x00 */ set_type(m, "Liquid Tracker"); nsize = hio_read8(f); for (i = 0; i < nsize; i++) { uint8 x = hio_read8(f); if (i < XMP_NAME_SIZE) mod->name[i] = x; } hio_read16l(f); hio_read16l(f); hio_read16l(f); hio_read16l(f); hio_read8(f); mod->pat = hio_read8(f); hio_read8(f); mod->chn = hio_read8(f); mod->trk = mod->pat * mod->chn; hio_read8(f); hio_read16l(f); hio_read16l(f); hio_read8(f); mod->ins = mod->smp = 63; for (i = 0; i < 256; i++) { uint8 x = hio_read8(f); if (x == 0xff) break; mod->xxo[i] = x; } hio_seek(f, 255 - i, SEEK_CUR); mod->len = i; MODULE_INFO(); if (instrument_init(mod) < 0) return -1; /* Read instrument names */ for (i = 0; i < mod->ins; i++) { int hasname, c2spd; if (subinstrument_alloc(mod, i, 1) < 0) return -1; nsize = hio_read8(f); hasname = 0; for (j = 0; j < nsize; j++) { uint8 x = hio_read8(f); if (x != 0x20) hasname = 1; if (j < 32) mod->xxi[i].name[j] = x; } if (!hasname) mod->xxi[i].name[0] = 0; hio_read32l(f); hio_read32l(f); mod->xxi[i].sub[0].vol = hio_read8(f); c2spd = hio_read16l(f); mod->xxs[i].len = hio_read16l(f); mod->xxs[i].lps = hio_read16l(f); mod->xxs[i].lpe = hio_read16l(f); hio_read32l(f); hio_read16l(f); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; /* mod->xxs[i].lps = 0; mod->xxs[i].lpe = 0; */ mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); c2spd = 8363 * c2spd / 8448; c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); } if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d ", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { uint32 x, note, ins, vol, fxt, fxp; event = &EVENT (i, k, j); x = hio_read32l(f); note = x & 0x0000003f; ins = (x & 0x00001fc0) >> 6; vol = (x & 0x000fe000) >> 13; fxt = (x & 0x00f00000) >> 20; fxp = (x & 0xff000000) >> 24; if (note != 0x3f) event->note = 36 + note; if (ins != 0x7f) event->ins = 1 + ins; if (vol != 0x7f) event->vol = vol; if (fxt != 0x0f) { event->fxt = fx[fxt]; event->fxp = fxp; } } } } /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (mod->xxs[i].len == 0) continue; if (load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; } m->quirk |= QUIRKS_ST3; m->read_event_type = READ_EVENT_ST3; return 0; }
static int get_patt(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; struct xmp_event *event, dummy; int i, len, chan; int rows, r; uint8 flag; i = hio_read8(f); /* pattern number */ len = hio_read32l(f); /* Sanity check */ if (i >= mod->pat || len <= 0) { return -1; } rows = hio_read8(f) + 1; if (pattern_tracks_alloc(mod, i, rows) < 0) return -1; for (r = 0; r < rows; ) { if ((flag = hio_read8(f)) == 0) { r++; continue; } chan = flag & 0x1f; event = chan < mod->chn ? &EVENT(i, chan, r) : &dummy; if (flag & 0x80) { uint8 fxp = hio_read8(f); uint8 fxt = hio_read8(f); switch (fxt) { case 0x14: /* speed */ fxt = FX_S3M_SPEED; break; default: if (fxt > 0x0f) { printf("unknown effect %02x %02x\n", fxt, fxp); fxt = fxp = 0; } } event->fxt = fxt; event->fxp = fxp; } if (flag & 0x40) { event->ins = hio_read8(f); event->note = hio_read8(f); if (event->note == 128) { event->note = XMP_KEY_OFF; } } if (flag & 0x20) { event->vol = 1 + hio_read8(f) / 2; } } return 9; }
static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; struct local_data *data = (struct local_data *)parm; int i, j; int srate, finetune, flags; int val, vwf, vra, vde, vsw, fade; uint8 buf[30]; hio_read8(f); /* 00 */ i = hio_read8(f); /* instrument number */ hio_read(&mod->xxi[i].name, 1, 28, f); adjust_string((char *)mod->xxi[i].name); mod->xxi[i].nsm = hio_read8(f); for (j = 0; j < 108; j++) { mod->xxi[i].map[j].ins = hio_read8(f); } hio_seek(f, 11, SEEK_CUR); /* unknown */ vwf = hio_read8(f); /* vibrato waveform */ vsw = hio_read8(f); /* vibrato sweep */ hio_read8(f); /* unknown */ hio_read8(f); /* unknown */ vde = hio_read8(f); /* vibrato depth */ vra = hio_read16l(f) / 16; /* vibrato speed */ hio_read8(f); /* unknown */ val = hio_read8(f); /* PV envelopes flags */ if (LSN(val) & 0x01) mod->xxi[i].aei.flg |= XMP_ENVELOPE_ON; if (LSN(val) & 0x02) mod->xxi[i].aei.flg |= XMP_ENVELOPE_SUS; if (LSN(val) & 0x04) mod->xxi[i].aei.flg |= XMP_ENVELOPE_LOOP; if (MSN(val) & 0x01) mod->xxi[i].pei.flg |= XMP_ENVELOPE_ON; if (MSN(val) & 0x02) mod->xxi[i].pei.flg |= XMP_ENVELOPE_SUS; if (MSN(val) & 0x04) mod->xxi[i].pei.flg |= XMP_ENVELOPE_LOOP; val = hio_read8(f); /* PV envelopes points */ mod->xxi[i].aei.npt = LSN(val) + 1; mod->xxi[i].pei.npt = MSN(val) + 1; val = hio_read8(f); /* PV envelopes sustain point */ mod->xxi[i].aei.sus = LSN(val); mod->xxi[i].pei.sus = MSN(val); val = hio_read8(f); /* PV envelopes loop start */ mod->xxi[i].aei.lps = LSN(val); mod->xxi[i].pei.lps = MSN(val); hio_read8(f); /* PV envelopes loop end */ mod->xxi[i].aei.lpe = LSN(val); mod->xxi[i].pei.lpe = MSN(val); if (mod->xxi[i].aei.npt <= 0 || mod->xxi[i].aei.npt >= XMP_MAX_ENV_POINTS) mod->xxi[i].aei.flg &= ~XMP_ENVELOPE_ON; if (mod->xxi[i].pei.npt <= 0 || mod->xxi[i].pei.npt >= XMP_MAX_ENV_POINTS) mod->xxi[i].pei.flg &= ~XMP_ENVELOPE_ON; hio_read(buf, 1, 30, f); /* volume envelope points */; for (j = 0; j < mod->xxi[i].aei.npt; j++) { mod->xxi[i].aei.data[j * 2] = readmem16l(buf + j * 3) / 16; mod->xxi[i].aei.data[j * 2 + 1] = buf[j * 3 + 2]; } hio_read(buf, 1, 30, f); /* pan envelope points */; for (j = 0; j < mod->xxi[i].pei.npt; j++) { mod->xxi[i].pei.data[j * 2] = readmem16l(buf + j * 3) / 16; mod->xxi[i].pei.data[j * 2 + 1] = buf[j * 3 + 2]; } fade = hio_read8(f); /* fadeout - 0x80->0x02 0x310->0x0c */ hio_read8(f); /* unknown */ D_(D_INFO "[%2X] %-28.28s %2d ", i, mod->xxi[i].name, mod->xxi[i].nsm); if (mod->xxi[i].nsm == 0) return 0; if (subinstrument_alloc(mod, i, mod->xxi[i].nsm) < 0) return -1; for (j = 0; j < mod->xxi[i].nsm; j++, data->snum++) { hio_read32b(f); /* SAMP */ hio_read32b(f); /* size */ hio_read(&mod->xxs[data->snum].name, 1, 28, f); adjust_string((char *)mod->xxs[data->snum].name); mod->xxi[i].sub[j].pan = hio_read8(f) * 4; if (mod->xxi[i].sub[j].pan == 0) /* not sure about this */ mod->xxi[i].sub[j].pan = 0x80; mod->xxi[i].sub[j].vol = hio_read8(f); flags = hio_read8(f); hio_read8(f); /* unknown - 0x80 */ mod->xxi[i].sub[j].vwf = vwf; mod->xxi[i].sub[j].vde = vde; mod->xxi[i].sub[j].vra = vra; mod->xxi[i].sub[j].vsw = vsw; mod->xxi[i].sub[j].sid = data->snum; mod->xxs[data->snum].len = hio_read32l(f); mod->xxs[data->snum].lps = hio_read32l(f); mod->xxs[data->snum].lpe = hio_read32l(f); mod->xxs[data->snum].flg = 0; if (flags & 0x04) mod->xxs[data->snum].flg |= XMP_SAMPLE_16BIT; if (flags & 0x08) mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP; if (flags & 0x10) mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP_BIDIR; /* if (flags & 0x80) mod->xxs[data->snum].flg |= ? */ srate = hio_read32l(f); finetune = 0; c2spd_to_note(srate, &mod->xxi[i].sub[j].xpo, &mod->xxi[i].sub[j].fin); mod->xxi[i].sub[j].fin += finetune; hio_read32l(f); /* 0x00000000 */ hio_read32l(f); /* unknown */ D_(D_INFO " %X: %05x%c%05x %05x %c V%02x P%02x %5d", j, mod->xxs[data->snum].len, mod->xxs[data->snum].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[data->snum].lps, mod->xxs[data->snum].lpe, mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[j].vol, mod->xxi[i].sub[j].pan, srate); if (mod->xxs[data->snum].len > 1) { int snum = data->snum; if (load_sample(m, f, 0, &mod->xxs[snum], NULL) < 0) return -1; } } return 0; }
static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; int i, srate, finetune, flags; int has_unsigned_sample; hio_read32b(f); /* 42 01 00 00 */ hio_read8(f); /* 00 */ i = hio_read8(f); /* instrument number */ hio_read(&mod->xxi[i].name, 1, 28, f); hio_seek(f, 290, SEEK_CUR); /* Sample/note map, envelopes */ mod->xxi[i].nsm = hio_read16l(f); D_(D_INFO "[%2X] %-28.28s %2d ", i, mod->xxi[i].name, mod->xxi[i].nsm); if (mod->xxi[i].nsm == 0) return 0; if (libxmp_alloc_subinstrument(mod, i, mod->xxi[i].nsm) < 0) return -1; /* FIXME: Currently reading only the first sample */ hio_read32b(f); /* RIFF */ hio_read32b(f); /* size */ hio_read32b(f); /* AS */ hio_read32b(f); /* SAMP */ hio_read32b(f); /* size */ hio_read32b(f); /* unknown - usually 0x40000000 */ hio_read(&mod->xxs[i].name, 1, 28, f); hio_read32b(f); /* unknown - 0x0000 */ hio_read8(f); /* unknown - 0x00 */ mod->xxi[i].sub[0].sid = i; mod->xxi[i].vol = hio_read8(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].vol = (hio_read16l(f) + 1) / 512; flags = hio_read16l(f); hio_read16l(f); /* unknown - 0x0080 */ mod->xxs[i].len = hio_read32l(f); mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); mod->xxs[i].flg = 0; has_unsigned_sample = 0; if (flags & 0x04) mod->xxs[i].flg |= XMP_SAMPLE_16BIT; if (flags & 0x08) mod->xxs[i].flg |= XMP_SAMPLE_LOOP; if (flags & 0x10) mod->xxs[i].flg |= XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR; if (~flags & 0x80) has_unsigned_sample = 1; srate = hio_read32l(f); finetune = 0; libxmp_c2spd_to_note(srate, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].fin += finetune; hio_read32l(f); /* 0x00000000 */ hio_read32l(f); /* unknown */ D_(D_INFO " %x: %05x%c%05x %05x %c V%02x %04x %5d", 0, mod->xxs[i].len, mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, flags, srate); if (mod->xxs[i].len > 1) { if (libxmp_load_sample(m, f, has_unsigned_sample ? SAMPLE_FLAG_UNS : 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }
static int s3m_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i; struct xmp_event *event = 0, dummy; struct s3m_file_header sfh; struct s3m_instrument_header sih; #ifndef LIBXMP_CORE_PLAYER struct s3m_adlib_header sah; char tracker_name[40]; int quirk87 = 0; #endif int pat_len; uint8 n, b, x8; uint16 *pp_ins; /* Parapointers to instruments */ uint16 *pp_pat; /* Parapointers to patterns */ int ret; LOAD_INIT(); hio_read(&sfh.name, 28, 1, f); /* Song name */ hio_read8(f); /* 0x1a */ sfh.type = hio_read8(f); /* File type */ hio_read16l(f); /* Reserved */ sfh.ordnum = hio_read16l(f); /* Number of orders (must be even) */ sfh.insnum = hio_read16l(f); /* Number of instruments */ sfh.patnum = hio_read16l(f); /* Number of patterns */ sfh.flags = hio_read16l(f); /* Flags */ sfh.version = hio_read16l(f); /* Tracker ID and version */ sfh.ffi = hio_read16l(f); /* File format information */ /* Sanity check */ if (sfh.ffi != 1 && sfh.ffi != 2) { goto err; } if (sfh.ordnum > 255 || sfh.insnum > 255 || sfh.patnum > 255) { goto err; } sfh.magic = hio_read32b(f); /* 'SCRM' */ sfh.gv = hio_read8(f); /* Global volume */ sfh.is = hio_read8(f); /* Initial speed */ sfh.it = hio_read8(f); /* Initial tempo */ sfh.mv = hio_read8(f); /* Master volume */ sfh.uc = hio_read8(f); /* Ultra click removal */ sfh.dp = hio_read8(f); /* Default pan positions if 0xfc */ hio_read32l(f); /* Reserved */ hio_read32l(f); /* Reserved */ sfh.special = hio_read16l(f); /* Ptr to special custom data */ hio_read(sfh.chset, 32, 1, f); /* Channel settings */ #if 0 if (sfh.magic != MAGIC_SCRM) return -1; #endif #ifndef LIBXMP_CORE_PLAYER /* S3M anomaly in return_of_litmus.s3m */ if (sfh.version == 0x1301 && sfh.name[27] == 0x87) quirk87 = 1; if (quirk87) { fix87(sfh.name); fix87(sfh.patnum); fix87(sfh.flags); } #endif copy_adjust(mod->name, sfh.name, 28); pp_ins = calloc(2, sfh.insnum); if (pp_ins == NULL) goto err; pp_pat = calloc (2, sfh.patnum); if (pp_pat == NULL) goto err2; if (sfh.flags & S3M_AMIGA_RANGE) m->quirk |= QUIRK_MODRNG; if (sfh.flags & S3M_ST300_VOLS) m->quirk |= QUIRK_VSALL; /* m->volbase = 4096 / sfh.gv; */ mod->spd = sfh.is; mod->bpm = sfh.it; mod->chn = 0; for (i = 0; i < 32; i++) { if (sfh.chset[i] == S3M_CH_OFF) continue; mod->chn = i + 1; if (sfh.mv & 0x80) { /* stereo */ int x = sfh.chset[i] & S3M_CH_PAN; mod->xxc[i].pan = (x & 0x0f) < 8 ? 0x30 : 0xc0; } else { mod->xxc[i].pan = 0x80; } } if (sfh.ordnum <= XMP_MAX_MOD_LENGTH) { mod->len = sfh.ordnum; hio_read(mod->xxo, 1, mod->len, f); } else { mod->len = XMP_MAX_MOD_LENGTH; hio_read(mod->xxo, 1, mod->len, f); hio_seek(f, sfh.ordnum - XMP_MAX_MOD_LENGTH, SEEK_CUR); } mod->pat = -1; for (i = 0; i < mod->len && mod->xxo[i] < 0xff; ++i) { if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; if (mod->pat > sfh.patnum) mod->pat = sfh.patnum; if (mod->pat == 0) goto err3; mod->trk = mod->pat * mod->chn; /* Load and convert header */ mod->ins = sfh.insnum; mod->smp = mod->ins; for (i = 0; i < sfh.insnum; i++) pp_ins[i] = hio_read16l(f); for (i = 0; i < sfh.patnum; i++) pp_pat[i] = hio_read16l(f); /* Default pan positions */ for (i = 0, sfh.dp -= 0xfc; !sfh.dp /* && n */ && (i < 32); i++) { uint8 x = hio_read8(f); if (x & S3M_PAN_SET) mod->xxc[i].pan = (x << 4) & 0xff; else mod->xxc[i].pan = sfh.mv % 0x80 ? 0x30 + 0xa0 * (i & 1) : 0x80; } m->c4rate = C4_NTSC_RATE; if (sfh.version == 0x1300) m->quirk |= QUIRK_VSALL; #ifndef LIBXMP_CORE_PLAYER switch (sfh.version >> 12) { case 1: snprintf(tracker_name, 40, "Scream Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); m->quirk |= QUIRK_ST3GVOL; break; case 2: snprintf(tracker_name, 40, "Imago Orpheus %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; case 3: if (sfh.version == 0x3216) { strcpy(tracker_name, "Impulse Tracker 2.14v3"); } else if (sfh.version == 0x3217) { strcpy(tracker_name, "Impulse Tracker 2.14v5"); } else { snprintf(tracker_name, 40, "Impulse Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); } break; case 5: snprintf(tracker_name, 40, "OpenMPT %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; case 4: if (sfh.version != 0x4100) { snprintf(tracker_name, 40, "Schism Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; } /* fall through */ case 6: snprintf(tracker_name, 40, "BeRoTracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; default: snprintf(tracker_name, 40, "unknown (%04x)", sfh.version); }
static int coco_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j; int seq_ptr, pat_ptr, smp_ptr[100]; LOAD_INIT(); mod->chn = hio_read8(f) & 0x3f; libxmp_read_title(f, mod->name, 20); for (i = 0; i < 20; i++) { if (mod->name[i] == 0x0d) mod->name[i] = 0; } libxmp_set_type(m, "Coconizer"); mod->ins = mod->smp = hio_read8(f); mod->len = hio_read8(f); mod->pat = hio_read8(f); mod->trk = mod->pat * mod->chn; seq_ptr = hio_read32l(f); pat_ptr = hio_read32l(f); MODULE_INFO(); if (libxmp_init_instrument(m) < 0) return -1; m->vol_table = (int *)arch_vol_table; m->volbase = 0xff; for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; smp_ptr[i] = hio_read32l(f); mod->xxs[i].len = hio_read32l(f); mod->xxi[i].sub[0].vol = 0xff - hio_read32l(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = mod->xxs[i].lps + hio_read32l(f); if (mod->xxs[i].lpe) mod->xxs[i].lpe -= 1; mod->xxs[i].flg = mod->xxs[i].lps > 0 ? XMP_SAMPLE_LOOP : 0; hio_read(mod->xxi[i].name, 1, 11, f); for (j = 0; j < 11; j++) { if (mod->xxi[i].name[j] == 0x0d) mod->xxi[i].name[j] = 0; } hio_read8(f); /* unused */ mod->xxi[i].sub[0].sid = i; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %-10.10s %05x %05x %05x %c V%02x", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); } /* Sequence */ hio_seek(f, start + seq_ptr, SEEK_SET); for (i = 0; ; i++) { uint8 x = hio_read8(f); if (x == 0xff) break; mod->xxo[i] = x; } for (i++; i % 4; i++) /* for alignment */ hio_read8(f); /* Patterns */ if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < (64 * mod->chn); j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); event->fxp = hio_read8(f); event->fxt = hio_read8(f); event->ins = hio_read8(f); event->note = hio_read8(f); if (event->note) event->note += 12; fix_effect(event); } } /* Read samples */ D_(D_INFO "Stored samples : %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (mod->xxi[i].nsm == 0) continue; hio_seek(f, start + smp_ptr[i], SEEK_SET); if (libxmp_load_sample(m, f, SAMPLE_FLAG_VIDC, &mod->xxs[i], NULL) < 0) return -1; } for (i = 0; i < mod->chn; i++) { mod->xxc[i].pan = DEFPAN((((i + 3) / 2) % 2) * 0xff); } return 0; }
static int load_patterns(struct module_data *m, int version, HIO_HANDLE *f) { struct xmp_module *mod = &m->mod; struct xm_pattern_header xph; struct xmp_event *event; uint8 *patbuf, *pat, b; int i, j, r; mod->pat++; if (pattern_init(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat - 1); /* Endianism fixed by Miodrag Vallat <*****@*****.**> * Mon, 04 Jan 1999 11:17:20 +0100 */ for (i = 0; i < mod->pat - 1; i++) { xph.length = hio_read32l(f); xph.packing = hio_read8(f); xph.rows = version > 0x0102 ? hio_read16l(f) : hio_read8(f) + 1; xph.datasize = hio_read16l(f); r = xph.rows; if (r == 0) r = 0x100; if (pattern_tracks_alloc(mod, i, r) < 0) return -1; if (xph.datasize) { pat = patbuf = calloc(1, xph.datasize); if (patbuf == NULL) return -1; hio_read(patbuf, 1, xph.datasize, f); for (j = 0; j < (mod->chn * r); j++) { if ((pat - patbuf) >= xph.datasize) break; event = &EVENT(i, j % mod->chn, j / mod->chn); if ((b = *pat++) & XM_EVENT_PACKING) { if (b & XM_EVENT_NOTE_FOLLOWS) event->note = *pat++; if (b & XM_EVENT_INSTRUMENT_FOLLOWS) event->ins = *pat++; if (b & XM_EVENT_VOLUME_FOLLOWS) event->vol = *pat++; if (b & XM_EVENT_FXTYPE_FOLLOWS) { event->fxt = *pat++; #if 0 if (event->fxt == FX_GLOBALVOL) event->fxt = FX_TRK_VOL; if (event->fxt == FX_G_VOLSLIDE) event->fxt = FX_TRK_VSLIDE; #endif } if (b & XM_EVENT_FXPARM_FOLLOWS) event->fxp = *pat++; } else { event->note = b; event->ins = *pat++; event->vol = *pat++; event->fxt = *pat++; event->fxp = *pat++; } if (event->note == 0x61) event->note = XMP_KEY_OFF; else if (event->note > 0) event->note += 12; if (!event->vol) continue; /* Volume set */ if ((event->vol >= 0x10) && (event->vol <= 0x50)) { event->vol -= 0x0f; continue; } /* Volume column effects */ switch (event->vol >> 4) { case 0x06: /* Volume slide down */ event->f2t = FX_VOLSLIDE_2; event->f2p = event->vol - 0x60; break; case 0x07: /* Volume slide up */ event->f2t = FX_VOLSLIDE_2; event->f2p = (event->vol - 0x70) << 4; break; case 0x08: /* Fine volume slide down */ event->f2t = FX_EXTENDED; event->f2p = (EX_F_VSLIDE_DN << 4) | (event->vol - 0x80); break; case 0x09: /* Fine volume slide up */ event->f2t = FX_EXTENDED; event->f2p = (EX_F_VSLIDE_UP << 4) | (event->vol - 0x90); break; case 0x0a: /* Set vibrato speed */ event->f2t = FX_VIBRATO; event->f2p = (event->vol - 0xa0) << 4; break; case 0x0b: /* Vibrato */ event->f2t = FX_VIBRATO; event->f2p = event->vol - 0xb0; break; case 0x0c: /* Set panning */ event->f2t = FX_SETPAN; event->f2p = ((event->vol - 0xc0) << 4) + 8; break; case 0x0d: /* Pan slide left */ event->f2t = FX_PANSLIDE; event->f2p = (event->vol - 0xd0) << 4; break; case 0x0e: /* Pan slide right */ event->f2t = FX_PANSLIDE; event->f2p = event->vol - 0xe0; break; case 0x0f: /* Tone portamento */ event->f2t = FX_TONEPORTA; event->f2p = (event->vol - 0xf0) << 4; break; } event->vol = 0; } free (patbuf); } }
static int amf_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct xmp_event *event; uint8 buf[1024]; int *trkmap, newtrk; int ver; LOAD_INIT(); hio_read(buf, 1, 3, f); ver = hio_read8(f); hio_read(buf, 1, 32, f); strncpy(mod->name, (char *)buf, 32); set_type(m, "DSMI %d.%d AMF", ver / 10, ver % 10); mod->ins = hio_read8(f); mod->len = hio_read8(f); mod->trk = hio_read16l(f); mod->chn = hio_read8(f); mod->smp = mod->ins; mod->pat = mod->len; if (ver == 0x0a) hio_read(buf, 1, 16, f); /* channel remap table */ if (ver >= 0x0d) { hio_read(buf, 1, 32, f); /* panning table */ for (i = 0; i < 32; i++) { mod->xxc->pan = 0x80 + 2 * (int8)buf[i]; } mod->bpm = hio_read8(f); mod->spd = hio_read8(f); } else if (ver >= 0x0b) { hio_read(buf, 1, 16, f); } MODULE_INFO(); /* Orders */ /* * Andre Timmermans <*****@*****.**> says: * * Order table: track numbers in this table are not explained, * but as you noticed you have to perform -1 to obtain the index * in the track table. For value 0, found in some files, I think * it means an empty track. */ for (i = 0; i < mod->len; i++) mod->xxo[i] = i; D_(D_INFO "Stored patterns: %d", mod->pat); mod->xxp = calloc(sizeof(struct xmp_pattern *), mod->pat + 1); if (mod->xxp == NULL) return -1; for (i = 0; i < mod->pat; i++) { if (pattern_alloc(mod, i) < 0) return -1; mod->xxp[i]->rows = ver >= 0x0e ? hio_read16l(f) : 64; for (j = 0; j < mod->chn; j++) { uint16 t = hio_read16l(f); mod->xxp[i]->index[j] = t; } } /* Instruments */ if (instrument_init(mod) < 0) return -1; /* Probe for 2-byte loop start 1.0 format * in facing_n.amf and sweetdrm.amf have only the sample * loop start specified in 2 bytes */ if (ver <= 0x0a) { uint8 b; uint32 len, start, end; long pos = hio_tell(f); for (i = 0; i < mod->ins; i++) { b = hio_read8(f); if (b != 0 && b != 1) { ver = 0x09; break; } hio_seek(f, 32 + 13, SEEK_CUR); if (hio_read32l(f) > 0x100000) { /* check index */ ver = 0x09; break; } len = hio_read32l(f); if (len > 0x100000) { /* check len */ ver = 0x09; break; } if (hio_read16l(f) == 0x0000) { /* check c2spd */ ver = 0x09; break; } if (hio_read8(f) > 0x40) { /* check volume */ ver = 0x09; break; } start = hio_read32l(f); if (start > len) { /* check loop start */ ver = 0x09; break; } end = hio_read32l(f); if (end > len) { /* check loop end */ ver = 0x09; break; } } hio_seek(f, pos, SEEK_SET); } for (i = 0; i < mod->ins; i++) { /*uint8 b;*/ int c2spd; if (subinstrument_alloc(mod, i, 1) < 0) return -1; /*b =*/ hio_read8(f); hio_read(buf, 1, 32, f); instrument_name(mod, i, buf, 32); hio_read(buf, 1, 13, f); /* sample name */ hio_read32l(f); /* sample index */ mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].sid = i; mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].len = hio_read32l(f); c2spd = hio_read16l(f); c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].vol = hio_read8(f); /* * Andre Timmermans <*****@*****.**> says: * * [Miodrag Vallat's] doc tells that in version 1.0 only * sample loop start is present (2 bytes) but the files I * have tells both start and end are present (2*4 bytes). * Maybe it should be read as version < 1.0. * * CM: confirmed with Maelcum's "The tribal zone" */ if (ver < 0x0a) { mod->xxs[i].lps = hio_read16l(f); mod->xxs[i].lpe = mod->xxs[i].len; } else { mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); } if (ver < 0x0a) { mod->xxs[i].flg = mod->xxs[i].lps > 0 ? XMP_SAMPLE_LOOP : 0; } else { mod->xxs[i].flg = mod->xxs[i].lpe > mod->xxs[i].lps ? XMP_SAMPLE_LOOP : 0; } D_(D_INFO "[%2X] %-32.32s %05x %05x %05x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); } /* Tracks */ trkmap = calloc(sizeof(int), mod->trk); if (trkmap == NULL) return -1; newtrk = 0; for (i = 0; i < mod->trk; i++) { /* read track table */ uint16 t; t = hio_read16l(f); trkmap[i] = t; if (t > newtrk) newtrk = t; /*printf("%d -> %d\n", i, t);*/ } for (i = 0; i < mod->pat; i++) { /* read track table */ for (j = 0; j < mod->chn; j++) { int k = mod->xxp[i]->index[j] - 1; /* Use empty track if an invalid track is requested * (such as in Lasse Makkonen "faster and louder") */ if (k < 0 || k >= mod->trk) k = 0; mod->xxp[i]->index[j] = trkmap[k]; /*printf("mod->xxp[%d]->info[%d].index = %d (k = %d)\n", i, j, trkmap[k], k);*/ } } mod->trk = newtrk; /* + empty track */ free(trkmap); D_(D_INFO "Stored tracks: %d", mod->trk); mod->trk++; mod->xxt = calloc (sizeof (struct xmp_track *), mod->trk); if (mod->xxt == NULL) return -1; /* Alloc track 0 as empty track */ if (track_alloc(mod, 0, 64) < 0) return -1; /* Alloc rest of the tracks */ for (i = 1; i < mod->trk; i++) { uint8 t1, t2, t3; int size; if (track_alloc(mod, i, 64) < 0) return -1; size = hio_read24l(f); /*printf("TRACK %d SIZE %d\n", i, size);*/ for (j = 0; j < size; j++) { t1 = hio_read8(f); /* row */ t2 = hio_read8(f); /* type */ t3 = hio_read8(f); /* parameter */ /*printf("track %d row %d: %02x %02x %02x\n", i, t1, t1, t2, t3);*/ if (t1 == 0xff && t2 == 0xff && t3 == 0xff) break; event = &mod->xxt[i]->event[t1]; if (t2 < 0x7f) { /* note */ if (t2 > 0) event->note = t2 + 1; event->vol = t3; } else if (t2 == 0x7f) { /* copy previous */ memcpy(event, &mod->xxt[i]->event[t1 - 1], sizeof(struct xmp_event)); } else if (t2 == 0x80) { /* instrument */ event->ins = t3 + 1; } else { /* effects */ uint8 fxp, fxt; fxp = fxt = 0; switch (t2) { case 0x81: fxt = FX_SPEED; fxp = t3; break; case 0x82: if ((int8)t3 > 0) { fxt = FX_VOLSLIDE; fxp = t3 << 4; } else { fxt = FX_VOLSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x83: event->vol = t3; break; case 0x84: /* AT: Not explained for 0x84, pitch * slide, value 0x00 corresponds to * S3M E00 and 0x80 stands for S3M F00 * (I checked with M2AMF) */ if ((int8)t3 >= 0) { fxt = FX_PORTA_DN; fxp = t3; } else if (t3 == 0x80) { fxt = FX_PORTA_UP; fxp = 0; } else { fxt = FX_PORTA_UP; fxp = -(int8)t3; } break; case 0x85: /* porta abs -- unknown */ break; case 0x86: fxt = FX_TONEPORTA; fxp = t3; break; /* AT: M2AMF maps both tremolo and tremor to * 0x87. Since tremor is only found in certain * formats, maybe it would be better to * consider it is a tremolo. */ case 0x87: fxt = FX_TREMOLO; fxp = t3; break; case 0x88: fxt = FX_ARPEGGIO; fxp = t3; break; case 0x89: fxt = FX_VIBRATO; fxp = t3; break; case 0x8a: if ((int8)t3 > 0) { fxt = FX_TONE_VSLIDE; fxp = t3 << 4; } else { fxt = FX_TONE_VSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x8b: if ((int8)t3 > 0) { fxt = FX_VIBRA_VSLIDE; fxp = t3 << 4; } else { fxt = FX_VIBRA_VSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x8c: fxt = FX_BREAK; fxp = t3; break; case 0x8d: fxt = FX_JUMP; fxp = t3; break; case 0x8e: /* sync -- unknown */ break; case 0x8f: fxt = FX_EXTENDED; fxp = (EX_RETRIG << 4) | (t3 & 0x0f); break; case 0x90: fxt = FX_OFFSET; fxp = t3; break; case 0x91: if ((int8)t3 > 0) { fxt = FX_EXTENDED; fxp = (EX_F_VSLIDE_UP << 4) | (t3 & 0x0f); } else { fxt = FX_EXTENDED; fxp = (EX_F_VSLIDE_DN << 4) | (t3 & 0x0f); } break; case 0x92: if ((int8)t3 > 0) { fxt = FX_PORTA_DN; fxp = 0xf0 | (fxp & 0x0f); } else { fxt = FX_PORTA_UP; fxp = 0xf0 | (fxp & 0x0f); } break; case 0x93: fxt = FX_EXTENDED; fxp = (EX_DELAY << 4) | (t3 & 0x0f); break; case 0x94: fxt = FX_EXTENDED; fxp = (EX_CUT << 4) | (t3 & 0x0f); break; case 0x95: fxt = FX_SPEED; if (t3 < 0x21) t3 = 0x21; fxp = t3; break; case 0x96: if ((int8)t3 > 0) { fxt = FX_PORTA_DN; fxp = 0xe0 | (fxp & 0x0f); } else { fxt = FX_PORTA_UP; fxp = 0xe0 | (fxp & 0x0f); } break; case 0x97: fxt = FX_SETPAN; fxp = 0x80 + 2 * (int8)t3; break; } event->fxt = fxt; event->fxp = fxp; } } } /* Samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; } m->quirk |= QUIRK_FINEFX; return 0; }
static int far_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, vib = 0; struct xmp_event *event; struct far_header ffh; struct far_header2 ffh2; struct far_instrument fih; uint8 sample_map[8]; LOAD_INIT(); hio_read32b(f); /* File magic: 'FAR\xfe' */ hio_read(&ffh.name, 40, 1, f); /* Song name */ hio_read(&ffh.crlf, 3, 1, f); /* 0x0d 0x0a 0x1A */ ffh.headersize = hio_read16l(f); /* Remaining header size in bytes */ ffh.version = hio_read8(f); /* Version MSN=major, LSN=minor */ hio_read(&ffh.ch_on, 16, 1, f); /* Channel on/off switches */ hio_seek(f, 9, SEEK_CUR); /* Current editing values */ ffh.tempo = hio_read8(f); /* Default tempo */ hio_read(&ffh.pan, 16, 1, f); /* Channel pan definitions */ hio_read32l(f); /* Grid, mode (for editor) */ ffh.textlen = hio_read16l(f); /* Length of embedded text */ /* Sanity check */ if (ffh.tempo == 0) { return -1; } hio_seek(f, ffh.textlen, SEEK_CUR); /* Skip song text */ hio_read(&ffh2.order, 256, 1, f); /* Orders */ ffh2.patterns = hio_read8(f); /* Number of stored patterns (?) */ ffh2.songlen = hio_read8(f); /* Song length in patterns */ ffh2.restart = hio_read8(f); /* Restart pos */ for (i = 0; i < 256; i++) { ffh2.patsize[i] = hio_read16l(f); /* Size of each pattern in bytes */ } mod->chn = 16; /*mod->pat=ffh2.patterns; (Error in specs? --claudio) */ mod->len = ffh2.songlen; mod->spd = 6; mod->bpm = 8 * 60 / ffh.tempo; memcpy (mod->xxo, ffh2.order, mod->len); for (mod->pat = i = 0; i < 256; i++) { if (ffh2.patsize[i]) mod->pat = i + 1; } mod->trk = mod->chn * mod->pat; strncpy(mod->name, (char *)ffh.name, 40); set_type(m, "Farandole Composer %d.%d", MSN(ffh.version), LSN(ffh.version)); MODULE_INFO(); if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Comment bytes : %d", ffh.textlen); D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { uint8 brk, note, ins, vol, fxb; int rows; if (pattern_alloc(mod, i) < 0) return -1; if (!ffh2.patsize[i]) continue; rows = (ffh2.patsize[i] - 2) / 64; /* Sanity check */ if (rows <= 0 || rows > 256) { return -1; } mod->xxp[i]->rows = rows; if (tracks_in_pattern_alloc(mod, i) < 0) return -1; brk = hio_read8(f) + 1; hio_read8(f); for (j = 0; j < mod->xxp[i]->rows * mod->chn; j++) { event = &EVENT(i, j % mod->chn, j / mod->chn); if ((j % mod->chn) == 0 && (j / mod->chn) == brk) event->f2t = FX_BREAK; note = hio_read8(f); ins = hio_read8(f); vol = hio_read8(f); fxb = hio_read8(f); if (note) event->note = note + 48; if (event->note || ins) event->ins = ins + 1; vol = 16 * LSN(vol) + MSN(vol); if (vol) event->vol = vol - 0x10; /* ? */ event->fxt = fx[MSN(fxb)]; event->fxp = LSN(fxb); switch (event->fxt) { case NONE: event->fxt = event->fxp = 0; break; case FX_FAR_PORTA_UP: event->fxt = FX_EXTENDED; event->fxp |= (EX_F_PORTA_UP << 4); break; case FX_FAR_PORTA_DN: event->fxt = FX_EXTENDED; event->fxp |= (EX_F_PORTA_DN << 4); break; case FX_FAR_RETRIG: event->fxt = FX_EXTENDED; event->fxp |= (EX_RETRIG << 4); break; case FX_FAR_DELAY: event->fxt = FX_EXTENDED; event->fxp |= (EX_DELAY << 4); break; case FX_FAR_SETVIBRATO: vib = event->fxp & 0x0f; event->fxt = event->fxp = 0; break; case FX_VIBRATO: event->fxp = (event->fxp << 4) + vib; break; case FX_PER_VIBRATO: event->fxp = (event->fxp << 4) + vib; break; case FX_FAR_VSLIDE_UP: /* Fine volume slide up */ event->fxt = FX_EXTENDED; event->fxp |= (EX_F_VSLIDE_UP << 4); break; case FX_FAR_VSLIDE_DN: /* Fine volume slide down */ event->fxt = FX_EXTENDED; event->fxp |= (EX_F_VSLIDE_DN << 4); break; case FX_SPEED: if (event->fxp != 0) { event->fxp = 8 * 60 / event->fxp; } else { event->fxt = 0; } break; } } } mod->ins = -1; hio_read(sample_map, 1, 8, f); for (i = 0; i < 64; i++) { if (sample_map[i / 8] & (1 << (i % 8))) mod->ins = i; } mod->ins++; mod->smp = mod->ins; if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { if (!(sample_map[i / 8] & (1 << (i % 8)))) continue; if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(&fih.name, 32, 1, f); /* Instrument name */ fih.length = hio_read32l(f); /* Length of sample (up to 64Kb) */ fih.finetune = hio_read8(f); /* Finetune (unsuported) */ fih.volume = hio_read8(f); /* Volume (unsuported?) */ fih.loop_start = hio_read32l(f);/* Loop start */ fih.loopend = hio_read32l(f); /* Loop end */ fih.sampletype = hio_read8(f); /* 1=16 bit sample */ fih.loopmode = hio_read8(f); /* Sanity check */ if (fih.length > 0x10000 || fih.loop_start > 0x10000 || fih.loopend > 0x10000) { return -1; } mod->xxs[i].len = fih.length; mod->xxs[i].lps = fih.loop_start; mod->xxs[i].lpe = fih.loopend; mod->xxs[i].flg = 0; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; if (fih.sampletype != 0) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } mod->xxs[i].flg |= fih.loopmode ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].vol = 0xff; /* fih.volume; */ mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, fih.name, 32); D_(D_INFO "[%2X] %-32.32s %04x %04x %04x %c V%02x", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, fih.loopmode ? 'L' : ' ', mod->xxi[i].sub[0].vol); if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; }
static int gdm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int vermaj, vermin, tvmaj, tvmin, tracker; int /*origfmt,*/ ord_ofs, pat_ofs, ins_ofs, smp_ofs; uint8 buffer[32], panmap[32]; int i; LOAD_INIT(); hio_read32b(f); /* skip magic */ hio_read(mod->name, 1, 32, f); hio_seek(f, 32, SEEK_CUR); /* skip author */ hio_seek(f, 7, SEEK_CUR); vermaj = hio_read8(f); vermin = hio_read8(f); tracker = hio_read16l(f); tvmaj = hio_read8(f); tvmin = hio_read8(f); if (tracker == 0) { libxmp_set_type(m, "GDM %d.%02d (2GDM %d.%02d)", vermaj, vermin, tvmaj, tvmin); } else { libxmp_set_type(m, "GDM %d.%02d (unknown tracker %d.%02d)", vermaj, vermin, tvmaj, tvmin); } hio_read(panmap, 32, 1, f); for (i = 0; i < 32; i++) { if (panmap[i] == 255) { panmap[i] = 8; mod->xxc[i].vol = 0; mod->xxc[i].flg |= XMP_CHANNEL_MUTE; } else if (panmap[i] == 16) { panmap[i] = 8; } mod->xxc[i].pan = 0x80 + (panmap[i] - 8) * 16; } mod->gvl = hio_read8(f); mod->spd = hio_read8(f); mod->bpm = hio_read8(f); /*origfmt =*/ hio_read16l(f); ord_ofs = hio_read32l(f); mod->len = hio_read8(f) + 1; pat_ofs = hio_read32l(f); mod->pat = hio_read8(f) + 1; ins_ofs = hio_read32l(f); smp_ofs = hio_read32l(f); mod->ins = mod->smp = hio_read8(f) + 1; m->c4rate = C4_NTSC_RATE; MODULE_INFO(); hio_seek(f, start + ord_ofs, SEEK_SET); for (i = 0; i < mod->len; i++) mod->xxo[i] = hio_read8(f); /* Read instrument data */ hio_seek(f, start + ins_ofs, SEEK_SET); if (libxmp_init_instrument(m) < 0) return -1; for (i = 0; i < mod->ins; i++) { int flg, c4spd, vol, pan; if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; if (hio_read(buffer, 1, 32, f) != 32) return -1; libxmp_instrument_name(mod, i, buffer, 32); hio_seek(f, 12, SEEK_CUR); /* skip filename */ hio_read8(f); /* skip EMS handle */ mod->xxs[i].len = hio_read32l(f); mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); flg = hio_read8(f); c4spd = hio_read16l(f); vol = hio_read8(f); pan = hio_read8(f); mod->xxi[i].sub[0].vol = vol > 0x40 ? 0x40 : vol; mod->xxi[i].sub[0].pan = pan > 15 ? 0x80 : 0x80 + (pan - 8) * 16; libxmp_c2spd_to_note(c4spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].sid = i; mod->xxs[i].flg = 0; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; if (flg & 0x01) { mod->xxs[i].flg |= XMP_SAMPLE_LOOP; } if (flg & 0x02) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } D_(D_INFO "[%2X] %-32.32s %05x%c%05x %05x %c V%02x P%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].pan, c4spd); }
static int stx_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i, broken = 0; struct xmp_event *event = 0, dummy; struct stx_file_header sfh; struct stx_instrument_header sih; uint8 n, b; uint16 x16; int bmod2stm = 0; uint16 *pp_ins; /* Parapointers to instruments */ uint16 *pp_pat; /* Parapointers to patterns */ LOAD_INIT(); hio_read(&sfh.name, 20, 1, f); hio_read(&sfh.magic, 8, 1, f); sfh.psize = hio_read16l(f); sfh.unknown1 = hio_read16l(f); sfh.pp_pat = hio_read16l(f); sfh.pp_ins = hio_read16l(f); sfh.pp_chn = hio_read16l(f); sfh.unknown2 = hio_read16l(f); sfh.unknown3 = hio_read16l(f); sfh.gvol = hio_read8(f); sfh.tempo = hio_read8(f); sfh.unknown4 = hio_read16l(f); sfh.unknown5 = hio_read16l(f); sfh.patnum = hio_read16l(f); sfh.insnum = hio_read16l(f); sfh.ordnum = hio_read16l(f); sfh.unknown6 = hio_read16l(f); sfh.unknown7 = hio_read16l(f); sfh.unknown8 = hio_read16l(f); hio_read(&sfh.magic2, 4, 1, f); /* Sanity check */ if (sfh.patnum > 254 || sfh.insnum > 256 || sfh.ordnum > 256) return -1; /* BMOD2STM does not convert pitch */ if (!strncmp ((char *) sfh.magic, "BMOD2STM", 8)) bmod2stm = 1; #if 0 if ((strncmp ((char *) sfh.magic, "!Scream!", 8) && !bmod2stm) || strncmp ((char *) sfh.magic2, "SCRM", 4)) return -1; #endif mod->ins = sfh.insnum; mod->pat = sfh.patnum; mod->trk = mod->pat * mod->chn; mod->len = sfh.ordnum; mod->spd = MSN (sfh.tempo); mod->smp = mod->ins; m->c4rate = C4_NTSC_RATE; /* STM2STX 1.0 released with STMIK 0.2 converts STMs with the pattern * length encoded in the first two bytes of the pattern (like S3M). */ hio_seek(f, start + (sfh.pp_pat << 4), SEEK_SET); x16 = hio_read16l(f); hio_seek(f, start + (x16 << 4), SEEK_SET); x16 = hio_read16l(f); if (x16 == sfh.psize) broken = 1; strncpy(mod->name, (char *)sfh.name, 20); if (bmod2stm) set_type(m, "BMOD2STM STX"); else snprintf(mod->type, XMP_NAME_SIZE, "STM2STX 1.%d", broken ? 0 : 1); MODULE_INFO(); pp_pat = calloc (2, mod->pat); if (pp_pat == NULL) goto err; pp_ins = calloc (2, mod->ins); if (pp_ins == NULL) goto err2; /* Read pattern pointers */ hio_seek(f, start + (sfh.pp_pat << 4), SEEK_SET); for (i = 0; i < mod->pat; i++) pp_pat[i] = hio_read16l(f); /* Read instrument pointers */ hio_seek(f, start + (sfh.pp_ins << 4), SEEK_SET); for (i = 0; i < mod->ins; i++) pp_ins[i] = hio_read16l(f); /* Skip channel table (?) */ hio_seek(f, start + (sfh.pp_chn << 4) + 32, SEEK_SET); /* Read orders */ for (i = 0; i < mod->len; i++) { mod->xxo[i] = hio_read8(f); hio_seek(f, 4, SEEK_CUR); } if (instrument_init(mod) < 0) goto err3; /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) goto err3; hio_seek(f, start + (pp_ins[i] << 4), SEEK_SET); sih.type = hio_read8(f); hio_read(&sih.dosname, 13, 1, f); sih.memseg = hio_read16l(f); sih.length = hio_read32l(f); sih.loopbeg = hio_read32l(f); sih.loopend = hio_read32l(f); sih.vol = hio_read8(f); sih.rsvd1 = hio_read8(f); sih.pack = hio_read8(f); sih.flags = hio_read8(f); sih.c2spd = hio_read16l(f); sih.rsvd2 = hio_read16l(f); hio_read(&sih.rsvd3, 4, 1, f); sih.int_gp = hio_read16l(f); sih.int_512 = hio_read16l(f); sih.int_last = hio_read32l(f); hio_read(&sih.name, 28, 1, f); hio_read(&sih.magic, 4, 1, f); mod->xxs[i].len = sih.length; mod->xxs[i].lps = sih.loopbeg; mod->xxs[i].lpe = sih.loopend; if (mod->xxs[i].lpe == 0xffff) mod->xxs[i].lpe = 0; mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].vol = sih.vol; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].nsm = 1; instrument_name(mod, i, sih.name, 12); D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x %5d\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, sih.c2spd); sih.c2spd = 8363 * sih.c2spd / 8448; c2spd_to_note(sih.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); } if (pattern_init(mod) < 0) goto err3; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) goto err3; if (pp_pat[i] == 0) continue; hio_seek(f, start + (pp_pat[i] << 4), SEEK_SET); if (broken) hio_seek(f, 2, SEEK_CUR); for (r = 0; r < 64; ) { b = hio_read8(f); if (b == S3M_EOR) { r++; continue; } c = b & S3M_CH_MASK; event = c >= mod->chn ? &dummy : &EVENT (i, c, r); if (b & S3M_NI_FOLLOW) { n = hio_read8(f); switch (n) { case 255: n = 0; break; /* Empty note */ case 254: n = XMP_KEY_OFF; break; /* Key off */ default: n = 37 + 12 * MSN (n) + LSN (n); } event->note = n; event->ins = hio_read8(f);; } if (b & S3M_VOL_FOLLOWS) { event->vol = hio_read8(f) + 1; } if (b & S3M_FX_FOLLOWS) { event->fxt = fx[hio_read8(f)]; event->fxp = hio_read8(f); switch (event->fxt) { case FX_SPEED: event->fxp = MSN (event->fxp); break; case FX_NONE: event->fxp = event->fxt = 0; break; } } } } free (pp_ins); free (pp_pat); /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) goto err; } m->quirk |= QUIRK_VSALL | QUIRKS_ST3; m->read_event_type = READ_EVENT_ST3; return 0; err3: free(pp_ins); err2: free(pp_pat); err: return -1; }
static int mtm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct mtm_file_header mfh; struct mtm_instrument_header mih; uint8 mt[192]; uint16 mp[32]; LOAD_INIT(); hio_read(&mfh.magic, 3, 1, f); /* "MTM" */ mfh.version = hio_read8(f); /* MSN=major, LSN=minor */ hio_read(&mfh.name, 20, 1, f); /* ASCIIZ Module name */ mfh.tracks = hio_read16l(f); /* Number of tracks saved */ mfh.patterns = hio_read8(f); /* Number of patterns saved */ mfh.modlen = hio_read8(f); /* Module length */ mfh.extralen = hio_read16l(f); /* Length of the comment field */ mfh.samples = hio_read8(f); /* Number of samples */ mfh.attr = hio_read8(f); /* Always zero */ mfh.rows = hio_read8(f); /* Number rows per track */ mfh.channels = hio_read8(f); /* Number of tracks per pattern */ hio_read(&mfh.pan, 32, 1, f); /* Pan positions for each channel */ #if 0 if (strncmp ((char *)mfh.magic, "MTM", 3)) return -1; #endif mod->trk = mfh.tracks + 1; mod->pat = mfh.patterns + 1; mod->len = mfh.modlen + 1; mod->ins = mfh.samples; mod->smp = mod->ins; mod->chn = mfh.channels; mod->spd = 6; mod->bpm = 125; strncpy(mod->name, (char *)mfh.name, 20); set_type(m, "MultiTracker %d.%02d MTM", MSN(mfh.version), LSN(mfh.version)); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; /* Read and convert instruments */ for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(&mih.name, 22, 1, f); /* Instrument name */ mih.length = hio_read32l(f); /* Instrument length in bytes */ mih.loop_start = hio_read32l(f); /* Sample loop start */ mih.loopend = hio_read32l(f); /* Sample loop end */ mih.finetune = hio_read8(f); /* Finetune */ mih.volume = hio_read8(f); /* Playback volume */ mih.attr = hio_read8(f); /* &0x01: 16bit sample */ mod->xxs[i].len = mih.length; mod->xxs[i].lps = mih.loop_start; mod->xxs[i].lpe = mih.loopend; mod->xxs[i].flg = mod->xxs[i].lpe ? XMP_SAMPLE_LOOP : 0; /* 1 == Forward loop */ if (mfh.attr & 1) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } mod->xxi[i].sub[0].vol = mih.volume; mod->xxi[i].sub[0].fin = mih.finetune; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, mih.name, 22); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %-22.22s %04x%c%04x %04x %c V%02x F%+03d\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin - 0x80); }
static int it_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int r, c, i, j, k, pat_len; struct xmp_event *event, dummy, lastevent[L_CHANNELS]; struct it_file_header ifh; struct it_instrument1_header i1h; struct it_instrument2_header i2h; struct it_sample_header ish; struct it_envelope env; uint8 b, mask[L_CHANNELS]; int max_ch; int inst_map[120], inst_rmap[XMP_MAX_KEYS]; #ifndef LIBXMP_CORE_PLAYER char tracker_name[40]; #endif uint32 *pp_ins; /* Pointers to instruments */ uint32 *pp_smp; /* Pointers to samples */ uint32 *pp_pat; /* Pointers to patterns */ uint8 last_fxp[64]; int dca2nna[] = { 0, 2, 3 }; int new_fx; LOAD_INIT(); /* Load and convert header */ hio_read32b(f); /* magic */ hio_read(&ifh.name, 26, 1, f); ifh.hilite_min = hio_read8(f); ifh.hilite_maj = hio_read8(f); ifh.ordnum = hio_read16l(f); ifh.insnum = hio_read16l(f); ifh.smpnum = hio_read16l(f); ifh.patnum = hio_read16l(f); ifh.cwt = hio_read16l(f); ifh.cmwt = hio_read16l(f); ifh.flags = hio_read16l(f); ifh.special = hio_read16l(f); ifh.gv = hio_read8(f); ifh.mv = hio_read8(f); ifh.is = hio_read8(f); ifh.it = hio_read8(f); ifh.sep = hio_read8(f); ifh.pwd = hio_read8(f); ifh.msglen = hio_read16l(f); ifh.msgofs = hio_read32l(f); ifh.rsvd = hio_read32l(f); hio_read(&ifh.chpan, 64, 1, f); hio_read(&ifh.chvol, 64, 1, f); strncpy(mod->name, (char *)ifh.name, XMP_NAME_SIZE); mod->len = ifh.ordnum; mod->ins = ifh.insnum; mod->smp = ifh.smpnum; mod->pat = ifh.patnum; if (mod->ins) { pp_ins = calloc(4, mod->ins); if (pp_ins == NULL) goto err; } else { pp_ins = NULL; } pp_smp = calloc(4, mod->smp); if (pp_smp == NULL) goto err2; pp_pat = calloc(4, mod->pat); if (pp_pat == NULL) goto err3; mod->spd = ifh.is; mod->bpm = ifh.it; if (ifh.flags & IT_LINEAR_FREQ) { m->quirk |= QUIRK_LINEAR; } if ((ifh.flags & IT_USE_INST) && ifh.cmwt >= 0x200) { m->quirk |= QUIRK_INSVOL; } for (i = 0; i < 64; i++) { struct xmp_channel *xxc = &mod->xxc[i]; if (ifh.chpan[i] == 100) /* Surround -> center */ ifh.chpan[i] = 32; if (ifh.chpan[i] & 0x80) { /* Channel mute */ ifh.chvol[i] = 0; mod->xxc[i].flg |= XMP_CHANNEL_MUTE; } if (ifh.flags & IT_STEREO) { xxc->pan = (int)ifh.chpan[i] * 0x80 >> 5; if (xxc->pan > 0xff) xxc->pan = 0xff; } else {
int xmp_smix_load_sample(xmp_context opaque, int num, char *path) { struct context_data *ctx = (struct context_data *)opaque; struct smix_data *smix = &ctx->smix; struct module_data *m = &ctx->m; struct xmp_instrument *xxi; struct xmp_sample *xxs; HIO_HANDLE *h; uint32 magic; int chn, rate, bits, size; int retval = -XMP_ERROR_INTERNAL; if (num >= smix->ins) { retval = -XMP_ERROR_INVALID; goto err; } xxi = &smix->xxi[num]; xxs = &smix->xxs[num]; h = hio_open_file(path, "rb"); if (h == NULL) { retval = -XMP_ERROR_SYSTEM; goto err; } /* Init instrument */ xxi->sub = calloc(sizeof(struct xmp_subinstrument), 1); if (xxi->sub == NULL) { retval = -XMP_ERROR_SYSTEM; goto err1; } xxi->vol = m->volbase; xxi->nsm = 1; xxi->sub[0].sid = num; xxi->sub[0].vol = xxi->vol; xxi->sub[0].pan = 0x80; /* Load sample */ magic = hio_read32b(h); if (magic != 0x52494646) { /* RIFF */ retval = -XMP_ERROR_FORMAT; goto err2; } hio_seek(h, 22, SEEK_SET); chn = hio_read16l(h); if (chn != 1) { retval = -XMP_ERROR_FORMAT; goto err2; } rate = hio_read32l(h); hio_seek(h, 34, SEEK_SET); bits = hio_read16l(h); hio_seek(h, 40, SEEK_SET); size = hio_read32l(h) / (bits / 8); c2spd_to_note(rate, &xxi->sub[0].xpo, &xxi->sub[0].fin); xxs->len = 8 * size / bits; xxs->lps = 0; xxs->lpe = 0; xxs->flg = bits == 16 ? XMP_SAMPLE_16BIT : 0; xxs->data = malloc(size); if (xxs->data == NULL) { retval = -XMP_ERROR_SYSTEM; goto err2; } hio_seek(h, 44, SEEK_SET); hio_read(xxs->data, 1, size, h); hio_close(h); return 0; err2: free(xxi->sub); xxi->sub = NULL; err1: hio_close(h); err: return retval; }
static int load_patterns(struct module_data *m, int version, HIO_HANDLE *f) { struct xmp_module *mod = &m->mod; struct xm_pattern_header xph; struct xmp_event *event; uint8 *patbuf, *pat, b; int i, j, r; mod->pat++; if (pattern_init(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat - 1); /* Endianism fixed by Miodrag Vallat <*****@*****.**> * Mon, 04 Jan 1999 11:17:20 +0100 */ for (i = 0; i < mod->pat - 1; i++) { const int headsize = version > 0x0102 ? 9 : 8; xph.length = hio_read32l(f); xph.packing = hio_read8(f); xph.rows = version > 0x0102 ? hio_read16l(f) : hio_read8(f) + 1; /* Sanity check */ if (xph.rows > 256) goto err; xph.datasize = hio_read16l(f); hio_seek(f, xph.length - headsize, SEEK_CUR); if (hio_error(f)) { goto err; } r = xph.rows; if (r == 0) r = 0x100; if (pattern_tracks_alloc(mod, i, r) < 0) goto err; if (xph.datasize) { int size = xph.datasize; pat = patbuf = calloc(1, size); if (patbuf == NULL) goto err; hio_read(patbuf, 1, size, f); for (j = 0; j < (mod->chn * r); j++) { /*if ((pat - patbuf) >= xph.datasize) break;*/ event = &EVENT(i, j % mod->chn, j / mod->chn); if (--size < 0) goto err2; if ((b = *pat++) & XM_EVENT_PACKING) { if (b & XM_EVENT_NOTE_FOLLOWS) { if (--size < 0) goto err2; event->note = *pat++; } if (b & XM_EVENT_INSTRUMENT_FOLLOWS) { if (--size < 0) goto err2; event->ins = *pat++; } if (b & XM_EVENT_VOLUME_FOLLOWS) { if (--size < 0) goto err2; event->vol = *pat++; } if (b & XM_EVENT_FXTYPE_FOLLOWS) { if (--size < 0) goto err2; event->fxt = *pat++; } if (b & XM_EVENT_FXPARM_FOLLOWS) { if (--size < 0) goto err2; event->fxp = *pat++; } } else { size -=4; if (size < 0) goto err2; event->note = b; event->ins = *pat++; event->vol = *pat++; event->fxt = *pat++; event->fxp = *pat++; } /* Sanity check */ switch (event->fxt) { case 18: case 19: case 22: case 23: case 24: case 26: case 28: case 30: case 31: case 32: event->fxt = 0; } if (event->fxt > 34) { event->fxt = 0; } if (event->note == 0x61) { /* See OpenMPT keyoff+instr.xm test case */ if (event->fxt == 0x0e && MSN(event->fxp) == 0x0d) { event->note = XMP_KEY_OFF; } else { event->note = event->ins ? XMP_KEY_FADE : XMP_KEY_OFF; } } else if (event->note > 0) { event->note += 12; } if (event->fxt == 0x0e) { switch (event->fxp) { case 0x43: case 0x73: event->fxp--; break; } } if (!event->vol) continue; /* Volume set */ if ((event->vol >= 0x10) && (event->vol <= 0x50)) { event->vol -= 0x0f; continue; } /* Volume column effects */ switch (event->vol >> 4) { case 0x06: /* Volume slide down */ event->f2t = FX_VOLSLIDE_2; event->f2p = event->vol - 0x60; break; case 0x07: /* Volume slide up */ event->f2t = FX_VOLSLIDE_2; event->f2p = (event->vol - 0x70) << 4; break; case 0x08: /* Fine volume slide down */ event->f2t = FX_EXTENDED; event->f2p = (EX_F_VSLIDE_DN << 4) | (event->vol - 0x80); break; case 0x09: /* Fine volume slide up */ event->f2t = FX_EXTENDED; event->f2p = (EX_F_VSLIDE_UP << 4) | (event->vol - 0x90); break; case 0x0a: /* Set vibrato speed */ event->f2t = FX_VIBRATO; event->f2p = (event->vol - 0xa0) << 4; break; case 0x0b: /* Vibrato */ event->f2t = FX_VIBRATO; event->f2p = event->vol - 0xb0; break; case 0x0c: /* Set panning */ event->f2t = FX_SETPAN; event->f2p = (event->vol - 0xc0) << 4; break; case 0x0d: /* Pan slide left */ event->f2t = FX_PANSL_NOMEM; event->f2p = (event->vol - 0xd0) << 4; break; case 0x0e: /* Pan slide right */ event->f2t = FX_PANSL_NOMEM; event->f2p = event->vol - 0xe0; break; case 0x0f: /* Tone portamento */ event->f2t = FX_TONEPORTA; event->f2p = (event->vol - 0xf0) << 4; /* From OpenMPT TonePortamentoMemory.xm: * "Another nice bug (...) is the combination of both * portamento commands (Mx and 3xx) in the same cell: * The 3xx parameter is ignored completely, and the Mx * parameter is doubled. (M2 3FF is the same as M4 000) */ if (event->fxt == FX_TONEPORTA || event->fxt == FX_TONE_VSLIDE) { if (event->fxt == FX_TONEPORTA) { event->fxt = 0; } else { event->fxt = FX_VOLSLIDE; } event->fxp = 0; if (event->f2p < 0x80) { event->f2p <<= 1; } else { event->f2p = 0xff; } } /* From OpenMPT porta-offset.xm: * "If there is a portamento command next to an offset * command, the offset command is ignored completely. In * particular, the offset parameter is not memorized." */ if (event->fxt == FX_OFFSET && event->f2t == FX_TONEPORTA) { event->fxt = event->fxp = 0; } break; } event->vol = 0; } free(patbuf); } }
static int psm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i; struct xmp_event *event; uint8 buf[1024]; uint32 p_ord, p_chn, p_pat, p_ins; uint32 p_smp[64]; int type, ver /*, mode*/; LOAD_INIT(); hio_read32b(f); hio_read(buf, 1, 60, f); strncpy(mod->name, (char *)buf, 60); type = hio_read8(f); /* song type */ ver = hio_read8(f); /* song version */ /*mode =*/ hio_read8(f); /* pattern version */ if (type & 0x01) /* song mode not supported */ return -1; libxmp_set_type(m, "Protracker Studio PSM %d.%02d", MSN(ver), LSN(ver)); mod->spd = hio_read8(f); mod->bpm = hio_read8(f); hio_read8(f); /* master volume */ hio_read16l(f); /* song length */ mod->len = hio_read16l(f); mod->pat = hio_read16l(f); mod->ins = hio_read16l(f); hio_read16l(f); /* ignore channels to play */ mod->chn = hio_read16l(f); /* use channels to proceed */ mod->smp = mod->ins; mod->trk = mod->pat * mod->chn; /* Sanity check */ if (mod->len > 256 || mod->pat > 256 || mod->ins > 255 || mod->chn > XMP_MAX_CHANNELS) { return -1; } p_ord = hio_read32l(f); p_chn = hio_read32l(f); p_pat = hio_read32l(f); p_ins = hio_read32l(f); /* should be this way but fails with Silverball song 6 */ //mod->flg |= ~type & 0x02 ? XXM_FLG_MODRNG : 0; m->c4rate = C4_NTSC_RATE; MODULE_INFO(); hio_seek(f, start + p_ord, SEEK_SET); hio_read(mod->xxo, 1, mod->len, f); hio_seek(f, start + p_chn, SEEK_SET); hio_read(buf, 1, 16, f); if (libxmp_init_instrument(m) < 0) return -1; hio_seek(f, start + p_ins, SEEK_SET); for (i = 0; i < mod->ins; i++) { uint16 flags, c2spd; int finetune; if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; hio_read(buf, 1, 13, f); /* sample filename */ hio_read(buf, 1, 24, f); /* sample description */ buf[24] = 0; /* add string termination */ strncpy((char *)mod->xxi[i].name, (char *)buf, 24); p_smp[i] = hio_read32l(f); hio_read32l(f); /* memory location */ hio_read16l(f); /* sample number */ flags = hio_read8(f); /* sample type */ mod->xxs[i].len = hio_read32l(f); mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); finetune = (int8)(hio_read8(f) << 4); mod->xxi[i].sub[0].vol = hio_read8(f); c2spd = hio_read16l(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxs[i].flg = flags & 0x80 ? XMP_SAMPLE_LOOP : 0; mod->xxs[i].flg |= flags & 0x20 ? XMP_SAMPLE_LOOP_BIDIR : 0; libxmp_c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].fin += finetune; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); } if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); hio_seek(f, start + p_pat, SEEK_SET); for (i = 0; i < mod->pat; i++) { int len; uint8 b, rows, chan; len = hio_read16l(f) - 4; rows = hio_read8(f); if (rows > 64) { return -1; } chan = hio_read8(f); if (chan > 32) { return -1; } if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0) return -1; for (r = 0; r < rows; r++) { while (len > 0) { b = hio_read8(f); len--; if (b == 0) break; c = b & 0x0f; if (c >= mod->chn) return -1; event = &EVENT(i, c, r); if (b & 0x80) { event->note = hio_read8(f) + 36 + 1; event->ins = hio_read8(f); len -= 2; } if (b & 0x40) { event->vol = hio_read8(f) + 1; len--; } if (b & 0x20) { event->fxt = hio_read8(f); event->fxp = hio_read8(f); len -= 2; } } } if (len > 0) hio_seek(f, len, SEEK_CUR); } /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { hio_seek(f, start + p_smp[i], SEEK_SET); if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) return -1; } return 0; }
static int rtm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, r; struct xmp_event *event; struct ObjectHeader oh; struct RTMMHeader rh; struct RTNDHeader rp; struct RTINHeader ri; struct RTSMHeader rs; int offset, smpnum, version; char tracker_name[21], composer[33]; LOAD_INIT(); if (read_object_header(f, &oh, "RTMM") < 0) return -1; version = oh.version; hio_read(tracker_name, 1, 20, f); tracker_name[20] = 0; hio_read(composer, 1, 32, f); composer[32] = 0; rh.flags = hio_read16l(f); /* bit 0: linear table, bit 1: track names */ rh.ntrack = hio_read8(f); rh.ninstr = hio_read8(f); rh.nposition = hio_read16l(f); rh.npattern = hio_read16l(f); rh.speed = hio_read8(f); rh.tempo = hio_read8(f); hio_read(&rh.panning, 32, 1, f); rh.extraDataSize = hio_read32l(f); /* Sanity check */ if (rh.nposition > 255 || rh.ntrack > 32 || rh.npattern > 255) { return -1; } if (version >= 0x0112) hio_seek(f, 32, SEEK_CUR); /* skip original name */ for (i = 0; i < rh.nposition; i++) { mod->xxo[i] = hio_read16l(f); if (mod->xxo[i] >= rh.npattern) { return -1; } } strncpy(mod->name, oh.name, 20); snprintf(mod->type, XMP_NAME_SIZE, "%s RTM %x.%02x", tracker_name, version >> 8, version & 0xff); /* strncpy(m->author, composer, XMP_NAME_SIZE); */ mod->len = rh.nposition; mod->pat = rh.npattern; mod->chn = rh.ntrack; mod->trk = mod->chn * mod->pat; mod->ins = rh.ninstr; mod->spd = rh.speed; mod->bpm = rh.tempo; m->c4rate = C4_NTSC_RATE; m->period_type = rh.flags & 0x01 ? PERIOD_LINEAR : PERIOD_AMIGA; MODULE_INFO(); for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = rh.panning[i] & 0xff; if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); offset = 42 + oh.headerSize + rh.extraDataSize; for (i = 0; i < mod->pat; i++) { uint8 c; hio_seek(f, start + offset, SEEK_SET); if (read_object_header(f, &oh, "RTND") < 0) { D_(D_CRIT "Error reading pattern %d", i); return -1; } rp.flags = hio_read16l(f); rp.ntrack = hio_read8(f); rp.nrows = hio_read16l(f); rp.datasize = hio_read32l(f); /* Sanity check */ if (rp.ntrack > rh.ntrack || rp.nrows > 256) { return -1; } offset += 42 + oh.headerSize + rp.datasize; if (libxmp_alloc_pattern_tracks(mod, i, rp.nrows) < 0) return -1; for (r = 0; r < rp.nrows; r++) { for (j = 0; /*j < rp.ntrack */; j++) { c = hio_read8(f); if (c == 0) /* next row */ break; /* Sanity check */ if (j >= rp.ntrack) { return -1; } event = &EVENT(i, j, r); if (c & 0x01) { /* set track */ j = hio_read8(f); /* Sanity check */ if (j >= rp.ntrack) { return -1; } event = &EVENT(i, j, r); } if (c & 0x02) { /* read note */ event->note = hio_read8(f) + 1; if (event->note == 0xff) { event->note = XMP_KEY_OFF; } else { event->note += 12; } } if (c & 0x04) /* read instrument */ event->ins = hio_read8(f); if (c & 0x08) /* read effect */ event->fxt = hio_read8(f); if (c & 0x10) /* read parameter */ event->fxp = hio_read8(f); if (c & 0x20) /* read effect 2 */ event->f2t = hio_read8(f); if (c & 0x40) /* read parameter 2 */ event->f2p = hio_read8(f); } } } /* * load instruments */ D_(D_INFO "Instruments: %d", mod->ins); hio_seek(f, start + offset, SEEK_SET); /* ESTIMATED value! We don't know the actual value at this point */ mod->smp = MAX_SAMP; if (libxmp_init_instrument(m) < 0) return -1; smpnum = 0; for (i = 0; i < mod->ins; i++) { struct xmp_instrument *xxi = &mod->xxi[i]; if (read_object_header(f, &oh, "RTIN") < 0) { D_(D_CRIT "Error reading instrument %d", i); return -1; } libxmp_instrument_name(mod, i, (uint8 *)&oh.name, 32); if (oh.headerSize == 0) { D_(D_INFO "[%2X] %-26.26s %2d ", i, xxi->name, xxi->nsm); ri.nsample = 0; continue; } ri.nsample = hio_read8(f); ri.flags = hio_read16l(f); /* bit 0 : default panning enabled */ if (hio_read(&ri.table, 1, 120, f) != 120) return -1; ri.volumeEnv.npoint = hio_read8(f); /* Sanity check */ if (ri.volumeEnv.npoint >= 12) return -1; for (j = 0; j < 12; j++) { ri.volumeEnv.point[j].x = hio_read32l(f); ri.volumeEnv.point[j].y = hio_read32l(f); } ri.volumeEnv.sustain = hio_read8(f); ri.volumeEnv.loopstart = hio_read8(f); ri.volumeEnv.loopend = hio_read8(f); ri.volumeEnv.flags = hio_read16l(f); /* bit 0:enable 1:sus 2:loop */ ri.panningEnv.npoint = hio_read8(f); /* Sanity check */ if (ri.panningEnv.npoint >= 12) return -1; for (j = 0; j < 12; j++) { ri.panningEnv.point[j].x = hio_read32l(f); ri.panningEnv.point[j].y = hio_read32l(f); } ri.panningEnv.sustain = hio_read8(f); ri.panningEnv.loopstart = hio_read8(f); ri.panningEnv.loopend = hio_read8(f); ri.panningEnv.flags = hio_read16l(f); ri.vibflg = hio_read8(f); ri.vibsweep = hio_read8(f); ri.vibdepth = hio_read8(f); ri.vibrate = hio_read8(f); ri.volfade = hio_read16l(f); if (version >= 0x0110) { ri.midiPort = hio_read8(f); ri.midiChannel = hio_read8(f); ri.midiProgram = hio_read8(f); ri.midiEnable = hio_read8(f); } if (version >= 0x0112) { ri.midiTranspose = hio_read8(f); ri.midiBenderRange = hio_read8(f); ri.midiBaseVolume = hio_read8(f); ri.midiUseVelocity = hio_read8(f); } xxi->nsm = ri.nsample; D_(D_INFO "[%2X] %-26.26s %2d", i, xxi->name, xxi->nsm); if (xxi->nsm > 16) xxi->nsm = 16; if (libxmp_alloc_subinstrument(mod, i, xxi->nsm) < 0) return -1; for (j = 0; j < 120; j++) xxi->map[j].ins = ri.table[j]; /* Envelope */ xxi->rls = ri.volfade; xxi->aei.npt = ri.volumeEnv.npoint; xxi->aei.sus = ri.volumeEnv.sustain; xxi->aei.lps = ri.volumeEnv.loopstart; xxi->aei.lpe = ri.volumeEnv.loopend; xxi->aei.flg = ri.volumeEnv.flags; xxi->pei.npt = ri.panningEnv.npoint; xxi->pei.sus = ri.panningEnv.sustain; xxi->pei.lps = ri.panningEnv.loopstart; xxi->pei.lpe = ri.panningEnv.loopend; xxi->pei.flg = ri.panningEnv.flags; for (j = 0; j < xxi->aei.npt; j++) { xxi->aei.data[j * 2 + 0] = ri.volumeEnv.point[j].x; xxi->aei.data[j * 2 + 1] = ri.volumeEnv.point[j].y / 2; } for (j = 0; j < xxi->pei.npt; j++) { xxi->pei.data[j * 2 + 0] = ri.panningEnv.point[j].x; xxi->pei.data[j * 2 + 1] = 32 + ri.panningEnv.point[j].y / 2; } /* For each sample */ for (j = 0; j < xxi->nsm; j++, smpnum++) { struct xmp_subinstrument *sub = &xxi->sub[j]; struct xmp_sample *xxs; if (read_object_header(f, &oh, "RTSM") < 0) { D_(D_CRIT "Error reading sample %d", j); return -1; } rs.flags = hio_read16l(f); rs.basevolume = hio_read8(f); rs.defaultvolume = hio_read8(f); rs.length = hio_read32l(f); rs.loop = hio_read32l(f); rs.loopbegin = hio_read32l(f); rs.loopend = hio_read32l(f); rs.basefreq = hio_read32l(f); rs.basenote = hio_read8(f); rs.panning = hio_read8(f); libxmp_c2spd_to_note(rs.basefreq, &sub->xpo, &sub->fin); sub->xpo += 48 - rs.basenote; sub->vol = rs.defaultvolume * rs.basevolume / 0x40; sub->pan = 0x80 + rs.panning * 2; sub->vwf = ri.vibflg; sub->vde = ri.vibdepth << 2; sub->vra = ri.vibrate; sub->vsw = ri.vibsweep; sub->sid = smpnum; if (smpnum >= mod->smp) { mod->xxs = libxmp_realloc_samples(mod->xxs, &mod->smp, mod->smp * 3 / 2); if (mod->xxs == NULL) return -1; } xxs = &mod->xxs[smpnum]; libxmp_copy_adjust(xxs->name, (uint8 *)oh.name, 31); xxs->len = rs.length; xxs->lps = rs.loopbegin; xxs->lpe = rs.loopend; xxs->flg = 0; if (rs.flags & 0x02) { xxs->flg |= XMP_SAMPLE_16BIT; xxs->len >>= 1; xxs->lps >>= 1; xxs->lpe >>= 1; } xxs->flg |= rs.loop & 0x03 ? XMP_SAMPLE_LOOP : 0; xxs->flg |= rs.loop == 2 ? XMP_SAMPLE_LOOP_BIDIR : 0; D_(D_INFO " [%1x] %05x%c%05x %05x %c " "V%02x F%+04d P%02x R%+03d", j, xxs->len, xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, sub->fin, sub->pan, sub->xpo); if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF, xxs, NULL) < 0) return -1; } }
static int stm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct xmp_event *event; struct stm_file_header sfh; uint8 b; int bmod2stm = 0; LOAD_INIT(); hio_read(&sfh.name, 20, 1, f); /* ASCIIZ song name */ hio_read(&sfh.magic, 8, 1, f); /* '!Scream!' */ sfh.rsvd1 = hio_read8(f); /* '\x1a' */ sfh.type = hio_read8(f); /* 1=song, 2=module */ sfh.vermaj = hio_read8(f); /* Major version number */ sfh.vermin = hio_read8(f); /* Minor version number */ sfh.tempo = hio_read8(f); /* Playback tempo */ sfh.patterns = hio_read8(f); /* Number of patterns */ sfh.gvol = hio_read8(f); /* Global volume */ hio_read(&sfh.rsvd2, 13, 1, f); /* Reserved */ for (i = 0; i < 31; i++) { hio_read(&sfh.ins[i].name, 12, 1, f); /* ASCIIZ instrument name */ sfh.ins[i].id = hio_read8(f); /* Id=0 */ sfh.ins[i].idisk = hio_read8(f); /* Instrument disk */ sfh.ins[i].rsvd1 = hio_read16l(f); /* Reserved */ sfh.ins[i].length = hio_read16l(f); /* Sample length */ sfh.ins[i].loopbeg = hio_read16l(f); /* Loop begin */ sfh.ins[i].loopend = hio_read16l(f); /* Loop end */ sfh.ins[i].volume = hio_read8(f); /* Playback volume */ sfh.ins[i].rsvd2 = hio_read8(f); /* Reserved */ sfh.ins[i].c2spd = hio_read16l(f); /* C4 speed */ sfh.ins[i].rsvd3 = hio_read32l(f); /* Reserved */ sfh.ins[i].paralen = hio_read16l(f); /* Length in paragraphs */ } if (!strncmp ((char *)sfh.magic, "BMOD2STM", 8)) bmod2stm = 1; mod->pat = sfh.patterns; mod->trk = mod->pat * mod->chn; mod->spd = MSN (sfh.tempo); mod->ins = 31; mod->smp = mod->ins; m->c4rate = C4_NTSC_RATE; copy_adjust(mod->name, sfh.name, 20); if (bmod2stm) { snprintf(mod->type, XMP_NAME_SIZE, "BMOD2STM STM"); } else { snprintf(mod->type, XMP_NAME_SIZE, "Scream Tracker %d.%02d STM", sfh.vermaj, sfh.vermin); } MODULE_INFO(); if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = sfh.ins[i].length; mod->xxs[i].lps = sfh.ins[i].loopbeg; mod->xxs[i].lpe = sfh.ins[i].loopend; if (mod->xxs[i].lpe == 0xffff) mod->xxs[i].lpe = 0; mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].vol = sfh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; instrument_name(mod, i, sfh.ins[i].name, 12); D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, sfh.ins[i].c2spd); sfh.ins[i].c2spd = 8363 * sfh.ins[i].c2spd / 8448; c2spd_to_note (sfh.ins[i].c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); } hio_read(mod->xxo, 1, 128, f); for (i = 0; i < 128; i++) if (mod->xxo[i] >= mod->pat) break; mod->len = i; D_(D_INFO "Module length: %d", mod->len); if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < 64 * mod->chn; j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); b = hio_read8(f); memset (event, 0, sizeof (struct xmp_event)); switch (b) { case 251: case 252: case 253: break; case 255: b = 0; default: event->note = b ? 13 + LSN(b) + 12 * (2 + MSN(b)) : 0; b = hio_read8(f); event->vol = b & 0x07; event->ins = (b & 0xf8) >> 3; b = hio_read8(f); event->vol += (b & 0xf0) >> 1; if (event->vol > 0x40) event->vol = 0; else event->vol++; event->fxt = fx[LSN(b)]; event->fxp = hio_read8(f); switch (event->fxt) { case FX_SPEED: event->fxp = MSN (event->fxp); break; case FX_NONE: event->fxp = event->fxt = 0; break; } } } } /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (mod->xxs[i].len > 1) { if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } else { mod->xxi[i].nsm = 0; } } m->quirk |= QUIRK_VSALL | QUIRKS_ST3; m->read_event_type = READ_EVENT_ST3; return 0; }
static int coco_test(HIO_HANDLE *f, char *t, const int start) { uint8 x, buf[20]; uint32 y; int n, i; x = hio_read8(f); /* check number of channels */ if (x != 0x84 && x != 0x88) return -1; hio_read(buf, 1, 20, f); /* read title */ if (check_cr(buf, 20) != 0) return -1; n = hio_read8(f); /* instruments */ if (n > 100) return -1; hio_read8(f); /* sequences */ hio_read8(f); /* patterns */ y = hio_read32l(f); if (y < 64 || y > 0x00100000) /* offset of sequence table */ return -1; y = hio_read32l(f); /* offset of patterns */ if (y < 64 || y > 0x00100000) return -1; for (i = 0; i < n; i++) { int ofs = hio_read32l(f); int len = hio_read32l(f); int vol = hio_read32l(f); int lps = hio_read32l(f); int lsz = hio_read32l(f); if (ofs < 64 || ofs > 0x00100000) return -1; if (vol > 0xff) return -1; if (len > 0x00100000 || lps > 0x00100000 || lsz > 0x00100000) return -1; if (lps + lsz - 1 > len) return -1; hio_read(buf, 1, 11, f); if (check_cr(buf, 11) != 0) return -1; hio_read8(f); /* unused */ } hio_seek(f, start + 1, SEEK_SET); libxmp_read_title(f, t, 20); #if 0 for (i = 0; i < 20; i++) { if (t[i] == 0x0d) t[i] = 0; } #endif return 0; }
static int ptm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i, smp_ofs[256]; struct xmp_event *event; struct ptm_file_header pfh; struct ptm_instrument_header pih; uint8 n, b; LOAD_INIT(); /* Load and convert header */ hio_read(&pfh.name, 28, 1, f); /* Song name */ pfh.doseof = hio_read8(f); /* 0x1a */ pfh.vermin = hio_read8(f); /* Minor version */ pfh.vermaj = hio_read8(f); /* Major type */ pfh.rsvd1 = hio_read8(f); /* Reserved */ pfh.ordnum = hio_read16l(f); /* Number of orders (must be even) */ pfh.insnum = hio_read16l(f); /* Number of instruments */ pfh.patnum = hio_read16l(f); /* Number of patterns */ pfh.chnnum = hio_read16l(f); /* Number of channels */ pfh.flags = hio_read16l(f); /* Flags (set to 0) */ pfh.rsvd2 = hio_read16l(f); /* Reserved */ pfh.magic = hio_read32b(f); /* 'PTMF' */ if (pfh.magic != MAGIC_PTMF) return -1; /* Sanity check */ if (pfh.ordnum > 256 || pfh.insnum > 255 || pfh.patnum > 128 || pfh.chnnum > 32) { return -1; } hio_read(&pfh.rsvd3, 16, 1, f); /* Reserved */ hio_read(&pfh.chset, 32, 1, f); /* Channel settings */ hio_read(&pfh.order, 256, 1, f); /* Orders */ for (i = 0; i < 128; i++) pfh.patseg[i] = hio_read16l(f); mod->len = pfh.ordnum; mod->ins = pfh.insnum; mod->pat = pfh.patnum; mod->chn = pfh.chnnum; mod->trk = mod->pat * mod->chn; mod->smp = mod->ins; mod->spd = 6; mod->bpm = 125; memcpy (mod->xxo, pfh.order, 256); m->c4rate = C4_NTSC_RATE; copy_adjust(mod->name, pfh.name, 28); set_type(m, "Poly Tracker PTM %d.%02x", pfh.vermaj, pfh.vermin); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { struct xmp_instrument *xxi = &mod->xxi[i]; struct xmp_sample *xxs = &mod->xxs[i]; struct xmp_subinstrument *sub; pih.type = hio_read8(f); /* Sample type */ hio_read(&pih.dosname, 12, 1, f); /* DOS file name */ pih.vol = hio_read8(f); /* Volume */ pih.c4spd = hio_read16l(f); /* C4 speed */ pih.smpseg = hio_read16l(f); /* Sample segment (not used) */ pih.smpofs = hio_read32l(f); /* Sample offset */ pih.length = hio_read32l(f); /* Length */ pih.loopbeg = hio_read32l(f); /* Loop begin */ pih.loopend = hio_read32l(f); /* Loop end */ pih.gusbeg = hio_read32l(f); /* GUS begin address */ pih.guslps = hio_read32l(f); /* GUS loop start address */ pih.guslpe = hio_read32l(f); /* GUS loop end address */ pih.gusflg = hio_read8(f); /* GUS loop flags */ pih.rsvd1 = hio_read8(f); /* Reserved */ hio_read(&pih.name, 28, 1, f); /* Instrument name */ pih.magic = hio_read32b(f); /* 'PTMS' */ if ((pih.type & 3) != 1) continue; if (subinstrument_alloc(mod, i, 1) < 0) return -1; sub = &xxi->sub[0]; smp_ofs[i] = pih.smpofs; xxs->len = pih.length; xxs->lps = pih.loopbeg; xxs->lpe = pih.loopend; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; xxs->flg = 0; if (pih.type & 0x04) { xxs->flg |= XMP_SAMPLE_LOOP; } if (pih.type & 0x08) { xxs->flg |= XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR; } if (pih.type & 0x10) { xxs->flg |= XMP_SAMPLE_16BIT; xxs->len >>= 1; xxs->lps >>= 1; xxs->lpe >>= 1; } sub->vol = pih.vol; sub->pan = 0x80; sub->sid = i; pih.magic = 0; instrument_name(mod, i, pih.name, 28); D_(D_INFO "[%2X] %-28.28s %05x%c%05x %05x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, pih.type & 0x10 ? '+' : ' ', xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, pih.c4spd); /* Convert C4SPD to relnote/finetune */ c2spd_to_note(pih.c4spd, &sub->xpo, &sub->fin); }