int mmd_load_hybrid_instrument(HIO_HANDLE *f, struct module_data *m, int i, int smp_idx, struct SynthInstr *synth, struct InstrExt *exp_smp, struct MMD0sample *sample) { struct xmp_module *mod = &m->mod; struct xmp_instrument *xxi = &mod->xxi[i]; struct xmp_subinstrument *sub; struct xmp_sample *xxs; int length, type; int pos = hio_tell(f); synth->defaultdecay = hio_read8(f); hio_seek(f, 3, SEEK_CUR); synth->rep = hio_read16b(f); synth->replen = hio_read16b(f); synth->voltbllen = hio_read16b(f); synth->wftbllen = hio_read16b(f); synth->volspeed = hio_read8(f); synth->wfspeed = hio_read8(f); synth->wforms = hio_read16b(f); hio_read(synth->voltbl, 1, 128, f);; hio_read(synth->wftbl, 1, 128, f);; hio_seek(f, pos - 6 + hio_read32b(f), SEEK_SET); length = hio_read32b(f); type = hio_read16b(f); if (med_new_instrument_extras(xxi) != 0) return -1; xxi->nsm = 1; if (subinstrument_alloc(mod, i, 1) < 0) return -1; MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed; MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed; sub = &xxi->sub[0]; sub->pan = 0x80; sub->vol = sample->svol; sub->xpo = sample->strans; sub->sid = smp_idx; sub->fin = exp_smp->finetune; xxs = &mod->xxs[smp_idx]; xxs->len = length; xxs->lps = 2 * sample->rep; xxs->lpe = xxs->lps + 2 * sample->replen; xxs->flg = sample->replen > 1 ? XMP_SAMPLE_LOOP : 0; if (load_sample(m, f, 0, xxs, NULL) < 0) return -1; return 0; }

void create_simple_module(struct context_data *ctx, int ins, int pat) { struct module_data *m = &ctx->m; struct xmp_module *mod = &m->mod; int i; load_prologue(ctx); /* Create module */ mod->len = 2; mod->pat = pat; mod->ins = ins; mod->chn = 4; mod->trk = mod->pat * mod->chn; mod->smp = mod->ins; mod->xxo[0] = 0; mod->xxo[1] = 1; pattern_init(mod); for (i = 0; i < mod->pat; i++) { pattern_tracks_alloc(mod, i, 64); } instrument_init(mod); for (i = 0; i < mod->ins; i++) { mod->xxi[i].nsm = 1; subinstrument_alloc(mod, i, 1); mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].sid = i; mod->xxs[i].len = 10000; mod->xxs[i].lps = 0; mod->xxs[i].lpe = 10000; mod->xxs[i].flg = XMP_SAMPLE_LOOP; mod->xxs[i].data = calloc(1, 10000); mod->xxs[i].data += 4; } /* End of module creation */ load_epilogue(ctx); prepare_scan(ctx); scan_sequences(ctx); ctx->state = XMP_STATE_LOADED; }

static int get_samp(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 looplen; /* Should be always 36 */ mod->ins = size / 32; /* sizeof(struct okt_instrument_header); */ mod->smp = mod->ins; if (instrument_init(mod) < 0) return -1; for (j = i = 0; i < mod->ins; i++) { struct xmp_instrument *xxi = &mod->xxi[i]; struct xmp_sample *xxs = &mod->xxs[j]; struct xmp_subinstrument *sub; if (subinstrument_alloc(mod, i, 1) < 0) return -1; sub = &xxi->sub[0]; hio_read(xxi->name, 1, 20, f); adjust_string((char *)xxi->name); /* Sample size is always rounded down */ xxs->len = hio_read32b(f) & ~1; xxs->lps = hio_read16b(f); looplen = hio_read16b(f); xxs->lpe = xxs->lps + looplen; xxs->flg = looplen > 2 ? XMP_SAMPLE_LOOP : 0; sub->vol = hio_read16b(f); data->mode[i] = hio_read16b(f); sub->pan = 0x80; sub->sid = j; data->idx[j] = i; if (xxs->len > 0) { xxi->nsm = 1; j++; } } return 0; }

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 ptdt_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 mod_header mh; uint8 mod_event[4]; hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); mh.ins[i].size = hio_read16b(f); mh.ins[i].finetune = hio_read8(f); mh.ins[i].volume = hio_read8(f); mh.ins[i].loop_start = hio_read16b(f); mh.ins[i].loop_size = hio_read16b(f); } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); hio_read(&mh.magic, 4, 1, f); mod->ins = 31; mod->smp = mod->ins; mod->chn = 4; mod->len = mh.len; mod->rst = mh.restart; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; mod->trk = mod->chn * mod->pat; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; mod->xxs[i].flg = mh.ins[i].loop_size > 1 ? XMP_SAMPLE_LOOP : 0; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = 0xfff; instrument_name(mod, i, mh.ins[i].name, 22); D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mh.ins[i].loop_size > 1 ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4); } if (pattern_init(mod) < 0) return -1; /* Load 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 * 4); j++) { event = &EVENT(i, j % 4, j / 4); hio_read(mod_event, 1, 4, f); decode_protracker_event(event, mod_event); } } m->quirk |= QUIRK_MODRNG; /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { if (!mod->xxs[i].len) continue; if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }

static int hsc_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int pat, i, r, c; struct xmp_event *event; uint8 *x, *sid, e[2], buf[128 * 12]; LOAD_INIT(); hio_read(buf, 1, 128 * 12, f); x = buf; for (i = 0; i < 128; i++, x += 12) { if (x[9] & ~0x3 || x[10] & ~0x3) /* Test waveform register */ break; if (x[8] & ~0xf) /* Test feedback & algorithm */ break; } mod->ins = i; hio_seek(f, start + 0, SEEK_SET); mod->chn = 9; mod->bpm = 135; mod->spd = 6; mod->smp = mod->ins; m->quirk |= QUIRK_LINEAR; set_type(m, "HSC-Tracker"); MODULE_INFO(); /* Read instruments */ if (instrument_init(mod) < 0) return -1; hio_read (buf, 1, 128 * 12, f); sid = buf; for (i = 0; i < mod->ins; i++, sid += 12) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].fin = (int8)sid[11] / 4; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].xpo = 0; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = LSN(sid[7]) * 32; /* carrier release */ if (load_sample(m, f, SAMPLE_FLAG_ADLIB | SAMPLE_FLAG_HSC, &mod->xxs[i], (char *)sid) < 0) return -1; } /* Read orders */ for (pat = i = 0; i < 51; i++) { hio_read (&mod->xxo[i], 1, 1, f); if (mod->xxo[i] & 0x80) break; /* FIXME: jump line */ if (mod->xxo[i] > pat) pat = mod->xxo[i]; } hio_seek(f, 50 - i, SEEK_CUR); mod->len = i; mod->pat = pat + 1; mod->trk = mod->pat * mod->chn; D_(D_INFO "Module length: %d", mod->len); D_(D_INFO "Instruments: %d", mod->ins); D_(D_INFO "Stored patterns: %d", mod->pat); if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ for (i = 0; i < mod->pat; i++) { int ins[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (r = 0; r < mod->xxp[i]->rows; r++) { for (c = 0; c < 9; c++) { hio_read (e, 1, 2, f); event = &EVENT (i, c, r); if (e[0] & 0x80) { ins[c] = e[1] + 1; } else if (e[0] == 0x7f) { event->note = XMP_KEY_OFF; } else if (e[0] > 0) { event->note = e[0] + 25; event->ins = ins[c]; } event->fxt = 0; event->fxp = 0; if (e[1] == 0x01) { event->fxt = 0x0d; event->fxp = 0; } } } } for (i = 0; i < mod->chn; i++) { mod->xxc[i].pan = 0x80; mod->xxc[i].flg = XMP_CHANNEL_SYNTH; } m->synth = &synth_adlib; return 0; }

