/* Effect translation */ static void xlat_fx(int c, struct xmp_event *e) { uint8 h = MSN (e->fxp), l = LSN (e->fxp); switch (e->fxt = fx[e->fxt]) { case FX_S3M_EXTENDED: /* Extended effects */ e->fxt = FX_EXTENDED; switch (h) { case 0x1: /* Glissando */ e->fxp = LSN (e->fxp) | (EX_GLISS << 4); break; case 0x2: /* Finetune */ e->fxp = LSN (e->fxp) | (EX_FINETUNE << 4); break; case 0x3: /* Vibrato wave */ e->fxp = LSN (e->fxp) | (EX_VIBRATO_WF << 4); break; case 0x4: /* Tremolo wave */ e->fxp = LSN (e->fxp) | (EX_TREMOLO_WF << 4); break; case 0x5: case 0x6: case 0x7: case 0x9: case 0xa: /* Ignore */ e->fxt = e->fxp = 0; break; case 0x8: /* Set pan */ e->fxt = FX_SETPAN; e->fxp = l << 4; break; case 0xb: /* Pattern loop */ e->fxp = LSN (e->fxp) | (EX_PATTERN_LOOP << 4); break; case 0xc: if (!l) e->fxt = e->fxp = 0; } break; case NONE: /* No effect */ e->fxt = e->fxp = 0; break; } }
static void get_pbod(struct xmp_context *ctx, int size, FILE *f) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; int j; uint16 rows; struct xxm_event *event; if (pattern >= m->xxh->pat) return; if (!pattern) { PATTERN_INIT(); reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat); } rows = read16b(f); PATTERN_ALLOC (pattern); m->xxp[pattern]->rows = rows; TRACK_ALLOC (pattern); for (j = 0; j < rows * m->xxh->chn; j++) { uint8 note, ins; event = &EVENT(pattern, j % m->xxh->chn, j / m->xxh->chn); memset(event, 0, sizeof(struct xxm_event)); note = read8(f); ins = read8(f); if (note) { event->note = 36 + note; event->ins = 1 + ins; } event->fxt = fx[read8(f)]; event->fxp = read8(f); if ((event->fxt == FX_VOLSET) && (event->fxp > 0x40)) { if (event->fxp <= 0x50) { event->fxt = FX_VOLSLIDE; event->fxp -= 0x40; } else if (event->fxp <= 0x60) { event->fxt = FX_VOLSLIDE; event->fxp = (event->fxp - 0x50) << 4; } else if (event->fxp <= 0x70) { event->fxt = FX_EXTENDED; event->fxp = (EX_F_VSLIDE_DN << 4) | (event->fxp - 0x60); } else if (event->fxp <= 0x80) { event->fxt = FX_EXTENDED; event->fxp = (EX_F_VSLIDE_UP << 4) | (event->fxp - 0x70); } } if (event->fxt == FX_ARPEGGIO) /* Arpeggio fixup */ event->fxp = (((24 - MSN (event->fxp)) % 12) << 4) | LSN (event->fxp); if (event->fxt == NONE) event->fxt = event->fxp = 0; } reportv(ctx, 0, "."); pattern++; }
static int far_load(struct module_data *m, FILE *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(); read32b(f); /* File magic: 'FAR\xfe' */ fread(&ffh.name, 40, 1, f); /* Song name */ fread(&ffh.crlf, 3, 1, f); /* 0x0d 0x0a 0x1A */ ffh.headersize = read16l(f); /* Remaining header size in bytes */ ffh.version = read8(f); /* Version MSN=major, LSN=minor */ fread(&ffh.ch_on, 16, 1, f); /* Channel on/off switches */ fseek(f, 9, SEEK_CUR); /* Current editing values */ ffh.tempo = read8(f); /* Default tempo */ fread(&ffh.pan, 16, 1, f); /* Channel pan definitions */ read32l(f); /* Grid, mode (for editor) */ ffh.textlen = read16l(f); /* Length of embedded text */ fseek(f, ffh.textlen, SEEK_CUR); /* Skip song text */ fread(&ffh2.order, 256, 1, f); /* Orders */ ffh2.patterns = read8(f); /* Number of stored patterns (?) */ ffh2.songlen = read8(f); /* Song length in patterns */ ffh2.restart = read8(f); /* Restart pos */ for (i = 0; i < 256; i++) ffh2.patsize[i] = 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(); PATTERN_INIT(); /* 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; PATTERN_ALLOC(i); if (!ffh2.patsize[i]) continue; mod->xxp[i]->rows = (ffh2.patsize[i] - 2) / 64; TRACK_ALLOC(i); brk = read8(f) + 1; 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 = read8(f); ins = read8(f); vol = read8(f); fxb = 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: event->fxp = 8 * 60 / event->fxp; break; } } } mod->ins = -1; fread(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; INSTRUMENT_INIT(); /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { if (!(sample_map[i / 8] & (1 << (i % 8)))) continue; mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); fread(&fih.name, 32, 1, f); /* Instrument name */ fih.length = read32l(f); /* Length of sample (up to 64Kb) */ fih.finetune = read8(f); /* Finetune (unsuported) */ fih.volume = read8(f); /* Volume (unsuported?) */ fih.loop_start = read32l(f); /* Loop start */ fih.loopend = read32l(f); /* Loop end */ fih.sampletype = read8(f); /* 1=16 bit sample */ fih.loopmode = read8(f); fih.length &= 0xffff; fih.loop_start &= 0xffff; fih.loopend &= 0xffff; mod->xxs[i].len = fih.length; mod->xxi[i].nsm = fih.length > 0 ? 1 : 0; mod->xxs[i].lps = fih.loop_start; mod->xxs[i].lpe = fih.loopend; mod->xxs[i].flg = 0; 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; copy_adjust(mod->xxi[i].name, 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); load_sample(f, 0, &mod->xxs[i], NULL); }
static int gdm_load(struct xmp_context *ctx, FILE *f, const int start) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; struct xxm_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(); read32b(f); /* skip magic */ fread(m->name, 1, 32, f); fread(m->author, 1, 32, f); fseek(f, 7, SEEK_CUR); vermaj = read8(f); vermin = read8(f); tracker = read16l(f); tvmaj = read8(f); tvmin = read8(f); if (tracker == 0) { sprintf(m->type, "GDM %d.%02d, (2GDM %d.%02d)", vermaj, vermin, tvmaj, tvmin); } else { sprintf(m->type, "GDM %d.%02d (unknown tracker %d.%02d)", vermaj, vermin, tvmaj, tvmin); } fread(panmap, 32, 1, f); for (i = 0; i < 32; i++) { if (panmap[i] != 0xff) m->xxh->chn = i + 1; if (panmap[i] == 16) panmap[i] = 8; m->xxc[i].pan = 0x80 + (panmap[i] - 8) * 16; } m->xxh->gvl = read8(f); m->xxh->tpo = read8(f); m->xxh->bpm = read8(f); origfmt = read16l(f); ord_ofs = read32l(f); m->xxh->len = read8(f); pat_ofs = read32l(f); m->xxh->pat = read8(f); ins_ofs = read32l(f); smp_ofs = read32l(f); m->xxh->ins = m->xxh->smp = read8(f); m->xxh->trk = m->xxh->pat * m->xxh->chn; MODULE_INFO(); if (origfmt > 9) origfmt = 9; reportv(ctx, 0, "Orig format : %s\n", fmt[origfmt]); fseek(f, start + ord_ofs, SEEK_SET); for (i = 0; i < m->xxh->len; i++) m->xxo[i] = read8(f); /* Read instrument data */ fseek(f, start + ins_ofs, SEEK_SET); INSTRUMENT_INIT(); reportv(ctx, 1, " Name Len LBeg LEnd L Vol Pan C4Spd\n"); for (i = 0; i < m->xxh->ins; i++) { int flg, c4spd, vol, pan; m->xxi[i] = calloc(sizeof(struct xxm_instrument), 1); fread(buffer, 32, 1, f); copy_adjust(m->xxih[i].name, buffer, 32); fseek(f, 12, SEEK_CUR); /* skip filename */ read8(f); /* skip EMS handle */ m->xxs[i].len = read32l(f); m->xxs[i].lps = read32l(f); m->xxs[i].lpe = read32l(f); flg = read8(f); c4spd = read16l(f); vol = read8(f); pan = read8(f); m->xxi[i][0].vol = vol > 0x40 ? 0x40 : vol; m->xxi[i][0].pan = pan > 15 ? 0x80 : 0x80 + (pan - 8) * 16; c2spd_to_note(c4spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin); m->xxih[i].nsm = !!(m->xxs[i].len); m->xxi[i][0].sid = i; m->xxs[i].flg = 0; if (flg & 0x01) m->xxs[i].flg |= WAVE_LOOPING; if (flg & 0x02) m->xxs[i].flg |= WAVE_16_BITS; if (V(1) && (strlen((char*)m->xxih[i].name) || (m->xxs[i].len > 1))) { report("[%2X] %-32.32s %05x%c%05x %05x %c V%02x P%02x %5d\n", i, m->xxih[i].name, m->xxs[i].len, m->xxs[i].flg & WAVE_16_BITS ? '+' : ' ', m->xxs[i].lps, m->xxs[i].lpe, m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ', m->xxi[i][0].vol, m->xxi[i][0].pan, c4spd); } } /* Read and convert patterns */ fseek(f, start + pat_ofs, SEEK_SET); PATTERN_INIT(); reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat); for (i = 0; i < m->xxh->pat; i++) { int len, c, r, k; PATTERN_ALLOC(i); m->xxp[i]->rows = 64; TRACK_ALLOC(i); len = read16l(f); len -= 2; for (r = 0; len > 0; ) { c = read8(f); len--; if (c == 0) { r++; continue; } assert((c & 0x1f) < m->xxh->chn); event = &EVENT (i, c & 0x1f, r); if (c & 0x20) { /* note and sample follows */ k = read8(f); event->note = 12 * MSN(k & 0x7f) + LSN(k); event->ins = read8(f); len -= 2; } if (c & 0x40) { /* effect(s) follow */ do { k = read8(f); len--; switch ((k & 0xc0) >> 6) { case 0: event->fxt = k & 0x1f; event->fxp = read8(f); len--; fix_effect(&event->fxt, &event->fxp); break; case 1: event->f2t = k & 0x1f; event->f2p = read8(f); len--; fix_effect(&event->f2t, &event->f2p); break; case 2: read8(f); len--; } } while (k & 0x20); } } reportv(ctx, 0, "."); } reportv(ctx, 0, "\n"); /* Read samples */ fseek(f, start + smp_ofs, SEEK_SET); reportv(ctx, 0, "Stored samples : %d ", m->xxh->smp); for (i = 0; i < m->xxh->ins; i++) { xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate, XMP_SMP_UNS, &m->xxs[m->xxi[i][0].sid], NULL); reportv(ctx, 0, "."); } reportv(ctx, 0, "\n"); return 0; }
static int stx_load(struct module_data *m, xmp_file 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(); xmp_fread(&sfh.name, 20, 1, f); xmp_fread(&sfh.magic, 8, 1, f); sfh.psize = read16l(f); sfh.unknown1 = read16l(f); sfh.pp_pat = read16l(f); sfh.pp_ins = read16l(f); sfh.pp_chn = read16l(f); sfh.unknown2 = read16l(f); sfh.unknown3 = read16l(f); sfh.gvol = read8(f); sfh.tempo = read8(f); sfh.unknown4 = read16l(f); sfh.unknown5 = read16l(f); sfh.patnum = read16l(f); sfh.insnum = read16l(f); sfh.ordnum = read16l(f); sfh.unknown6 = read16l(f); sfh.unknown7 = read16l(f); sfh.unknown8 = read16l(f); xmp_fread(&sfh.magic2, 4, 1, f); /* 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). */ xmp_fseek(f, start + (sfh.pp_pat << 4), SEEK_SET); x16 = read16l(f); xmp_fseek(f, start + (x16 << 4), SEEK_SET); x16 = 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); pp_ins = calloc (2, mod->ins); /* Read pattern pointers */ xmp_fseek(f, start + (sfh.pp_pat << 4), SEEK_SET); for (i = 0; i < mod->pat; i++) pp_pat[i] = read16l(f); /* Read instrument pointers */ xmp_fseek(f, start + (sfh.pp_ins << 4), SEEK_SET); for (i = 0; i < mod->ins; i++) pp_ins[i] = read16l(f); /* Skip channel table (?) */ xmp_fseek(f, start + (sfh.pp_chn << 4) + 32, SEEK_SET); /* Read orders */ for (i = 0; i < mod->len; i++) { mod->xxo[i] = read8(f); xmp_fseek(f, 4, SEEK_CUR); } INSTRUMENT_INIT(); /* Read and convert instruments and samples */ for (i = 0; i < mod->ins; i++) { mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); xmp_fseek(f, start + (pp_ins[i] << 4), SEEK_SET); sih.type = read8(f); xmp_fread(&sih.dosname, 13, 1, f); sih.memseg = read16l(f); sih.length = read32l(f); sih.loopbeg = read32l(f); sih.loopend = read32l(f); sih.vol = read8(f); sih.rsvd1 = read8(f); sih.pack = read8(f); sih.flags = read8(f); sih.c2spd = read16l(f); sih.rsvd2 = read16l(f); xmp_fread(&sih.rsvd3, 4, 1, f); sih.int_gp = read16l(f); sih.int_512 = read16l(f); sih.int_last = read32l(f); xmp_fread(&sih.name, 28, 1, f); xmp_fread(&sih.magic, 4, 1, f); mod->xxi[i].nsm = !!(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; copy_adjust(mod->xxi[i].name, 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); } PATTERN_INIT(); /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { PATTERN_ALLOC (i); mod->xxp[i]->rows = 64; TRACK_ALLOC (i); if (!pp_pat[i]) continue; xmp_fseek(f, start + (pp_pat[i] << 4), SEEK_SET); if (broken) xmp_fseek(f, 2, SEEK_CUR); for (r = 0; r < 64; ) { b = 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 = 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 = read8(f);; } if (b & S3M_VOL_FOLLOWS) { event->vol = read8(f) + 1; } if (b & S3M_FX_FOLLOWS) { event->fxt = fx[read8(f)]; event->fxp = 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_pat); free (pp_ins); /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { load_sample(m, f, 0, &mod->xxs[mod->xxi[i].sub[0].sid], NULL); } m->quirk |= QUIRK_VSALL | QUIRKS_ST3; m->read_event_type = READ_EVENT_ST3; return 0; }
static int hsc_load(struct module_data *m, xmp_file 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(); xmp_fread(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; xmp_fseek(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 */ INSTRUMENT_INIT(); xmp_fread (buf, 1, 128 * 12, f); sid = buf; for (i = 0; i < mod->ins; i++, sid += 12) { mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 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 */ load_sample(m, f, SAMPLE_FLAG_ADLIB | SAMPLE_FLAG_HSC, &mod->xxs[i], (char *)sid); } /* Read orders */ for (pat = i = 0; i < 51; i++) { xmp_fread (&mod->xxo[i], 1, 1, f); if (mod->xxo[i] & 0x80) break; /* FIXME: jump line */ if (mod->xxo[i] > pat) pat = mod->xxo[i]; } xmp_fseek(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); PATTERN_INIT(); /* Read and convert patterns */ for (i = 0; i < mod->pat; i++) { int ins[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; PATTERN_ALLOC (i); mod->xxp[i]->rows = 64; TRACK_ALLOC (i); for (r = 0; r < mod->xxp[i]->rows; r++) { for (c = 0; c < 9; c++) { xmp_fread (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_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 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; }
void process_fx(struct context_data *ctx, struct channel_data *xc, int chn, uint8 note, uint8 fxt, uint8 fxp, int fnum) { struct player_data *p = &ctx->p; struct module_data *m = &ctx->m; struct xmp_module *mod = &m->mod; struct flow_control *f = &p->flow; int h, l; switch (fxt) { case FX_ARPEGGIO: fx_arpeggio: if (fxp != 0) { xc->arpeggio.val[0] = 0; xc->arpeggio.val[1] = MSN(fxp); xc->arpeggio.val[2] = LSN(fxp); xc->arpeggio.size = 3; } break; case FX_S3M_ARPEGGIO: EFFECT_MEMORY(fxp, xc->arpeggio.memory); goto fx_arpeggio; #ifndef LIBXMP_CORE_PLAYER case FX_OKT_ARP3: if (fxp != 0) { xc->arpeggio.val[0] = -MSN(fxp); xc->arpeggio.val[1] = 0; xc->arpeggio.val[2] = LSN(fxp); xc->arpeggio.size = 3; } break; case FX_OKT_ARP4: if (fxp != 0) { xc->arpeggio.val[0] = 0; xc->arpeggio.val[1] = LSN(fxp); xc->arpeggio.val[2] = 0; xc->arpeggio.val[3] = -MSN(fxp); xc->arpeggio.size = 4; } break; case FX_OKT_ARP5: if (fxp != 0) { xc->arpeggio.val[0] = LSN(fxp); xc->arpeggio.val[1] = LSN(fxp); xc->arpeggio.val[2] = 0; xc->arpeggio.size = 3; } break; #endif case FX_PORTA_UP: /* Portamento up */ EFFECT_MEMORY(fxp, xc->freq.memory); if (HAS_QUIRK(QUIRK_FINEFX) && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { switch (MSN(fxp)) { case 0xf: fxp &= 0x0f; goto fx_f_porta_up; case 0xe: fxp &= 0x0f; fxp |= 0x10; goto fx_xf_porta; } } SET(PITCHBEND); if (fxp != 0) { xc->freq.slide = -fxp; if (HAS_QUIRK(QUIRK_UNISLD)) xc->porta.memory = fxp; } else if (xc->freq.slide > 0) { xc->freq.slide *= -1; } break; case FX_PORTA_DN: /* Portamento down */ EFFECT_MEMORY(fxp, xc->freq.memory); if (HAS_QUIRK(QUIRK_FINEFX) && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { switch (MSN(fxp)) { case 0xf: fxp &= 0x0f; goto fx_f_porta_dn; case 0xe: fxp &= 0x0f; fxp |= 0x20; goto fx_xf_porta; } } SET(PITCHBEND); if (fxp != 0) { xc->freq.slide = fxp; if (HAS_QUIRK(QUIRK_UNISLD)) xc->porta.memory = fxp; } else if (xc->freq.slide < 0) { xc->freq.slide *= -1; } break; case FX_TONEPORTA: /* Tone portamento */ if (HAS_QUIRK(QUIRK_IGSTPOR)) { if (note == 0 && xc->porta.dir == 0) break; } if (!IS_VALID_INSTRUMENT(xc->ins)) break; do_toneporta(m, xc, note); EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory); if (fxp != 0) { if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */ xc->freq.memory = fxp; xc->porta.slide = fxp; } SET(TONEPORTA); break; case FX_VIBRATO: /* Vibrato */ EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); SET(VIBRATO); SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp)); break; case FX_FINE_VIBRATO: /* Fine vibrato */ EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); SET(VIBRATO); SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp)); break; case FX_TONE_VSLIDE: /* Toneporta + vol slide */ if (!IS_VALID_INSTRUMENT(xc->ins)) break; do_toneporta(m, xc, note); SET(TONEPORTA); goto fx_volslide; case FX_VIBRA_VSLIDE: /* Vibrato + vol slide */ SET(VIBRATO); goto fx_volslide; case FX_TREMOLO: /* Tremolo */ EFFECT_MEMORY_SETONLY(fxp, xc->tremolo.memory); SET(TREMOLO); SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp)); break; case FX_SETPAN: /* Set pan */ xc->pan.val = fxp; break; case FX_OFFSET: /* Set sample offset */ SET(OFFSET); if (fxp) { xc->offset_val = xc->offset = fxp << 8; } else { xc->offset_val = xc->offset; } break; case FX_VOLSLIDE: /* Volume slide */ fx_volslide: /* S3M file volume slide note: * DFy Fine volume down by y (...) If y is 0, the command will * be treated as a volume slide up with a value of f (15). * If a DFF command is specified, the volume will be slid * up. */ if (HAS_QUIRK(QUIRK_FINEFX)) { h = MSN(fxp); l = LSN(fxp); if (l == 0xf && h != 0) { xc->vol.memory = fxp; fxp >>= 4; goto fx_f_vslide_up; } else if (h == 0xf && l != 0) { xc->vol.memory = fxp; fxp &= 0x0f; goto fx_f_vslide_dn; } }
static void get_pbod(struct module_data *m, int size, xmp_file f, void *parm) { struct xmp_module *mod = &m->mod; struct local_data *data = (struct local_data *)parm; int j; uint16 rows; struct xmp_event *event; if (data->pattern >= mod->pat) return; if (!data->pattern) { PATTERN_INIT(); D_(D_INFO "Stored patterns: %d", mod->pat); } rows = read16b(f); PATTERN_ALLOC(data->pattern); mod->xxp[data->pattern]->rows = rows; TRACK_ALLOC(data->pattern); for (j = 0; j < rows * mod->chn; j++) { uint8 note, ins; event = &EVENT(data->pattern, j % mod->chn, j / mod->chn); memset(event, 0, sizeof(struct xmp_event)); note = read8(f); ins = read8(f); if (note) { event->note = 48 + note; event->ins = 1 + ins; } event->fxt = fx[read8(f)]; event->fxp = read8(f); if ((event->fxt == FX_VOLSET) && (event->fxp > 0x40)) { if (event->fxp <= 0x50) { event->fxt = FX_VOLSLIDE; event->fxp -= 0x40; } else if (event->fxp <= 0x60) { event->fxt = FX_VOLSLIDE; event->fxp = (event->fxp - 0x50) << 4; } else if (event->fxp <= 0x70) { event->fxt = FX_EXTENDED; event->fxp = (EX_F_VSLIDE_DN << 4) | (event->fxp - 0x60); } else if (event->fxp <= 0x80) { event->fxt = FX_EXTENDED; event->fxp = (EX_F_VSLIDE_UP << 4) | (event->fxp - 0x70); } } if (event->fxt == FX_ARPEGGIO) /* Arpeggio fixup */ event->fxp = (((24 - MSN (event->fxp)) % 12) << 4) | LSN (event->fxp); if (event->fxt == NONE) event->fxt = event->fxp = 0; } data->pattern++; }
void process_fx(struct xmp_context *ctx, int chn, uint8 note, uint8 fxt, uint8 fxp, struct xmp_channel *xc) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; int h, l; switch (fxt) { case FX_ARPEGGIO: if (!fxp) break; xc->a_val[0] = 0; xc->a_val[1] = 100 * MSN(fxp); xc->a_val[2] = 100 * LSN(fxp); xc->a_size = 3; break; case FX_OKT_ARP3: if (!fxp) break; xc->a_val[0] = -100 * MSN(fxp); xc->a_val[1] = 0; xc->a_val[2] = 100 * LSN(fxp);; xc->a_size = 3; case FX_OKT_ARP4: if (!fxp) break; xc->a_val[0] = 0; xc->a_val[1] = 100 * LSN(fxp);; xc->a_val[2] = 0; xc->a_val[3] = -100 * MSN(fxp); xc->a_size = 4; break; case FX_OKT_ARP5: if (!fxp) break; xc->a_val[0] = 100 * LSN(fxp);; xc->a_val[1] = 100 * LSN(fxp);; xc->a_val[2] = 0; xc->a_size = 3; break; case FX_PORTA_UP: /* Portamento up */ fx_porta_up: if (m->fetch & XMP_CTL_FINEFX) { switch (MSN(fxp)) { case 0xf: xc->porta = fxp; fxp &= 0x0f; goto ex_f_porta_up; case 0xe: xc->porta = fxp; fxp &= 0x0e; fxp |= 0x10; goto fx_xf_porta; } if (!fxp) { if ((fxp = xc->porta) != 0) goto fx_porta_up; } } SET(PITCHBEND); if ((xc->porta = fxp) != 0) xc->f_val = -fxp; else if (xc->f_val > 0) xc->f_val *= -1; break; case FX_PORTA_DN: /* Portamento down */ fx_porta_dn: if (m->fetch & XMP_CTL_FINEFX) { switch (MSN(fxp)) { case 0xf: xc->porta = fxp; fxp &= 0x0f; goto ex_f_porta_dn; case 0xe: xc->porta = fxp; fxp &= 0x0e; fxp |= 0x20; goto fx_xf_porta; } if (!fxp) { if ((fxp = xc->porta) != 0) goto fx_porta_dn; } } SET(PITCHBEND); if ((xc->porta = fxp) != 0) xc->f_val = fxp; else if (xc->f_val < 0) xc->f_val *= -1; break; case FX_TONEPORTA: /* Tone portamento */ if (!TEST (IS_VALID)) break; DO_TONEPORTA(); if (fxp) xc->s_val = fxp; SET(TONEPORTA); break; case FX_PER_PORTA_UP: /* Persistent portamento up */ SET_PER(PITCHBEND); xc->f_val = -fxp; if ((xc->porta = fxp) == 0) RESET_PER(PITCHBEND); break; case FX_PER_PORTA_DN: /* Persistent portamento down */ SET(PITCHBEND); xc->f_val = fxp; if ((xc->porta = fxp) == 0) RESET_PER(PITCHBEND); break; case FX_PER_TPORTA: /* Persistent tone portamento */ if (!TEST(IS_VALID)) break; SET_PER(TONEPORTA); DO_TONEPORTA(); xc->s_val = fxp; if (fxp == 0) RESET_PER(TONEPORTA); break; case FX_PER_VSLD_UP: /* Persistent volslide up */ SET_PER(VOL_SLIDE); xc->v_val = fxp; if (fxp == 0) RESET_PER(VOL_SLIDE); break; case FX_PER_VSLD_DN: /* Persistent volslide down */ SET_PER(VOL_SLIDE); xc->v_val = -fxp; if (fxp == 0) RESET_PER(VOL_SLIDE); break; case FX_TEMPO_CP: /* Set tempo and ... */ if (fxp) p->tempo = fxp; /* fall through */ case FX_PER_CANCEL: /* Cancel persistent effects */ xc->per_flags = 0; break; case FX_VIBRATO: /* Vibrato */ SET(VIBRATO); if (LSN(fxp)) xc->y_depth = LSN(fxp) * 4; if (MSN(fxp)) xc->y_rate = MSN(fxp); break; case FX_FINE2_VIBRA: /* Fine vibrato (2x) */ SET(VIBRATO); if (LSN(fxp)) xc->y_depth = LSN(fxp) * 2; if (MSN(fxp)) xc->y_rate = MSN(fxp); break; case FX_FINE4_VIBRA: /* Fine vibrato (4x) */ SET(VIBRATO); if (LSN(fxp)) xc->y_depth = LSN(fxp); if (MSN(fxp)) xc->y_rate = MSN(fxp); break; case FX_PER_VIBRATO: /* Persistent vibrato */ SET_PER(VIBRATO); if (LSN(fxp)) xc->y_depth = LSN(fxp) * 4; else RESET_PER(VIBRATO); if (MSN(fxp)) xc->y_rate = MSN(fxp); break; case FX_TONE_VSLIDE: /* Toneporta + vol slide */ if (!TEST (IS_VALID)) break; DO_TONEPORTA (); SET(TONEPORTA); goto fx_volslide; case FX_VIBRA_VSLIDE: /* Vibrato + vol slide */ SET(VIBRATO); goto fx_volslide; case FX_TREMOLO: /* Tremolo */ SET(TREMOLO); if (MSN(fxp)) xc->t_rate = MSN(fxp); if (LSN(fxp)) xc->t_depth = LSN(fxp); break; case FX_SETPAN: /* Set pan */ SET(NEW_PAN); xc->pan = fxp; break; case FX_OFFSET: /* Set sample offset */ SET(OFFSET); if (fxp) xc->offset_val = xc->offset = fxp << 8; else xc->offset_val = xc->offset; break; case FX_VOLSLIDE: /* Volume slide */ fx_volslide: if (m->fetch & XMP_CTL_FINEFX) { h = MSN(fxp); l = LSN(fxp); if (h == 0xf && l != 0) { xc->volslide = fxp; fxp &= 0x0f; goto ex_f_vslide_dn; } else if (h == 0xe && l != 0) { xc->volslide = fxp; fxp &= 0x0f; goto ex_f_vslide_dn; /* FIXME */ } else if (l == 0xf && h != 0) { xc->volslide = fxp; fxp >>= 4; goto ex_f_vslide_up; } else if (l == 0xe && h != 0) {
static void get_patt(struct xmp_context *ctx, int size, FILE *f) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; int i, c, r, n, sz; struct xxm_event *event, dummy; uint8 x; PATTERN_INIT(); reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat); /* * Note: channel and flag bytes are inverted in the format * description document */ for (i = 0; i < m->xxh->pat; i++) { PATTERN_ALLOC(i); m->xxp[i]->rows = read16b(f); TRACK_ALLOC(i); sz = read32b(f); //printf("rows = %d, size = %d\n", m->xxp[i]->rows, sz); r = 0; c = -1; while (sz > 0) { //printf(" offset=%x, sz = %d, ", ftell(f), sz); c = read8(f); if (--sz <= 0) break; //printf("c = %02x\n", c); if (c == 0) { r++; c = -1; continue; } c--; n = read8(f); if (--sz <= 0) break; //printf(" n = %d\n", n); if (c >= m->xxh->chn || r >= m->xxp[i]->rows) event = &dummy; else event = &EVENT(i, c, r); if (n & 0x01) { x = read8(f); event->note = 1 + MSN(x) * 12 + LSN(x); if (--sz <= 0) break; } if (n & 0x02) { event->ins = read8(f); if (--sz <= 0) break; } if (n & 0x04) { event->fxt = read8(f); if (--sz <= 0) break; } if (n & 0x08) { event->fxp = read8(f); if (--sz <= 0) break; } if (n & 0x10) { event->f2t = read8(f); if (--sz <= 0) break; } if (n & 0x20) { event->f2p = read8(f); if (--sz <= 0) break; } if (event->fxt == 0x1c) event->fxt = FX_S3M_BPM; if (event->fxt > 0x1c) event->fxt = event->f2p = 0; if (event->f2t == 0x1c) event->f2t = FX_S3M_BPM; if (event->f2t > 0x1c) event->f2t = event->f2p = 0; } reportv(ctx, 0, "."); } reportv(ctx, 0, "\n"); }
static void get_patt(struct module_data *m, int size, FILE *f, void *parm) { struct xmp_module *mod = &m->mod; int i, c, r, n, sz; struct xmp_event *event, dummy; uint8 x; PATTERN_INIT(); D_(D_INFO "Stored patterns: %d ", mod->pat); /* * Note: channel and flag bytes are inverted in the format * description document */ for (i = 0; i < mod->pat; i++) { PATTERN_ALLOC(i); mod->xxp[i]->rows = read16b(f); TRACK_ALLOC(i); sz = read32b(f); //printf("rows = %d, size = %d\n", mod->xxp[i]->rows, sz); r = 0; c = -1; while (sz > 0) { //printf(" offset=%x, sz = %d, ", ftell(f), sz); c = read8(f); if (--sz <= 0) break; //printf("c = %02x\n", c); if (c == 0) { r++; c = -1; continue; } c--; n = read8(f); if (--sz <= 0) break; //printf(" n = %d\n", n); if (c >= mod->chn || r >= mod->xxp[i]->rows) event = &dummy; else event = &EVENT(i, c, r); if (n & 0x01) { x = read8(f); event->note = 13 + MSN(x) * 12 + LSN(x); if (--sz <= 0) break; } if (n & 0x02) { event->ins = read8(f); if (--sz <= 0) break; } if (n & 0x04) { event->fxt = read8(f); if (--sz <= 0) break; } if (n & 0x08) { event->fxp = read8(f); if (--sz <= 0) break; } if (n & 0x10) { event->f2t = read8(f); if (--sz <= 0) break; } if (n & 0x20) { event->f2p = read8(f); if (--sz <= 0) break; } if (event->fxt == 0x1c) event->fxt = FX_S3M_BPM; if (event->fxt > 0x1c) event->fxt = event->f2p = 0; if (event->f2t == 0x1c) event->f2t = FX_S3M_BPM; if (event->f2t > 0x1c) event->f2t = event->f2p = 0; } } }
static int get_pbod(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; struct xmp_event *e; uint16 rows; int j; if (data->pattern >= mod->pat) return 0; if (!data->pattern) { if (pattern_init(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); } rows = hio_read16b(f); if (pattern_tracks_alloc(mod, data->pattern, rows) < 0) return -1; for (j = 0; j < rows * mod->chn; j++) { uint8 note, ins; e = &EVENT(data->pattern, j % mod->chn, j / mod->chn); memset(e, 0, sizeof(struct xmp_event)); note = hio_read8(f); ins = hio_read8(f); if (note) { e->note = 48 + note; e->ins = 1 + ins; } e->fxt = fx[hio_read8(f)]; e->fxp = hio_read8(f); if ((e->fxt == FX_VOLSET) && (e->fxp > 0x40)) { if (e->fxp <= 0x50) { e->fxt = FX_VOLSLIDE; e->fxp -= 0x40; } else if (e->fxp <= 0x60) { e->fxt = FX_VOLSLIDE; e->fxp = (e->fxp - 0x50) << 4; } else if (e->fxp <= 0x70) { e->fxt = FX_F_VSLIDE_DN; e->fxp = e->fxp - 0x60; } else if (e->fxp <= 0x80) { e->fxt = FX_F_VSLIDE_UP; e->fxp = e->fxp - 0x70; } } if (e->fxt == FX_ARPEGGIO) /* Arpeggio fixup */ e->fxp = (((24 - MSN(e->fxp)) % 12) << 4) | LSN(e->fxp); if (e->fxt == NONE) e->fxt = e->fxp = 0; } data->pattern++; return 0; }
void mmd_xlat_fx(struct xmp_event *event, int bpm_on, int bpmlen, int med_8ch) { if (event->fxt > 0x0f) { event->fxt = event->fxp = 0; return; } switch (event->fxt) { case 0x05: /* Old vibrato */ event->fxp = (LSN(event->fxp) << 4) | MSN(event->fxp); break; case 0x06: /* Not defined in MED 3.2 */ case 0x07: /* Not defined in MED 3.2 */ break; case 0x08: /* Set hold/decay */ break; case 0x09: /* Set secondary tempo */ event->fxt = FX_SPEED; break; case 0x0d: /* Volume slide */ event->fxt = FX_VOLSLIDE; break; case 0x0e: /* Synth JMP */ break; case 0x0f: if (event->fxp == 0x00) { /* Jump to next block */ event->fxt = 0x0d; break; } else if (event->fxp <= 0xf0) { event->fxt = FX_S3M_BPM; event->fxp = med_8ch ? mmd_get_8ch_tempo(event->fxp) : (bpm_on ? event->fxp/bpmlen : event->fxp); break; } else switch (event->fxp) { case 0xf1: /* Play note twice */ event->fxt = FX_EXTENDED; event->fxp = (EX_RETRIG << 4) | 3; break; case 0xf2: /* Delay note */ event->fxt = FX_EXTENDED; event->fxp = (EX_DELAY << 4) | 3; break; case 0xf3: /* Play note three times */ event->fxt = FX_EXTENDED; event->fxp = (EX_RETRIG << 4) | 2; break; case 0xf8: /* Turn filter off */ case 0xf9: /* Turn filter on */ case 0xfa: /* MIDI pedal on */ case 0xfb: /* MIDI pedal off */ case 0xfd: /* Set pitch */ case 0xfe: /* End of song */ event->fxt = event->fxp = 0; break; case 0xff: /* Note cut */ event->fxt = FX_EXTENDED; event->fxp = (EX_CUT << 4) | 3; break; default: event->fxt = event->fxp = 0; } break; } }
static int unpack_block(struct module_data *m, uint16 bnum, uint8 *from) { struct xmp_module *mod = &m->mod; struct xmp_event *event; uint32 linemsk0 = *((uint32 *)from), linemsk1 = *((uint32 *)from + 1); uint32 fxmsk0 = *((uint32 *)from + 2), fxmsk1 = *((uint32 *)from + 3); uint32 *lmptr = &linemsk0, *fxptr = &fxmsk0; uint16 fromn = 0, lmsk; uint8 *fromst = from + 16, bcnt, *tmpto; uint8 *patbuf, *to; int i, j, trkn = mod->chn; from += 16; patbuf = to = calloc(3, 4 * 64); if (to == NULL) return -1; for (i = 0; i < 64; i++) { if (i == 32) { lmptr = &linemsk1; fxptr = &fxmsk1; } if (*lmptr & MASK) { lmsk = get_nibbles(fromst, &fromn, (uint8)(trkn / 4)); lmsk <<= (16 - trkn); tmpto = to; for (bcnt = 0; bcnt < trkn; bcnt++) { if (lmsk & 0x8000) { *tmpto = (uint8)get_nibbles(fromst, &fromn,2); *(tmpto + 1) = (get_nibble(fromst, &fromn) << 4); } lmsk <<= 1; tmpto += 3; } } if (*fxptr & MASK) { lmsk = get_nibbles(fromst,&fromn,(uint8)(trkn / 4)); lmsk <<= (16 - trkn); tmpto = to; for (bcnt = 0; bcnt < trkn; bcnt++) { if (lmsk & 0x8000) { *(tmpto+1) |= get_nibble(fromst, &fromn); *(tmpto+2) = (uint8)get_nibbles(fromst, &fromn,2); } lmsk <<= 1; tmpto += 3; } } to += 3 * trkn; *lmptr <<= 1; *fxptr <<= 1; } for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { event = &EVENT(bnum, j, i); event->note = patbuf[i * 12 + j * 3 + 0]; if (event->note) event->note += 48; event->ins = patbuf[i * 12 + j * 3 + 1] >> 4; if (event->ins) event->ins++; event->fxt = patbuf[i * 12 + j * 3 + 1] & 0x0f; event->fxp = patbuf[i * 12 + j * 3 + 2]; switch (event->fxt) { case 0x00: /* arpeggio */ case 0x01: /* slide up */ case 0x02: /* slide down */ case 0x03: /* portamento */ case 0x04: /* vibrato? */ break; case 0x0c: /* set volume (BCD) */ event->fxp = MSN(event->fxp) * 10 + LSN(event->fxp); break; case 0x0d: /* volume slides */ event->fxt = FX_VOLSLIDE; break; case 0x0f: /* tempo/break */ if (event->fxp == 0) event->fxt = FX_BREAK; if (event->fxp == 0xff) { event->fxp = event->fxt = 0; event->vol = 1; } else if (event->fxp == 0xfe) { event->fxp = event->fxt = 0; } else if (event->fxp == 0xf1) { event->fxt = FX_EXTENDED; event->fxp = (EX_RETRIG << 4) | 3; } else if (event->fxp == 0xf2) { event->fxt = FX_EXTENDED; event->fxp = (EX_CUT << 4) | 3; } else if (event->fxp == 0xf3) { event->fxt = FX_EXTENDED; event->fxp = (EX_DELAY << 4) | 3; } else if (event->fxp > 10) { event->fxt = FX_S3M_BPM; event->fxp = 125 * event->fxp / 33; } break; default: event->fxp = event->fxt = 0; } } } free(patbuf); return 0; }
static void xlat_fx(int c, struct xmp_event *e, uint8 *last_fxp, int new_fx) { uint8 h = MSN(e->fxp), l = LSN(e->fxp); switch (e->fxt = fx[e->fxt]) { case FX_XTND: /* Extended effect */ e->fxt = FX_EXTENDED; if (h == 0 && e->fxp == 0) { e->fxp = last_fxp[c]; h = MSN(e->fxp); l = LSN(e->fxp); } else { last_fxp[c] = e->fxp; } switch (h) { case 0x1: /* Glissando */ e->fxp = 0x30 | l; break; case 0x2: /* Finetune */ e->fxp = 0x50 | l; break; case 0x3: /* Vibrato wave */ e->fxp = 0x40 | l; break; case 0x4: /* Tremolo wave */ e->fxp = 0x70 | l; break; case 0x5: /* Panbrello wave */ if (l <= 3) { e->fxt = FX_PANBRELLO_WF; e->fxp = l; } else { e->fxt = e->fxp = 0; } break; case 0x6: /* Pattern delay */ e->fxp = 0xe0 | l; break; case 0x7: /* Instrument functions */ e->fxt = FX_IT_INSTFUNC; e->fxp &= 0x0f; break; case 0x8: /* Set pan position */ e->fxt = FX_MASTER_PAN; e->fxp = l << 4; break; case 0x9: /* 0x91 = set surround -- NOT IMPLEMENTED */ e->fxt = e->fxp = 0; break; case 0xb: /* Pattern loop */ e->fxp = 0x60 | l; break; case 0xc: /* Note cut */ case 0xd: /* Note delay */ if ((e->fxp = l) == 0) e->fxp++; /* SD0 and SC0 becomes SD1 and SC1 */ e->fxp |= h << 4; break; case 0xe: /* Pattern row delay */ e->fxt = FX_IT_ROWDELAY; e->fxp = l; break; default: e->fxt = e->fxp = 0; } break; case FX_FLT_CUTOFF: if (e->fxp > 0x7f && e->fxp < 0x90) { /* Resonance */ e->fxt = FX_FLT_RESN; e->fxp = (e->fxp - 0x80) * 16; } else { /* Cutoff */ e->fxp *= 2; } break; case FX_TREMOR: if (!new_fx && e->fxp != 0) { e->fxp = ((MSN(e->fxp) + 1) << 4) | (LSN(e->fxp) + 1); } break; case FX_GLOBALVOL: if (e->fxp > 0x80) { /* See storlek test 16 */ e->fxt = e->fxp = 0; } break; case FX_NONE: /* No effect */ e->fxt = e->fxp = 0; break; } }
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; }
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 mgt_load(struct xmp_context *ctx, FILE *f, const int start) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; struct xxm_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(); read24b(f); /* MGT */ ver = read8(f); read32b(f); /* MCS */ sprintf(m->type, "MGT v%d.%d (Megatracker)", MSN(ver), LSN(ver)); m->xxh->chn = read16b(f); read16b(f); /* number of songs */ m->xxh->len = read16b(f); m->xxh->pat = read16b(f); m->xxh->trk = read16b(f); m->xxh->ins = m->xxh->smp = read16b(f); read16b(f); /* reserved */ read32b(f); /* reserved */ sng_ptr = read32b(f); seq_ptr = read32b(f); ins_ptr = read32b(f); pat_ptr = read32b(f); trk_ptr = read32b(f); smp_ptr = read32b(f); read32b(f); /* total smp len */ read32b(f); /* unpacked trk size */ fseek(f, start + sng_ptr, SEEK_SET); fread(m->name, 1, 32, f); seq_ptr = read32b(f); m->xxh->len = read16b(f); m->xxh->rst = read16b(f); m->xxh->bpm = read8(f); m->xxh->tpo = read8(f); read16b(f); /* global volume */ read8(f); /* master L */ read8(f); /* master R */ for (i = 0; i < m->xxh->chn; i++) { read16b(f); /* pan */ } MODULE_INFO(); /* Sequence */ fseek(f, start + seq_ptr, SEEK_SET); for (i = 0; i < m->xxh->len; i++) m->xxo[i] = read16b(f); /* Instruments */ INSTRUMENT_INIT(); fseek(f, start + ins_ptr, SEEK_SET); reportv(ctx, 1, " Name Len LBeg LEnd L Vol C2Spd\n"); for (i = 0; i < m->xxh->ins; i++) { int c2spd, flags; m->xxi[i] = calloc(sizeof(struct xxm_instrument), 1); fread(m->xxih[i].name, 1, 32, f); sdata[i] = read32b(f); m->xxs[i].len = read32b(f); m->xxs[i].lps = read32b(f); m->xxs[i].lpe = m->xxs[i].lps + read32b(f); read32b(f); read32b(f); c2spd = read32b(f); c2spd_to_note(c2spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin); m->xxi[i][0].vol = read16b(f) >> 4; read8(f); /* vol L */ read8(f); /* vol R */ m->xxi[i][0].pan = 0x80; flags = read8(f); m->xxs[i].flg = flags & 0x03 ? WAVE_LOOPING : 0; m->xxs[i].flg |= flags & 0x02 ? WAVE_BIDIR_LOOP : 0; m->xxi[i][0].fin += 0 * read8(f); // FIXME read8(f); /* unused */ read8(f); read8(f); read8(f); read16b(f); read32b(f); read32b(f); m->xxih[i].nsm = !!m->xxs[i].len; m->xxi[i][0].sid = i; if (V(1) && (strlen((char*)m->xxih[i].name) || (m->xxs[i].len > 1))) { report("[%2X] %-32.32s %04x %04x %04x %c V%02x %5d\n", i, m->xxih[i].name, m->xxs[i].len, m->xxs[i].lps, m->xxs[i].lpe, m->xxs[i].flg & WAVE_BIDIR_LOOP ? 'B' : m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ', m->xxi[i][0].vol, c2spd); } } /* PATTERN_INIT - alloc extra track*/ PATTERN_INIT(); reportv(ctx, 0, "Stored tracks : %d ", m->xxh->trk); /* Tracks */ for (i = 1; i < m->xxh->trk; i++) { int offset, rows; uint8 b; fseek(f, start + trk_ptr + i * 4, SEEK_SET); offset = read32b(f); fseek(f, start + offset, SEEK_SET); rows = read16b(f); m->xxt[i] = calloc(sizeof(struct xxm_track) + sizeof(struct xxm_event) * rows, 1); m->xxt[i]->rows = rows; //printf("\n=== Track %d ===\n\n", i); for (j = 0; j < rows; j++) { uint8 note, f2p; b = read8(f); j += b & 0x03; note = 0; event = &m->xxt[i]->event[j]; if (b & 0x04) note = read8(f); if (b & 0x08) event->ins = read8(f); if (b & 0x10) event->vol = read8(f); if (b & 0x20) event->fxt = read8(f); if (b & 0x40) event->fxp = read8(f); if (b & 0x80) f2p = read8(f); if (note == 1) event->note = XMP_KEY_OFF; else if (note > 11) /* adjusted to play codeine.mgt */ event->note = note - 11; /* 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);*/ } if (V(0) && i % m->xxh->chn == 0) report("."); } reportv(ctx, 0, "\n"); /* Extra track */ m->xxt[0] = calloc(sizeof(struct xxm_track) + sizeof(struct xxm_event) * 64 - 1, 1); m->xxt[0]->rows = 64; /* Read and convert patterns */ reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat); fseek(f, start + pat_ptr, SEEK_SET); for (i = 0; i < m->xxh->pat; i++) { PATTERN_ALLOC(i); m->xxp[i]->rows = read16b(f); for (j = 0; j < m->xxh->chn; j++) { m->xxp[i]->info[j].index = read16b(f) - 1; //printf("%3d ", m->xxp[i]->info[j].index); } reportv(ctx, 0, "."); //printf("\n"); } reportv(ctx, 0, "\n"); /* Read samples */ reportv(ctx, 0, "Stored samples : %d ", m->xxh->smp); for (i = 0; i < m->xxh->ins; i++) { if (m->xxih[i].nsm == 0) continue; fseek(f, start + sdata[i], SEEK_SET); xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate, 0, &m->xxs[m->xxi[i][0].sid], NULL); reportv(ctx, 0, "."); } reportv(ctx, 0, "\n"); return 0; }
static int s3m_load(struct module_data *m, FILE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i; struct s3m_adlib_header sah; struct xmp_event *event = 0, dummy; struct s3m_file_header sfh; struct s3m_instrument_header sih; int pat_len; uint8 n, b, x8; char tracker_name[40]; int quirk87 = 0; uint16 *pp_ins; /* Parapointers to instruments */ uint16 *pp_pat; /* Parapointers to patterns */ uint8 arpeggio_val[32]; LOAD_INIT(); fread(&sfh.name, 28, 1, f); /* Song name */ read8(f); /* 0x1a */ sfh.type = read8(f); /* File type */ read16l(f); /* Reserved */ sfh.ordnum = read16l(f); /* Number of orders (must be even) */ sfh.insnum = read16l(f); /* Number of instruments */ sfh.patnum = read16l(f); /* Number of patterns */ sfh.flags = read16l(f); /* Flags */ sfh.version = read16l(f); /* Tracker ID and version */ sfh.ffi = read16l(f); /* File format information */ sfh.magic = read32b(f); /* 'SCRM' */ sfh.gv = read8(f); /* Global volume */ sfh.is = read8(f); /* Initial speed */ sfh.it = read8(f); /* Initial tempo */ sfh.mv = read8(f); /* Master volume */ sfh.uc = read8(f); /* Ultra click removal */ sfh.dp = read8(f); /* Default pan positions if 0xfc */ read32l(f); /* Reserved */ read32l(f); /* Reserved */ sfh.special = read16l(f); /* Ptr to special custom data */ fread(sfh.chset, 32, 1, f); /* Channel settings */ #if 0 if (sfh.magic != MAGIC_SCRM) return -1; #endif /* S3M anomaly in return_of_litmus.s3m */ if (sfh.version == 0x1301 && sfh.name[27] == 0x87) quirk87 = 1; if (quirk87) { fix87(sfh.name); fix87(sfh.patnum); fix87(sfh.flags); } copy_adjust(mod->name, sfh.name, 28); /* Load and convert header */ mod->len = sfh.ordnum; mod->ins = sfh.insnum; mod->smp = mod->ins; mod->pat = sfh.patnum; pp_ins = calloc (2, mod->ins); pp_pat = calloc (2, mod->pat); if (sfh.flags & S3M_AMIGA_RANGE) m->quirk |= QUIRK_MODRNG; if (sfh.flags & S3M_ST300_VOLS) m->quirk |= QUIRK_VSALL; /* m->volbase = 4096 / sfh.gv; */ mod->spd = sfh.is; mod->bpm = sfh.it; for (i = 0; i < 32; i++) { if (sfh.chset[i] == S3M_CH_OFF) continue; mod->chn = i + 1; if (sfh.mv & 0x80) { /* stereo */ int x = sfh.chset[i] & S3M_CH_PAN; mod->xxc[i].pan = (x & 0x0f) < 8 ? 0x00 : 0xff; } else { mod->xxc[i].pan = 0x80; } } mod->trk = mod->pat * mod->chn; fread(mod->xxo, 1, mod->len, f); for (i = 0; i < mod->ins; i++) pp_ins[i] = read16l(f); for (i = 0; i < mod->pat; i++) pp_pat[i] = read16l(f); /* Default pan positions */ for (i = 0, sfh.dp -= 0xfc; !sfh.dp /* && n */ && (i < 32); i++) { uint8 x = read8(f); if (x & S3M_PAN_SET) mod->xxc[i].pan = (x << 4) & 0xff; else mod->xxc[i].pan = sfh.mv % 0x80 ? 0x30 + 0xa0 * (i & 1) : 0x80; } m->c4rate = C4_NTSC_RATE; if (sfh.version == 0x1300) m->quirk |= QUIRK_VSALL; switch (sfh.version >> 12) { case 1: snprintf(tracker_name, 40, "Scream Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); m->quirk |= QUIRK_ST3GVOL; break; case 2: snprintf(tracker_name, 40, "Imago Orpheus %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; case 3: if (sfh.version == 0x3216) { strcpy(tracker_name, "Impulse Tracker 2.14v3"); } else if (sfh.version == 0x3217) { strcpy(tracker_name, "Impulse Tracker 2.14v5"); } else { snprintf(tracker_name, 40, "Impulse Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); } break; case 4: snprintf(tracker_name, 40, "Schism Tracker %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; case 5: snprintf(tracker_name, 40, "OpenMPT %d.%02x", (sfh.version & 0x0f00) >> 8, sfh.version & 0xff); break; default: snprintf(tracker_name, 40, "unknown (%04x)", sfh.version); } snprintf(mod->type, XMP_NAME_SIZE, "%s S3M", tracker_name); MODULE_INFO(); PATTERN_INIT(); /* Read patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); memset (arpeggio_val, 0, 32); for (i = 0; i < mod->pat; i++) { PATTERN_ALLOC (i); mod->xxp[i]->rows = 64; TRACK_ALLOC (i); if (!pp_pat[i]) continue; fseek(f, start + pp_pat[i] * 16, SEEK_SET); r = 0; pat_len = read16l(f) - 2; /* Used to be (--pat_len >= 0). Replaced by Rudolf Cejka * <*****@*****.**>, fixes hunt.s3m * ftp://us.aminet.net/pub/aminet/mods/8voic/s3m_hunt.lha */ while (r < mod->xxp[i]->rows) { b = 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) { switch(n = read8(f)) { case 255: n = 0; break; /* Empty note */ case 254: n = XMP_KEY_OFF; break; /* Key off */ default: n = 13 + 12 * MSN (n) + LSN (n); } event->note = n; event->ins = read8(f); pat_len -= 2; } if (b & S3M_VOL_FOLLOWS) { event->vol = read8(f) + 1; pat_len--; } if (b & S3M_FX_FOLLOWS) { event->fxt = read8(f); event->fxp = read8(f); xlat_fx(c, event, arpeggio_val); pat_len -= 2; } } } D_(D_INFO "Stereo enabled: %s", sfh.mv & 0x80 ? "yes" : "no"); D_(D_INFO "Pan settings: %s", sfh.dp ? "no" : "yes"); INSTRUMENT_INIT(); /* Read and convert instruments and samples */ D_(D_INFO "Instruments: %d", mod->ins); for (i = 0; i < mod->ins; i++) { mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); fseek(f, start + pp_ins[i] * 16, SEEK_SET); x8 = read8(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; if (x8 >= 2) { /* OPL2 FM instrument */ fread(&sah.dosname, 12, 1, f); /* DOS file name */ fread(&sah.rsvd1, 3, 1, f); /* 0x00 0x00 0x00 */ fread(&sah.reg, 12, 1, f); /* Adlib registers */ sah.vol = read8(f); sah.dsk = read8(f); read16l(f); sah.c2spd = read16l(f); /* C 4 speed */ read16l(f); fread(&sah.rsvd4, 12, 1, f); /* Reserved */ fread(&sah.name, 28, 1, f); /* Instrument name */ sah.magic = read32b(f); /* 'SCRI' */ if (sah.magic != MAGIC_SCRI) { D_(D_CRIT "error: FM instrument magic"); return -2; } sah.magic = 0; copy_adjust(mod->xxi[i].name, sah.name, 28); mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].vol = sah.vol; c2spd_to_note(sah.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].xpo += 12; load_sample(f, SAMPLE_FLAG_ADLIB, &mod->xxs[i], (char *)&sah.reg); D_(D_INFO "[%2X] %-28.28s", i, mod->xxi[i].name); continue; } fread(&sih.dosname, 13, 1, f); /* DOS file name */ sih.memseg = read16l(f); /* Pointer to sample data */ sih.length = read32l(f); /* Length */ sih.loopbeg = read32l(f); /* Loop begin */ sih.loopend = read32l(f); /* Loop end */ sih.vol = read8(f); /* Volume */ sih.rsvd1 = read8(f); /* Reserved */ sih.pack = read8(f); /* Packing type (not used) */ sih.flags = read8(f); /* Loop/stereo/16bit samples flags */ sih.c2spd = read16l(f); /* C 4 speed */ sih.rsvd2 = read16l(f); /* Reserved */ fread(&sih.rsvd3, 4, 1, f); /* Reserved */ sih.int_gp = read16l(f); /* Internal - GUS pointer */ sih.int_512 = read16l(f); /* Internal - SB pointer */ sih.int_last = read32l(f); /* Internal - SB index */ fread(&sih.name, 28, 1, f); /* Instrument name */ sih.magic = read32b(f); /* 'SCRS' */ if (x8 == 1 && sih.magic != MAGIC_SCRS) { D_(D_CRIT "error: instrument magic"); return -2; } if (quirk87) { fix87(sih.length); fix87(sih.loopbeg); fix87(sih.loopend); fix87(sih.flags); } mod->xxs[i].len = sih.length; mod->xxi[i].nsm = sih.length > 0 ? 1 : 0; mod->xxs[i].lps = sih.loopbeg; mod->xxs[i].lpe = sih.loopend; mod->xxs[i].flg = sih.flags & 1 ? XMP_SAMPLE_LOOP : 0; if (sih.flags & 4) { 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 = sih.vol; sih.magic = 0; copy_adjust(mod->xxi[i].name, sih.name, 28); D_(D_INFO "[%2X] %-28.28s %04x%c%04x %04x %c V%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, sih.c2spd); c2spd_to_note(sih.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); fseek(f, start + 16L * sih.memseg, SEEK_SET); load_sample(f, (sfh.ffi - 1) * SAMPLE_FLAG_UNS, &mod->xxs[i], NULL); }
static int polly_load(struct module_data *m, FILE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; uint8 *buf; int i, j, k; LOAD_INIT(); read8(f); /* skip 0xae */ /* * File is RLE-encoded, escape is 0xAE (Aleksi Eeben's initials). * Actual 0xAE is encoded as 0xAE 0x01 */ if ((buf = calloc(1, 0x10000)) == NULL) return -1; decode_rle(buf, f, 0x10000); for (i = 0; buf[ORD_OFS + i] != 0 && i < 128; i++) mod->xxo[i] = buf[ORD_OFS + i] - 0xe0; mod->len = i; memcpy(mod->name, buf + ORD_OFS + 160, 16); /* memcpy(m->author, buf + ORD_OFS + 176, 16); */ set_type(m, "Polly Tracker"); MODULE_INFO(); mod->spd = 0x03; mod->bpm = 0x7d * buf[ORD_OFS + 193] / 0x88; #if 0 for (i = 0; i < 1024; i++) { if ((i % 16) == 0) printf("\n"); printf("%02x ", buf[ORD_OFS + i]); } #endif mod->pat = 0; for (i = 0; i < mod->len; i++) { if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; mod->chn = 4; mod->trk = mod->pat * mod->chn; PATTERN_INIT(); D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { PATTERN_ALLOC(i); mod->xxp[i]->rows = 64; TRACK_ALLOC(i); for (j = 0; j < 64; j++) { for (k = 0; k < 4; k++) { uint8 x = buf[i * PAT_SIZE + j * 4 + k]; event = &EVENT(i, k, j); if (x == 0xf0) { event->fxt = FX_BREAK; event->fxp = 0; continue; } event->note = LSN(x); if (event->note) event->note += 48; event->ins = MSN(x); } } } mod->ins = mod->smp = 15; INSTRUMENT_INIT(); for (i = 0; i < 15; i++) { mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1); mod->xxs[i].len = buf[ORD_OFS + 129 + i] < 0x10 ? 0 : 256 * buf[ORD_OFS + 145 + i]; mod->xxi[i].sub[0].fin = 0; mod->xxi[i].sub[0].vol = 0x40; mod->xxs[i].lps = 0; mod->xxs[i].lpe = 0; mod->xxs[i].flg = 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].nsm = !!(mod->xxs[i].len); mod->xxi[i].rls = 0xfff; D_(D_INFO "[%2X] %04x %04x %04x %c V%02x", i, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, ' ', mod->xxi[i].sub[0].vol); } /* Convert samples from 6 to 8 bits */ for (i = SMP_OFS; i < 0x10000; i++) buf[i] = buf[i] << 2; /* Read samples */ D_(D_INFO "Loading samples: %d", mod->ins); for (i = 0; i < mod->ins; i++) { if (mod->xxs[i].len == 0) continue; load_sample(NULL, SAMPLE_FLAG_NOLOAD | SAMPLE_FLAG_UNS, &mod->xxs[mod->xxi[i].sub[0].sid], (char*)buf + ORD_OFS + 256 + 256 * (buf[ORD_OFS + 129 + i] - 0x10)); } free(buf); /* make it mono */ for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = 0x80; m->quirk |= QUIRK_MODRNG; return 0; }
static int psm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int c, r, i; struct xmp_event *event; uint8 buf[1024]; uint32 p_ord, p_chn, p_pat, p_ins; uint32 p_smp[64]; int type, ver /*, mode*/; LOAD_INIT(); hio_read32b(f); hio_read(buf, 1, 60, f); strncpy(mod->name, (char *)buf, 60); type = hio_read8(f); /* song type */ ver = hio_read8(f); /* song version */ /*mode =*/ hio_read8(f); /* pattern version */ if (type & 0x01) /* song mode not supported */ return -1; libxmp_set_type(m, "Protracker Studio PSM %d.%02d", MSN(ver), LSN(ver)); mod->spd = hio_read8(f); mod->bpm = hio_read8(f); hio_read8(f); /* master volume */ hio_read16l(f); /* song length */ mod->len = hio_read16l(f); mod->pat = hio_read16l(f); mod->ins = hio_read16l(f); hio_read16l(f); /* ignore channels to play */ mod->chn = hio_read16l(f); /* use channels to proceed */ mod->smp = mod->ins; mod->trk = mod->pat * mod->chn; /* Sanity check */ if (mod->len > 256 || mod->pat > 256 || mod->ins > 255 || mod->chn > XMP_MAX_CHANNELS) { return -1; } p_ord = hio_read32l(f); p_chn = hio_read32l(f); p_pat = hio_read32l(f); p_ins = hio_read32l(f); /* should be this way but fails with Silverball song 6 */ //mod->flg |= ~type & 0x02 ? XXM_FLG_MODRNG : 0; m->c4rate = C4_NTSC_RATE; MODULE_INFO(); hio_seek(f, start + p_ord, SEEK_SET); hio_read(mod->xxo, 1, mod->len, f); hio_seek(f, start + p_chn, SEEK_SET); hio_read(buf, 1, 16, f); if (libxmp_init_instrument(m) < 0) return -1; hio_seek(f, start + p_ins, SEEK_SET); for (i = 0; i < mod->ins; i++) { uint16 flags, c2spd; int finetune; if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; hio_read(buf, 1, 13, f); /* sample filename */ hio_read(buf, 1, 24, f); /* sample description */ buf[24] = 0; /* add string termination */ strncpy((char *)mod->xxi[i].name, (char *)buf, 24); p_smp[i] = hio_read32l(f); hio_read32l(f); /* memory location */ hio_read16l(f); /* sample number */ flags = hio_read8(f); /* sample type */ mod->xxs[i].len = hio_read32l(f); mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); finetune = (int8)(hio_read8(f) << 4); mod->xxi[i].sub[0].vol = hio_read8(f); c2spd = hio_read16l(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxs[i].flg = flags & 0x80 ? XMP_SAMPLE_LOOP : 0; mod->xxs[i].flg |= flags & 0x20 ? XMP_SAMPLE_LOOP_BIDIR : 0; libxmp_c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].fin += finetune; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); } if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); hio_seek(f, start + p_pat, SEEK_SET); for (i = 0; i < mod->pat; i++) { int len; uint8 b, rows, chan; len = hio_read16l(f) - 4; rows = hio_read8(f); if (rows > 64) { return -1; } chan = hio_read8(f); if (chan > 32) { return -1; } if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0) return -1; for (r = 0; r < rows; r++) { while (len > 0) { b = hio_read8(f); len--; if (b == 0) break; c = b & 0x0f; if (c >= mod->chn) return -1; event = &EVENT(i, c, r); if (b & 0x80) { event->note = hio_read8(f) + 36 + 1; event->ins = hio_read8(f); len -= 2; } if (b & 0x40) { event->vol = hio_read8(f) + 1; len--; } if (b & 0x20) { event->fxt = hio_read8(f); event->fxp = hio_read8(f); len -= 2; } } } if (len > 0) hio_seek(f, len, SEEK_CUR); } /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { hio_seek(f, start + p_smp[i], SEEK_SET); if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) return -1; } return 0; }
static int ptm_load(struct xmp_context *ctx, FILE *f, const int start) { struct xmp_player_context *p = &ctx->p; struct xmp_mod_context *m = &p->m; int c, r, i, smp_ofs[256]; struct xxm_event *event; struct ptm_file_header pfh; struct ptm_instrument_header pih; uint8 n, b; LOAD_INIT(); /* Load and convert header */ fread(&pfh.name, 28, 1, f); /* Song name */ pfh.doseof = read8(f); /* 0x1a */ pfh.vermin = read8(f); /* Minor version */ pfh.vermaj = read8(f); /* Major type */ pfh.rsvd1 = read8(f); /* Reserved */ pfh.ordnum = read16l(f); /* Number of orders (must be even) */ pfh.insnum = read16l(f); /* Number of instruments */ pfh.patnum = read16l(f); /* Number of patterns */ pfh.chnnum = read16l(f); /* Number of channels */ pfh.flags = read16l(f); /* Flags (set to 0) */ pfh.rsvd2 = read16l(f); /* Reserved */ pfh.magic = read32b(f); /* 'PTMF' */ #if 0 if (pfh.magic != MAGIC_PTMF) return -1; #endif fread(&pfh.rsvd3, 16, 1, f); /* Reserved */ fread(&pfh.chset, 32, 1, f); /* Channel settings */ fread(&pfh.order, 256, 1, f); /* Orders */ for (i = 0; i < 128; i++) pfh.patseg[i] = read16l(f); m->xxh->len = pfh.ordnum; m->xxh->ins = pfh.insnum; m->xxh->pat = pfh.patnum; m->xxh->chn = pfh.chnnum; m->xxh->trk = m->xxh->pat * m->xxh->chn; m->xxh->smp = m->xxh->ins; m->xxh->tpo = 6; m->xxh->bpm = 125; memcpy (m->xxo, pfh.order, 256); m->c4rate = C4_NTSC_RATE; copy_adjust((uint8 *)m->name, pfh.name, 28); sprintf(m->type, "PTMF %d.%02x (Poly Tracker)", pfh.vermaj, pfh.vermin); MODULE_INFO(); INSTRUMENT_INIT(); /* Read and convert instruments and samples */ reportv(ctx, 1, " Instrument name Len LBeg LEnd L Vol C4Spd\n"); for (i = 0; i < m->xxh->ins; i++) { m->xxi[i] = calloc (sizeof (struct xxm_instrument), 1); pih.type = read8(f); /* Sample type */ fread(&pih.dosname, 12, 1, f); /* DOS file name */ pih.vol = read8(f); /* Volume */ pih.c4spd = read16l(f); /* C4 speed */ pih.smpseg = read16l(f); /* Sample segment (not used) */ pih.smpofs = read32l(f); /* Sample offset */ pih.length = read32l(f); /* Length */ pih.loopbeg = read32l(f); /* Loop begin */ pih.loopend = read32l(f); /* Loop end */ pih.gusbeg = read32l(f); /* GUS begin address */ pih.guslps = read32l(f); /* GUS loop start address */ pih.guslpe = read32l(f); /* GUS loop end address */ pih.gusflg = read8(f); /* GUS loop flags */ pih.rsvd1 = read8(f); /* Reserved */ fread(&pih.name, 28, 1, f); /* Instrument name */ pih.magic = read32b(f); /* 'PTMS' */ if ((pih.type & 3) != 1) continue; smp_ofs[i] = pih.smpofs; m->xxih[i].nsm = !!(m->xxs[i].len = pih.length); m->xxs[i].lps = pih.loopbeg; m->xxs[i].lpe = pih.loopend; if (m->xxs[i].lpe) m->xxs[i].lpe--; m->xxs[i].flg = pih.type & 0x04 ? WAVE_LOOPING : 0; m->xxs[i].flg |= pih.type & 0x08 ? WAVE_LOOPING | WAVE_BIDIR_LOOP : 0; m->xxs[i].flg |= pih.type & 0x10 ? WAVE_16_BITS : 0; m->xxi[i][0].vol = pih.vol; m->xxi[i][0].pan = 0x80; m->xxi[i][0].sid = i; pih.magic = 0; copy_adjust(m->xxih[i].name, pih.name, 28); if ((V(1)) && (strlen((char *)m->xxih[i].name) || m->xxs[i].len)) report ("[%2X] %-28.28s %05x%c%05x %05x %c V%02x %5d\n", i, m->xxih[i].name, m->xxs[i].len, pih.type & 0x10 ? '+' : ' ', m->xxs[i].lps, m->xxs[i].lpe, m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ', m->xxi[i][0].vol, pih.c4spd); /* Convert C4SPD to relnote/finetune */ c2spd_to_note (pih.c4spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin); } PATTERN_INIT(); /* Read patterns */ reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat); for (i = 0; i < m->xxh->pat; i++) { if (!pfh.patseg[i]) continue; PATTERN_ALLOC (i); m->xxp[i]->rows = 64; TRACK_ALLOC (i); fseek(f, start + 16L * pfh.patseg[i], SEEK_SET); r = 0; while (r < 64) { fread (&b, 1, 1, f); if (!b) { r++; continue; } c = b & PTM_CH_MASK; if (c >= m->xxh->chn) continue; event = &EVENT (i, c, r); if (b & PTM_NI_FOLLOW) { fread (&n, 1, 1, f); switch (n) { case 255: n = 0; break; /* Empty note */ case 254: n = XMP_KEY_OFF; break; /* Key off */ } event->note = n; fread (&n, 1, 1, f); event->ins = n; } if (b & PTM_FX_FOLLOWS) { event->fxt = read8(f); event->fxp = read8(f); if (event->fxt > 0x17) event->fxt = event->fxp = 0; switch (event->fxt) { case 0x0e: /* Extended effect */ if (MSN(event->fxp) == 0x8) { /* Pan set */ event->fxt = FX_SETPAN; event->fxp = LSN (event->fxp) << 4; } break; case 0x10: /* Set global volume */ event->fxt = FX_GLOBALVOL; break; case 0x11: /* Multi retrig */ event->fxt = FX_MULTI_RETRIG; break; case 0x12: /* Fine vibrato */ event->fxt = FX_FINE4_VIBRA; break; case 0x13: /* Note slide down */ event->fxt = FX_NSLIDE_DN; break; case 0x14: /* Note slide up */ event->fxt = FX_NSLIDE_UP; break; case 0x15: /* Note slide down + retrig */ event->fxt = FX_NSLIDE_R_DN; break; case 0x16: /* Note slide up + retrig */ event->fxt = FX_NSLIDE_R_UP; break; case 0x17: /* Reverse sample */ event->fxt = event->fxp = 0; break; } } if (b & PTM_VOL_FOLLOWS) { event->vol = read8(f) + 1; } } reportv(ctx, 0, "."); } reportv(ctx, 0, "\nStored samples : %d ", m->xxh->smp); for (i = 0; i < m->xxh->smp; i++) { if (!m->xxs[i].len) continue; fseek(f, start + smp_ofs[m->xxi[i][0].sid], SEEK_SET); xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate, XMP_SMP_8BDIFF, &m->xxs[m->xxi[i][0].sid], NULL); reportv(ctx, 0, "."); } reportv(ctx, 0, "\n"); m->vol_xlat = ptm_vol; for (i = 0; i < m->xxh->chn; i++) m->xxc[i].pan = pfh.chset[i] << 4; return 0; }
void process_fx(struct context_data *ctx, struct channel_data *xc, int chn, struct xmp_event *e, int fnum) { struct player_data *p = &ctx->p; struct module_data *m = &ctx->m; struct xmp_module *mod = &m->mod; struct flow_control *f = &p->flow; uint8 note, fxp, fxt; int h, l; /* key_porta is IT only */ if (m->read_event_type != READ_EVENT_IT) { xc->key_porta = xc->key; } note = e->note; if (fnum == 0) { fxt = e->fxt; fxp = e->fxp; } else { fxt = e->f2t; fxp = e->f2p; } switch (fxt) { case FX_ARPEGGIO: fx_arpeggio: if (fxp != 0) { xc->arpeggio.val[0] = 0; xc->arpeggio.val[1] = MSN(fxp); xc->arpeggio.val[2] = LSN(fxp); xc->arpeggio.size = 3; } break; case FX_S3M_ARPEGGIO: EFFECT_MEMORY(fxp, xc->arpeggio.memory); goto fx_arpeggio; #ifndef LIBXMP_CORE_PLAYER case FX_OKT_ARP3: if (fxp != 0) { xc->arpeggio.val[0] = -MSN(fxp); xc->arpeggio.val[1] = 0; xc->arpeggio.val[2] = LSN(fxp); xc->arpeggio.size = 3; } break; case FX_OKT_ARP4: if (fxp != 0) { xc->arpeggio.val[0] = 0; xc->arpeggio.val[1] = LSN(fxp); xc->arpeggio.val[2] = 0; xc->arpeggio.val[3] = -MSN(fxp); xc->arpeggio.size = 4; } break; case FX_OKT_ARP5: if (fxp != 0) { xc->arpeggio.val[0] = LSN(fxp); xc->arpeggio.val[1] = LSN(fxp); xc->arpeggio.val[2] = 0; xc->arpeggio.size = 3; } break; #endif case FX_PORTA_UP: /* Portamento up */ EFFECT_MEMORY(fxp, xc->freq.memory); if (HAS_QUIRK(QUIRK_FINEFX) && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { switch (MSN(fxp)) { case 0xf: fxp &= 0x0f; goto fx_f_porta_up; case 0xe: fxp &= 0x0f; fxp |= 0x10; goto fx_xf_porta; } } SET(PITCHBEND); if (fxp != 0) { xc->freq.slide = -fxp; if (HAS_QUIRK(QUIRK_UNISLD)) xc->porta.memory = fxp; } else if (xc->freq.slide > 0) { xc->freq.slide *= -1; } break; case FX_PORTA_DN: /* Portamento down */ EFFECT_MEMORY(fxp, xc->freq.memory); if (HAS_QUIRK(QUIRK_FINEFX) && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) { switch (MSN(fxp)) { case 0xf: fxp &= 0x0f; goto fx_f_porta_dn; case 0xe: fxp &= 0x0f; fxp |= 0x20; goto fx_xf_porta; } } SET(PITCHBEND); if (fxp != 0) { xc->freq.slide = fxp; if (HAS_QUIRK(QUIRK_UNISLD)) xc->porta.memory = fxp; } else if (xc->freq.slide < 0) { xc->freq.slide *= -1; } break; case FX_TONEPORTA: /* Tone portamento */ if (HAS_QUIRK(QUIRK_IGSTPOR)) { if (note == 0 && xc->porta.dir == 0) break; } if (!IS_VALID_INSTRUMENT(xc->ins)) break; do_toneporta(m, xc, note); EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory); if (fxp != 0) { if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */ xc->freq.memory = fxp; xc->porta.slide = fxp; } SET(TONEPORTA); break; case FX_VIBRATO: /* Vibrato */ EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); SET(VIBRATO); SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp)); break; case FX_FINE_VIBRATO: /* Fine vibrato */ EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory); SET(VIBRATO); SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp)); break; case FX_TONE_VSLIDE: /* Toneporta + vol slide */ if (!IS_VALID_INSTRUMENT(xc->ins)) break; do_toneporta(m, xc, note); SET(TONEPORTA); goto fx_volslide; case FX_VIBRA_VSLIDE: /* Vibrato + vol slide */ SET(VIBRATO); goto fx_volslide; case FX_TREMOLO: /* Tremolo */ EFFECT_MEMORY_SETONLY(fxp, xc->tremolo.memory); SET(TREMOLO); SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp)); break; case FX_SETPAN: /* Set pan */ /* From OpenMPT PanOff.xm: * "Another chapter of weird FT2 bugs: Note-Off + Note Delay * + Volume Column Panning = Panning effect is ignored." */ if (!HAS_QUIRK(QUIRK_FT2BUGS) /* If not FT2 */ || fnum == 0 /* or not vol column */ || e->note != XMP_KEY_OFF /* or not keyoff */ || e->fxt != FX_EXTENDED /* or not delay */ || MSN(e->fxp) != EX_DELAY) { xc->pan.val = fxp; xc->pan.surround = 0; } break; case FX_OFFSET: /* Set sample offset */ EFFECT_MEMORY(fxp, xc->offset.memory); SET(OFFSET); if (note) { xc->offset.val &= xc->offset.val & ~0xffff; xc->offset.val |= fxp << 8; xc->offset.val2 = fxp << 8; } if (e->ins) { xc->offset.val2 = fxp << 8; } break; case FX_VOLSLIDE: /* Volume slide */ fx_volslide: /* S3M file volume slide note: * DFy Fine volume down by y (...) If y is 0, the command will * be treated as a volume slide up with a value of f (15). * If a DFF command is specified, the volume will be slid * up. */ if (HAS_QUIRK(QUIRK_FINEFX)) { h = MSN(fxp); l = LSN(fxp); if (l == 0xf && h != 0) { xc->vol.memory = fxp; fxp >>= 4; goto fx_f_vslide_up; } else if (h == 0xf && l != 0) { xc->vol.memory = fxp; fxp &= 0x0f; goto fx_f_vslide_dn; } }