/* Extended Module Player * Copyright (C) 1996-1999 Claudio Matsuoka and Hipolito Carraro Jr * * This file is part of the Extended Module Player and is distributed * under the terms of the GNU General Public License. See doc/COPYING * for more information. */ /* Ultimate Soundtracker support based on the module format description * written by Michael Schwendt */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "load.h" #include "mod.h" #include "period.h" int st_load (FILE *f) { int i, j; int smp_size, hdr_size, pat_size; struct xxm_event *event; struct st_header mh; uint8 mod_event[4]; int ust = 1, nt = 0, serr = 0; /* int lps_mult = xmp_ctl->fetch & XMP_CTL_FIXLOOP ? 1 : 2; */ char *modtype; int fxused; LOAD_INIT (); xxh->ins = 15; xxh->smp = xxh->ins; smp_size = 0; pat_size = 0; //lps_mult = 1; hdr_size = sizeof (struct st_header); fread (&mh, 1, sizeof (struct st_header), f); xxh->len = mh.len; xxh->rst = mh.restart; /* UST: The byte at module offset 471 is BPM, not the song restart */ if (xxh->rst < 0x20) ust = 0; #if 0 if (xxh->rst == 0x78) /* Is it correct? */ nt = 1; #endif if (xxh->rst >= xxh->len) xxh->rst = 0; memcpy (xxo, mh.order, 128); for (i = 0; i < 128; i++) if (xxo[i] > xxh->pat) xxh->pat = xxo[i]; xxh->pat++; if (xxh->pat > 0x7f || xxh->len == 0 || xxh->len > 0x7f) return -1; pat_size = 256 * xxh->chn * xxh->pat; for (i = 0; i < xxh->ins; i++) { B_ENDIAN16 (mh.ins[i].size); B_ENDIAN16 (mh.ins[i].loop_start); B_ENDIAN16 (mh.ins[i].loop_size); if (mh.ins[i].volume > 0x40) return -1; if (mh.ins[i].finetune > 0x0f) return -1; /* UST: Volume word does not contain a "Finetuning" value in its * high-byte. */ if (mh.ins[i].finetune) ust = 0; if (mh.ins[i].size > 0x8000 || (mh.ins[i].loop_start >> 1) > 0x8000 || mh.ins[i].loop_size > 0x8000) return -1; if (mh.ins[i].loop_size > 1 && mh.ins[i].loop_size > mh.ins[i].size) return -1; if ((mh.ins[i].loop_start >> 1) > mh.ins[i].size) return -1; if (mh.ins[i].size && (mh.ins[i].loop_start >> 1) == mh.ins[i].size) return -1; if (mh.ins[i].size == 0 && mh.ins[i].loop_start > 0) return -1; if (mh.ins[i].size == 0 && mh.ins[i].loop_size == 1) nt = 1; /* UST: Maximum sample length is 9999 bytes decimal, but 1387 words * hexadecimal. Longest samples on original sample disk ST-01 were * 9900 bytes. */ if (mh.ins[i].size > 0x1387 || mh.ins[i].loop_start > 9999 || mh.ins[i].loop_size > 0x1387) ust = 0; smp_size += 2 * mh.ins[i].size; } if (smp_size < 8) return -1; /* Relaxed limit -- was 4 */ if (abs (serr = xmp_ctl->size - (600 + xxh->pat*1024 + smp_size)) > 8192) return -1; INSTRUMENT_INIT (); for (i = 0; i < xxh->ins; i++) { xxi[i] = calloc (sizeof (struct xxm_instrument), 1); xxs[i].len = 2 * mh.ins[i].size; xxs[i].lps = mh.ins[i].loop_start; xxs[i].lpe = xxs[i].lps + 2 * mh.ins[i].loop_size; xxs[i].flg = mh.ins[i].loop_size > 1 ? WAVE_LOOPING : 0; xxi[i][0].fin = (int8)(mh.ins[i].finetune << 4); xxi[i][0].vol = mh.ins[i].volume; xxi[i][0].pan = 0x80; xxi[i][0].sid = i; xxih[i].nsm = !!(xxs[i].len); strncpy (xxih[i].name, mh.ins[i].name, 22); str_adj (xxih[i].name); } #if 0 /* Another filter for Soundtracker modules */ if (xxh->ins == 15 && sizeof (struct st_header) + pat_size + smp_size > xmp_ctl->size) return -1; #endif xxh->trk = xxh->chn * xxh->pat; strncpy (xmp_ctl->name, (char *) mh.name, 20); if (nt) strcpy (tracker_name, "Sound/Noisetracker"); else strcpy (tracker_name, "old Soundtracker"); strcpy (xmp_ctl->type, "15 instrument module"); MODULE_INFO (); if (serr && V(0)) report ("File size error: %d\n", serr); PATTERN_INIT (); /* Load and convert patterns */ fxused = 0; if (V(0)) report ("Stored patterns: %d ", xxh->pat); for (i = 0; i < xxh->pat; i++) { PATTERN_ALLOC (i); xxp[i]->rows = 64; TRACK_ALLOC (i); for (j = 0; j < (64 * xxh->chn); j++) { event = &EVENT (i, j % xxh->chn, j / xxh->chn); fread (mod_event, 1, 4, f); cvt_pt_event (event, mod_event); if (event->fxt) fxused |= 1 << event->fxt; else if (event->fxp) fxused |= 1; /* UST: Only effects 1 (arpeggio) and 2 (pitchbend) are * available. */ if (event->fxt != 1 && event->fxp != 2) ust = 0; /* Special translation for e8 (set panning) effect. * This is not an official Protracker effect but DMP uses * it for panning, and a couple of modules follow this * "standard". */ if ((event->fxt == 0x0e) && ((event->fxp & 0xf0) == 0x80)) { event->fxt = FX_SETPAN; event->fxp <<= 4; } } if (V (0)) report ("."); } if (fxused == 0) modtype = "MasterSoundtracker 1.1"; else if ((fxused & ~0x0006) == 0) modtype = "Ultimate Soundtracker"; else if ((fxused & ~0xd007) == 0) modtype = "Soundtracker IX"; else if ((fxused & ~0xf807) == 0) modtype = "D.O.C. Soundtracker"; else if ((fxused & ~0xfc07) == 0) modtype = "Soundtracker 2.3/2.4"; else if ((fxused & ~0xfc3f) == 0) modtype = "Noisetracker 1.0/1.2"; else if ((fxused & ~0xfcbf) == 0) modtype = "Noisetracker 2.0"; else if ((fxused & ~0xfeff) == 0) modtype = "Protracker"; else modtype = NULL; if (V (0)) { if (modtype) report ("\nCompatibility : %s\n", modtype); } if (V (1)) report (" Instrument name Len LBeg LEnd L Vol Fin\n"); for (i = 0; (V (1)) && (i < xxh->ins); i++) { if ((strlen ((char *) xxih[i].name) || (xxs[i].len > 2))) report ("[%2X] %-22.22s %04x %04x %04x %c V%02x %+d\n", i, xxih[i].name, xxs[i].len, xxs[i].lps, xxs[i].lpe, mh.ins[i].loop_size > 1 ? 'L' : ' ', xxi[i][0].vol, (char) xxi[i][0].fin >> 4); } xxh->flg |= XXM_FLG_MODRNG; /* Perform the necessary conversions for Ultimate Soundtracker */ if (ust) { /* Fix restart & bpm */ /* Fix sample loops */ /* Fix effects */ } /* Load samples */ if (V (0)) report ("Stored samples : %d ", xxh->smp); for (i = 0; i < xxh->smp; i++) { if (!xxs[i].len) continue; xmp_drv_loadpatch (f, xxi[i][0].sid, xmp_ctl->c4rate, 0, &xxs[xxi[i][0].sid], NULL); if (V (0)) report ("."); } if (V (0)) report ("\n"); return 0; }