static int get_emic(struct module_data *m, int size, HIO_HANDLE * f, void *parm) { struct xmp_module *mod = &m->mod; int i, ver; uint8 reorder[256]; ver = hio_read16b(f); hio_read(mod->name, 1, 20, f); hio_seek(f, 20, SEEK_CUR); mod->bpm = hio_read8(f); mod->ins = hio_read8(f); mod->smp = mod->ins; m->quirk |= QUIRK_MODRNG; snprintf(mod->type, XMP_NAME_SIZE, "Quadra Composer EMOD v%d", ver); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; 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; if (subinstrument_alloc(mod, i, 1) < 0) return -1; sub = &xxi->sub[0]; hio_read8(f); /* num */ sub->vol = hio_read8(f); xxs->len = 2 * hio_read16b(f); hio_read(xxi->name, 1, 20, f); xxs->flg = hio_read8(f) & 1 ? XMP_SAMPLE_LOOP : 0; sub->fin = hio_read8s(f) << 4; xxs->lps = 2 * hio_read16b(f); xxs->lpe = xxs->lps + 2 * hio_read16b(f); hio_read32b(f); /* ptr */ xxi->nsm = 1; sub->pan = 0x80; sub->sid = i; D_(D_INFO "[%2X] %-20.20s %05x %05x %05x %c V%02x %+d", i, xxi->name, xxs->len, xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, sub->fin >> 4); } hio_read8(f); /* pad */ mod->pat = hio_read8(f); mod->trk = mod->pat * mod->chn; if (pattern_init(mod) < 0) return -1; memset(reorder, 0, 256); for (i = 0; i < mod->pat; i++) { reorder[hio_read8(f)] = i; if (pattern_tracks_alloc(mod, i, hio_read8(f) + 1) < 0) return -1; hio_seek(f, 20, SEEK_CUR); /* skip name */ hio_read32b(f); /* ptr */ } mod->len = hio_read8(f); D_(D_INFO "Module length: %d", mod->len); for (i = 0; i < mod->len; i++) mod->xxo[i] = reorder[hio_read8(f)]; return 0; }

static int mod_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 mod_header mh; uint8 mod_event[4]; char magic[8]; int ptkloop = 0; /* Protracker loop */ LOAD_INIT(); mod->ins = 31; mod->smp = mod->ins; mod->chn = 0; m->quirk |= QUIRK_MODRNG; hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ mh.ins[i].size = hio_read16b(f); /* Length in 16-bit words */ mh.ins[i].finetune = hio_read8(f); /* Finetune (signed nibble) */ mh.ins[i].volume = hio_read8(f); /* Linear playback volume */ mh.ins[i].loop_start = hio_read16b(f); /* Loop start in 16-bit words */ mh.ins[i].loop_size = hio_read16b(f); /* Loop size in 16-bit words */ } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); memset(magic, 0, 8); hio_read(magic, 4, 1, f); if (!memcmp(magic, "M.K.", 4)) { mod->chn = 4; } else if (!strncmp(magic + 2, "CH", 2) && isdigit((int)magic[0]) && isdigit((int)magic[1])) { mod->chn = (*magic - '0') * 10 + magic[1] - '0'; } else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) { mod->chn = *magic - '0'; } else { return -1; } strncpy(mod->name, (char *) mh.name, 20); mod->len = mh.len; /* mod->rst = mh.restart; */ if (mod->rst >= mod->len) mod->rst = 0; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { /* This fixes dragnet.mod (garbage in the order list) */ if (mod->xxo[i] > 0x7f) break; if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; if (mod->xxs[i].lpe > mod->xxs[i].len) mod->xxs[i].lpe = mod->xxs[i].len; mod->xxs[i].flg = (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe >= 4) ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, mh.ins[i].name, 22); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; } mod->trk = mod->chn * mod->pat; set_type(m, mod->chn == 4 ? "Protracker" : "Fasttracker"); MODULE_INFO(); for (i = 0; i < mod->ins; i++) { D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4, ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 && mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' '); } if (pattern_init(mod) < 0) return -1; /* Load 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); hio_read (mod_event, 1, 4, f); decode_protracker_event(event, mod_event); } } /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { int flags; if (!mod->xxs[i].len) continue; flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0; if (load_sample(m, f, flags, &mod->xxs[i], NULL) < 0) return -1; } if (mod->chn > 4) { m->quirk &= ~QUIRK_MODRNG; m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; } return 0; }

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) { set_type(m, "GDM %d.%02d (2GDM %d.%02d)", vermaj, vermin, tvmaj, tvmin); } else { 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; 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 (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { int flg, c4spd, vol, pan; if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(buffer, 32, 1, f); 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; 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 get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; int i, c2spd; uint8 name[30]; mod->ins = mod->smp = hio_read16b(f); D_(D_INFO "Instruments : %d ", mod->ins); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { int fine, replen, flag; if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read32b(f); /* reserved */ mod->xxs[i].len = hio_read32b(f); mod->xxi[i].nsm = !!mod->xxs[i].len; fine = hio_read8s(f); /* finetune */ mod->xxi[i].sub[0].vol = hio_read8(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].lps = hio_read32b(f); replen = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + replen - 1; mod->xxs[i].flg = replen > 2 ? XMP_SAMPLE_LOOP : 0; hio_read(name, 22, 1, f); instrument_name(mod, i, name, 22); flag = hio_read16b(f); /* bit 0-7:resol 8:stereo */ if ((flag & 0xff) > 8) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } hio_read32b(f); /* midi note (0x00300000) */ c2spd = hio_read32b(f); /* frequency */ c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); /* It's strange that we have both c2spd and finetune */ mod->xxi[i].sub[0].fin += fine; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-22.22s %05x%c%05x %05x %c%c %2db V%02x F%+03d %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[i].lps, replen, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', flag & 0x100 ? 'S' : ' ', flag & 0xff, mod->xxi[i].sub[0].vol, fine, c2spd); }

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 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 <[email protected]> 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 <[email protected]> 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 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; read_title(f, mod->name, 20); for (i = 0; i < 20; i++) { if (mod->name[i] == 0x0d) mod->name[i] = 0; } 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 (instrument_init(mod) < 0) return -1; m->vol_table = (int *)arch_vol_table; m->volbase = 0xff; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(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 (pattern_init(mod) < 0) return -1; 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); 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 (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 = (((i + 3) / 2) % 2) * 0xff; return 0; }

