int mmd_load_hybrid_instrument(HIO_HANDLE *f, struct module_data *m, int i, int smp_idx, struct SynthInstr *synth, struct InstrExt *exp_smp, struct MMD0sample *sample) { struct xmp_module *mod = &m->mod; struct xmp_instrument *xxi = &mod->xxi[i]; struct xmp_subinstrument *sub; struct xmp_sample *xxs; int length, type; int pos = hio_tell(f); synth->defaultdecay = hio_read8(f); hio_seek(f, 3, SEEK_CUR); synth->rep = hio_read16b(f); synth->replen = hio_read16b(f); synth->voltbllen = hio_read16b(f); synth->wftbllen = hio_read16b(f); synth->volspeed = hio_read8(f); synth->wfspeed = hio_read8(f); synth->wforms = hio_read16b(f); hio_read(synth->voltbl, 1, 128, f);; hio_read(synth->wftbl, 1, 128, f);; hio_seek(f, pos - 6 + hio_read32b(f), SEEK_SET); length = hio_read32b(f); type = hio_read16b(f); if (med_new_instrument_extras(xxi) != 0) return -1; xxi->nsm = 1; if (subinstrument_alloc(mod, i, 1) < 0) return -1; MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed; MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed; sub = &xxi->sub[0]; sub->pan = 0x80; sub->vol = sample->svol; sub->xpo = sample->strans; sub->sid = smp_idx; sub->fin = exp_smp->finetune; xxs = &mod->xxs[smp_idx]; xxs->len = length; xxs->lps = 2 * sample->rep; xxs->lpe = xxs->lps + 2 * sample->replen; xxs->flg = sample->replen > 1 ? XMP_SAMPLE_LOOP : 0; if (load_sample(m, f, 0, xxs, NULL) < 0) return -1; return 0; }
int load_sample(struct module_data *m, HIO_HANDLE *f, int flags, struct xmp_sample *xxs, void *buffer) { int bytelen, extralen, unroll_extralen, i; /* Adlib FM patches */ if (flags & SAMPLE_FLAG_ADLIB) { const int size = 11; if (flags & SAMPLE_FLAG_HSC) { convert_hsc_to_sbi(buffer); } xxs->data = malloc(size + 4); if (xxs->data == NULL) return -1; *(uint32 *)xxs->data = 0; xxs->data += 4; memcpy(xxs->data, buffer, size); xxs->flg |= XMP_SAMPLE_SYNTH; xxs->len = size; return 0; } /* Empty samples */ if (xxs->len == 0) { return 0; } /* Skip sample loading * FIXME: fails for ADPCM samples */ if (m && m->smpctl & XMP_SMPCTL_SKIP) { if (~flags & SAMPLE_FLAG_NOLOAD) hio_seek(f, xxs->len, SEEK_CUR); return 0; } /* Loop parameters sanity check */ if (xxs->lpe > xxs->len) { xxs->lpe = xxs->len; } if (xxs->lps >= xxs->len || xxs->lps >= xxs->lpe) { xxs->lps = xxs->lpe = 0; xxs->flg &= ~(XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR); } /* Patches with samples * Allocate extra sample for interpolation. */ bytelen = xxs->len; extralen = 4; unroll_extralen = 0; /* Disable birectional loop flag if sample is not looped */ if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { if (~xxs->flg & XMP_SAMPLE_LOOP) xxs->flg &= ~XMP_SAMPLE_LOOP_BIDIR; } /* Unroll bidirectional loops */ if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) { unroll_extralen = (xxs->lpe - xxs->lps) - (xxs->len - xxs->lpe); if (unroll_extralen < 0) { unroll_extralen = 0; } } if (xxs->flg & XMP_SAMPLE_16BIT) { bytelen *= 2; extralen *= 2; unroll_extralen *= 2; } /* add guard bytes before the buffer for higher order interpolation */ xxs->data = malloc(bytelen + extralen + unroll_extralen + 4); if (xxs->data == NULL) return -1; *(uint32 *)xxs->data = 0; xxs->data += 4; if (flags & SAMPLE_FLAG_NOLOAD) { memcpy(xxs->data, buffer, bytelen); } else { uint8 buf[5]; long pos = hio_tell(f); int num = hio_read(buf, 1, 5, f); hio_seek(f, pos, SEEK_SET); if (num == 5 && !memcmp(buf, "ADPCM", 5)) { int x2 = bytelen >> 1; char table[16]; hio_seek(f, 5, SEEK_CUR); /* Skip "ADPCM" */ hio_read(table, 1, 16, f); hio_read(xxs->data + x2, 1, x2, f); adpcm4_decoder((uint8 *)xxs->data + x2, (uint8 *)xxs->data, table, bytelen); } else {
static int mfp_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, k, x, y; struct xmp_event *event; struct stat st; char smp_filename[PATH_MAX]; HIO_HANDLE *s; int size1, size2; int pat_addr, pat_table[128][4]; uint8 buf[1024], mod_event[4]; int row; LOAD_INIT(); set_type(m, "Magnetic Fields Packer"); MODULE_INFO(); mod->chn = 4; mod->ins = mod->smp = 31; if (instrument_init(mod) < 0) return -1; for (i = 0; i < 31; i++) { int loop_size; if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * hio_read16b(f); mod->xxi[i].sub[0].fin = (int8)(hio_read8(f) << 4); mod->xxi[i].sub[0].vol = hio_read8(f); mod->xxs[i].lps = 2 * hio_read16b(f); loop_size = hio_read16b(f); mod->xxs[i].lpe = mod->xxs[i].lps + 2 * loop_size; mod->xxs[i].flg = loop_size > 1 ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; mod->xxi[i].rls = 0xfff; if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; D_(D_INFO "[%2X] %04x %04x %04x %c V%02x %+d", i, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, loop_size > 1 ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4); } mod->len = mod->pat = hio_read8(f); hio_read8(f); /* restart */ for (i = 0; i < 128; i++) mod->xxo[i] = hio_read8(f); #if 0 for (i = 0; i < 128; i++) { mod->xxo[i] = hio_read8(f); if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; #endif mod->trk = mod->pat * mod->chn; /* Read and convert patterns */ if (pattern_init(mod) < 0) return -1; size1 = hio_read16b(f); size2 = hio_read16b(f); for (i = 0; i < size1; i++) { /* Read pattern table */ for (j = 0; j < 4; j++) { pat_table[i][j] = hio_read16b(f); } } D_(D_INFO "Stored patterns: %d ", mod->pat); pat_addr = hio_tell(f); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < 4; j++) { hio_seek(f, pat_addr + pat_table[i][j], SEEK_SET); hio_read(buf, 1, 1024, f); for (row = k = 0; k < 4; k++) { for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++, row++) { event = &EVENT(i, j, row); memcpy(mod_event, &buf[buf[buf[buf[k] + x] + y] * 2], 4); decode_protracker_event(event, mod_event); } } } } } /* Read samples */ D_(D_INFO "Loading samples: %d", mod->ins); /* first check smp.filename */ if (strlen(m->basename) < 5 || m->basename[3] != '.') { fprintf(stderr, "libxmp: invalid filename %s\n", m->basename); goto err; } m->basename[0] = 's'; m->basename[1] = 'm'; m->basename[2] = 'p'; snprintf(smp_filename, sizeof(smp_filename), "%s%s", m->dirname, m->basename); if (stat(smp_filename, &st) < 0) { /* handle .set filenames like in Kid Chaos*/ char *x; if (strchr(m->basename, '-')) { if ((x = strrchr(smp_filename, '-'))) strcpy(x, ".set"); } if (stat(smp_filename, &st) < 0) { fprintf(stderr, "libxmp: missing file %s\n", smp_filename); goto err; } } if ((s = hio_open_file(smp_filename, "rb")) == NULL) { fprintf(stderr, "libxmp: can't open sample file %s\n", smp_filename); goto err; } for (i = 0; i < mod->ins; i++) { if (load_sample(m, s, SAMPLE_FLAG_FULLREP, &mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0) return -1; } hio_close(s); m->quirk |= QUIRK_MODRNG; return 0; err: for (i = 0; i < mod->ins; i++) { mod->xxi[i].nsm = 0; memset(&mod->xxs[i], 0, sizeof(struct xmp_sample)); } return 0; }
int mmd_load_synth_instrument(HIO_HANDLE *f, struct module_data *m, int i, int smp_idx, struct SynthInstr *synth, struct InstrExt *exp_smp, struct MMD0sample *sample) { struct xmp_module *mod = &m->mod; struct xmp_instrument *xxi = &mod->xxi[i]; int pos = hio_tell(f); int j; synth->defaultdecay = hio_read8(f); hio_seek(f, 3, SEEK_CUR); synth->rep = hio_read16b(f); synth->replen = hio_read16b(f); synth->voltbllen = hio_read16b(f); synth->wftbllen = hio_read16b(f); synth->volspeed = hio_read8(f); synth->wfspeed = hio_read8(f); synth->wforms = hio_read16b(f); hio_read(synth->voltbl, 1, 128, f);; hio_read(synth->wftbl, 1, 128, f);; for (j = 0; j < 64; j++) synth->wf[j] = hio_read32b(f); D_(D_INFO " VS:%02x WS:%02x WF:%02x %02x %+3d %+1d", synth->volspeed, synth->wfspeed, synth->wforms & 0xff, sample->svol, sample->strans, exp_smp->finetune); if (synth->wforms == 0xffff) return 1; if (synth->wforms > 64) return -1; if (med_new_instrument_extras(&mod->xxi[i]) != 0) return -1; mod->xxi[i].nsm = synth->wforms; if (subinstrument_alloc(mod, i, synth->wforms) < 0) return -1; MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed; MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed; for (j = 0; j < synth->wforms; j++) { struct xmp_subinstrument *sub = &xxi->sub[j]; struct xmp_sample *xxs = &mod->xxs[smp_idx]; sub->pan = 0x80; sub->vol = sample->svol; sub->xpo = sample->strans - 24; sub->sid = smp_idx; sub->fin = exp_smp->finetune; hio_seek(f, pos - 6 + synth->wf[j], SEEK_SET); xxs->len = hio_read16b(f) * 2; xxs->lps = 0; xxs->lpe = mod->xxs[smp_idx].len; xxs->flg = XMP_SAMPLE_LOOP; if (load_sample(m, f, 0, xxs, NULL) < 0) return -1; smp_idx++; } return 0; }
static int gal4_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 = iff_new(); if (handle == NULL) return -1; /* IFF chunk IDs */ ret = iff_register(handle, "MAIN", get_main); ret |= iff_register(handle, "ORDR", get_ordr); ret |= iff_register(handle, "PATT", get_patt_cnt); ret |= iff_register(handle, "INST", get_inst_cnt); if (ret != 0) return -1; iff_set_quirk(handle, IFF_LITTLE_ENDIAN); iff_set_quirk(handle, IFF_CHUNK_TRUNC4); /* Load IFF chunks */ if (iff_load(handle, m, f, &data) < 0) { iff_release(handle); return -1; } iff_release(handle); mod->trk = mod->pat * mod->chn; MODULE_INFO(); if (instrument_init(mod) < 0) return -1; if (pattern_init(mod) < 0) return -1; D_(D_INFO "Stored patterns: %d\n", mod->pat); D_(D_INFO "Stored samples : %d ", mod->smp); hio_seek(f, start + offset, SEEK_SET); data.snum = 0; handle = iff_new(); if (handle == NULL) return -1; /* IFF chunk IDs */ ret = iff_register(handle, "PATT", get_patt); ret |= iff_register(handle, "INST", get_inst); if (ret != 0) return -1; iff_set_quirk(handle, IFF_LITTLE_ENDIAN); iff_set_quirk(handle, IFF_CHUNK_TRUNC4); /* Load IFF chunks */ if (iff_load(handle, m, f, &data) < 0) { iff_release(handle); return -1; } iff_release(handle); /* Alloc missing patterns */ for (i = 0; i < mod->pat; i++) { if (mod->xxp[i] == NULL) { if (pattern_tracks_alloc(mod, i, 64) < 0) { return -1; } } } for (i = 0; i < mod->chn; i++) { mod->xxc[i].pan = 0x80; } m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; return 0; }
static int amf_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; struct xmp_event *event; uint8 buf[1024]; int *trkmap, newtrk; int ver; LOAD_INIT(); hio_read(buf, 1, 3, f); ver = hio_read8(f); hio_read(buf, 1, 32, f); strncpy(mod->name, (char *)buf, 32); set_type(m, "DSMI %d.%d AMF", ver / 10, ver % 10); mod->ins = hio_read8(f); mod->len = hio_read8(f); mod->trk = hio_read16l(f); mod->chn = hio_read8(f); mod->smp = mod->ins; mod->pat = mod->len; if (ver == 0x0a) hio_read(buf, 1, 16, f); /* channel remap table */ if (ver >= 0x0d) { hio_read(buf, 1, 32, f); /* panning table */ for (i = 0; i < 32; i++) { mod->xxc->pan = 0x80 + 2 * (int8)buf[i]; } mod->bpm = hio_read8(f); mod->spd = hio_read8(f); } else if (ver >= 0x0b) { hio_read(buf, 1, 16, f); } MODULE_INFO(); /* Orders */ /* * Andre Timmermans <*****@*****.**> says: * * Order table: track numbers in this table are not explained, * but as you noticed you have to perform -1 to obtain the index * in the track table. For value 0, found in some files, I think * it means an empty track. */ for (i = 0; i < mod->len; i++) mod->xxo[i] = i; D_(D_INFO "Stored patterns: %d", mod->pat); mod->xxp = calloc(sizeof(struct xmp_pattern *), mod->pat + 1); if (mod->xxp == NULL) return -1; for (i = 0; i < mod->pat; i++) { if (pattern_alloc(mod, i) < 0) return -1; mod->xxp[i]->rows = ver >= 0x0e ? hio_read16l(f) : 64; for (j = 0; j < mod->chn; j++) { uint16 t = hio_read16l(f); mod->xxp[i]->index[j] = t; } } /* Instruments */ if (instrument_init(mod) < 0) return -1; /* Probe for 2-byte loop start 1.0 format * in facing_n.amf and sweetdrm.amf have only the sample * loop start specified in 2 bytes */ if (ver <= 0x0a) { uint8 b; uint32 len, start, end; long pos = hio_tell(f); for (i = 0; i < mod->ins; i++) { b = hio_read8(f); if (b != 0 && b != 1) { ver = 0x09; break; } hio_seek(f, 32 + 13, SEEK_CUR); if (hio_read32l(f) > 0x100000) { /* check index */ ver = 0x09; break; } len = hio_read32l(f); if (len > 0x100000) { /* check len */ ver = 0x09; break; } if (hio_read16l(f) == 0x0000) { /* check c2spd */ ver = 0x09; break; } if (hio_read8(f) > 0x40) { /* check volume */ ver = 0x09; break; } start = hio_read32l(f); if (start > len) { /* check loop start */ ver = 0x09; break; } end = hio_read32l(f); if (end > len) { /* check loop end */ ver = 0x09; break; } } hio_seek(f, pos, SEEK_SET); } for (i = 0; i < mod->ins; i++) { /*uint8 b;*/ int c2spd; if (subinstrument_alloc(mod, i, 1) < 0) return -1; /*b =*/ hio_read8(f); hio_read(buf, 1, 32, f); instrument_name(mod, i, buf, 32); hio_read(buf, 1, 13, f); /* sample name */ hio_read32l(f); /* sample index */ mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].sid = i; mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].len = hio_read32l(f); c2spd = hio_read16l(f); c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxi[i].sub[0].vol = hio_read8(f); /* * Andre Timmermans <*****@*****.**> says: * * [Miodrag Vallat's] doc tells that in version 1.0 only * sample loop start is present (2 bytes) but the files I * have tells both start and end are present (2*4 bytes). * Maybe it should be read as version < 1.0. * * CM: confirmed with Maelcum's "The tribal zone" */ if (ver < 0x0a) { mod->xxs[i].lps = hio_read16l(f); mod->xxs[i].lpe = mod->xxs[i].len; } else { mod->xxs[i].lps = hio_read32l(f); mod->xxs[i].lpe = hio_read32l(f); } if (ver < 0x0a) { mod->xxs[i].flg = mod->xxs[i].lps > 0 ? XMP_SAMPLE_LOOP : 0; } else { mod->xxs[i].flg = mod->xxs[i].lpe > mod->xxs[i].lps ? XMP_SAMPLE_LOOP : 0; } D_(D_INFO "[%2X] %-32.32s %05x %05x %05x %c V%02x %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, c2spd); } /* Tracks */ trkmap = calloc(sizeof(int), mod->trk); if (trkmap == NULL) return -1; newtrk = 0; for (i = 0; i < mod->trk; i++) { /* read track table */ uint16 t; t = hio_read16l(f); trkmap[i] = t; if (t > newtrk) newtrk = t; /*printf("%d -> %d\n", i, t);*/ } for (i = 0; i < mod->pat; i++) { /* read track table */ for (j = 0; j < mod->chn; j++) { int k = mod->xxp[i]->index[j] - 1; /* Use empty track if an invalid track is requested * (such as in Lasse Makkonen "faster and louder") */ if (k < 0 || k >= mod->trk) k = 0; mod->xxp[i]->index[j] = trkmap[k]; /*printf("mod->xxp[%d]->info[%d].index = %d (k = %d)\n", i, j, trkmap[k], k);*/ } } mod->trk = newtrk; /* + empty track */ free(trkmap); D_(D_INFO "Stored tracks: %d", mod->trk); mod->trk++; mod->xxt = calloc (sizeof (struct xmp_track *), mod->trk); if (mod->xxt == NULL) return -1; /* Alloc track 0 as empty track */ if (track_alloc(mod, 0, 64) < 0) return -1; /* Alloc rest of the tracks */ for (i = 1; i < mod->trk; i++) { uint8 t1, t2, t3; int size; if (track_alloc(mod, i, 64) < 0) return -1; size = hio_read24l(f); /*printf("TRACK %d SIZE %d\n", i, size);*/ for (j = 0; j < size; j++) { t1 = hio_read8(f); /* row */ t2 = hio_read8(f); /* type */ t3 = hio_read8(f); /* parameter */ /*printf("track %d row %d: %02x %02x %02x\n", i, t1, t1, t2, t3);*/ if (t1 == 0xff && t2 == 0xff && t3 == 0xff) break; event = &mod->xxt[i]->event[t1]; if (t2 < 0x7f) { /* note */ if (t2 > 0) event->note = t2 + 1; event->vol = t3; } else if (t2 == 0x7f) { /* copy previous */ memcpy(event, &mod->xxt[i]->event[t1 - 1], sizeof(struct xmp_event)); } else if (t2 == 0x80) { /* instrument */ event->ins = t3 + 1; } else { /* effects */ uint8 fxp, fxt; fxp = fxt = 0; switch (t2) { case 0x81: fxt = FX_SPEED; fxp = t3; break; case 0x82: if ((int8)t3 > 0) { fxt = FX_VOLSLIDE; fxp = t3 << 4; } else { fxt = FX_VOLSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x83: event->vol = t3; break; case 0x84: /* AT: Not explained for 0x84, pitch * slide, value 0x00 corresponds to * S3M E00 and 0x80 stands for S3M F00 * (I checked with M2AMF) */ if ((int8)t3 >= 0) { fxt = FX_PORTA_DN; fxp = t3; } else if (t3 == 0x80) { fxt = FX_PORTA_UP; fxp = 0; } else { fxt = FX_PORTA_UP; fxp = -(int8)t3; } break; case 0x85: /* porta abs -- unknown */ break; case 0x86: fxt = FX_TONEPORTA; fxp = t3; break; /* AT: M2AMF maps both tremolo and tremor to * 0x87. Since tremor is only found in certain * formats, maybe it would be better to * consider it is a tremolo. */ case 0x87: fxt = FX_TREMOLO; fxp = t3; break; case 0x88: fxt = FX_ARPEGGIO; fxp = t3; break; case 0x89: fxt = FX_VIBRATO; fxp = t3; break; case 0x8a: if ((int8)t3 > 0) { fxt = FX_TONE_VSLIDE; fxp = t3 << 4; } else { fxt = FX_TONE_VSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x8b: if ((int8)t3 > 0) { fxt = FX_VIBRA_VSLIDE; fxp = t3 << 4; } else { fxt = FX_VIBRA_VSLIDE; fxp = -(int8)t3 & 0x0f; } break; case 0x8c: fxt = FX_BREAK; fxp = t3; break; case 0x8d: fxt = FX_JUMP; fxp = t3; break; case 0x8e: /* sync -- unknown */ break; case 0x8f: fxt = FX_EXTENDED; fxp = (EX_RETRIG << 4) | (t3 & 0x0f); break; case 0x90: fxt = FX_OFFSET; fxp = t3; break; case 0x91: if ((int8)t3 > 0) { fxt = FX_EXTENDED; fxp = (EX_F_VSLIDE_UP << 4) | (t3 & 0x0f); } else { fxt = FX_EXTENDED; fxp = (EX_F_VSLIDE_DN << 4) | (t3 & 0x0f); } break; case 0x92: if ((int8)t3 > 0) { fxt = FX_PORTA_DN; fxp = 0xf0 | (fxp & 0x0f); } else { fxt = FX_PORTA_UP; fxp = 0xf0 | (fxp & 0x0f); } break; case 0x93: fxt = FX_EXTENDED; fxp = (EX_DELAY << 4) | (t3 & 0x0f); break; case 0x94: fxt = FX_EXTENDED; fxp = (EX_CUT << 4) | (t3 & 0x0f); break; case 0x95: fxt = FX_SPEED; if (t3 < 0x21) t3 = 0x21; fxp = t3; break; case 0x96: if ((int8)t3 > 0) { fxt = FX_PORTA_DN; fxp = 0xe0 | (fxp & 0x0f); } else { fxt = FX_PORTA_UP; fxp = 0xe0 | (fxp & 0x0f); } break; case 0x97: fxt = FX_SETPAN; fxp = 0x80 + 2 * (int8)t3; break; } event->fxt = fxt; event->fxp = fxp; } } } /* Samples */ D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->ins; i++) { if (load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0) return -1; } m->quirk |= QUIRK_FINEFX; return 0; }
static int 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 depack_skyt(HIO_HANDLE *in, FILE *out) { uint8 c1, c2, c3, c4; uint8 ptable[128]; uint8 pat_pos; uint8 pat[1024]; int i = 0, j = 0, k = 0; int trkval[128][4]; int trk_addr; int size, ssize = 0; memset(ptable, 0, 128); memset(trkval, 0, 128 * 4); pw_write_zero(out, 20); /* write title */ /* read and write sample descriptions */ for (i = 0; i < 31; i++) { pw_write_zero(out, 22); /*sample name */ write16b(out, size = hio_read16b(in)); /* sample size */ ssize += size * 2; write8(out, hio_read8(in)); /* finetune */ write8(out, hio_read8(in)); /* volume */ write16b(out, hio_read16b(in)); /* loop start */ write16b(out, hio_read16b(in)); /* loop size */ } hio_read32b(in); /* bypass 8 empty bytes */ hio_read32b(in); hio_read32b(in); /* bypass "SKYT" ID */ pat_pos = hio_read8(in) + 1; /* pattern table lenght */ if (pat_pos >= 128) { return -1; } write8(out, pat_pos); write8(out, 0x7f); /* write NoiseTracker byte */ /* read track numbers ... and deduce pattern list */ for (i = 0; i < pat_pos; i++) { for (j = 0; j < 4; j++) { trkval[i][j] = hio_read16b(in); } } /* write pseudo pattern list */ for (i = 0; i < 128; i++) { write8(out, i < pat_pos ? i : 0); } write32b(out, PW_MOD_MAGIC); /* write ptk's ID */ hio_read8(in); /* bypass $00 unknown byte */ /* get track address */ trk_addr = hio_tell(in); /* track data */ for (i = 0; i < pat_pos; i++) { memset(pat, 0, 1024); for (j = 0; j < 4; j++) { hio_seek(in, trk_addr + ((trkval[i][j] - 1)<<8), SEEK_SET); for (k = 0; k < 64; k++) { int x = k * 16 + j * 4; c1 = hio_read8(in); c2 = hio_read8(in); c3 = hio_read8(in); c4 = hio_read8(in); pat[x] = (c2 & 0xf0) | ptk_table[c1][0]; pat[x + 1] = ptk_table[c1][1]; pat[x + 2] = ((c2 << 4) & 0xf0) | c3; pat[x + 3] = c4; } } fwrite(pat, 1024, 1, out); } /* sample data */ pw_move_data(out, in, ssize); return 0; }
static int mod_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; int smp_size, pat_size, wow, ptsong = 0; struct xmp_event *event; struct mod_header mh; uint8 mod_event[4]; char *x, pathname[PATH_MAX] = "", *tracker = ""; int detected = 0; char magic[8], idbuffer[32]; int ptkloop = 0; /* Protracker loop */ int tracker_id = TRACKER_PROTRACKER; LOAD_INIT(); mod->ins = 31; mod->smp = mod->ins; mod->chn = 0; smp_size = 0; pat_size = 0; m->quirk |= QUIRK_MODRNG; hio_read(&mh.name, 20, 1, f); for (i = 0; i < 31; i++) { hio_read(&mh.ins[i].name, 22, 1, f); /* Instrument name */ mh.ins[i].size = hio_read16b(f); /* Length in 16-bit words */ mh.ins[i].finetune = hio_read8(f); /* Finetune (signed nibble) */ mh.ins[i].volume = hio_read8(f); /* Linear playback volume */ mh.ins[i].loop_start = hio_read16b(f); /* Loop start in 16-bit words */ mh.ins[i].loop_size = hio_read16b(f); /* Loop size in 16-bit words */ smp_size += 2 * mh.ins[i].size; } mh.len = hio_read8(f); mh.restart = hio_read8(f); hio_read(&mh.order, 128, 1, f); memset(magic, 0, 8); hio_read(magic, 4, 1, f); for (i = 0; mod_magic[i].ch; i++) { if (!(strncmp (magic, mod_magic[i].magic, 4))) { mod->chn = mod_magic[i].ch; tracker_id = mod_magic[i].id; detected = mod_magic[i].flag; break; } } if (!mod->chn) { if (!strncmp(magic + 2, "CH", 2) && isdigit((int)magic[0]) && isdigit((int)magic[1])) { mod->chn = (*magic - '0') * 10 + magic[1] - '0'; } else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) { mod->chn = *magic - '0'; } else { return -1; } tracker_id = mod->chn & 1 ? TRACKER_TAKETRACKER : TRACKER_FASTTRACKER2; detected = 1; m->quirk &= ~QUIRK_MODRNG; } strncpy(mod->name, (char *) mh.name, 20); mod->len = mh.len; /* mod->rst = mh.restart; */ if (mod->rst >= mod->len) mod->rst = 0; memcpy(mod->xxo, mh.order, 128); for (i = 0; i < 128; i++) { /* This fixes dragnet.mod (garbage in the order list) */ if (mod->xxo[i] > 0x7f) break; if (mod->xxo[i] > mod->pat) mod->pat = mod->xxo[i]; } mod->pat++; pat_size = 256 * mod->chn * mod->pat; if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxs[i].len = 2 * mh.ins[i].size; mod->xxs[i].lps = 2 * mh.ins[i].loop_start; mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size; if (mod->xxs[i].lpe > mod->xxs[i].len) mod->xxs[i].lpe = mod->xxs[i].len; mod->xxs[i].flg = (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe >= 4) ? XMP_SAMPLE_LOOP : 0; mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4); mod->xxi[i].sub[0].vol = mh.ins[i].volume; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].sid = i; instrument_name(mod, i, mh.ins[i].name, 22); if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; } /* * Experimental tracker-detection routine */ if (detected) goto skip_test; /* Test for Flextrax modules * * FlexTrax is a soundtracker for Atari Falcon030 compatible computers. * FlexTrax supports the standard MOD file format (up to eight channels) * for compatibility reasons but also features a new enhanced module * format FLX. The FLX format is an extended version of the standard * MOD file format with support for real-time sound effects like reverb * and delay. */ if (0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size < m->size) { int pos = hio_tell(f); hio_seek(f, start + 0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size, SEEK_SET); hio_read(idbuffer, 1, 4, f); hio_seek(f, start + pos, SEEK_SET); if (!memcmp(idbuffer, "FLEX", 4)) { tracker_id = TRACKER_FLEXTRAX; goto skip_test; } } /* Test for Mod's Grave WOW modules * * Stefan Danes <*****@*****.**> said: * This weird format is identical to '8CHN' but still uses the 'M.K.' ID. * You can only test for WOW by calculating the size of the module for 8 * channels and comparing this to the actual module length. If it's equal, * the module is an 8 channel WOW. */ if ((wow = (!strncmp(magic, "M.K.", 4) && (0x43c + mod->pat * 32 * 0x40 + smp_size == m->size)))) { mod->chn = 8; tracker_id = TRACKER_MODSGRAVE; goto skip_test; } /* Test for Protracker song files */ else if ((ptsong = (!strncmp((char *)magic, "M.K.", 4) && (0x43c + mod->pat * 0x400 == m->size)))) { tracker_id = TRACKER_PROTRACKER; goto skip_test; } /* Test Protracker-like files */ if (mod->chn == 4 && mh.restart == mod->pat) { tracker_id = TRACKER_SOUNDTRACKER; } else if (mod->chn == 4 && mh.restart == 0x78) { tracker_id = TRACKER_NOISETRACKER; } else if (mh.restart < 0x7f) { if (mod->chn == 4) { tracker_id = TRACKER_NOISETRACKER; } else { tracker_id = TRACKER_UNKNOWN; } mod->rst = mh.restart; } if (mod->chn != 4 && mh.restart == 0x7f) { tracker_id = TRACKER_SCREAMTRACKER3; m->quirk &= ~QUIRK_MODRNG; m->read_event_type = READ_EVENT_ST3; } if (mod->chn == 4 && mh.restart == 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i < 31) { tracker_id = TRACKER_CLONE; } } if (mh.restart != 0x78 && mh.restart < 0x7f) { for (i = 0; i < 31; i++) { if (mh.ins[i].loop_size == 0) break; } if (i == 31) { /* All loops are size 2 or greater */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 1 && mh.ins[i].volume == 0) { tracker_id = TRACKER_CONVERTED; goto skip_test; } } for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i == 31) { /* No st- instruments */ for (i = 0; i < 31; i++) { if (mh.ins[i].size == 0 && mh.ins[i].loop_size == 1) { switch (mod->chn) { case 4: tracker_id = TRACKER_NOISETRACKER; /* or Octalyser */ break; case 6: case 8: tracker_id = TRACKER_OCTALYSER; break; default: tracker_id = TRACKER_UNKNOWN; } goto skip_test; } } if (mod->chn == 4) { tracker_id = TRACKER_PROTRACKER; } else if (mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; /* FastTracker 1.01? */ m->quirk &= ~QUIRK_MODRNG; } else { tracker_id = TRACKER_UNKNOWN; } } } else { /* Has loops with 0 size */ for (i = 15; i < 31; i++) { if (strlen((char *)mh.ins[i].name) || mh.ins[i].size > 0) break; } if (i == 31 && is_st_ins((char *)mh.ins[14].name)) { tracker_id = TRACKER_CONVERTEDST; goto skip_test; } /* Assume that Fast Tracker modules won't have ST- instruments */ for (i = 0; i < 31; i++) { if (is_st_ins((char *)mh.ins[i].name)) break; } if (i < 31) { tracker_id = TRACKER_UNKNOWN_CONV; goto skip_test; } if (mod->chn == 4 || mod->chn == 6 || mod->chn == 8) { tracker_id = TRACKER_FASTTRACKER; m->quirk &= ~QUIRK_MODRNG; goto skip_test; } tracker_id = TRACKER_UNKNOWN; /* ??!? */ } } skip_test: switch (tracker_id) { case TRACKER_PROTRACKER: tracker = "Protracker"; ptkloop = 1; break; case TRACKER_NOISETRACKER: tracker = "Noisetracker"; ptkloop = 1; break; case TRACKER_SOUNDTRACKER: tracker = "Soundtracker"; ptkloop = 1; break; case TRACKER_FASTTRACKER: tracker = "Fast Tracker"; break; case TRACKER_FASTTRACKER2: tracker = "FastTracker 2"; break; case TRACKER_OCTALYSER: tracker = "Octalyser"; break; case TRACKER_TAKETRACKER: tracker = "TakeTracker"; break; case TRACKER_DIGITALTRACKER: tracker = "Digital Tracker"; break; case TRACKER_FLEXTRAX: tracker = "Flextrax"; break; case TRACKER_MODSGRAVE: tracker = "Mod's Grave"; break; case TRACKER_SCREAMTRACKER3: tracker = "Scream Tracker III"; break; case TRACKER_UNKNOWN_CONV: tracker = "unknown or converted"; break; case TRACKER_CONVERTEDST: tracker = "converted ST2.2 or earlier"; break; case TRACKER_CONVERTED: tracker = "converted"; break; case TRACKER_CLONE: tracker = "Protracker clone"; break; default: case TRACKER_UNKNOWN: tracker = "unknown"; break; } mod->trk = mod->chn * mod->pat; snprintf(mod->type, XMP_NAME_SIZE, "%s (%s)", tracker, magic); MODULE_INFO(); for (i = 0; i < mod->ins; i++) { D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4, ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 && mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' '); } if (pattern_init(mod) < 0) return -1; /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; for (j = 0; j < (64 * mod->chn); j++) { event = &EVENT (i, j % mod->chn, j / mod->chn); hio_read (mod_event, 1, 4, f); switch (tracker_id) { case TRACKER_NOISETRACKER: decode_noisetracker_event(event, mod_event); break; case TRACKER_PROTRACKER: default: decode_protracker_event(event, mod_event); break; } } } /* Load samples */ if (m->filename && (x = strrchr(m->filename, '/'))) strncpy(pathname, m->filename, x - m->filename); D_(D_INFO "Stored samples: %d", mod->smp); for (i = 0; i < mod->smp; i++) { int flags; if (!mod->xxs[i].len) continue; flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0; if (ptsong) { HIO_HANDLE *s; char sn[256]; snprintf(sn, XMP_NAME_SIZE, "%s%s", pathname, mod->xxi[i].name); if ((s = hio_open_file(sn, "rb"))) { if (load_sample(m, s, flags, &mod->xxs[i], NULL) < 0) { hio_close(s); return -1; } hio_close(s); } } else { if (load_sample(m, f, flags, &mod->xxs[i], NULL) < 0) return -1; } } if (mod->chn > 4) { m->quirk &= ~QUIRK_MODRNG; m->quirk |= QUIRKS_FT2; m->read_event_type = READ_EVENT_FT2; } else if (strcmp(tracker, "Protracker") == 0) { m->quirk |= QUIRK_INVLOOP; } return 0; }
static int depack_pha(HIO_HANDLE *in, FILE *out) { uint8 c1, c2; uint8 pnum[128]; uint8 pnum1[128]; uint8 nop; uint8 *pdata; uint8 *pat; uint8 onote[4][4]; uint8 note, ins, fxt, fxp; uint8 npat = 0x00; int paddr[128]; int i, j, k; int paddr1[128]; int paddr2[128]; int tmp_ptr, tmp; int pat_addr; int psize; int size, ssize = 0; int smp_addr; short ocpt[4]; memset(paddr, 0, 128 * 4); memset(paddr1, 0, 128 * 4); memset(paddr2, 0, 128 * 4); memset(pnum, 0, 128); memset(pnum1, 0, 128); memset(onote, 0, 4 * 4); memset(ocpt, 0, 4 * 2); pw_write_zero(out, 20); /* title */ for (i = 0; i < 31; i++) { int vol, fin, lps, lsz; pw_write_zero(out, 22); /* sample name */ write16b(out, size = hio_read16b(in)); /* size */ ssize += size * 2; hio_read8(in); /* ??? */ vol = hio_read8(in); /* volume */ lps = hio_read16b(in); /* loop start */ lsz = hio_read16b(in); /* loop size */ hio_read32b(in); /* sample address */ hio_read8(in); /* ??? */ fin = hio_read8(in); /* finetune - 11 */ if (fin != 0) { fin += 11; } write8(out, fin); write8(out, vol); write16b(out, lps); write16b(out, lsz); } hio_seek(in, 14, SEEK_CUR); /* bypass unknown 14 bytes */ for (i = 0; i < 128; i++) paddr[i] = hio_read32b(in); /* ordering of patterns addresses */ tmp_ptr = 0; for (i = 0; i < 128; i++) { if (i == 0) { pnum[0] = 0; tmp_ptr++; continue; } for (j = 0; j < i; j++) { if (paddr[i] == paddr[j]) { pnum[i] = pnum[j]; break; } } if (j == i) pnum[i] = tmp_ptr++; } /* correct re-order */ for (i = 0; i < 128; i++) paddr1[i] = paddr[i]; restart: for (i = 0; i < 128; i++) { for (j = 0; j < i; j++) { if (paddr1[i] < paddr1[j]) { tmp = pnum[j]; pnum[j] = pnum[i]; pnum[i] = tmp; tmp = paddr1[j]; paddr1[j] = paddr1[i]; paddr1[i] = tmp; goto restart; } } } j = 0; for (i = 0; i < 128; i++) { if (i == 0) { paddr2[j] = paddr1[i]; continue; } if (paddr1[i] == paddr2[j]) continue; paddr2[++j] = paddr1[i]; } /* try to take care of unused patterns ... HARRRRRRD */ memset(paddr1, 0, 128 * 4); j = 0; k = paddr[0]; /* 120 ... leaves 8 unused ptk_tableible patterns .. */ for (i = 0; i < 120; i++) { paddr1[j] = paddr2[i]; j += 1; if ((paddr2[i + 1] - paddr2[i]) > 1024) { paddr1[j] = paddr2[i] + 1024; j += 1; } } for (c1 = 0; c1 < 128; c1++) { for (c2 = 0; c2 < 128; c2++) { if (paddr[c1] == paddr1[c2]) { pnum1[c1] = c2; } } } memset(pnum, 0, 128); pat_addr = 999999l; for (i = 0; i < 128; i++) { pnum[i] = pnum1[i]; if (paddr[i] < pat_addr) pat_addr = paddr[i]; } /* try to get the number of pattern in pattern list */ for (nop = 128; nop > 0; nop--) { if (pnum[nop - 1] != 0) break; } /* write this value */ write8(out, nop); /* get highest pattern number */ for (i = 0; i < nop; i++) if (pnum[i] > npat) npat = pnum[i]; write8(out, 0x7f); /* ntk restart byte */ for (i = 0; i < 128; i++) /* write pattern list */ write8(out, pnum[i]); write32b(out, PW_MOD_MAGIC); /* ID string */ smp_addr = hio_tell(in); hio_seek(in, pat_addr, SEEK_SET); /* pattern datas */ /* read ALL pattern data */ /* FIXME: shouldn't use file size */ #if 0 j = ftell (in); fseek (in, 0, 2); /* SEEK_END */ psize = ftell (in) - j; fseek (in, j, 0); /* SEEK_SET */ #endif psize = npat * 1024; pdata = (uint8 *) malloc (psize); psize = hio_read(pdata, 1, psize, in); npat += 1; /* coz first value is $00 */ pat = (uint8 *)malloc(npat * 1024); memset(pat, 0, npat * 1024); j = 0; for (i = 0; j < psize; i++) { if (pdata[i] == 0xff) { i += 1; ocpt[(k + 3) % 4] = 0xff - pdata[i]; continue; } if (ocpt[k % 4] != 0) { ins = onote[k % 4][0]; note = onote[k % 4][1]; fxt = onote[k % 4][2]; fxp = onote[k % 4][3]; ocpt[k % 4] -= 1; pat[j] = ins & 0xf0; pat[j] |= ptk_table[(note / 2)][0]; pat[j + 1] = ptk_table[(note / 2)][1]; pat[j + 2] = (ins << 4) & 0xf0; pat[j + 2] |= fxt; pat[j + 3] = fxp; k += 1; j += 4; i -= 1; continue; } ins = pdata[i]; note = pdata[i + 1]; fxt = pdata[i + 2]; fxp = pdata[i + 3]; onote[k % 4][0] = ins; onote[k % 4][1] = note; onote[k % 4][2] = fxt; onote[k % 4][3] = fxp; i += 3; pat[j] = ins & 0xf0; pat[j] |= ptk_table[(note / 2)][0]; pat[j + 1] = ptk_table[(note / 2)][1]; pat[j + 2] = (ins << 4) & 0xf0; pat[j + 2] |= fxt; pat[j + 3] = fxp; k += 1; j += 4; } fwrite(pat, npat * 1024, 1, out); free(pdata); free(pat); /* Sample data */ hio_seek(in, smp_addr, SEEK_SET); pw_move_data(out, in, ssize); return 0; }
static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j, k; struct MMD0 header; struct MMD2song song; struct MMD1Block block; struct InstrHdr instr; struct SynthInstr synth; struct InstrExt exp_smp; struct MMD0exp expdata; struct xmp_event *event; int ver = 0; int smp_idx = 0; uint8 e[4]; int song_offset; int seqtable_offset; int trackvols_offset; int trackpans_offset; int blockarr_offset; int smplarr_offset; int expdata_offset; int expsmp_offset; int songname_offset; int iinfo_offset; int playseq_offset; int pos; int bpm_on, bpmlen, med_8ch; LOAD_INIT(); hio_read(&header.id, 4, 1, f); ver = *((char *)&header.id + 3) - '1' + 1; D_(D_WARN "load header"); header.modlen = hio_read32b(f); song_offset = hio_read32b(f); D_(D_INFO "song_offset = 0x%08x", song_offset); hio_read16b(f); hio_read16b(f); blockarr_offset = hio_read32b(f); D_(D_INFO "blockarr_offset = 0x%08x", blockarr_offset); hio_read32b(f); smplarr_offset = hio_read32b(f); D_(D_INFO "smplarr_offset = 0x%08x", smplarr_offset); hio_read32b(f); expdata_offset = hio_read32b(f); D_(D_INFO "expdata_offset = 0x%08x", expdata_offset); hio_read32b(f); header.pstate = hio_read16b(f); header.pblock = hio_read16b(f); header.pline = hio_read16b(f); header.pseqnum = hio_read16b(f); header.actplayline = hio_read16b(f); header.counter = hio_read8(f); header.extra_songs = hio_read8(f); /* * song structure */ D_(D_WARN "load song"); hio_seek(f, start + song_offset, SEEK_SET); for (i = 0; i < 63; i++) { song.sample[i].rep = hio_read16b(f); song.sample[i].replen = hio_read16b(f); song.sample[i].midich = hio_read8(f); song.sample[i].midipreset = hio_read8(f); song.sample[i].svol = hio_read8(f); song.sample[i].strans = hio_read8s(f); } song.numblocks = hio_read16b(f); song.songlen = hio_read16b(f); D_(D_INFO "song.songlen = %d", song.songlen); seqtable_offset = hio_read32b(f); hio_read32b(f); trackvols_offset = hio_read32b(f); song.numtracks = hio_read16b(f); song.numpseqs = hio_read16b(f); trackpans_offset = hio_read32b(f); song.flags3 = hio_read32b(f); song.voladj = hio_read16b(f); song.channels = hio_read16b(f); song.mix_echotype = hio_read8(f); song.mix_echodepth = hio_read8(f); song.mix_echolen = hio_read16b(f); song.mix_stereosep = hio_read8(f); hio_seek(f, 223, SEEK_CUR); song.deftempo = hio_read16b(f); song.playtransp = hio_read8(f); song.flags = hio_read8(f); song.flags2 = hio_read8(f); song.tempo2 = hio_read8(f); for (i = 0; i < 16; i++) hio_read8(f); /* reserved */ song.mastervol = hio_read8(f); song.numsamples = hio_read8(f); /* * read sequence */ hio_seek(f, start + seqtable_offset, SEEK_SET); playseq_offset = hio_read32b(f); hio_seek(f, start + playseq_offset, SEEK_SET); hio_seek(f, 32, SEEK_CUR); /* skip name */ hio_read32b(f); hio_read32b(f); mod->len = hio_read16b(f); for (i = 0; i < mod->len; i++) mod->xxo[i] = hio_read16b(f); /* * convert header */ m->c4rate = C4_NTSC_RATE; m->quirk |= song.flags & FLAG_STSLIDE ? 0 : QUIRK_VSALL | QUIRK_PBALL; med_8ch = song.flags & FLAG_8CHANNEL; bpm_on = song.flags2 & FLAG2_BPM; bpmlen = 1 + (song.flags2 & FLAG2_BMASK); m->time_factor = MED_TIME_FACTOR; mmd_set_bpm(m, med_8ch, song.deftempo, bpm_on, bpmlen); mod->spd = song.tempo2; mod->pat = song.numblocks; mod->ins = song.numsamples; mod->rst = 0; mod->chn = 0; mod->name[0] = 0; /* * Obtain number of samples from each instrument */ mod->smp = 0; for (i = 0; i < mod->ins; i++) { uint32 smpl_offset; int16 type; hio_seek(f, start + smplarr_offset + i * 4, SEEK_SET); smpl_offset = hio_read32b(f); if (smpl_offset == 0) continue; hio_seek(f, start + smpl_offset, SEEK_SET); hio_read32b(f); /* length */ type = hio_read16b(f); if (type == -1) { /* type is synth? */ hio_seek(f, 14, SEEK_CUR); mod->smp += hio_read16b(f); /* wforms */ } else { mod->smp++; } } /* * expdata */ D_(D_WARN "load expdata"); expdata.s_ext_entries = 0; expdata.s_ext_entrsz = 0; expdata.i_ext_entries = 0; expdata.i_ext_entrsz = 0; expsmp_offset = 0; iinfo_offset = 0; if (expdata_offset) { hio_seek(f, start + expdata_offset, SEEK_SET); hio_read32b(f); expsmp_offset = hio_read32b(f); D_(D_INFO "expsmp_offset = 0x%08x", expsmp_offset); expdata.s_ext_entries = hio_read16b(f); expdata.s_ext_entrsz = hio_read16b(f); hio_read32b(f); hio_read32b(f); iinfo_offset = hio_read32b(f); D_(D_INFO "iinfo_offset = 0x%08x", iinfo_offset); expdata.i_ext_entries = hio_read16b(f); expdata.i_ext_entrsz = hio_read16b(f); hio_read32b(f); hio_read32b(f); hio_read32b(f); hio_read32b(f); songname_offset = hio_read32b(f); D_(D_INFO "songname_offset = 0x%08x", songname_offset); expdata.songnamelen = hio_read32b(f); hio_seek(f, start + songname_offset, SEEK_SET); D_(D_INFO "expdata.songnamelen = %d", expdata.songnamelen); for (i = 0; i < expdata.songnamelen; i++) { if (i >= XMP_NAME_SIZE) break; mod->name[i] = hio_read8(f); } } /* * Quickly scan patterns to check the number of channels */ D_(D_WARN "find number of channels"); for (i = 0; i < mod->pat; i++) { int block_offset; hio_seek(f, start + blockarr_offset + i * 4, SEEK_SET); block_offset = hio_read32b(f); D_(D_INFO "block %d block_offset = 0x%08x", i, block_offset); if (block_offset == 0) continue; hio_seek(f, start + block_offset, SEEK_SET); block.numtracks = hio_read16b(f); block.lines = hio_read16b(f); if (block.numtracks > mod->chn) mod->chn = block.numtracks; } mod->trk = mod->pat * mod->chn; if (ver == 2) set_type(m, "OctaMED v5 MMD2"); else set_type(m, "OctaMED Soundstudio MMD%c", '0' + ver); MODULE_INFO(); D_(D_INFO "BPM mode: %s (length = %d)", bpm_on ? "on" : "off", bpmlen); D_(D_INFO "Song transpose : %d", song.playtransp); D_(D_INFO "Stored patterns: %d", mod->pat); /* * Read and convert patterns */ D_(D_WARN "read patterns"); if (pattern_init(mod) < 0) return -1; for (i = 0; i < mod->pat; i++) { int block_offset; hio_seek(f, start + blockarr_offset + i * 4, SEEK_SET); block_offset = hio_read32b(f); if (block_offset == 0) continue; hio_seek(f, start + block_offset, SEEK_SET); block.numtracks = hio_read16b(f); block.lines = hio_read16b(f); hio_read32b(f); if (pattern_tracks_alloc(mod, i, block.lines + 1) < 0) return -1; for (j = 0; j < mod->xxp[i]->rows; j++) { for (k = 0; k < block.numtracks; k++) { e[0] = hio_read8(f); e[1] = hio_read8(f); e[2] = hio_read8(f); e[3] = hio_read8(f); event = &EVENT(i, k, j); event->note = e[0] & 0x7f; if (event->note) { event->note += song.playtransp; if (ver == 2) event->note += 12; else event->note -= 12; }; if (event->note < 0 || event->note >= XMP_MAX_KEYS) event->note = 0; event->ins = e[1] & 0x3f; /* Decay */ if (event->ins && !event->note) { event->f2t = FX_MED_HOLD; } event->fxt = e[2]; event->fxp = e[3]; mmd_xlat_fx(event, bpm_on, bpmlen, med_8ch); } } } if (med_new_module_extras(m) != 0) return -1; /* * Read and convert instruments and samples */ D_(D_WARN "read instruments"); if (instrument_init(mod) < 0) return -1; D_(D_INFO "Instruments: %d", mod->ins); for (smp_idx = i = 0; i < mod->ins; i++) { int smpl_offset; char name[40] = ""; hio_seek(f, start + smplarr_offset + i * 4, SEEK_SET); smpl_offset = hio_read32b(f); D_(D_INFO "sample %d smpl_offset = 0x%08x", i, smpl_offset); if (smpl_offset == 0) continue; hio_seek(f, start + smpl_offset, SEEK_SET); instr.length = hio_read32b(f); instr.type = hio_read16b(f); pos = hio_tell(f); if (expdata_offset && i < expdata.i_ext_entries) { hio_seek(f, iinfo_offset + i * expdata.i_ext_entrsz, SEEK_SET); hio_read(name, 40, 1, f); D_(D_INFO "[%2x] %-40.40s %d", i, name, instr.type); } exp_smp.finetune = 0; if (expdata_offset && i < expdata.s_ext_entries) { hio_seek(f, expsmp_offset + i * expdata.s_ext_entrsz, SEEK_SET); exp_smp.hold = hio_read8(f); exp_smp.decay = hio_read8(f); exp_smp.suppress_midi_off = hio_read8(f); exp_smp.finetune = hio_read8(f); if (expdata.s_ext_entrsz > 4) { /* Octamed V5 */ exp_smp.default_pitch = hio_read8(f); exp_smp.instr_flags = hio_read8(f); } } hio_seek(f, pos, SEEK_SET); if (instr.type == -2) { /* Hybrid */ int ret = mmd_load_hybrid_instrument(f, m, i, smp_idx, &synth, &exp_smp, &song.sample[i]); if (ret < 0) return -1; smp_idx++; if (mmd_alloc_tables(m, i, &synth) != 0) return -1; continue; } if (instr.type == -1) { /* Synthetic */ int ret = mmd_load_synth_instrument(f, m, i, smp_idx, &synth, &exp_smp, &song.sample[i]); if (ret > 0) continue; if (ret < 0) return -1; smp_idx += synth.wforms; if (mmd_alloc_tables(m, i, &synth) != 0) return -1; continue; } if (instr.type >= 1 && instr.type <= 6) { /* IFFOCT */ int ret; const int oct = num_oct[instr.type - 1]; hio_seek(f, start + smpl_offset + 6, SEEK_SET); ret = mmd_load_iffoct_instrument(f, m, i, smp_idx, &instr, oct, &exp_smp, &song.sample[i]); if (ret < 0) return -1; smp_idx += oct; continue; } /* Filter out stereo samples */ if ((instr.type & ~(S_16 | STEREO)) != 0) continue; if (instr.type == 0) { /* Sample */ int ret; hio_seek(f, start + smpl_offset + 6, SEEK_SET); ret = mmd_load_sampled_instrument(f, m, i, smp_idx, &instr, &expdata, &exp_smp, &song.sample[i], ver); if (ret < 0) return -1; smp_idx++; continue; } } hio_seek(f, start + trackvols_offset, SEEK_SET); for (i = 0; i < mod->chn; i++) mod->xxc[i].vol = hio_read8(f);; if (trackpans_offset) { hio_seek(f, start + trackpans_offset, SEEK_SET); for (i = 0; i < mod->chn; i++) { int p = 8 * hio_read8s(f); mod->xxc[i].pan = 0x80 + (p > 127 ? 127 : p); } } else { for (i = 0; i < mod->chn; i++) mod->xxc[i].pan = 0x80; } m->read_event_type = READ_EVENT_MED; return 0; }
/** * @brief reads an ABK pattern into a xmp_event structure. * @param f stream to read data from. * @param events events object to populate. * @param pattern_offset_abs the absolute file offset to the start of the patter to read. * @return returns the size of the pattern. */ static int read_abk_pattern(HIO_HANDLE *f, struct xmp_event *events, uint32 pattern_offset_abs) { uint8 position; uint8 command; uint8 param; uint8 inst = 0; uint8 jumped = 0; uint8 per_command = 0; uint8 per_param = 0; uint16 delay; uint16 patdata; uint32 storepos; storepos = hio_tell(f); /* count how many abk positions are used in this pattern */ position = 0; hio_seek(f, pattern_offset_abs, SEEK_SET); /* read the first bit of pattern data */ patdata = hio_read16b(f); while ((patdata != 0x8000) && (jumped == 0)) { if (patdata == 0x9100) { break; } if (patdata & 0x8000) { command = (patdata >> 8) & 0x7F; param = patdata & 0x007F; if (command != 0x03 && command != 0x09 && command != 0x0b && command != 0x0c && command != 0x0d && command < 0x10) { per_command = 0; per_param = 0; } switch (command) { case 0x01: /* portamento up */ case 0x0e: events[position].fxt = FX_PORTA_UP; events[position].fxp = param; break; case 0x02: /* portamento down */ case 0x0f: events[position].fxt = FX_PORTA_DN; events[position].fxp = param; break; case 0x03: /* set volume */ events[position].fxt = FX_VOLSET; events[position].fxp = param; break; case 0x04: /* stop effect */ break; case 0x05: /* repeat */ events[position].fxt = FX_EXTENDED; if (param == 0) { events[position].fxp = 0x50; } else { events[position].fxp = 0x60 | (param & 0x0f); } break; case 0x06: /* lowpass filter off */ events[position].fxt = FX_EXTENDED; events[position].fxp = 0x00; break; case 0x07: /* lowpass filter on */ events[position].fxt = FX_EXTENDED; events[position].fxp = 0x01; break; case 0x08: /* set tempo */ if (param > 0) { events[position].fxt = FX_SPEED; events[position].fxp = 100/param; } break; case 0x09: /* set instrument */ inst = param + 1; break; case 0x0a: /* arpeggio */ per_command = FX_ARPEGGIO; per_param = param; break; case 0x0b: /* tone portamento */ per_command = FX_TONEPORTA; per_param = param; break; case 0x0c: /* vibrato */ per_command = FX_VIBRATO; per_param = param; break; case 0x0d: /* volume slide */ if (param != 0) { per_command = FX_VOLSLIDE; per_param = param; } else { per_command = 0; per_param = 0; } break; case 0x10: /* delay */ if (per_command != 0 || per_param != 0) { int i; for (i = 0; i < param && position < 64; i++) { events[position].fxt = per_command; events[position].fxp = per_param; position++; } } else { position += param; } if (position >= 64) { jumped = 1; } break; case 0x11: /* position jump */ events[position].fxt = FX_JUMP; events[position].fxp = param; /* break out of the loop because we've jumped.*/ jumped = 1; break; default: #if 0 /* write out an error for any unprocessed commands.*/ D_(D_WARN "ABK UNPROCESSED COMMAND: %x,%x\n", command, param); break; #else return -1; #endif } } else { if (patdata & 0x4000)
static int depack_crb(HIO_HANDLE *in, FILE *out) { uint8 c1; uint8 ptable[128]; uint8 pat_pos, pat_max; uint8 pat[1024]; int taddr[512]; int i, j, k, l, m; int size, ssize = 0; memset(ptable, 0, 128); memset(taddr, 0, 512 * 4); pw_write_zero(out, 20); /* write title */ /* read and write sample descriptions */ for (i = 0; i < 31; i++) { pw_write_zero(out, 22); /*sample name */ write16b(out, size = hio_read16b(in)); /* size */ ssize += size * 2; write8(out, hio_read8(in)); /* finetune */ write8(out, hio_read8(in)); /* volume */ write16b(out, hio_read16b(in)); /* loop start */ size = hio_read16b(in); /* loop size */ write16b(out, size ? size : 1); } write8(out, pat_pos = hio_read8(in)); /* pat table length */ write8(out, hio_read8(in)); /* NoiseTracker byte */ /* read and write pattern list and get highest patt number */ for (pat_max = i = 0; i < 128; i++) { write8(out, c1 = hio_read8(in)); if (c1 > pat_max) pat_max = c1; } pat_max++; /* write ptk's ID */ write32b(out, PW_MOD_MAGIC); /* pattern data */ for (i = 0; i < pat_max; i++) { memset(pat, 0, 1024); for (j = 0; j < 4; j++) { int x = hio_tell(in); if (x < 0) { return -1; } taddr[i * 4 + j] = x; for (k = 0; k < 64; k++) { int y = k * 16 + j * 4; c1 = hio_read8(in); if (c1 == 0x80) { k += hio_read24b(in); continue; } if (c1 == 0xc0) { m = hio_read24b(in); l = hio_tell(in); /* Sanity check */ if (l < 0 || m >= 2048) return -1; hio_seek(in, taddr[m >> 2], SEEK_SET); for (m = 0; m < 64; m++) { int x = m * 16 + j * 4; c1 = hio_read8(in); if (c1 == 0x80) { m += hio_read24b(in); continue; } pat[x] = c1; pat[x + 1] = hio_read8(in); pat[x + 2] = hio_read8(in); pat[x + 3] = hio_read8(in); } hio_seek(in, l, SEEK_SET); k += 100; continue; } pat[y] = c1; pat[y + 1] = hio_read8(in); pat[y + 2] = hio_read8(in); pat[y + 3] = hio_read8(in); } } fwrite (pat, 1024, 1, out); }
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; }