Пример #1
0
static int s3m_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 = 0, dummy;
    struct s3m_file_header sfh;
    struct s3m_instrument_header sih;
#ifndef LIBXMP_CORE_PLAYER
    struct s3m_adlib_header sah;
    char tracker_name[40];
    int quirk87 = 0;
#endif
    int pat_len;
    uint8 n, b, x8;
    uint16 *pp_ins;		/* Parapointers to instruments */
    uint16 *pp_pat;		/* Parapointers to patterns */
    int ret;

    LOAD_INIT();

    hio_read(&sfh.name, 28, 1, f);	/* Song name */
    hio_read8(f);			/* 0x1a */
    sfh.type = hio_read8(f);		/* File type */
    hio_read16l(f);			/* Reserved */
    sfh.ordnum = hio_read16l(f);	/* Number of orders (must be even) */
    sfh.insnum = hio_read16l(f);	/* Number of instruments */
    sfh.patnum = hio_read16l(f);	/* Number of patterns */
    sfh.flags = hio_read16l(f);		/* Flags */
    sfh.version = hio_read16l(f);	/* Tracker ID and version */
    sfh.ffi = hio_read16l(f);		/* File format information */

    /* Sanity check */
    if (sfh.ffi != 1 && sfh.ffi != 2) {
	goto err;
    }
    if (sfh.ordnum > 255 || sfh.insnum > 255 || sfh.patnum > 255) {
	goto err;
    }

    sfh.magic = hio_read32b(f);		/* 'SCRM' */
    sfh.gv = hio_read8(f);		/* Global volume */
    sfh.is = hio_read8(f);		/* Initial speed */
    sfh.it = hio_read8(f);		/* Initial tempo */
    sfh.mv = hio_read8(f);		/* Master volume */
    sfh.uc = hio_read8(f);		/* Ultra click removal */
    sfh.dp = hio_read8(f);		/* Default pan positions if 0xfc */
    hio_read32l(f);			/* Reserved */
    hio_read32l(f);			/* Reserved */
    sfh.special = hio_read16l(f);	/* Ptr to special custom data */
    hio_read(sfh.chset, 32, 1, f);	/* Channel settings */

#if 0
    if (sfh.magic != MAGIC_SCRM)
	return -1;
#endif

#ifndef LIBXMP_CORE_PLAYER
    /* S3M anomaly in return_of_litmus.s3m */
    if (sfh.version == 0x1301 && sfh.name[27] == 0x87)
	quirk87 = 1;

    if (quirk87) {
	fix87(sfh.name);
	fix87(sfh.patnum);
	fix87(sfh.flags);
    }
#endif

    copy_adjust(mod->name, sfh.name, 28);

    pp_ins = calloc(2, sfh.insnum);
    if (pp_ins == NULL)
	goto err;

    pp_pat = calloc (2, sfh.patnum);
    if (pp_pat == NULL)
	goto err2;

    if (sfh.flags & S3M_AMIGA_RANGE)
	m->quirk |= QUIRK_MODRNG;
    if (sfh.flags & S3M_ST300_VOLS)
	m->quirk |= QUIRK_VSALL;
    /* m->volbase = 4096 / sfh.gv; */
    mod->spd = sfh.is;
    mod->bpm = sfh.it;
    mod->chn = 0;
    
    for (i = 0; i < 32; i++) {
	if (sfh.chset[i] == S3M_CH_OFF)
	    continue;

	mod->chn = i + 1;

	if (sfh.mv & 0x80) {	/* stereo */
		int x = sfh.chset[i] & S3M_CH_PAN;
		mod->xxc[i].pan = (x & 0x0f) < 8 ? 0x30 : 0xc0;
	} else {
		mod->xxc[i].pan = 0x80;
	}
    }

    if (sfh.ordnum <= XMP_MAX_MOD_LENGTH) {
	mod->len = sfh.ordnum;
	hio_read(mod->xxo, 1, mod->len, f);
    } else {
	mod->len = XMP_MAX_MOD_LENGTH;
	hio_read(mod->xxo, 1, mod->len, f);
	hio_seek(f, sfh.ordnum - XMP_MAX_MOD_LENGTH, SEEK_CUR);
    }

    mod->pat = -1;
    for (i = 0; i < mod->len && mod->xxo[i] < 0xff; ++i) {
	if (mod->xxo[i] > mod->pat)
            mod->pat = mod->xxo[i];
    }
    mod->pat++;
    if (mod->pat > sfh.patnum)
	mod->pat = sfh.patnum;
    if (mod->pat == 0)
	goto err3;

    mod->trk = mod->pat * mod->chn;
    /* Load and convert header */
    mod->ins = sfh.insnum;
    mod->smp = mod->ins;

    for (i = 0; i < sfh.insnum; i++)
	pp_ins[i] = hio_read16l(f);
 
    for (i = 0; i < sfh.patnum; i++)
	pp_pat[i] = hio_read16l(f);

    /* Default pan positions */

    for (i = 0, sfh.dp -= 0xfc; !sfh.dp /* && n */ && (i < 32); i++) {
	uint8 x = hio_read8(f);
	if (x & S3M_PAN_SET)
	    mod->xxc[i].pan = (x << 4) & 0xff;
	else
	    mod->xxc[i].pan = sfh.mv % 0x80 ? 0x30 + 0xa0 * (i & 1) : 0x80;
    }

    m->c4rate = C4_NTSC_RATE;

    if (sfh.version == 0x1300)
	m->quirk |= QUIRK_VSALL;