static int chip_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct mod_header mh; uint8 *tidx; int i, j, tnum; LOAD_INIT(); if ((tidx = calloc(1, 1024)) == NULL) { goto err; } hio_read(&mh.name, 20, 1, f); hio_read16b(f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); mh.ins[i].size = hio_read16b(f); mh.ins[i].finetune = hio_read8(f); mh.ins[i].volume = hio_read8(f); mh.ins[i].loop_start = hio_read16b(f); mh.ins[i].loop_size = hio_read16b(f); } hio_read(&mh.magic, 4, 1, f); mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(tidx, 1024, 1, f); hio_read16b(f); mod->chn = 4; mod->ins = 31; mod->smp = mod->ins; mod->len = mh.len; mod->pat = mh.len; mod->rst = mh.restart; tnum = 0; for (i = 0; i < mod->len; i++) { mod->xxo[i] = i; for (j = 0; j < 4; j++) { int t = tidx[2 * (4 * i + j)]; if (t > tnum) tnum = t; } } mod->trk = tnum + 1; strncpy(mod->name, (char *)mh.name, 20); set_type(m, "Chiptracker"); MODULE_INFO(); if (instrument_init(mod) < 0) goto err2; 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; if (subinstrument_alloc(mod, i, 1) < 0) goto err2; sub = &xxi->sub[0]; xxs->len = 2 * mh.ins[i].size; xxs->lps = mh.ins[i].loop_start; xxs->lpe = xxs->lps + 2 * mh.ins[i].loop_size; xxs->flg = mh.ins[i].loop_size > 1 ? XMP_SAMPLE_LOOP : 0; sub->fin = (int8) (mh.ins[i].finetune << 4); sub->vol = mh.ins[i].volume; sub->pan = 0x80; sub->sid = i; if (xxs->len > 0) xxi->nsm = 1; instrument_name(mod, i, mh.ins[i].name, 22); } if (pattern_init(mod) < 0) goto err2; for (i = 0; i < mod->len; i++) { if (pattern_alloc(mod, i) < 0) goto err2; mod->xxp[i]->rows = 64; for (j = 0; j < 4; j++) { int t = tidx[2 * (4 * i + j)]; mod->xxp[i]->index[j] = t; } } /* Load and convert tracks */ D_(D_INFO "Stored tracks: %d", mod->trk); for (i = 0; i < mod->trk; i++) { if (track_alloc(mod, i, 64) < 0) goto err2; for (j = 0; j < 64; j++) { struct xmp_event *event = &mod->xxt[i]->event[j]; uint8 e[4]; hio_read(e, 1, 4, f); if (e[0] && e[0] != 0xa8) event->note = 13 + e[0] / 2; event->ins = e[1]; event->fxt = e[2] & 0x0f; event->fxp = e[3]; } } m->quirk |= QUIRK_MODRNG; /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { if (mod->xxs[i].len == 0) continue; if (load_sample(m, f, SAMPLE_FLAG_FULLREP, &mod->xxs[i], NULL) < 0) goto err2; } free(tidx); return 0; err2: free(tidx); err: return -1; }

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 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); adjust_string((char *)mod->xxi[i].name); 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 (subinstrument_alloc(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); adjust_string((char *)mod->xxs[i].name); 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; 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 (load_sample(m, f, has_unsigned_sample ? SAMPLE_FLAG_UNS : 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }

static int mod_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; int smp_size, pat_size, wow, ptsong = 0; struct xmp_event *event; struct mod_header mh; uint8 mod_event[4]; char *x, pathname[PATH_MAX] = "", *tracker = ""; int detected = 0; char magic[8], idbuffer[32]; int ptkloop = 0; /* Protracker loop */ int tracker_id = TRACKER_PROTRACKER; LOAD_INIT(); mod->ins = 31; mod->smp = mod->ins; mod->chn = 0; smp_size = 0; pat_size = 0; m->quirk |= QUIRK_MODRNG; hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ mh.ins[i].size = hio_read16b(f); /* Length in 16-bit words */ mh.ins[i].finetune = hio_read8(f); /* Finetune (signed nibble) */ mh.ins[i].volume = hio_read8(f); /* Linear playback volume */ mh.ins[i].loop_start = hio_read16b(f); /* Loop start in 16-bit words */ mh.ins[i].loop_size = hio_read16b(f); /* Loop size in 16-bit words */ smp_size += 2 * mh.ins[i].size; } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); memset(magic, 0, 8); hio_read(magic, 4, 1, f); for (i = 0; mod_magic[i].ch; i++) { if (!(strncmp (magic, mod_magic[i].magic, 4))) { mod->chn = mod_magic[i].ch; tracker_id = mod_magic[i].id; detected = mod_magic[i].flag; break; } } if (!mod->chn) { if (!strncmp(magic + 2, "CH", 2) && isdigit((int)magic[0]) && isdigit((int)magic[1])) { mod->chn = (*magic - '0') * 10 + magic[1] - '0'; } else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) { mod->chn = *magic - '0'; } else { return -1; } tracker_id = mod->chn & 1 ? TRACKER_TAKETRACKER : TRACKER_FASTTRACKER2; detected = 1; m->quirk &= ~QUIRK_MODRNG; } strncpy(mod->name, (char *) mh.name, 20); mod->len = mh.len; /* mod->rst = mh.restart; */ if (mod->rst >= mod->len) mod->rst = 0; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { /* This fixes dragnet.mod (garbage in the order list) */ if (mod->xxo[i] > 0x7f) break; if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; pat_size = 256 * mod->chn * mod->pat; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; if (mod->xxs[i].lpe > mod->xxs[i].len) mod->xxs[i].lpe = mod->xxs[i].len; mod->xxs[i].flg = (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe >= 4) ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, mh.ins[i].name, 22); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; } /* * Experimental tracker-detection routine */ if (detected) goto skip_test; /* Test for Flextrax modules * * FlexTrax is a soundtracker for Atari Falcon030 compatible computers. * FlexTrax supports the standard MOD file format (up to eight channels) * for compatibility reasons but also features a new enhanced module * format FLX. The FLX format is an extended version of the standard * MOD file format with support for real-time sound effects like reverb * and delay. */ if (0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size < m->size) { int pos = hio_tell(f); hio_seek(f, start + 0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size, SEEK_SET); hio_read(idbuffer, 1, 4, f); hio_seek(f, start + pos, SEEK_SET); if (!memcmp(idbuffer, "FLEX", 4)) { tracker_id = TRACKER_FLEXTRAX; goto skip_test; } } /* Test for Mod's Grave WOW modules * * Stefan Danes <[email protected]> said: * This weird format is identical to '8CHN' but still uses the 'M.K.' ID. * You can only test for WOW by calculating the size of the module for 8 * channels and comparing this to the actual module length. If it's equal, * the module is an 8 channel WOW. */ if ((wow = (!strncmp(magic, "M.K.", 4) && (0x43c + mod->pat * 32 * 0x40 + smp_size == m->size)))) { mod->chn = 8; tracker_id = TRACKER_MODSGRAVE; goto skip_test; } /* Test for Protracker song files */ else if ((ptsong = (!strncmp((char *)magic, "M.K.", 4) && (0x43c + mod->pat * 0x400 == m->size)))) { tracker_id = TRACKER_PROTRACKER; goto skip_test; } /* Test Protracker-like files */ if (mod->chn == 4 && mh.restart == mod->pat) { tracker_id = TRACKER_SOUNDTRACKER; } else if (mod->chn == 4 && mh.restart == 0x78) { tracker_id = TRACKER_NOISETRACKER; } else if (mh.restart < 0x7f) { if (mod->chn == 4) { tracker_id = TRACKER_NOISETRACKER; } else { tracker_id = TRACKER_UNKNOWN; } mod->rst = mh.restart; } if (mod->chn != 4 && mh.restart == 0x7f) { tracker_id = TRACKER_SCREAMTRACKER3; m->quirk &= ~QUIRK_MODRNG; m->read_event_type = READ_EVENT_ST3; } if (mod->chn == 4 && mh.restart == 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i < 31) { tracker_id = TRACKER_CLONE; } } if (mh.restart != 0x78 && mh.restart < 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i == 31) { /* All loops are size 2 or greater */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 1 && mh.ins[i].volume == 0) { tracker_id = TRACKER_CONVERTED; goto skip_test; } } for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i == 31) { /* No st- instruments */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 0 && mh.ins[i].loop_size == 1) { switch (mod->chn) { case 4: tracker_id = TRACKER_NOISETRACKER; /* or Octalyser */ break; case 6: case 8: tracker_id = TRACKER_OCTALYSER; break; default: tracker_id = TRACKER_UNKNOWN; } goto skip_test; } } if (mod->chn == 4) { tracker_id = TRACKER_PROTRACKER; } else if (mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; /* FastTracker 1.01? */ m->quirk &= ~QUIRK_MODRNG; } else { tracker_id = TRACKER_UNKNOWN; } } } else { /* Has loops with 0 size */ for (i = 15; i < 31; i++) { if (strlen((char *)mh.ins[i].name) || mh.ins[i].size > 0) break; } if (i == 31 && is_st_ins((char *)mh.ins[14].name)) { tracker_id = TRACKER_CONVERTEDST; goto skip_test; } /* Assume that Fast Tracker modules won't have ST- instruments */ for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i < 31) { tracker_id = TRACKER_UNKNOWN_CONV; goto skip_test; } if (mod->chn == 4 || mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; m->quirk &= ~QUIRK_MODRNG; goto skip_test; } tracker_id = TRACKER_UNKNOWN; /* ??!? */ } } skip_test: switch (tracker_id) { case TRACKER_PROTRACKER: tracker = "Protracker"; ptkloop = 1; break; case TRACKER_NOISETRACKER: tracker = "Noisetracker"; ptkloop = 1; break; case TRACKER_SOUNDTRACKER: tracker = "Soundtracker"; ptkloop = 1; break; case TRACKER_FASTTRACKER: tracker = "Fast Tracker"; break; case TRACKER_FASTTRACKER2: tracker = "FastTracker 2"; break; case TRACKER_OCTALYSER: tracker = "Octalyser"; break; case TRACKER_TAKETRACKER: tracker = "TakeTracker"; break; case TRACKER_DIGITALTRACKER: tracker = "Digital Tracker"; break; case TRACKER_FLEXTRAX: tracker = "Flextrax"; break; case TRACKER_MODSGRAVE: tracker = "Mod's Grave"; break; case TRACKER_SCREAMTRACKER3: tracker = "Scream Tracker III"; break; case TRACKER_UNKNOWN_CONV: tracker = "unknown or converted"; break; case TRACKER_CONVERTEDST: tracker = "converted ST2.2 or earlier"; break; case TRACKER_CONVERTED: tracker = "converted"; break; case TRACKER_CLONE: tracker = "Protracker clone"; break; default: case TRACKER_UNKNOWN: tracker = "unknown"; break; } mod->trk = mod->chn * mod->pat; snprintf(mod->type, XMP_NAME_SIZE, "%s (%s)", tracker, magic); MODULE_INFO(); for (i = 0; i < mod->ins; i++) { D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4, ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 && mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' '); } if (pattern_init(mod) < 0) return -1; /* Load 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); hio_read (mod_event, 1, 4, f); switch (tracker_id) { case TRACKER_NOISETRACKER: decode_noisetracker_event(event, mod_event); break; case TRACKER_PROTRACKER: default: decode_protracker_event(event, mod_event); break; } } } /* Load samples */ if (m->filename && (x = strrchr(m->filename, '/'))) strncpy(pathname, m->filename, x - m->filename); D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { int flags; if (!mod->xxs[i].len) continue; flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0; if (ptsong) { HIO_HANDLE *s; char sn[256]; snprintf(sn, XMP_NAME_SIZE, "%s%s", pathname, mod->xxi[i].name); if ((s = hio_open_file(sn, "rb"))) { if (load_sample(m, s, flags, &mod->xxs[i], NULL) < 0) { hio_close(s); return -1; } hio_close(s); } } else { if (load_sample(m, f, flags, &mod->xxs[i], NULL) < 0) return -1; } } if (mod->chn > 4) { m->quirk &= ~QUIRK_MODRNG; m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; } else if (strcmp(tracker, "Protracker") == 0) { m->quirk |= QUIRK_INVLOOP; } return 0; }

