static int rtm_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, r; struct xmp_event *event; struct ObjectHeader oh; struct RTMMHeader rh; struct RTNDHeader rp; struct RTINHeader ri; struct RTSMHeader rs; int offset, smpnum, version; char tracker_name[21], composer[33]; LOAD_INIT(); if (read_object_header(f, &oh, "RTMM") < 0) return -1; version = oh.version; hio_read(tracker_name, 1, 20, f); tracker_name[20] = 0; hio_read(composer, 1, 32, f); composer[32] = 0; rh.flags = hio_read16l(f); /* bit 0: linear table, bit 1: track names */ rh.ntrack = hio_read8(f); rh.ninstr = hio_read8(f); rh.nposition = hio_read16l(f); rh.npattern = hio_read16l(f); rh.speed = hio_read8(f); rh.tempo = hio_read8(f); hio_read(&rh.panning, 32, 1, f); rh.extraDataSize = hio_read32l(f); /* Sanity check */ if (rh.nposition > 255 || rh.ntrack > 32 || rh.npattern > 255) { return -1; } if (version >= 0x0112) hio_seek(f, 32, SEEK_CUR); /* skip original name */ for (i = 0; i < rh.nposition; i++) { mod->xxo[i] = hio_read16l(f); if (mod->xxo[i] >= rh.npattern) { return -1; } } strncpy(mod->name, oh.name, 20); snprintf(mod->type, XMP_NAME_SIZE, "%s RTM %x.%02x", tracker_name, version >> 8, version & 0xff); /* strncpy(m->author, composer, XMP_NAME_SIZE); */ mod->len = rh.nposition; mod->pat = rh.npattern; mod->chn = rh.ntrack; mod->trk = mod->chn * mod->pat; mod->ins = rh.ninstr; mod->spd = rh.speed; mod->bpm = rh.tempo; m->c4rate = C4_NTSC_RATE; m->period_type = rh.flags & 0x01 ? PERIOD_LINEAR : PERIOD_AMIGA; MODULE_INFO(); for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = rh.panning[i] & 0xff; if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); offset = 42 + oh.headerSize + rh.extraDataSize; for (i = 0; i < mod->pat; i++) { uint8 c; hio_seek(f, start + offset, SEEK_SET); if (read_object_header(f, &oh, "RTND") < 0) { D_(D_CRIT "Error reading pattern %d", i); return -1; } rp.flags = hio_read16l(f); rp.ntrack = hio_read8(f); rp.nrows = hio_read16l(f); rp.datasize = hio_read32l(f); /* Sanity check */ if (rp.ntrack > rh.ntrack || rp.nrows > 256) { return -1; } offset += 42 + oh.headerSize + rp.datasize; if (libxmp_alloc_pattern_tracks(mod, i, rp.nrows) < 0) return -1; for (r = 0; r < rp.nrows; r++) { for (j = 0; /*j < rp.ntrack */; j++) { c = hio_read8(f); if (c == 0) /* next row */ break; /* Sanity check */ if (j >= rp.ntrack) { return -1; } event = &EVENT(i, j, r); if (c & 0x01) { /* set track */ j = hio_read8(f); /* Sanity check */ if (j >= rp.ntrack) { return -1; } event = &EVENT(i, j, r); } if (c & 0x02) { /* read note */ event->note = hio_read8(f) + 1; if (event->note == 0xff) { event->note = XMP_KEY_OFF; } else { event->note += 12; } } if (c & 0x04) /* read instrument */ event->ins = hio_read8(f); if (c & 0x08) /* read effect */ event->fxt = hio_read8(f); if (c & 0x10) /* read parameter */ event->fxp = hio_read8(f); if (c & 0x20) /* read effect 2 */ event->f2t = hio_read8(f); if (c & 0x40) /* read parameter 2 */ event->f2p = hio_read8(f); } } } /* * load instruments */ D_(D_INFO "Instruments: %d", mod->ins); hio_seek(f, start + offset, SEEK_SET); /* ESTIMATED value! We don't know the actual value at this point */ mod->smp = MAX_SAMP; if (libxmp_init_instrument(m) < 0) return -1; smpnum = 0; for (i = 0; i < mod->ins; i++) { struct xmp_instrument *xxi = &mod->xxi[i]; if (read_object_header(f, &oh, "RTIN") < 0) { D_(D_CRIT "Error reading instrument %d", i); return -1; } libxmp_instrument_name(mod, i, (uint8 *)&oh.name, 32); if (oh.headerSize == 0) { D_(D_INFO "[%2X] %-26.26s %2d ", i, xxi->name, xxi->nsm); ri.nsample = 0; continue; } ri.nsample = hio_read8(f); ri.flags = hio_read16l(f); /* bit 0 : default panning enabled */ if (hio_read(&ri.table, 1, 120, f) != 120) return -1; ri.volumeEnv.npoint = hio_read8(f); /* Sanity check */ if (ri.volumeEnv.npoint >= 12) return -1; for (j = 0; j < 12; j++) { ri.volumeEnv.point[j].x = hio_read32l(f); ri.volumeEnv.point[j].y = hio_read32l(f); } ri.volumeEnv.sustain = hio_read8(f); ri.volumeEnv.loopstart = hio_read8(f); ri.volumeEnv.loopend = hio_read8(f); ri.volumeEnv.flags = hio_read16l(f); /* bit 0:enable 1:sus 2:loop */ ri.panningEnv.npoint = hio_read8(f); /* Sanity check */ if (ri.panningEnv.npoint >= 12) return -1; for (j = 0; j < 12; j++) { ri.panningEnv.point[j].x = hio_read32l(f); ri.panningEnv.point[j].y = hio_read32l(f); } ri.panningEnv.sustain = hio_read8(f); ri.panningEnv.loopstart = hio_read8(f); ri.panningEnv.loopend = hio_read8(f); ri.panningEnv.flags = hio_read16l(f); ri.vibflg = hio_read8(f); ri.vibsweep = hio_read8(f); ri.vibdepth = hio_read8(f); ri.vibrate = hio_read8(f); ri.volfade = hio_read16l(f); if (version >= 0x0110) { ri.midiPort = hio_read8(f); ri.midiChannel = hio_read8(f); ri.midiProgram = hio_read8(f); ri.midiEnable = hio_read8(f); } if (version >= 0x0112) { ri.midiTranspose = hio_read8(f); ri.midiBenderRange = hio_read8(f); ri.midiBaseVolume = hio_read8(f); ri.midiUseVelocity = hio_read8(f); } xxi->nsm = ri.nsample; D_(D_INFO "[%2X] %-26.26s %2d", i, xxi->name, xxi->nsm); if (xxi->nsm > 16) xxi->nsm = 16; if (libxmp_alloc_subinstrument(mod, i, xxi->nsm) < 0) return -1; for (j = 0; j < 120; j++) xxi->map[j].ins = ri.table[j]; /* Envelope */ xxi->rls = ri.volfade; xxi->aei.npt = ri.volumeEnv.npoint; xxi->aei.sus = ri.volumeEnv.sustain; xxi->aei.lps = ri.volumeEnv.loopstart; xxi->aei.lpe = ri.volumeEnv.loopend; xxi->aei.flg = ri.volumeEnv.flags; xxi->pei.npt = ri.panningEnv.npoint; xxi->pei.sus = ri.panningEnv.sustain; xxi->pei.lps = ri.panningEnv.loopstart; xxi->pei.lpe = ri.panningEnv.loopend; xxi->pei.flg = ri.panningEnv.flags; for (j = 0; j < xxi->aei.npt; j++) { xxi->aei.data[j * 2 + 0] = ri.volumeEnv.point[j].x; xxi->aei.data[j * 2 + 1] = ri.volumeEnv.point[j].y / 2; } for (j = 0; j < xxi->pei.npt; j++) { xxi->pei.data[j * 2 + 0] = ri.panningEnv.point[j].x; xxi->pei.data[j * 2 + 1] = 32 + ri.panningEnv.point[j].y / 2; } /* For each sample */ for (j = 0; j < xxi->nsm; j++, smpnum++) { struct xmp_subinstrument *sub = &xxi->sub[j]; struct xmp_sample *xxs; if (read_object_header(f, &oh, "RTSM") < 0) { D_(D_CRIT "Error reading sample %d", j); return -1; } rs.flags = hio_read16l(f); rs.basevolume = hio_read8(f); rs.defaultvolume = hio_read8(f); rs.length = hio_read32l(f); rs.loop = hio_read32l(f); rs.loopbegin = hio_read32l(f); rs.loopend = hio_read32l(f); rs.basefreq = hio_read32l(f); rs.basenote = hio_read8(f); rs.panning = hio_read8(f); libxmp_c2spd_to_note(rs.basefreq, &sub->xpo, &sub->fin); sub->xpo += 48 - rs.basenote; sub->vol = rs.defaultvolume * rs.basevolume / 0x40; sub->pan = 0x80 + rs.panning * 2; sub->vwf = ri.vibflg; sub->vde = ri.vibdepth << 2; sub->vra = ri.vibrate; sub->vsw = ri.vibsweep; sub->sid = smpnum; if (smpnum >= mod->smp) { mod->xxs = libxmp_realloc_samples(mod->xxs, &mod->smp, mod->smp * 3 / 2); if (mod->xxs == NULL) return -1; } xxs = &mod->xxs[smpnum]; libxmp_copy_adjust(xxs->name, (uint8 *)oh.name, 31); xxs->len = rs.length; xxs->lps = rs.loopbegin; xxs->lpe = rs.loopend; xxs->flg = 0; if (rs.flags & 0x02) { xxs->flg |= XMP_SAMPLE_16BIT; xxs->len >>= 1; xxs->lps >>= 1; xxs->lpe >>= 1; } xxs->flg |= rs.loop & 0x03 ? XMP_SAMPLE_LOOP : 0; xxs->flg |= rs.loop == 2 ? XMP_SAMPLE_LOOP_BIDIR : 0; D_(D_INFO " [%1x] %05x%c%05x %05x %c " "V%02x F%+04d P%02x R%+03d", j, xxs->len, xxs->flg & XMP_SAMPLE_16BIT ? '+' : ' ', xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, sub->fin, sub->pan, sub->xpo); if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF, xxs, NULL) < 0) return -1; } }
static int coco_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j; int seq_ptr, pat_ptr, smp_ptr[100]; LOAD_INIT(); mod->chn = hio_read8(f) & 0x3f; libxmp_read_title(f, mod->name, 20); for (i = 0; i < 20; i++) { if (mod->name[i] == 0x0d) mod->name[i] = 0; } libxmp_set_type(m, "Coconizer"); mod->ins = mod->smp = hio_read8(f); mod->len = hio_read8(f); mod->pat = hio_read8(f); mod->trk = mod->pat * mod->chn; seq_ptr = hio_read32l(f); pat_ptr = hio_read32l(f); MODULE_INFO(); if (libxmp_init_instrument(m) < 0) return -1; m->vol_table = (int *)arch_vol_table; m->volbase = 0xff; for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; smp_ptr[i] = hio_read32l(f); mod->xxs[i].len = hio_read32l(f); mod->xxi[i].sub[0].vol = 0xff - hio_read32l(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = mod->xxs[i].lps + hio_read32l(f); if (mod->xxs[i].lpe) mod->xxs[i].lpe -= 1; mod->xxs[i].flg = mod->xxs[i].lps > 0 ? XMP_SAMPLE_LOOP : 0; hio_read(mod->xxi[i].name, 1, 11, f); for (j = 0; j < 11; j++) { if (mod->xxi[i].name[j] == 0x0d) mod->xxi[i].name[j] = 0; } hio_read8(f); /* unused */ mod->xxi[i].sub[0].sid = i; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %-10.10s %05x %05x %05x %c V%02x", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); } /* Sequence */ hio_seek(f, start + seq_ptr, SEEK_SET); for (i = 0; ; i++) { uint8 x = hio_read8(f); if (x == 0xff) break; mod->xxo[i] = x; } for (i++; i % 4; i++) /* for alignment */ hio_read8(f); /* Patterns */ if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < (64 * mod->chn); j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); event->fxp = hio_read8(f); event->fxt = hio_read8(f); event->ins = hio_read8(f); event->note = hio_read8(f); if (event->note) event->note += 12; fix_effect(event); } } /* Read samples */ D_(D_INFO "Stored samples : %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (mod->xxi[i].nsm == 0) continue; hio_seek(f, start + smp_ptr[i], SEEK_SET); if (libxmp_load_sample(m, f, SAMPLE_FLAG_VIDC, &mod->xxs[i], NULL) < 0) return -1; } for (i = 0; i < mod->chn; i++) { mod->xxc[i].pan = DEFPAN((((i + 3) / 2) % 2) * 0xff); } return 0; }
static int get_patt(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; struct xmp_event *event, dummy; int i, len, chan; int rows, r; uint8 flag; i = hio_read8(f); /* pattern number */ len = hio_read32l(f); rows = hio_read8(f) + 1; if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0) return -1; for (r = 0; r < rows; ) { if ((flag = hio_read8(f)) == 0) { r++; continue; } chan = flag & 0x1f; event = chan < mod->chn ? &EVENT(i, chan, r) : &dummy; if (flag & 0x80) { uint8 fxp = hio_read8(f); uint8 fxt = hio_read8(f); switch (fxt) { case 0x14: /* speed */ fxt = FX_S3M_SPEED; break; default: if (fxt > 0x0f) { printf("unknown effect %02x %02x\n", fxt, fxp); fxt = fxp = 0; } } event->fxt = fxt; event->fxp = fxp; } if (flag & 0x40) { event->ins = hio_read8(f); event->note = hio_read8(f); if (event->note == 128) { event->note = XMP_KEY_OFF; } } if (flag & 0x20) { event->vol = 1 + hio_read8(f) / 2; } } return 0; }
static int gal5_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; iff_handle handle; int i, ret, offset; struct local_data data; LOAD_INIT(); hio_read32b(f); /* Skip RIFF */ hio_read32b(f); /* Skip size */ hio_read32b(f); /* Skip AM */ offset = hio_tell(f); mod->smp = mod->ins = 0; handle = libxmp_iff_new(); if (handle == NULL) return -1; m->c4rate = C4_NTSC_RATE; /* IFF chunk IDs */ ret = libxmp_iff_register(handle, "INIT", get_init); /* Galaxy 5.0 */ ret |= libxmp_iff_register(handle, "ORDR", get_ordr); ret |= libxmp_iff_register(handle, "PATT", get_patt_cnt); ret |= libxmp_iff_register(handle, "INST", get_inst_cnt); if (ret != 0) return -1; libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN); libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED); libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2); /* Load IFF chunks */ if (libxmp_iff_load(handle, m, f, &data) < 0) { libxmp_iff_release(handle); return -1; } libxmp_iff_release(handle); mod->trk = mod->pat * mod->chn; mod->smp = mod->ins; MODULE_INFO(); if (libxmp_init_instrument(m) < 0) return -1; if (libxmp_init_pattern(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d", mod->pat); D_(D_INFO "Stored samples: %d ", mod->smp); hio_seek(f, start + offset, SEEK_SET); handle = libxmp_iff_new(); if (handle == NULL) return -1; /* IFF chunk IDs */ ret = libxmp_iff_register(handle, "PATT", get_patt); ret |= libxmp_iff_register(handle, "INST", get_inst); if (ret != 0) return -1; libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN); libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED); libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2); /* Load IFF chunks */ if (libxmp_iff_load(handle, m, f, &data) < 0) { libxmp_iff_release(handle); return -1; } libxmp_iff_release(handle); /* Alloc missing patterns */ for (i = 0; i < mod->pat; i++) { if (mod->xxp[i] == NULL) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) { return -1; } } } for (i = 0; i < mod->chn; i++) { mod->xxc[i].pan = data.chn_pan[i] * 2; } m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; 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; libxmp_set_type(m, "HSC-Tracker"); MODULE_INFO(); /* Read instruments */ if (libxmp_init_instrument(m) < 0) return -1; hio_read(buf, 1, 128 * 12, f); sid = buf; for (i = 0; i < mod->ins; i++, sid += 12) { if (libxmp_alloc_subinstrument(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 (libxmp_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++) { mod->xxo[i] = hio_read8(f); if (mod->xxo[i] > 127) 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 (libxmp_init_pattern(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 (libxmp_alloc_pattern_tracks(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 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 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(); libxmp_set_type(m, "Magnetic Fields Packer"); MODULE_INFO(); mod->chn = 4; mod->ins = mod->smp = 31; if (libxmp_init_instrument(m) < 0) return -1; for (i = 0; i < 31; i++) { int loop_size; if (libxmp_alloc_subinstrument(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 (hio_error(f)) { return -1; } mod->trk = mod->pat * mod->chn; /* Read and convert patterns */ if (libxmp_init_pattern(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 (libxmp_alloc_pattern_tracks(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); libxmp_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, PATH_MAX, "%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(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 (libxmp_load_sample(m, s, SAMPLE_FLAG_FULLREP, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) { free(s); return -1; } } hio_close(s); m->period_type = PERIOD_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 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)) libxmp_set_type(m, "IIgs SoundSmith"); else if (!memcmp(buffer, "IAN92a", 8)) libxmp_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 (libxmp_init_instrument(m) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; hio_read(buffer, 1, 22, f); if (buffer[0]) { buffer[buffer[0] + 1] = 0; libxmp_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 (libxmp_init_pattern(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 (libxmp_alloc_pattern_tracks(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 pw_load(struct module_data *m, HIO_HANDLE *h, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; struct mod_header mh; uint8 mod_event[4]; HIO_HANDLE *f; FILE *temp; char *name; char *temp_name; int i, j; /* Prowizard depacking */ if ((temp = make_temp_file(&temp_name)) == NULL) { goto err; } if (pw_wizardry(h, temp, &name) < 0) { fclose(temp); goto err2; } /* Module loading */ if ((f = hio_open_file(temp)) == NULL) { goto err2; } if (hio_seek(f, 0, start) < 0) { goto err3; } 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); if (memcmp(mh.magic, "M.K.", 4)) { goto err3; } 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; snprintf(mod->name, XMP_NAME_SIZE, "%s", (char *)mh.name); snprintf(mod->type, XMP_NAME_SIZE, "%s", name); MODULE_INFO(); if (libxmp_init_instrument(m) < 0) { goto err3; } for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) goto err3; 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; 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; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; libxmp_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 (libxmp_init_pattern(mod) < 0) { goto err3; } /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) goto err3; for (j = 0; j < (64 * 4); j++) { event = &EVENT(i, j % 4, j / 4); hio_read(mod_event, 1, 4, f); libxmp_decode_protracker_event(event, mod_event); } } m->period_type = PERIOD_MODRNG; /* Load samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { if (libxmp_load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) goto err3; } hio_close(f); unlink_temp_file(temp_name); return 0; err3: hio_close(f); err2: unlink_temp_file(temp_name); err: return -1; }
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 (libxmp_init_instrument(m) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(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; libxmp_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 (libxmp_init_pattern(mod) < 0) return -1; /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < (64 * 4); j++) { event = &EVENT(i, j % 4, j / 4); hio_read(mod_event, 1, 4, f); libxmp_decode_protracker_event(event, mod_event); } } m->period_type = PERIOD_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 (libxmp_load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } 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 */ libxmp_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; m->c4rate = C4_NTSC_RATE; MODULE_INFO(); if (libxmp_init_instrument(m) < 0) return -1; /* Read instrument names */ for (i = 0; i < mod->ins; i++) { int hasname, c2spd; if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; nsize = hio_read8(f); if (hio_error(f)) { return -1; } 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); libxmp_c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); } if (libxmp_init_pattern(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d ", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < 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 (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; } m->quirk |= QUIRKS_ST3; m->read_event_type = READ_EVENT_ST3; return 0; }
static int 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; libxmp_set_type(m, "Aley's Module"); MODULE_INFO(); if (libxmp_init_pattern(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < 64 * mod->chn; j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); b = hio_read8(f); if (b) event->note = (b == 37) ? 0x61 : b + 48; event->ins = hio_read8(f); } } if (libxmp_init_instrument(m) < 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 (libxmp_alloc_subinstrument(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_file(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 (libxmp_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 tcb_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[10]; int base_offs, soffs[16]; uint8 unk1[16], unk2[16], unk3[16]; LOAD_INIT(); hio_read(buffer, 8, 1, f); libxmp_set_type(m, "TCB Tracker", buffer); hio_read16b(f); /* ? */ mod->pat = hio_read16b(f); mod->ins = 16; mod->smp = mod->ins; mod->chn = 4; mod->trk = mod->pat * mod->chn; m->quirk |= QUIRK_MODRNG; hio_read16b(f); /* ? */ for (i = 0; i < 128; i++) mod->xxo[i] = hio_read8(f); mod->len = hio_read8(f); hio_read8(f); /* ? */ hio_read16b(f); /* ? */ MODULE_INFO(); if (libxmp_init_instrument(m) < 0) return -1; /* Read instrument names */ for (i = 0; i < mod->ins; i++) { if (libxmp_alloc_subinstrument(mod, i, 1) < 0) return -1; hio_read(buffer, 8, 1, f); libxmp_instrument_name(mod, i, buffer, 8); } hio_read16b(f); /* ? */ for (i = 0; i < 5; i++) hio_read16b(f); for (i = 0; i < 5; i++) hio_read16b(f); for (i = 0; i < 5; i++) hio_read16b(f); if (libxmp_init_pattern(mod) < 0) return -1; /* Read and convert patterns */ D_(D_INFO "Stored patterns: %d ", mod->pat); for (i = 0; i < mod->pat; i++) { if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) return -1; for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < mod->chn; k++) { int b; event = &EVENT (i, k, j); b = hio_read8(f); if (b) { event->note = 12 * (b >> 4); event->note += (b & 0xf) + 36; } b = hio_read8(f); event->ins = b >> 4; if (event->ins) event->ins += 1; if (b &= 0x0f) { switch (b) { case 0xd: event->fxt = FX_BREAK; event->fxp = 0; break; default: printf("---> %02x\n", b); } } } } } base_offs = hio_tell(f); hio_read32b(f); /* remaining size */ /* Read instrument data */ for (i = 0; i < mod->ins; i++) { mod->xxi[i].sub[0].vol = hio_read8(f) / 2; mod->xxi[i].sub[0].pan = 0x80; unk1[i] = hio_read8(f); unk2[i] = hio_read8(f); unk3[i] = hio_read8(f); } for (i = 0; i < mod->ins; i++) { soffs[i] = hio_read32b(f); mod->xxs[i].len = hio_read32b(f); } hio_read32b(f); hio_read32b(f); hio_read32b(f); hio_read32b(f); for (i = 0; i < mod->ins; i++) { mod->xxi[i].nsm = !!(mod->xxs[i].len); 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] %-8.8s %04x %04x %04x %c " "V%02x %02x %02x %02x\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, unk1[i], unk2[i], unk3[i]); } /* Read samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { hio_seek(f, start + base_offs + soffs[i], SEEK_SET); if (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; } return 0; }