#ifndef LIBXMP_CORE_PLAYER
    switch (sfh.version >> 12) {
    case 1:
	snprintf(tracker_name, 40, "Scream Tracker %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	m->quirk |= QUIRK_ST3GVOL;
	break;
    case 2:
	snprintf(tracker_name, 40, "Imago Orpheus %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    case 3:
	if (sfh.version == 0x3216) {
		strcpy(tracker_name, "Impulse Tracker 2.14v3");
	} else if (sfh.version == 0x3217) {
		strcpy(tracker_name, "Impulse Tracker 2.14v5");
	} else {
		snprintf(tracker_name, 40, "Impulse Tracker %d.%02x",
			(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	}
	break;
    case 5:
	snprintf(tracker_name, 40, "OpenMPT %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    case 4:
	if (sfh.version != 0x4100) {
		snprintf(tracker_name, 40, "Schism Tracker %d.%02x",
			(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
		break;
	}
	/* fall through */
    case 6:
	snprintf(tracker_name, 40, "BeRoTracker %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    default:
	snprintf(tracker_name, 40, "unknown (%04x)", sfh.version);
    }
Пример #2
0
static int s3m_load(struct module_data *m, FILE *f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int c, r, i;
    struct s3m_adlib_header sah;
    struct xmp_event *event = 0, dummy;
    struct s3m_file_header sfh;
    struct s3m_instrument_header sih;
    int pat_len;
    uint8 n, b, x8;
    char tracker_name[40];
    int quirk87 = 0;
    uint16 *pp_ins;		/* Parapointers to instruments */
    uint16 *pp_pat;		/* Parapointers to patterns */
    uint8 arpeggio_val[32];

    LOAD_INIT();

    fread(&sfh.name, 28, 1, f);		/* Song name */
    read8(f);				/* 0x1a */
    sfh.type = read8(f);		/* File type */
    read16l(f);				/* Reserved */
    sfh.ordnum = read16l(f);		/* Number of orders (must be even) */
    sfh.insnum = read16l(f);		/* Number of instruments */
    sfh.patnum = read16l(f);		/* Number of patterns */
    sfh.flags = read16l(f);		/* Flags */
    sfh.version = read16l(f);		/* Tracker ID and version */
    sfh.ffi = read16l(f);		/* File format information */
    sfh.magic = read32b(f);		/* 'SCRM' */
    sfh.gv = read8(f);			/* Global volume */
    sfh.is = read8(f);			/* Initial speed */
    sfh.it = read8(f);			/* Initial tempo */
    sfh.mv = read8(f);			/* Master volume */
    sfh.uc = read8(f);			/* Ultra click removal */
    sfh.dp = read8(f);			/* Default pan positions if 0xfc */
    read32l(f);				/* Reserved */
    read32l(f);				/* Reserved */
    sfh.special = read16l(f);		/* Ptr to special custom data */
    fread(sfh.chset, 32, 1, f);		/* Channel settings */

#if 0
    if (sfh.magic != MAGIC_SCRM)
	return -1;
#endif

    /* S3M anomaly in return_of_litmus.s3m */
    if (sfh.version == 0x1301 && sfh.name[27] == 0x87)
	quirk87 = 1;

    if (quirk87) {
	fix87(sfh.name);
	fix87(sfh.patnum);
	fix87(sfh.flags);
    }

    copy_adjust(mod->name, sfh.name, 28);

    /* Load and convert header */
    mod->len = sfh.ordnum;
    mod->ins = sfh.insnum;
    mod->smp = mod->ins;
    mod->pat = sfh.patnum;
    pp_ins = calloc (2, mod->ins);
    pp_pat = calloc (2, mod->pat);
    if (sfh.flags & S3M_AMIGA_RANGE)
	m->quirk |= QUIRK_MODRNG;
    if (sfh.flags & S3M_ST300_VOLS)
	m->quirk |= QUIRK_VSALL;
    /* m->volbase = 4096 / sfh.gv; */
    mod->spd = sfh.is;
    mod->bpm = sfh.it;

    for (i = 0; i < 32; i++) {
	if (sfh.chset[i] == S3M_CH_OFF)
	    continue;

	mod->chn = i + 1;

	if (sfh.mv & 0x80) {	/* stereo */
		int x = sfh.chset[i] & S3M_CH_PAN;
		mod->xxc[i].pan = (x & 0x0f) < 8 ? 0x00 : 0xff;
	} else {
		mod->xxc[i].pan = 0x80;
	}
    }
    mod->trk = mod->pat * mod->chn;

    fread(mod->xxo, 1, mod->len, f);

    for (i = 0; i < mod->ins; i++)
	pp_ins[i] = read16l(f);
 
    for (i = 0; i < mod->pat; i++)
	pp_pat[i] = read16l(f);

    /* Default pan positions */

    for (i = 0, sfh.dp -= 0xfc; !sfh.dp /* && n */ && (i < 32); i++) {
	uint8 x = read8(f);
	if (x & S3M_PAN_SET)
	    mod->xxc[i].pan = (x << 4) & 0xff;
	else
	    mod->xxc[i].pan = sfh.mv % 0x80 ? 0x30 + 0xa0 * (i & 1) : 0x80;
    }

    m->c4rate = C4_NTSC_RATE;

    if (sfh.version == 0x1300)
	m->quirk |= QUIRK_VSALL;

    switch (sfh.version >> 12) {
    case 1:
	snprintf(tracker_name, 40, "Scream Tracker %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	m->quirk |= QUIRK_ST3GVOL;
	break;
    case 2:
	snprintf(tracker_name, 40, "Imago Orpheus %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    case 3:
	if (sfh.version == 0x3216) {
		strcpy(tracker_name, "Impulse Tracker 2.14v3");
	} else if (sfh.version == 0x3217) {
		strcpy(tracker_name, "Impulse Tracker 2.14v5");
	} else {
		snprintf(tracker_name, 40, "Impulse Tracker %d.%02x",
			(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	}
	break;
    case 4:
	snprintf(tracker_name, 40, "Schism Tracker %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    case 5:
	snprintf(tracker_name, 40, "OpenMPT %d.%02x",
		(sfh.version & 0x0f00) >> 8, sfh.version & 0xff);
	break;
    default:
	snprintf(tracker_name, 40, "unknown (%04x)", sfh.version);
    }

    snprintf(mod->type, XMP_NAME_SIZE, "%s S3M", tracker_name);

    MODULE_INFO();

    PATTERN_INIT();

    /* Read patterns */

    D_(D_INFO "Stored patterns: %d", mod->pat);

    memset (arpeggio_val, 0, 32);

    for (i = 0; i < mod->pat; i++) {
	PATTERN_ALLOC (i);
	mod->xxp[i]->rows = 64;
	TRACK_ALLOC (i);

	if (!pp_pat[i])
	    continue;

	fseek(f, start + pp_pat[i] * 16, SEEK_SET);
	r = 0;
	pat_len = read16l(f) - 2;

	/* Used to be (--pat_len >= 0). Replaced by Rudolf Cejka
	 * <*****@*****.**>, fixes hunt.s3m
	 * ftp://us.aminet.net/pub/aminet/mods/8voic/s3m_hunt.lha
	 */
	while (r < mod->xxp[i]->rows) {
	    b = read8(f);

	    if (b == S3M_EOR) {
		r++;
		continue;
	    }

	    c = b & S3M_CH_MASK;
	    event = c >= mod->chn ? &dummy : &EVENT (i, c, r);

	    if (b & S3M_NI_FOLLOW) {
		switch(n = read8(f)) {
		case 255:
		    n = 0;
		    break;	/* Empty note */
		case 254:
		    n = XMP_KEY_OFF;
		    break;	/* Key off */
		default:
		    n = 13 + 12 * MSN (n) + LSN (n);
		}
		event->note = n;
		event->ins = read8(f);
		pat_len -= 2;
	    }

	    if (b & S3M_VOL_FOLLOWS) {
		event->vol = read8(f) + 1;
		pat_len--;
	    }

	    if (b & S3M_FX_FOLLOWS) {
		event->fxt = read8(f);
		event->fxp = read8(f);
		xlat_fx(c, event, arpeggio_val);
		pat_len -= 2;
	    }
	}
    }

    D_(D_INFO "Stereo enabled: %s", sfh.mv & 0x80 ? "yes" : "no");
    D_(D_INFO "Pan settings: %s", sfh.dp ? "no" : "yes");

    INSTRUMENT_INIT();

    /* Read and convert instruments and samples */

    D_(D_INFO "Instruments: %d", mod->ins);

    for (i = 0; i < mod->ins; i++) {
	mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1);
	fseek(f, start + pp_ins[i] * 16, SEEK_SET);
	x8 = read8(f);
	mod->xxi[i].sub[0].pan = 0x80;
	mod->xxi[i].sub[0].sid = i;

	if (x8 >= 2) {
	    /* OPL2 FM instrument */

	    fread(&sah.dosname, 12, 1, f);	/* DOS file name */
	    fread(&sah.rsvd1, 3, 1, f);		/* 0x00 0x00 0x00 */
	    fread(&sah.reg, 12, 1, f);		/* Adlib registers */
	    sah.vol = read8(f);
	    sah.dsk = read8(f);
	    read16l(f);
	    sah.c2spd = read16l(f);		/* C 4 speed */
	    read16l(f);
	    fread(&sah.rsvd4, 12, 1, f);	/* Reserved */
	    fread(&sah.name, 28, 1, f);		/* Instrument name */
	    sah.magic = read32b(f);		/* 'SCRI' */

	    if (sah.magic != MAGIC_SCRI) {
		D_(D_CRIT "error: FM instrument magic");
		return -2;
	    }
	    sah.magic = 0;

	    copy_adjust(mod->xxi[i].name, sah.name, 28);

	    mod->xxi[i].nsm = 1;
	    mod->xxi[i].sub[0].vol = sah.vol;
	    c2spd_to_note(sah.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
	    mod->xxi[i].sub[0].xpo += 12;
	    load_sample(f, SAMPLE_FLAG_ADLIB, &mod->xxs[i], (char *)&sah.reg);
	    D_(D_INFO "[%2X] %-28.28s", i, mod->xxi[i].name);

	    continue;
	}

	fread(&sih.dosname, 13, 1, f);		/* DOS file name */
	sih.memseg = read16l(f);		/* Pointer to sample data */
	sih.length = read32l(f);		/* Length */
	sih.loopbeg = read32l(f);		/* Loop begin */
	sih.loopend = read32l(f);		/* Loop end */
	sih.vol = read8(f);			/* Volume */
	sih.rsvd1 = read8(f);			/* Reserved */
	sih.pack = read8(f);			/* Packing type (not used) */
	sih.flags = read8(f);		/* Loop/stereo/16bit samples flags */
	sih.c2spd = read16l(f);			/* C 4 speed */
	sih.rsvd2 = read16l(f);			/* Reserved */
	fread(&sih.rsvd3, 4, 1, f);		/* Reserved */
	sih.int_gp = read16l(f);		/* Internal - GUS pointer */
	sih.int_512 = read16l(f);		/* Internal - SB pointer */
	sih.int_last = read32l(f);		/* Internal - SB index */
	fread(&sih.name, 28, 1, f);		/* Instrument name */
	sih.magic = read32b(f);			/* 'SCRS' */

	if (x8 == 1 && sih.magic != MAGIC_SCRS) {
	    D_(D_CRIT "error: instrument magic");
	    return -2;
	}

	if (quirk87) {
	    fix87(sih.length);
	    fix87(sih.loopbeg);
	    fix87(sih.loopend);
	    fix87(sih.flags);
	}

	mod->xxs[i].len = sih.length;
	mod->xxi[i].nsm = sih.length > 0 ? 1 : 0;
	mod->xxs[i].lps = sih.loopbeg;
	mod->xxs[i].lpe = sih.loopend;

	mod->xxs[i].flg = sih.flags & 1 ? XMP_SAMPLE_LOOP : 0;

	if (sih.flags & 4) {
	    mod->xxs[i].flg |= XMP_SAMPLE_16BIT;
	    mod->xxs[i].len >>= 1;
	    mod->xxs[i].lps >>= 1;
	    mod->xxs[i].lpe >>= 1;
	}

	mod->xxi[i].sub[0].vol = sih.vol;
	sih.magic = 0;

	copy_adjust(mod->xxi[i].name, sih.name, 28);

	D_(D_INFO "[%2X] %-28.28s %04x%c%04x %04x %c V%02x %5d",
			i, mod->xxi[i].name, mod->xxs[i].len,
			mod->xxs[i].flg & XMP_SAMPLE_16BIT ?'+' : ' ',
			mod->xxs[i].lps, mod->xxs[i].lpe,
			mod->xxs[i].flg & XMP_SAMPLE_LOOP ?  'L' : ' ',
			mod->xxi[i].sub[0].vol, sih.c2spd);

	c2spd_to_note(sih.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);

	fseek(f, start + 16L * sih.memseg, SEEK_SET);
	load_sample(f, (sfh.ffi - 1) * SAMPLE_FLAG_UNS, &mod->xxs[i], NULL);
    }