static int alm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct alm_file_header afh; struct xmp_event *event; struct stat stat; uint8 b; char *basename; char filename[NAME_SIZE]; char modulename[NAME_SIZE]; LOAD_INIT(); hio_read(&afh.id, 7, 1, f); if (!strncmp((char *)afh.id, "ALEYMOD", 7)) /* Version 1.0 */ mod->spd = afh.speed / 2; strncpy(modulename, m->filename, NAME_SIZE); basename = strtok (modulename, "."); afh.speed = hio_read8(f); afh.length = hio_read8(f); afh.restart = hio_read8(f); hio_read(&afh.order, 128, 1, f); mod->len = afh.length; mod->rst = afh.restart; memcpy (mod->xxo, afh.order, mod->len); for (mod->pat = i = 0; i < mod->len; i++) if (mod->pat < afh.order[i]) mod->pat = afh.order[i]; mod->pat++; mod->ins = 31; mod->trk = mod->pat * mod->chn; mod->smp = mod->ins; m->c4rate = C4_NTSC_RATE; set_type(m, "Aley's Module"); MODULE_INFO(); 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); if (b) event->note = (b == 37) ? 0x61 : b + 48; event->ins = hio_read8(f); } } if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ D_(D_INFO "Loading samples: %d", mod->ins); for (i = 0; i < mod->ins; i++) { HIO_HANDLE *s; if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); snprintf(filename, NAME_SIZE, "%s.%d", basename, i + 1); s = hio_open(filename, "rb"); if (s == NULL) continue; mod->xxi[i].nsm = 1; hio_stat(s, &stat); b = hio_read8(s); /* Get first octet */ mod->xxs[i].len = stat.st_size - 5 * !b; if (!b) { /* Instrument with header */ mod->xxs[i].lps = hio_read16l(f); mod->xxs[i].lpe = hio_read16l(f); mod->xxs[i].flg = mod->xxs[i].lpe > mod->xxs[i].lps ? XMP_SAMPLE_LOOP : 0; } else { hio_seek(s, 0, SEEK_SET); } mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x", i, filename, 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); if (load_sample(m, s, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; hio_close(s); } /* ALM is LRLR, not LRRL */ for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = DEFPAN((i % 2) * 0xff); return 0; }

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; }

int mmd_load_synth_instrument(HIO_HANDLE *f, struct module_data *m, int i, int smp_idx, struct SynthInstr *synth, struct InstrExt *exp_smp, struct MMD0sample *sample) { struct xmp_module *mod = &m->mod; struct xmp_instrument *xxi = &mod->xxi[i]; int pos = hio_tell(f); int j; synth->defaultdecay = hio_read8(f); hio_seek(f, 3, SEEK_CUR); synth->rep = hio_read16b(f); synth->replen = hio_read16b(f); synth->voltbllen = hio_read16b(f); synth->wftbllen = hio_read16b(f); synth->volspeed = hio_read8(f); synth->wfspeed = hio_read8(f); synth->wforms = hio_read16b(f); hio_read(synth->voltbl, 1, 128, f);; hio_read(synth->wftbl, 1, 128, f);; for (j = 0; j < 64; j++) synth->wf[j] = hio_read32b(f); D_(D_INFO " VS:%02x WS:%02x WF:%02x %02x %+3d %+1d", synth->volspeed, synth->wfspeed, synth->wforms & 0xff, sample->svol, sample->strans, exp_smp->finetune); if (synth->wforms == 0xffff) return 1; if (synth->wforms > 64) return -1; if (med_new_instrument_extras(&mod->xxi[i]) != 0) return -1; mod->xxi[i].nsm = synth->wforms; if (subinstrument_alloc(mod, i, synth->wforms) < 0) return -1; MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed; MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed; for (j = 0; j < synth->wforms; j++) { struct xmp_subinstrument *sub = &xxi->sub[j]; struct xmp_sample *xxs = &mod->xxs[smp_idx]; sub->pan = 0x80; sub->vol = sample->svol; sub->xpo = sample->strans - 24; sub->sid = smp_idx; sub->fin = exp_smp->finetune; hio_seek(f, pos - 6 + synth->wf[j], SEEK_SET); xxs->len = hio_read16b(f) * 2; xxs->lps = 0; xxs->lpe = mod->xxs[smp_idx].len; xxs->flg = XMP_SAMPLE_LOOP; if (load_sample(m, f, 0, xxs, NULL) < 0) return -1; smp_idx++; } return 0; }

