static int get_emic(struct module_data *m, int size, HIO_HANDLE * f, void *parm) { struct xmp_module *mod = &m->mod; int i, ver; uint8 reorder[256]; ver = hio_read16b(f); hio_read(mod->name, 1, 20, f); hio_seek(f, 20, SEEK_CUR); mod->bpm = hio_read8(f); mod->ins = hio_read8(f); mod->smp = mod->ins; m->quirk |= QUIRK_MODRNG; snprintf(mod->type, XMP_NAME_SIZE, "Quadra Composer EMOD v%d", ver); MODULE_INFO(); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { struct xmp_instrument *xxi = &mod->xxi[i]; struct xmp_sample *xxs = &mod->xxs[i]; struct xmp_subinstrument *sub; if (subinstrument_alloc(mod, i, 1) < 0) return -1; sub = &xxi->sub[0]; hio_read8(f); /* num */ sub->vol = hio_read8(f); xxs->len = 2 * hio_read16b(f); hio_read(xxi->name, 1, 20, f); xxs->flg = hio_read8(f) & 1 ? XMP_SAMPLE_LOOP : 0; sub->fin = hio_read8s(f) << 4; xxs->lps = 2 * hio_read16b(f); xxs->lpe = xxs->lps + 2 * hio_read16b(f); hio_read32b(f); /* ptr */ xxi->nsm = 1; sub->pan = 0x80; sub->sid = i; D_(D_INFO "[%2X] %-20.20s %05x %05x %05x %c V%02x %+d", i, xxi->name, xxs->len, xxs->lps, xxs->lpe, xxs->flg & XMP_SAMPLE_LOOP ? 'L' : ' ', sub->vol, sub->fin >> 4); } hio_read8(f); /* pad */ mod->pat = hio_read8(f); mod->trk = mod->pat * mod->chn; if (pattern_init(mod) < 0) return -1; memset(reorder, 0, 256); for (i = 0; i < mod->pat; i++) { reorder[hio_read8(f)] = i; if (pattern_tracks_alloc(mod, i, hio_read8(f) + 1) < 0) return -1; hio_seek(f, 20, SEEK_CUR); /* skip name */ hio_read32b(f); /* ptr */ } mod->len = hio_read8(f); D_(D_INFO "Module length: %d", mod->len); for (i = 0; i < mod->len; i++) mod->xxo[i] = reorder[hio_read8(f)]; return 0; }
static int stc_load(struct module_data *m, HIO_HANDLE * f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event /*, *noise*/; int i, j; uint8 buf[100]; int pos_ptr, orn_ptr, pat_ptr; struct stc_ord stc_ord[256]; struct stc_pat stc_pat[MAX_PAT]; int num, flag, orn; int *decoded; struct spectrum_extra *se; LOAD_INIT(); mod->spd = hio_read8(f); /* Speed */ pos_ptr = hio_read16l(f); /* Positions pointer */ orn_ptr = hio_read16l(f); /* Ornaments pointer */ pat_ptr = hio_read16l(f); /* Patterns pointer */ hio_read(buf, 18, 1, f); /* Title */ copy_adjust(mod->name, (uint8 *)buf, 18); set_type(m, "ZX Spectrum Sound Tracker"); hio_read16l(f); /* Size */ /* Read orders */ hio_seek(f, pos_ptr, SEEK_SET); mod->len = hio_read8(f) + 1; for (num = i = 0; i < mod->len; i++) { stc_ord[i].pattern = hio_read8(f); stc_ord[i].height = hio_read8s(f); //printf("%d %d -- ", stc_ord[i].pattern, stc_ord[i].height); for (flag = j = 0; j < i; j++) { if (stc_ord[i].pattern == stc_ord[j].pattern && stc_ord[i].height == stc_ord[j].height) { mod->xxo[i] = mod->xxo[j]; flag = 1; break; } } if (!flag) { mod->xxo[i] = num++; } //printf("%d\n", mod->xxo[i]); } mod->chn = 3; mod->pat = num; mod->trk = mod->pat * mod->chn; mod->ins = 15; mod->smp = mod->ins; orn = (pat_ptr - orn_ptr) / 33; MODULE_INFO(); /* Read patterns */ if (pattern_init(mod) < 0) return -1; hio_seek(f, pat_ptr, SEEK_SET); decoded = calloc(mod->pat, sizeof(int)); D_(D_INFO "Stored patterns: %d ", mod->pat); for (i = 0; i < MAX_PAT; i++) { if (hio_read8(f) == 0xff) break; stc_pat[i].ch[0] = hio_read16l(f); stc_pat[i].ch[1] = hio_read16l(f); stc_pat[i].ch[2] = hio_read16l(f); } for (i = 0; i < mod->len; i++) { /* pattern */ int src = stc_ord[i].pattern - 1; int dest = mod->xxo[i]; int trans = stc_ord[i].height; if (decoded[dest]) continue; //printf("%d/%d) Read pattern %d -> %d\n", i, mod->len, src, dest); if (pattern_tracks_alloc(mod, dest, 64) < 0) return -1; for (j = 0; j < 3; j++) { /* row */ int row = 0; int x; int rowinc = 0; hio_seek(f, stc_pat[src].ch[j], SEEK_SET); do { for (;;) { x = hio_read8(f); if (x == 0xff) break; //printf("pat %d, channel %d, row %d, x = %02x\n", dest, j, row, x); event = &EVENT(dest, j, row); if (x <= 0x5f) { event->note = x + 18 + trans; row += 1 + rowinc; break; } if (x <= 0x6f) { event->ins = x - 0x5f - 1; } else if (x <= 0x7f) { /* ornament*/ event->fxt = FX_SYNTH_0; event->fxp = x - 0x70; } else if (x == 0x80) { event->note = XMP_KEY_OFF; row += 1 + rowinc; break; } else if (x == 0x81) { /* ? */ row += 1 + rowinc; } else if (x == 0x82) { /* disable ornament/envelope */ event->fxt = FX_SYNTH_0; event->fxp = 0; event->f2t = FX_SYNTH_2; event->f2p = 0; } else if (x <= 0x8e) { /* envelope */ event->fxt = FX_SYNTH_0 + x - 0x80; /* R13 */ event->fxp = hio_read8(f); /* R11 */ event->f2t = FX_SYNTH_1; event->f2p = hio_read8(f); /* R12 */ } else { rowinc = x - 0xa1; } } } while (x != 0xff); } decoded[dest] = 1; } free(decoded); /* Read instruments */ if (instrument_init(mod) < 0) return -1; hio_seek(f, 27, SEEK_SET); D_(D_INFO "Instruments: %d", mod->ins); for (i = 0; i < mod->ins; i++) { struct spectrum_sample ss; memset(&ss, 0, sizeof (struct spectrum_sample)); if (subinstrument_alloc(mod, i, 1) < 0) return -1; mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].vol = 0x40; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].xpo = -1; mod->xxi[i].sub[0].sid = i; hio_read(buf, 1, 99, f); if (buf[97] == 0) { ss.loop = 32; ss.length = 33; } else { ss.loop = buf[97] - 1; if (ss.loop > 31) ss.loop = 31; ss.length = buf[97] + buf[98]; if (ss.length > 32) ss.length = 32; if (ss.length == 0) ss.length = 1; if (ss.loop >= ss.length) ss.loop = ss.length - 1; if (ss.length < 32) { ss.length += 33 - (ss.loop + 1); ss.loop = 32; } } /* Read sample ticks */ for (j = 0; j < 31; j++) { struct spectrum_stick *sst = &ss.stick[j]; uint8 *chdata = &buf[1 + j * 3]; memset(sst, 0, sizeof (struct spectrum_stick)); if (~chdata[1] & 0x80) { sst->flags |= SPECTRUM_FLAG_MIXNOISE; sst->noise_env_inc = chdata[1] & 0x1f; if (sst->noise_env_inc & 0x10) sst->noise_env_inc |= 0xf0; } if (~chdata[1] & 0x40) sst->flags |= SPECTRUM_FLAG_MIXTONE; sst->vol = chdata[0] & 0x0f; sst->tone_inc = (((int)(chdata[0] & 0xf0)) << 4) | chdata[2]; if (~chdata[1] & 0x20) sst->tone_inc = -sst->tone_inc; sst->flags |= SPECTRUM_FLAG_ENVELOPE; /*if (j != 0) { reportv(ctx, 1, " "); } reportv(ctx, 1, "%02X %c%c%c %c%03x %x\n", j, sst->flags & SPECTRUM_FLAG_MIXTONE ? 'T' : 't', sst->flags & SPECTRUM_FLAG_MIXNOISE ? 'N' : 'n', sst->flags & SPECTRUM_FLAG_ENVELOPE ? 'E' : 'e', sst->tone_inc >= 0 ? '+' : '-', sst->tone_inc >= 0 ? sst->tone_inc : -sst->tone_inc, sst->vol);*/ } if (load_sample(m, f, SAMPLE_FLAG_SPECTRUM, &mod->xxs[i], (char *)&ss) < 0) { return -1; } } /* Read ornaments */ hio_seek(f, orn_ptr, SEEK_SET); m->extra = calloc(1, sizeof (struct spectrum_extra)); se = m->extra; D_(D_INFO "Ornaments: %d", orn); for (i = 0; i < orn; i++) { int index; struct spectrum_ornament *so; index = hio_read8(f); so = &se->ornament[index]; so->length = 32; so->loop = 31; for (j = 0; j < 32; j++) { so->val[j] = hio_read8s(f); } } for (i = 0; i < 4; i++) { mod->xxc[i].pan = 0x80; mod->xxc[i].flg = XMP_CHANNEL_SYNTH; } m->synth = &synth_spectrum; return 0; }
static int gtk_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; struct xmp_event *event; int i, j, k; uint8 buffer[40]; int rows, bits, c2spd, size; int ver, patmax; LOAD_INIT(); hio_read(buffer, 4, 1, f); ver = buffer[3]; hio_read(mod->name, 32, 1, f); set_type(m, "Graoumf Tracker GTK v%d", ver); hio_seek(f, 160, SEEK_CUR); /* skip comments */ mod->ins = hio_read16b(f); mod->smp = mod->ins; rows = hio_read16b(f); mod->chn = hio_read16b(f); mod->len = hio_read16b(f); mod->rst = hio_read16b(f); m->volbase = 0x100; MODULE_INFO(); D_(D_INFO "Instruments : %d ", mod->ins); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read(buffer, 28, 1, f); instrument_name(mod, i, buffer, 28); if (ver == 1) { hio_read32b(f); mod->xxs[i].len = hio_read32b(f); mod->xxs[i].lps = hio_read32b(f); size = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + size - 1; hio_read16b(f); hio_read16b(f); mod->xxi[i].sub[0].vol = 0xff; mod->xxi[i].sub[0].pan = 0x80; bits = 1; c2spd = 8363; } else { hio_seek(f, 14, SEEK_CUR); hio_read16b(f); /* autobal */ bits = hio_read16b(f); /* 1 = 8 bits, 2 = 16 bits */ c2spd = hio_read16b(f); c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); mod->xxs[i].len = hio_read32b(f); mod->xxs[i].lps = hio_read32b(f); size = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + size - 1; mod->xxi[i].sub[0].vol = hio_read16b(f); hio_read8(f); mod->xxi[i].sub[0].fin = hio_read8s(f); } if (mod->xxs[i].len > 0) mod->xxi[i].nsm = 1; mod->xxi[i].sub[0].sid = i; mod->xxs[i].flg = size > 2 ? XMP_SAMPLE_LOOP : 0; if (bits > 1) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } D_(D_INFO "[%2X] %-28.28s %05x%c%05x %05x %c " "V%02x F%+03d %5d", i, mod->xxi[i].name, mod->xxs[i].len, bits > 1 ? '+' : ' ', mod->xxs[i].lps, size, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin, c2spd); }
static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm) { struct xmp_module *mod = &m->mod; int i, c2spd; uint8 name[30]; mod->ins = mod->smp = hio_read16b(f); D_(D_INFO "Instruments : %d ", mod->ins); if (instrument_init(mod) < 0) return -1; for (i = 0; i < mod->ins; i++) { int fine, replen, flag; if (subinstrument_alloc(mod, i, 1) < 0) return -1; hio_read32b(f); /* reserved */ mod->xxs[i].len = hio_read32b(f); mod->xxi[i].nsm = !!mod->xxs[i].len; fine = hio_read8s(f); /* finetune */ mod->xxi[i].sub[0].vol = hio_read8(f); mod->xxi[i].sub[0].pan = 0x80; mod->xxs[i].lps = hio_read32b(f); replen = hio_read32b(f); mod->xxs[i].lpe = mod->xxs[i].lps + replen - 1; mod->xxs[i].flg = replen > 2 ? XMP_SAMPLE_LOOP : 0; hio_read(name, 22, 1, f); instrument_name(mod, i, name, 22); flag = hio_read16b(f); /* bit 0-7:resol 8:stereo */ if ((flag & 0xff) > 8) { mod->xxs[i].flg |= XMP_SAMPLE_16BIT; mod->xxs[i].len >>= 1; mod->xxs[i].lps >>= 1; mod->xxs[i].lpe >>= 1; } hio_read32b(f); /* midi note (0x00300000) */ c2spd = hio_read32b(f); /* frequency */ c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin); /* It's strange that we have both c2spd and finetune */ mod->xxi[i].sub[0].fin += fine; mod->xxi[i].sub[0].sid = i; D_(D_INFO "[%2X] %-22.22s %05x%c%05x %05x %c%c %2db V%02x F%+03d %5d", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ', mod->xxs[i].lps, replen, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', flag & 0x100 ? 'S' : ' ', flag & 0xff, mod->xxi[i].sub[0].vol, fine, c2spd); }
static int med3_load(struct module_data *m, HIO_HANDLE *f, const int start) { struct xmp_module *mod = &m->mod; int i, j; uint32 mask; int transp, sliding; LOAD_INIT(); hio_read32b(f); set_type(m, "MED 2.00 MED3"); mod->ins = mod->smp = 32; if (instrument_init(mod) < 0) return -1; /* read instrument names */ for (i = 0; i < 32; i++) { uint8 c, buf[40]; for (j = 0; j < 40; j++) { c = hio_read8(f); buf[j] = c; if (c == 0) break; } instrument_name(mod, i, buf, 32); if (subinstrument_alloc(mod, i, 1) < 0) return -1; } /* read instrument volumes */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { mod->xxi[i].sub[0].vol = mask & MASK ? hio_read8(f) : 0; mod->xxi[i].sub[0].pan = 0x80; mod->xxi[i].sub[0].fin = 0; mod->xxi[i].sub[0].sid = i; } /* read instrument loops */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { mod->xxs[i].lps = mask & MASK ? hio_read16b(f) : 0; } /* read instrument loop length */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { uint32 lsiz = mask & MASK ? hio_read16b(f) : 0; mod->xxs[i].len = mod->xxs[i].lps + lsiz; mod->xxs[i].lpe = mod->xxs[i].lps + lsiz; mod->xxs[i].flg = lsiz > 1 ? XMP_SAMPLE_LOOP : 0; } mod->chn = 4; mod->pat = hio_read16b(f); mod->trk = mod->chn * mod->pat; mod->len = hio_read16b(f); hio_read(mod->xxo, 1, mod->len, f); mod->spd = hio_read16b(f); if (mod->spd > 10) { mod->bpm = 125 * mod->spd / 33; mod->spd = 6; } transp = hio_read8s(f); hio_read8(f); /* flags */ sliding = hio_read16b(f); /* sliding */ hio_read32b(f); /* jumping mask */ hio_seek(f, 16, SEEK_CUR); /* rgb */ /* read midi channels */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (mask & MASK) hio_read8(f); } /* read midi programs */ mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (mask & MASK) hio_read8(f); } MODULE_INFO(); D_(D_INFO "Sliding: %d", sliding); D_(D_INFO "Play transpose: %d", transp); if (sliding == 6) m->quirk |= QUIRK_VSALL | QUIRK_PBALL; for (i = 0; i < 32; i++) mod->xxi[i].sub[0].xpo = transp; if (pattern_init(mod) < 0) return -1; /* Load and convert patterns */ D_(D_INFO "Stored patterns: %d", mod->pat); for (i = 0; i < mod->pat; i++) { uint32 *conv; uint8 b, tracks; uint16 convsz; if (pattern_tracks_alloc(mod, i, 64) < 0) return -1; tracks = hio_read8(f); b = hio_read8(f); convsz = hio_read16b(f); conv = calloc(1, convsz + 16); if (conv == NULL) return -1; if (b & M0F_LINEMSK00) *conv = 0L; else if (b & M0F_LINEMSK0F) *conv = 0xffffffff; else *conv = hio_read32b(f); if (b & M0F_LINEMSK10) *(conv + 1) = 0L; else if (b & M0F_LINEMSK1F) *(conv + 1) = 0xffffffff; else *(conv + 1) = hio_read32b(f); if (b & M0F_FXMSK00) *(conv + 2) = 0L; else if (b & M0F_FXMSK0F) *(conv + 2) = 0xffffffff; else *(conv + 2) = hio_read32b(f); if (b & M0F_FXMSK10) *(conv + 3) = 0L; else if (b & M0F_FXMSK1F) *(conv + 3) = 0xffffffff; else *(conv + 3) = hio_read32b(f); hio_read(conv + 4, 1, convsz, f); if (unpack_block(m, i, (uint8 *)conv) < 0) { free(conv); return -1; } free(conv); } /* Load samples */ D_(D_INFO "Instruments: %d", mod->ins); mask = hio_read32b(f); for (i = 0; i < 32; i++, mask <<= 1) { if (~mask & MASK) continue; mod->xxi[i].nsm = 1; mod->xxs[i].len = hio_read32b(f); if (mod->xxs[i].len == 0) mod->xxi[i].nsm = 0; if (hio_read16b(f)) /* type */ continue; D_(D_INFO "[%2X] %-32.32s %04x %04x %04x %c V%02x ", i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ', mod->xxi[i].sub[0].vol); if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0) return -1; } return 0; }
static int 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; }