static int gtk_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; uint8 buffer[40]; int rows, bits, c2spd, size; int ver, patmax; LOAD_INIT(); hio_read(buffer, 4, 1, f); ver = buffer[3]; hio_read(mod->name, 32, 1, f); set_type(m, "Graoumf Tracker GTK v%d", ver); hio_seek(f, 160, SEEK_CUR); /* skip comments */ mod->ins = hio_read16b(f); mod->smp = mod->ins; rows = hio_read16b(f); mod->chn = hio_read16b(f); mod->len = hio_read16b(f); mod->rst = hio_read16b(f); m->volbase = 0x100; MODULE_INFO(); D_(D_INFO "Instruments : %d ", mod->ins); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(buffer, 28, 1, f); instrument_name(mod, i, buffer, 28); if (ver == 1) { hio_read32b(f); mod->xxs[i].len = hio_read32b(f); mod->xxs[i].lps = hio_read32b(f); size = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + size - 1; hio_read16b(f); hio_read16b(f); mod->xxi[i].sub[0].vol = 0xff; mod->xxi[i].sub[0].pan = 0x80; bits = 1; c2spd = 8363; } else { hio_seek(f, 14, SEEK_CUR); hio_read16b(f); /* autobal */ bits = hio_read16b(f); /* 1 = 8 bits, 2 = 16 bits */ c2spd = hio_read16b(f); c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxs[i].len = hio_read32b(f); mod->xxs[i].lps = hio_read32b(f); size = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + size - 1; mod->xxi[i].sub[0].vol = hio_read16b(f); hio_read8(f); mod->xxi[i].sub[0].fin = hio_read8s(f); } if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].sid = i; mod->xxs[i].flg = size > 2 ? XMP_SAMPLE_LOOP : 0; if (bits > 1) { 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] %-28.28s %05x%c%05x %05x %c " "V%02x F%+03d %5d", i, mod->xxi[i].name, mod->xxs[i].len, bits > 1 ? '+' : ' ', mod->xxs[i].lps, size, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin, c2spd); }

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 hmn_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 mod_header mh; struct mupp mupp[31]; uint8 mod_event[4]; int mupp_index, num_mupp; LOAD_INIT(); /* * clr.b $1c(a6) ;prog on/off * CMP.L #'Mupp',-$16(a3,d4.l) * bne.s noprgo * move.l a0,-(a7) * move.b #1,$1c(a6) ;prog on * move.l l697,a0 * lea $43c(a0),a0 * moveq #0,d2 * move.b -$16+$4(a3,d4.l),d2 ;pattno * mulu #$400,d2 * lea (a0,d2.l),a0 * move.l a0,4(a6) ;proginstr data-start * moveq #0,d2 * MOVE.B $3C0(A0),$12(A6) * AND.B #$7F,$12(A6) * move.b $380(a0),d2 * mulu #$20,d2 * lea (a0,d2.w),a0 * move.l a0,$a(a6) ;loopstartmempoi = startmempoi * move.B $3(a3,d4.l),$13(a6) ;volume * move.b -$16+$5(a3,d4.l),8(a6) ;dataloopstart * move.b -$16+$6(a3,d4.l),9(a6) ;dataloopend * move.w #$10,$e(a6) ;looplen * move.l (a7)+,a0 * MOVE.W $12(A6),(A2) * AND.W #$FF,(A2) * BRA.S L505_LQ */ /* * Wavetable structure is 22 * 32 byte waveforms and 32 byte * wave control data with looping. */ memset(mupp, 0, 31 * sizeof (struct mupp)); hio_read(&mh.name, 20, 1, f); num_mupp = 0; for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ if (memcmp(mh.ins[i].name, "Mupp", 4) == 0) { mupp[i].prgon = 1; mupp[i].pattno = mh.ins[i].name[4]; mupp[i].dataloopstart = mh.ins[i].name[5]; mupp[i].dataloopend = mh.ins[i].name[6]; num_mupp++; } mh.ins[i].size = hio_read16b(f); mh.ins[i].finetune = hio_read8(f); mh.ins[i].volume = hio_read8(f); mh.ins[i].loop_start = hio_read16b(f); mh.ins[i].loop_size = hio_read16b(f); } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); hio_read(&mh.magic, 4, 1, f); mod->chn = 4; mod->ins = 31; mod->smp = mod->ins + 28 * num_mupp; mod->len = mh.len; mod->rst = mh.restart; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; mod->trk = mod->chn * mod->pat; if (hmn_new_module_extras(m) != 0) return -1; strncpy(mod->name, (char *)mh.name, 20); set_type(m, "%s (%4.4s)", "His Master's Noise", mh.magic); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (mupp[i].prgon) { mod->xxi[i].nsm = 28; snprintf(mod->xxi[i].name, 32, "Mupp %02x %02x %02x", mupp[i].pattno, mupp[i].dataloopstart, mupp[i].dataloopend); if (hmn_new_instrument_extras(&mod->xxi[i]) != 0) return -1; } else { mod->xxi[i].nsm = 1; instrument_name(mod, i, mh.ins[i].name, 22); mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; mod->xxs[i].flg = mh.ins[i].loop_size > 1 ? XMP_SAMPLE_LOOP : 0; } if (subinstrument_alloc(mod, i, mod->xxi[i].nsm) < 0) return -1; for (j = 0; j < mod->xxi[i].nsm; j++) { mod->xxi[i].sub[j].fin = -(int8)(mh.ins[i].finetune << 3); mod->xxi[i].sub[j].vol = mh.ins[i].volume; mod->xxi[i].sub[j].pan = 0x80; mod->xxi[i].sub[j].sid = i; } } if (pattern_init(mod) < 0) return -1; /* Load 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 * 4); j++) { event = &EVENT(i, j % 4, j / 4); hio_read(mod_event, 1, 4, f); decode_protracker_event(event, mod_event); switch (event->fxt) { case 0x07: event->fxt = FX_MEGAARP; break; case 0x08: case 0x09: case 0x0e: event->fxt = event->fxp = 0; break; } } } m->quirk |= QUIRK_MODRNG; /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < 31; i++) { if (load_sample(m, f, SAMPLE_FLAG_FULLREP, &mod->xxs[i], NULL) < 0) { return -1; } } /* Load Mupp samples */ mupp_index = 0; for (i = 0; i < 31; i ++) { struct hmn_instrument_extras *extra = (struct hmn_instrument_extras *)mod->xxi[i].extra; if (!mupp[i].prgon) continue; hio_seek(f, start + 1084 + 1024 * mupp[i].pattno, SEEK_SET); for (j = 0; j < 28; j++) { int k = 31 + 28 * mupp_index + j; mod->xxi[i].sub[j].sid = k; mod->xxs[k].len = 32; mod->xxs[k].lps = 0; mod->xxs[k].lpe = 32; mod->xxs[k].flg = XMP_SAMPLE_LOOP; if (load_sample(m, f, 0, &mod->xxs[k], NULL) < 0) return -1; } extra->dataloopstart = mupp[i].dataloopstart; extra->dataloopend = mupp[i].dataloopend; hio_read(extra->data, 1, 64, f); hio_read(extra->progvolume, 1, 64, f); mupp_index++; } return 0; }

static int mtp_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; uint8 buffer[25]; int blocksize; LOAD_INIT(); hio_read(buffer, 6, 1, f); if (!memcmp(buffer, "SONGOK", 6)) set_type(m, "IIgs SoundSmith"); else if (!memcmp(buffer, "IAN92a", 8)) set_type(m, "IIgs MegaTracker"); else return -1; blocksize = hio_read16l(f); mod->spd = hio_read16l(f); hio_seek(f, 10, SEEK_CUR); /* skip 10 reserved bytes */ mod->ins = mod->smp = 15; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(buffer, 1, 22, f); if (buffer[0]) { buffer[buffer[0] + 1] = 0; instrument_name(mod, i, buffer + 1, 22); } hio_read16l(f); /* skip 2 reserved bytes */ mod->xxi[i].sub[0].vol = hio_read8(f) >> 2; mod->xxi[i].sub[0].pan = 0x80; hio_seek(f, 5, SEEK_CUR); /* skip 5 bytes */ } mod->len = hio_read8(f) & 0x7f; hio_read8(f); hio_read(mod->xxo, 1, 128, f); MODULE_INFO(); hio_seek(f, start + 600, SEEK_SET); mod->chn = 14; mod->pat = blocksize / (14 * 64); mod->trk = mod->pat * mod->chn; if (pattern_init(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); /* Load notes */ 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++) { event = &EVENT(i, k, j); event->note = hio_read8(f);; if (event->note) event->note += 24; } } } /* Load fx1 */ for (i = 0; i < mod->pat; i++) { for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { uint8 x; event = &EVENT(i, k, j); x = hio_read8(f);; event->ins = x >> 4; switch (x & 0x0f) { case 0x00: event->fxt = FX_ARPEGGIO; break; case 0x03: event->fxt = FX_VOLSET; break; case 0x05: event->fxt = FX_VOLSLIDE_DN; break; case 0x06: event->fxt = FX_VOLSLIDE_UP; break; case 0x0f: event->fxt = FX_SPEED; break; } } } } /* Load fx2 */ for (i = 0; i < mod->pat; i++) { for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { event = &EVENT(i, k, j); event->fxp = hio_read8(f);; switch (event->fxt) { case FX_VOLSET: case FX_VOLSLIDE_DN: case FX_VOLSLIDE_UP: event->fxp >>= 2; } } } } /* Read instrument data */ D_(D_INFO "Instruments : %d ", mod->ins); for (i = 0; i < mod->ins; i++) { HIO_HANDLE *s; char filename[1024]; if (!mod->xxi[i].name[0]) continue; strncpy(filename, m->dirname, NAME_SIZE); if (*filename) strncat(filename, "/", NAME_SIZE); strncat(filename, (char *)mod->xxi[i].name, NAME_SIZE); if ((s = hio_open_file(filename, "rb")) != NULL) { asif_load(m, s, i); hio_close(s); } #if 0 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; #endif D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %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); } return 0; }

static int stc_load(struct module_data *m, HIO_HANDLE * f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event /*, *noise*/; int i, j; uint8 buf[100]; int pos_ptr, orn_ptr, pat_ptr; struct stc_ord stc_ord[256]; struct stc_pat stc_pat[MAX_PAT]; int num, flag, orn; int *decoded; struct spectrum_extra *se; LOAD_INIT(); mod->spd = hio_read8(f); /* Speed */ pos_ptr = hio_read16l(f); /* Positions pointer */ orn_ptr = hio_read16l(f); /* Ornaments pointer */ pat_ptr = hio_read16l(f); /* Patterns pointer */ hio_read(buf, 18, 1, f); /* Title */ copy_adjust(mod->name, (uint8 *)buf, 18); set_type(m, "ZX Spectrum Sound Tracker"); hio_read16l(f); /* Size */ /* Read orders */ hio_seek(f, pos_ptr, SEEK_SET); mod->len = hio_read8(f) + 1; for (num = i = 0; i < mod->len; i++) { stc_ord[i].pattern = hio_read8(f); stc_ord[i].height = hio_read8s(f); //printf("%d %d -- ", stc_ord[i].pattern, stc_ord[i].height); for (flag = j = 0; j < i; j++) { if (stc_ord[i].pattern == stc_ord[j].pattern && stc_ord[i].height == stc_ord[j].height) { mod->xxo[i] = mod->xxo[j]; flag = 1; break; } } if (!flag) { mod->xxo[i] = num++; } //printf("%d\n", mod->xxo[i]); } mod->chn = 3; mod->pat = num; mod->trk = mod->pat * mod->chn; mod->ins = 15; mod->smp = mod->ins; orn = (pat_ptr - orn_ptr) / 33; MODULE_INFO(); /* Read patterns */ if (pattern_init(mod) < 0) return -1; hio_seek(f, pat_ptr, SEEK_SET); decoded = calloc(mod->pat, sizeof(int)); D_(D_INFO "Stored patterns: %d ", mod->pat); for (i = 0; i < MAX_PAT; i++) { if (hio_read8(f) == 0xff) break; stc_pat[i].ch[0] = hio_read16l(f); stc_pat[i].ch[1] = hio_read16l(f); stc_pat[i].ch[2] = hio_read16l(f); } for (i = 0; i < mod->len; i++) { /* pattern */ int src = stc_ord[i].pattern - 1; int dest = mod->xxo[i]; int trans = stc_ord[i].height; if (decoded[dest]) continue; //printf("%d/%d) Read pattern %d -> %d\n", i, mod->len, src, dest); if (pattern_tracks_alloc(mod, dest, 64) < 0) return -1; for (j = 0; j < 3; j++) { /* row */ int row = 0; int x; int rowinc = 0; hio_seek(f, stc_pat[src].ch[j], SEEK_SET); do { for (;;) { x = hio_read8(f); if (x == 0xff) break; //printf("pat %d, channel %d, row %d, x = %02x\n", dest, j, row, x); event = &EVENT(dest, j, row); if (x <= 0x5f) { event->note = x + 18 + trans; row += 1 + rowinc; break; } if (x <= 0x6f) { event->ins = x - 0x5f - 1; } else if (x <= 0x7f) { /* ornament*/ event->fxt = FX_SYNTH_0; event->fxp = x - 0x70; } else if (x == 0x80) { event->note = XMP_KEY_OFF; row += 1 + rowinc; break; } else if (x == 0x81) { /* ? */ row += 1 + rowinc; } else if (x == 0x82) { /* disable ornament/envelope */ event->fxt = FX_SYNTH_0; event->fxp = 0; event->f2t = FX_SYNTH_2; event->f2p = 0; } else if (x <= 0x8e) { /* envelope */ event->fxt = FX_SYNTH_0 + x - 0x80; /* R13 */ event->fxp = hio_read8(f); /* R11 */ event->f2t = FX_SYNTH_1; event->f2p = hio_read8(f); /* R12 */ } else { rowinc = x - 0xa1; } } } while (x != 0xff); } decoded[dest] = 1; } free(decoded); /* Read instruments */ if (instrument_init(mod) < 0) return -1; hio_seek(f, 27, SEEK_SET); D_(D_INFO "Instruments: %d", mod->ins); for (i = 0; i < mod->ins; i++) { struct spectrum_sample ss; memset(&ss, 0, sizeof (struct spectrum_sample)); if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].xpo = -1; mod->xxi[i].sub[0].sid = i; hio_read(buf, 1, 99, f); if (buf[97] == 0) { ss.loop = 32; ss.length = 33; } else { ss.loop = buf[97] - 1; if (ss.loop > 31) ss.loop = 31; ss.length = buf[97] + buf[98]; if (ss.length > 32) ss.length = 32; if (ss.length == 0) ss.length = 1; if (ss.loop >= ss.length) ss.loop = ss.length - 1; if (ss.length < 32) { ss.length += 33 - (ss.loop + 1); ss.loop = 32; } } /* Read sample ticks */ for (j = 0; j < 31; j++) { struct spectrum_stick *sst = &ss.stick[j]; uint8 *chdata = &buf[1 + j * 3]; memset(sst, 0, sizeof (struct spectrum_stick)); if (~chdata[1] & 0x80) { sst->flags |= SPECTRUM_FLAG_MIXNOISE; sst->noise_env_inc = chdata[1] & 0x1f; if (sst->noise_env_inc & 0x10) sst->noise_env_inc |= 0xf0; } if (~chdata[1] & 0x40) sst->flags |= SPECTRUM_FLAG_MIXTONE; sst->vol = chdata[0] & 0x0f; sst->tone_inc = (((int)(chdata[0] & 0xf0)) << 4) | chdata[2]; if (~chdata[1] & 0x20) sst->tone_inc = -sst->tone_inc; sst->flags |= SPECTRUM_FLAG_ENVELOPE; /*if (j != 0) { reportv(ctx, 1, " "); } reportv(ctx, 1, "%02X %c%c%c %c%03x %x\n", j, sst->flags & SPECTRUM_FLAG_MIXTONE ? 'T' : 't', sst->flags & SPECTRUM_FLAG_MIXNOISE ? 'N' : 'n', sst->flags & SPECTRUM_FLAG_ENVELOPE ? 'E' : 'e', sst->tone_inc >= 0 ? '+' : '-', sst->tone_inc >= 0 ? sst->tone_inc : -sst->tone_inc, sst->vol);*/ } if (load_sample(m, f, SAMPLE_FLAG_SPECTRUM, &mod->xxs[i], (char *)&ss) < 0) { return -1; } } /* Read ornaments */ hio_seek(f, orn_ptr, SEEK_SET); m->extra = calloc(1, sizeof (struct spectrum_extra)); se = m->extra; D_(D_INFO "Ornaments: %d", orn); for (i = 0; i < orn; i++) { int index; struct spectrum_ornament *so; index = hio_read8(f); so = &se->ornament[index]; so->length = 32; so->loop = 31; for (j = 0; j < 32; j++) { so->val[j] = hio_read8s(f); } } for (i = 0; i < 4; i++) { mod->xxc[i].pan = 0x80; mod->xxc[i].flg = XMP_CHANNEL_SYNTH; } m->synth = &synth_spectrum; return 0; }

static int med3_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; uint32 mask; int transp, sliding; LOAD_INIT(); hio_read32b(f); set_type(m, "MED 2.00 MED3"); mod->ins = mod->smp = 32; if (instrument_init(mod) < 0) return -1; /* read instrument names */ for (i = 0; i < 32; i++) { uint8 c, buf[40]; for (j = 0; j < 40; j++) { c = hio_read8(f); buf[j] = c; if (c == 0) break; } instrument_name(mod, i, buf, 32); if (subinstrument_alloc(mod, i, 1) < 0) return -1; } /* read instrument volumes */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { mod->xxi[i].sub[0].vol = mask & MASK ? hio_read8(f) : 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].fin = 0; mod->xxi[i].sub[0].sid = i; } /* read instrument loops */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { mod->xxs[i].lps = mask & MASK ? hio_read16b(f) : 0; } /* read instrument loop length */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { uint32 lsiz = mask & MASK ? hio_read16b(f) : 0; mod->xxs[i].len = mod->xxs[i].lps + lsiz; mod->xxs[i].lpe = mod->xxs[i].lps + lsiz; mod->xxs[i].flg = lsiz > 1 ? XMP_SAMPLE_LOOP : 0; } mod->chn = 4; mod->pat = hio_read16b(f); mod->trk = mod->chn * mod->pat; mod->len = hio_read16b(f); hio_read(mod->xxo, 1, mod->len, f); mod->spd = hio_read16b(f); if (mod->spd > 10) { mod->bpm = 125 * mod->spd / 33; mod->spd = 6; } transp = hio_read8s(f); hio_read8(f); /* flags */ sliding = hio_read16b(f); /* sliding */ hio_read32b(f); /* jumping mask */ hio_seek(f, 16, SEEK_CUR); /* rgb */ /* read midi channels */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (mask & MASK) hio_read8(f); } /* read midi programs */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (mask & MASK) hio_read8(f); } MODULE_INFO(); D_(D_INFO "Sliding: %d", sliding); D_(D_INFO "Play transpose: %d", transp); if (sliding == 6) m->quirk |= QUIRK_VSALL | QUIRK_PBALL; for (i = 0; i < 32; i++) mod->xxi[i].sub[0].xpo = transp; if (pattern_init(mod) < 0) return -1; /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { uint32 *conv; uint8 b, tracks; uint16 convsz; if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; tracks = hio_read8(f); b = hio_read8(f); convsz = hio_read16b(f); conv = calloc(1, convsz + 16); if (conv == NULL) return -1; if (b & M0F_LINEMSK00) *conv = 0L; else if (b & M0F_LINEMSK0F) *conv = 0xffffffff; else *conv = hio_read32b(f); if (b & M0F_LINEMSK10) *(conv + 1) = 0L; else if (b & M0F_LINEMSK1F) *(conv + 1) = 0xffffffff; else *(conv + 1) = hio_read32b(f); if (b & M0F_FXMSK00) *(conv + 2) = 0L; else if (b & M0F_FXMSK0F) *(conv + 2) = 0xffffffff; else *(conv + 2) = hio_read32b(f); if (b & M0F_FXMSK10) *(conv + 3) = 0L; else if (b & M0F_FXMSK1F) *(conv + 3) = 0xffffffff; else *(conv + 3) = hio_read32b(f); hio_read(conv + 4, 1, convsz, f); if (unpack_block(m, i, (uint8 *)conv) < 0) { free(conv); return -1; } free(conv); } /* Load samples */ D_(D_INFO "Instruments: %d", mod->ins); mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (~mask & MASK) continue; mod->xxi[i].nsm = 1; mod->xxs[i].len = hio_read32b(f); if (mod->xxs[i].len == 0) mod->xxi[i].nsm = 0; if (hio_read16b(f)) /* type */ continue; 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, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }

static int asylum_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j; LOAD_INIT(); hio_seek(f, 32, SEEK_CUR); /* skip magic */ mod->spd = hio_read8(f); /* initial speed */ mod->bpm = hio_read8(f); /* initial BPM */ mod->ins = hio_read8(f); /* number of instruments */ mod->pat = hio_read8(f); /* number of patterns */ mod->len = hio_read8(f); /* module length */ hio_read8(f); hio_read(mod->xxo, 1, mod->len, f); /* read orders */ hio_seek(f, start + 294, SEEK_SET); mod->chn = 8; mod->smp = mod->ins; mod->trk = mod->pat * mod->chn; snprintf(mod->type, XMP_NAME_SIZE, "Asylum Music Format v1.0"); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { uint8 insbuf[37]; if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(insbuf, 1, 37, f); instrument_name(mod, i, insbuf, 22); mod->xxi[i].sub[0].fin = (int8)(insbuf[22] << 4); mod->xxi[i].sub[0].vol = insbuf[23]; mod->xxi[i].sub[0].xpo = (int8)insbuf[24]; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxs[i].len = readmem32l(insbuf + 25); mod->xxs[i].lps = readmem32l(insbuf + 29); mod->xxs[i].lpe = mod->xxs[i].lps + readmem32l(insbuf + 33); mod->xxs[i].flg = mod->xxs[i].lpe > 2 ? XMP_SAMPLE_LOOP : 0; D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %d", 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, mod->xxi[i].sub[0].fin); } hio_seek(f, 37 * (64 - mod->ins), SEEK_CUR); 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++) { uint8 note; event = &EVENT(i, j % mod->chn, j / mod->chn); memset(event, 0, sizeof(struct xmp_event)); note = hio_read8(f); if (note != 0) { event->note = note + 13; } event->ins = hio_read8(f); event->fxt = hio_read8(f); event->fxp = hio_read8(f); } } /* 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; mod->xxi[i].nsm = 1; } } return 0; }

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 mfp_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, k, x, y; struct xmp_event *event; struct stat st; char smp_filename[PATH_MAX]; HIO_HANDLE *s; int size1, size2; int pat_addr, pat_table[128][4]; uint8 buf[1024], mod_event[4]; int row; LOAD_INIT(); set_type(m, "Magnetic Fields Packer"); MODULE_INFO(); mod->chn = 4; mod->ins = mod->smp = 31; if (instrument_init(mod) < 0) return -1; for (i = 0; i < 31; i++) { int loop_size; if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * hio_read16b(f); mod->xxi[i].sub[0].fin = (int8)(hio_read8(f) << 4); mod->xxi[i].sub[0].vol = hio_read8(f); mod->xxs[i].lps = 2 * hio_read16b(f); loop_size = hio_read16b(f); mod->xxs[i].lpe = mod->xxs[i].lps + 2 * loop_size; mod->xxs[i].flg = loop_size > 1 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = 0xfff; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %04x %04x %04x %c V%02x %+d", i, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, loop_size > 1 ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4); } mod->len = mod->pat = hio_read8(f); hio_read8(f); /* restart */ for (i = 0; i < 128; i++) mod->xxo[i] = hio_read8(f); #if 0 for (i = 0; i < 128; i++) { mod->xxo[i] = hio_read8(f); if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; #endif mod->trk = mod->pat * mod->chn; /* Read and convert patterns */ if (pattern_init(mod) < 0) return -1; size1 = hio_read16b(f); size2 = hio_read16b(f); for (i = 0; i < size1; i++) { /* Read pattern table */ for (j = 0; j < 4; j++) { pat_table[i][j] = hio_read16b(f); } } D_(D_INFO "Stored patterns: %d ", mod->pat); pat_addr = hio_tell(f); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < 4; j++) { hio_seek(f, pat_addr + pat_table[i][j], SEEK_SET); hio_read(buf, 1, 1024, f); for (row = k = 0; k < 4; k++) { for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++, row++) { event = &EVENT(i, j, row); memcpy(mod_event, &buf[buf[buf[buf[k] + x] + y] * 2], 4); decode_protracker_event(event, mod_event); } } } } } /* Read samples */ D_(D_INFO "Loading samples: %d", mod->ins); /* first check smp.filename */ if (strlen(m->basename) < 5 || m->basename[3] != '.') { fprintf(stderr, "libxmp: invalid filename %s\n", m->basename); goto err; } m->basename[0] = 's'; m->basename[1] = 'm'; m->basename[2] = 'p'; snprintf(smp_filename, sizeof(smp_filename), "%s%s", m->dirname, m->basename); if (stat(smp_filename, &st) < 0) { /* handle .set filenames like in Kid Chaos*/ char *x; if (strchr(m->basename, '-')) { if ((x = strrchr(smp_filename, '-'))) strcpy(x, ".set"); } if (stat(smp_filename, &st) < 0) { fprintf(stderr, "libxmp: missing file %s\n", smp_filename); goto err; } } if ((s = hio_open_file(smp_filename, "rb")) == NULL) { fprintf(stderr, "libxmp: can't open sample file %s\n", smp_filename); goto err; } for (i = 0; i < mod->ins; i++) { if (load_sample(m, s, SAMPLE_FLAG_FULLREP, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) return -1; } hio_close(s); m->quirk |= QUIRK_MODRNG; return 0; err: for (i = 0; i < mod->ins; i++) { mod->xxi[i].nsm = 0; memset(&mod->xxs[i], 0, sizeof(struct xmp_sample)); } return 0; }

static int mgt_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 ver; int sng_ptr, seq_ptr, ins_ptr, pat_ptr, trk_ptr, smp_ptr; int sdata[64]; LOAD_INIT(); hio_read24b(f); /* MGT */ ver = hio_read8(f); hio_read32b(f); /* MCS */ set_type(m, "Megatracker MGT v%d.%d", MSN(ver), LSN(ver)); mod->chn = hio_read16b(f); hio_read16b(f); /* number of songs */ mod->len = hio_read16b(f); mod->pat = hio_read16b(f); mod->trk = hio_read16b(f); mod->ins = mod->smp = hio_read16b(f); hio_read16b(f); /* reserved */ hio_read32b(f); /* reserved */ sng_ptr = hio_read32b(f); seq_ptr = hio_read32b(f); ins_ptr = hio_read32b(f); pat_ptr = hio_read32b(f); trk_ptr = hio_read32b(f); smp_ptr = hio_read32b(f); hio_read32b(f); /* total smp len */ hio_read32b(f); /* unpacked trk size */ hio_seek(f, start + sng_ptr, SEEK_SET); hio_read(mod->name, 1, 32, f); seq_ptr = hio_read32b(f); mod->len = hio_read16b(f); mod->rst = hio_read16b(f); mod->bpm = hio_read8(f); mod->spd = hio_read8(f); hio_read16b(f); /* global volume */ hio_read8(f); /* master L */ hio_read8(f); /* master R */ for (i = 0; i < mod->chn; i++) { hio_read16b(f); /* pan */ } MODULE_INFO(); /* Sequence */ hio_seek(f, start + seq_ptr, SEEK_SET); for (i = 0; i < mod->len; i++) mod->xxo[i] = hio_read16b(f); /* Instruments */ if (instrument_init(mod) < 0) return -1; hio_seek(f, start + ins_ptr, SEEK_SET); for (i = 0; i < mod->ins; i++) { int c2spd, flags; if (subinstrument_alloc(mod, i , 1) < 0) return -1; hio_read(mod->xxi[i].name, 1, 32, f); sdata[i] = hio_read32b(f); mod->xxs[i].len = hio_read32b(f); mod->xxs[i].lps = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + hio_read32b(f); hio_read32b(f); hio_read32b(f); c2spd = hio_read32b(f); c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].vol = hio_read16b(f) >> 4; hio_read8(f); /* vol L */ hio_read8(f); /* vol R */ mod->xxi[i].sub[0].pan = 0x80; flags = hio_read8(f); mod->xxs[i].flg = flags & 0x03 ? XMP_SAMPLE_LOOP : 0; mod->xxs[i].flg |= flags & 0x02 ? XMP_SAMPLE_LOOP_BIDIR : 0; mod->xxi[i].sub[0].fin += 0 * hio_read8(f); // FIXME hio_read8(f); /* unused */ hio_read8(f); hio_read8(f); hio_read8(f); hio_read16b(f); hio_read32b(f); hio_read32b(f); mod->xxi[i].nsm = !!mod->xxs[i].len; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-32.32s %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_BIDIR ? 'B' : mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); } /* PATTERN_INIT - alloc extra track*/ if (pattern_init(mod) < 0) return -1; D_(D_INFO "Stored tracks: %d", mod->trk); /* Tracks */ for (i = 1; i < mod->trk; i++) { int offset, rows; uint8 b; hio_seek(f, start + trk_ptr + i * 4, SEEK_SET); offset = hio_read32b(f); hio_seek(f, start + offset, SEEK_SET); rows = hio_read16b(f); if (track_alloc(mod, i, rows) < 0) return -1; //printf("\n=== Track %d ===\n\n", i); for (j = 0; j < rows; j++) { uint8 note, f2p; b = hio_read8(f); j += b & 0x03; note = 0; event = &mod->xxt[i]->event[j]; if (b & 0x04) note = hio_read8(f); if (b & 0x08) event->ins = hio_read8(f); if (b & 0x10) event->vol = hio_read8(f); if (b & 0x20) event->fxt = hio_read8(f); if (b & 0x40) event->fxp = hio_read8(f); if (b & 0x80) f2p = hio_read8(f); if (note == 1) event->note = XMP_KEY_OFF; else if (note > 11) /* adjusted to play codeine.mgt */ event->note = note + 1; /* effects */ if (event->fxt < 0x10) /* like amiga */ ; else switch (event->fxt) { case 0x13: case 0x14: case 0x15: case 0x17: case 0x1c: case 0x1d: case 0x1e: event->fxt = FX_EXTENDED; event->fxp = ((event->fxt & 0x0f) << 4) | (event->fxp & 0x0f); break; default: event->fxt = event->fxp = 0; } /* volume and volume column effects */ if ((event->vol >= 0x10) && (event->vol <= 0x50)) { event->vol -= 0x0f; continue; } 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; /*printf("%02x %02x %02x %02x %02x %02x\n", j, event->note, event->ins, event->vol, event->fxt, event->fxp);*/ } } /* Extra track */ mod->xxt[0] = calloc(sizeof(struct xmp_track) + sizeof(struct xmp_event) * 64 - 1, 1); mod->xxt[0]->rows = 64; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); hio_seek(f, start + pat_ptr, SEEK_SET); for (i = 0; i < mod->pat; i++) { if (pattern_alloc(mod, i) < 0) return -1; mod->xxp[i]->rows = hio_read16b(f); for (j = 0; j < mod->chn; j++) { mod->xxp[i]->index[j] = hio_read16b(f) - 1; } } /* 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 + sdata[i], SEEK_SET); if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }