コード例 #1
0
void cvt_pt_event(struct xxm_event *event, uint8 *mod_event)
{
	event->note = period_to_note((LSN(mod_event[0]) << 8) + mod_event[1]);
	event->ins = ((MSN(mod_event[0]) << 4) | MSN(mod_event[2]));
	event->fxt = LSN(mod_event[2]);
	event->fxp = mod_event[3];

	disable_continue_fx(event);
}
コード例 #2
0
ファイル: common.c プロジェクト: B0rschti/libxmp-4.3.0
void decode_protracker_event(struct xmp_event *event, uint8 *mod_event)
{
	int fxt = LSN(mod_event[2]);

	memset(event, 0, sizeof (struct xmp_event));
	event->note = period_to_note((LSN(mod_event[0]) << 8) + mod_event[1]);
	event->ins = ((MSN(mod_event[0]) << 4) | MSN(mod_event[2]));

	if (fxt != 0x08) {
		event->fxt = fxt;
		event->fxp = mod_event[3];
	}

	disable_continue_fx(event);
}
コード例 #3
0
ファイル: s3m_load.c プロジェクト: bithorder/libxmp
/* Effect translation */
static void xlat_fx(int c, struct xmp_event *e, uint8 *arpeggio_val)
{
    uint8 h = MSN (e->fxp), l = LSN (e->fxp);

    switch (e->fxt = fx[e->fxt]) {
    case FX_ARPEGGIO:			/* Arpeggio */
        if (e->fxp)
            arpeggio_val[c] = e->fxp;
        else
            e->fxp = arpeggio_val[c];
        break;
    case FX_S3M_EXTENDED:		/* Extended effects */
        e->fxt = FX_EXTENDED;
        switch (h) {
        case 0x1:			/* Glissando */
            e->fxp = LSN (e->fxp) | (EX_GLISS << 4);
            break;
        case 0x2:			/* Finetune */
            e->fxp = LSN (e->fxp) | (EX_FINETUNE << 4);
            break;
        case 0x3:			/* Vibrato wave */
            e->fxp = LSN (e->fxp) | (EX_VIBRATO_WF << 4);
            break;
        case 0x4:			/* Tremolo wave */
            e->fxp = LSN (e->fxp) | (EX_TREMOLO_WF << 4);
            break;
        case 0x5:
        case 0x6:
        case 0x7:
        case 0x9:
        case 0xa:			/* Ignore */
            e->fxt = e->fxp = 0;
            break;
        case 0x8:			/* Set pan */
            e->fxt = FX_MASTER_PAN;
            e->fxp = l << 4;
            break;
        case 0xb:			/* Pattern loop */
            e->fxp = LSN (e->fxp) | (EX_PATTERN_LOOP << 4);
            break;
        case 0xc:
            if (!l)
                e->fxt = e->fxp = 0;
        }
        break;
    case NONE:				/* No effect */
        e->fxt = e->fxp = 0;
        break;
    }
}
コード例 #4
0
ファイル: hsc_load.c プロジェクト: bithorder/libxmp
static int hsc_test(xmp_file f, char *t, const int start)
{
    int p, i, r, c;
    uint8 buf[1200];

    xmp_fseek(f, 128 * 12, SEEK_CUR);

    if (xmp_fread(buf, 1, 51, f) != 51)
	return -1;

    for (p = i = 0; i < 51; i++) {
	if (buf[i] == 0xff)
	    break;
	if (buf[i] > p)
	    p = buf[i];
    }
    if (!i || !p || i > 50 || p > 50)		/* Test number of patterns */
	return -1;		

    for (i = 0; i < p; i++) {
	xmp_fread(buf, 1, 64 * 9 * 2, f);
	for (r = 0; r < 64; r++) {
	    for (c = 0; c < 9; c++) {
		uint8 n = buf[r * 9 * 2 + c * 2];
		uint8 m = buf[r * 9 * 2 + c * 2 + 1];
		if (m > 0x06 && m < 0x10 && n != 0x80)	/* Test effects 07..0f */
		    return -1;
		if (MSN(m) > 6 && MSN(m) < 10)	/* Test effects 7x .. 9x */
		    return -1;
	    }
	}
    }

    read_title(f, t, 0);

    return 0;
}
コード例 #5
0
ファイル: med4_load.c プロジェクト: bithorder/libxmp
static void fix_effect(struct xmp_event *event)
{
	switch (event->fxt) {
	case 0x00:	/* arpeggio */
	case 0x01:	/* slide up */
	case 0x02:	/* slide down */
	case 0x03:	/* portamento */
	case 0x04:	/* vibrato? */
		break;
	case 0x0c:	/* set volume (BCD) */
		event->fxp = MSN(event->fxp) * 10 +
					LSN(event->fxp);
		break;
	case 0x0d:	/* volume slides */
		event->fxt = FX_VOLSLIDE;
		break;
	case 0x0f:	/* tempo/break */
		if (event->fxp == 0)
			event->fxt = FX_BREAK;
		if (event->fxp == 0xff) {
			event->fxp = event->fxt = 0;
			event->vol = 1;
		} else if (event->fxp == 0xfe) {
			event->fxp = event->fxt = 0;
		} else if (event->fxp == 0xf1) {
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_RETRIG << 4) | 3;
		} else if (event->fxp == 0xf2) {
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_CUT << 4) | 3;
		} else if (event->fxp == 0xf3) {
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_DELAY << 4) | 3;
		} else if (event->fxp > 10) {
			event->fxt = FX_S3M_BPM;
			event->fxp = 125 * event->fxp / 33;
		}
		break;
	default:
		event->fxp = event->fxt = 0;
	}
}
コード例 #6
0
ファイル: mdl_load.c プロジェクト: cmatsuoka/chiptune.js
static void xlat_fx_common(uint8 *t, uint8 *p)
{
    switch (*t) {
    case 0x00:			/* - - No effect */
	*p = 0;
	break;
    case 0x07:			/* 7 - Set BPM */
	*t = FX_S3M_BPM;
	break;
    case 0x08:			/* 8 - Set pan */
    case 0x09:			/* 9 - Set envelope -- not supported */
    case 0x0a:			/* A - Not used */
	*t = *p = 0x00;
	break;
    case 0x0b:			/* B - Position jump */
    case 0x0c:			/* C - Set volume */
    case 0x0d:			/* D - Pattern break */
	/* Like protracker */
	break;
    case 0x0e:			/* E - Extended */
	switch (MSN (*p)) {
	case 0x0:		/* E0 - not used */
	case 0x3:		/* E3 - not used */
	case 0x8:		/* Set sample status -- unsupported */
	    *t = *p = 0x00;
	    break;
	case 0x1:		/* Pan slide left */
	    *t = FX_PANSLIDE;
	    *p <<= 4;
	    break;
	case 0x2:		/* Pan slide right */
	    *t = FX_PANSLIDE;
	    *p &= 0x0f;
	    break;
	}
	break;
    case 0x0f:
	*t = FX_S3M_SPEED;
	break;
    }
}
コード例 #7
0
ファイル: mgt_load.c プロジェクト: djdron/zxtune
static int mgt_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_event *event;
	int i, j;
	int ver;
	int sng_ptr, seq_ptr, ins_ptr, pat_ptr, trk_ptr, smp_ptr;
	int sdata[64];

	LOAD_INIT();

	hio_read24b(f);		/* MGT */
	ver = hio_read8(f);
	hio_read32b(f);		/* MCS */

	set_type(m, "Megatracker MGT v%d.%d", MSN(ver), LSN(ver));

	mod->chn = hio_read16b(f);
	hio_read16b(f);			/* number of songs */
	mod->len = hio_read16b(f);
	mod->pat = hio_read16b(f);
	mod->trk = hio_read16b(f);
	mod->ins = mod->smp = hio_read16b(f);
	hio_read16b(f);			/* reserved */
	hio_read32b(f);			/* reserved */

	sng_ptr = hio_read32b(f);
	seq_ptr = hio_read32b(f);
	ins_ptr = hio_read32b(f);
	pat_ptr = hio_read32b(f);
	trk_ptr = hio_read32b(f);
	smp_ptr = hio_read32b(f);
	hio_read32b(f);			/* total smp len */
	hio_read32b(f);			/* unpacked trk size */

	hio_seek(f, start + sng_ptr, SEEK_SET);

	hio_read(mod->name, 1, 32, f);
	seq_ptr = hio_read32b(f);
	mod->len = hio_read16b(f);
	mod->rst = hio_read16b(f);
	mod->bpm = hio_read8(f);
	mod->spd = hio_read8(f);
	hio_read16b(f);			/* global volume */
	hio_read8(f);			/* master L */
	hio_read8(f);			/* master R */

	for (i = 0; i < mod->chn; i++) {
		hio_read16b(f);		/* pan */
	}
	
	MODULE_INFO();

	/* Sequence */

	hio_seek(f, start + seq_ptr, SEEK_SET);
	for (i = 0; i < mod->len; i++)
		mod->xxo[i] = hio_read16b(f);

	/* Instruments */

	if (instrument_init(mod) < 0)
		return -1;

	hio_seek(f, start + ins_ptr, SEEK_SET);

	for (i = 0; i < mod->ins; i++) {
		int c2spd, flags;

		if (subinstrument_alloc(mod, i , 1) < 0)
			return -1;

		hio_read(mod->xxi[i].name, 1, 32, f);
		sdata[i] = hio_read32b(f);
		mod->xxs[i].len = hio_read32b(f);
		mod->xxs[i].lps = hio_read32b(f);
		mod->xxs[i].lpe = mod->xxs[i].lps + hio_read32b(f);
		hio_read32b(f);
		hio_read32b(f);
		c2spd = hio_read32b(f);
		c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
		mod->xxi[i].sub[0].vol = hio_read16b(f) >> 4;
		hio_read8(f);		/* vol L */
		hio_read8(f);		/* vol R */
		mod->xxi[i].sub[0].pan = 0x80;
		flags = hio_read8(f);
		mod->xxs[i].flg = flags & 0x03 ? XMP_SAMPLE_LOOP : 0;
		mod->xxs[i].flg |= flags & 0x02 ? XMP_SAMPLE_LOOP_BIDIR : 0;
		mod->xxi[i].sub[0].fin += 0 * hio_read8(f);	// FIXME
		hio_read8(f);		/* unused */
		hio_read8(f);
		hio_read8(f);
		hio_read8(f);
		hio_read16b(f);
		hio_read32b(f);
		hio_read32b(f);

		mod->xxi[i].nsm = !!mod->xxs[i].len;
		mod->xxi[i].sub[0].sid = i;
		
		D_(D_INFO "[%2X] %-32.32s %04x %04x %04x %c V%02x %5d\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_BIDIR ? 'B' :
				mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
				mod->xxi[i].sub[0].vol, c2spd);
	}

	/* PATTERN_INIT - alloc extra track*/
	if (pattern_init(mod) < 0)
		return -1;

	D_(D_INFO "Stored tracks: %d", mod->trk);

	/* Tracks */

	for (i = 1; i < mod->trk; i++) {
		int offset, rows;
		uint8 b;

		hio_seek(f, start + trk_ptr + i * 4, SEEK_SET);
		offset = hio_read32b(f);
		hio_seek(f, start + offset, SEEK_SET);

		rows = hio_read16b(f);

		if (track_alloc(mod, i, rows) < 0)
			return -1;

		//printf("\n=== Track %d ===\n\n", i);
		for (j = 0; j < rows; j++) {
			uint8 note, f2p;

			b = hio_read8(f);
			j += b & 0x03;

			note = 0;
			event = &mod->xxt[i]->event[j];
			if (b & 0x04)
				note = hio_read8(f);
			if (b & 0x08)
				event->ins = hio_read8(f);
			if (b & 0x10)
				event->vol = hio_read8(f);
			if (b & 0x20)
				event->fxt = hio_read8(f);
			if (b & 0x40)
				event->fxp = hio_read8(f);
			if (b & 0x80)
				f2p = hio_read8(f);

			if (note == 1)
				event->note = XMP_KEY_OFF;
			else if (note > 11) /* adjusted to play codeine.mgt */
				event->note = note + 1;

			/* effects */
			if (event->fxt < 0x10)
				/* like amiga */ ;
			else switch (event->fxt) {
			case 0x13: 
			case 0x14: 
			case 0x15: 
			case 0x17: 
			case 0x1c: 
			case 0x1d: 
			case 0x1e: 
				event->fxt = FX_EXTENDED;
				event->fxp = ((event->fxt & 0x0f) << 4) |
							(event->fxp & 0x0f);
				break;
			default:
				event->fxt = event->fxp = 0;
			}

			/* volume and volume column effects */
			if ((event->vol >= 0x10) && (event->vol <= 0x50)) {
				event->vol -= 0x0f;
				continue;
			}

			switch (event->vol >> 4) {
			case 0x06:	/* Volume slide down */
				event->f2t = FX_VOLSLIDE_2;
				event->f2p = event->vol - 0x60;
				break;
			case 0x07:	/* Volume slide up */
				event->f2t = FX_VOLSLIDE_2;
				event->f2p = (event->vol - 0x70) << 4;
				break;
			case 0x08:	/* Fine volume slide down */
				event->f2t = FX_EXTENDED;
				event->f2p = (EX_F_VSLIDE_DN << 4) |
							(event->vol - 0x80);
				break;
			case 0x09:	/* Fine volume slide up */
				event->f2t = FX_EXTENDED;
				event->f2p = (EX_F_VSLIDE_UP << 4) |
							(event->vol - 0x90);
				break;
			case 0x0a:	/* Set vibrato speed */
				event->f2t = FX_VIBRATO;
				event->f2p = (event->vol - 0xa0) << 4;
				break;
			case 0x0b:	/* Vibrato */
				event->f2t = FX_VIBRATO;
				event->f2p = event->vol - 0xb0;
				break;
			case 0x0c:	/* Set panning */
				event->f2t = FX_SETPAN;
				event->f2p = ((event->vol - 0xc0) << 4) + 8;
				break;
			case 0x0d:	/* Pan slide left */
				event->f2t = FX_PANSLIDE;
				event->f2p = (event->vol - 0xd0) << 4;
				break;
			case 0x0e:	/* Pan slide right */
				event->f2t = FX_PANSLIDE;
				event->f2p = event->vol - 0xe0;
				break;
			case 0x0f:	/* Tone portamento */
				event->f2t = FX_TONEPORTA;
				event->f2p = (event->vol - 0xf0) << 4;
				break;
			}
	
			event->vol = 0;

			/*printf("%02x  %02x %02x %02x %02x %02x\n",
				j, event->note, event->ins, event->vol,
				event->fxt, event->fxp);*/
		}
	}

	/* Extra track */
	mod->xxt[0] = calloc(sizeof(struct xmp_track) +
			sizeof(struct xmp_event) * 64 - 1, 1);
	mod->xxt[0]->rows = 64;

	/* Read and convert patterns */
	D_(D_INFO "Stored patterns: %d", mod->pat);

	hio_seek(f, start + pat_ptr, SEEK_SET);

	for (i = 0; i < mod->pat; i++) {
		if (pattern_alloc(mod, i) < 0)
			return -1;

		mod->xxp[i]->rows = hio_read16b(f);
		for (j = 0; j < mod->chn; j++) {
			mod->xxp[i]->index[j] = hio_read16b(f) - 1;
		}
	}

	/* Read samples */

	D_(D_INFO "Stored samples: %d", mod->smp);

	for (i = 0; i < mod->ins; i++) {
		if (mod->xxi[i].nsm == 0)
			continue;

		hio_seek(f, start + sdata[i], SEEK_SET);
		if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0)
			return -1;
	}

	return 0;
}
コード例 #8
0
ファイル: med3_load.c プロジェクト: GCrean/libxmp
static int unpack_block(struct module_data *m, uint16 bnum, uint8 *from)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_event *event;
	uint32 linemsk0 = *((uint32 *)from), linemsk1 = *((uint32 *)from + 1);
	uint32 fxmsk0 = *((uint32 *)from + 2), fxmsk1 = *((uint32 *)from + 3);
	uint32 *lmptr = &linemsk0, *fxptr = &fxmsk0;
	uint16 fromn = 0, lmsk;
	uint8 *fromst = from + 16, bcnt, *tmpto;
	uint8 *patbuf, *to;
	int i, j, trkn = mod->chn;

	from += 16;
	patbuf = to = calloc(3, 4 * 64);
	if (to == NULL)
		return -1;

	for (i = 0; i < 64; i++) {
		if (i == 32) {
			lmptr = &linemsk1;
			fxptr = &fxmsk1;
		}

		if (*lmptr & MASK) {
			lmsk = get_nibbles(fromst, &fromn, (uint8)(trkn / 4));
			lmsk <<= (16 - trkn);
			tmpto = to;

			for (bcnt = 0; bcnt < trkn; bcnt++) {
				if (lmsk & 0x8000) {
					*tmpto = (uint8)get_nibbles(fromst,
						&fromn,2);
					*(tmpto + 1) = (get_nibble(fromst,
							&fromn) << 4);
				}
				lmsk <<= 1;
				tmpto += 3;
			}
		}

		if (*fxptr & MASK) {
			lmsk = get_nibbles(fromst,&fromn,(uint8)(trkn / 4));
			lmsk <<= (16 - trkn);
			tmpto = to;

			for (bcnt = 0; bcnt < trkn; bcnt++) {
				if (lmsk & 0x8000) {
					*(tmpto+1) |= get_nibble(fromst,
							&fromn);
					*(tmpto+2) = (uint8)get_nibbles(fromst,
							&fromn,2);
				}
				lmsk <<= 1;
				tmpto += 3;
			}
		}
		to += 3 * trkn;
		*lmptr <<= 1;
		*fxptr <<= 1;
	}

	for (i = 0; i < 64; i++) {
		for (j = 0; j < 4; j++) {
			event = &EVENT(bnum, j, i);

			event->note = patbuf[i * 12 + j * 3 + 0];
			if (event->note)
				event->note += 48;
			event->ins  = patbuf[i * 12 + j * 3 + 1] >> 4;
			if (event->ins)
				event->ins++;
			event->fxt  = patbuf[i * 12 + j * 3 + 1] & 0x0f;
			event->fxp  = patbuf[i * 12 + j * 3 + 2];

			switch (event->fxt) {
			case 0x00:	/* arpeggio */
			case 0x01:	/* slide up */
			case 0x02:	/* slide down */
			case 0x03:	/* portamento */
			case 0x04:	/* vibrato? */
				break;
			case 0x0c:	/* set volume (BCD) */
				event->fxp = MSN(event->fxp) * 10 +
							LSN(event->fxp);
				break;
			case 0x0d:	/* volume slides */
				event->fxt = FX_VOLSLIDE;
				break;
			case 0x0f:	/* tempo/break */
				if (event->fxp == 0)
					event->fxt = FX_BREAK;
				if (event->fxp == 0xff) {
					event->fxp = event->fxt = 0;
					event->vol = 1;
				} else if (event->fxp == 0xfe) {
					event->fxp = event->fxt = 0;
				} else if (event->fxp == 0xf1) {
					event->fxt = FX_EXTENDED;
					event->fxp = (EX_RETRIG << 4) | 3;
				} else if (event->fxp == 0xf2) {
					event->fxt = FX_EXTENDED;
					event->fxp = (EX_CUT << 4) | 3;
				} else if (event->fxp == 0xf3) {
					event->fxt = FX_EXTENDED;
					event->fxp = (EX_DELAY << 4) | 3;
				} else if (event->fxp > 10) {
					event->fxt = FX_S3M_BPM;
					event->fxp = 125 * event->fxp / 33;
				}
				break;
			default:
				event->fxp = event->fxt = 0;
			}
		}
	}

	free(patbuf);

	return 0;
}
コード例 #9
0
ファイル: stm_load.c プロジェクト: GCrean/libxmp
static int stm_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int i, j;
    struct xmp_event *event;
    struct stm_file_header sfh;
    uint8 b;
    int bmod2stm = 0;

    LOAD_INIT();

    hio_read(&sfh.name, 20, 1, f);		/* ASCIIZ song name */
    hio_read(&sfh.magic, 8, 1, f);		/* '!Scream!' */
    sfh.rsvd1 = hio_read8(f);			/* '\x1a' */
    sfh.type = hio_read8(f);			/* 1=song, 2=module */
    sfh.vermaj = hio_read8(f);			/* Major version number */
    sfh.vermin = hio_read8(f);			/* Minor version number */
    sfh.tempo = hio_read8(f);			/* Playback tempo */
    sfh.patterns = hio_read8(f);		/* Number of patterns */
    sfh.gvol = hio_read8(f);			/* Global volume */
    hio_read(&sfh.rsvd2, 13, 1, f);		/* Reserved */

    for (i = 0; i < 31; i++) {
	hio_read(&sfh.ins[i].name, 12, 1, f);	/* ASCIIZ instrument name */
	sfh.ins[i].id = hio_read8(f);		/* Id=0 */
	sfh.ins[i].idisk = hio_read8(f);	/* Instrument disk */
	sfh.ins[i].rsvd1 = hio_read16l(f);	/* Reserved */
	sfh.ins[i].length = hio_read16l(f);	/* Sample length */
	sfh.ins[i].loopbeg = hio_read16l(f);	/* Loop begin */
	sfh.ins[i].loopend = hio_read16l(f);	/* Loop end */
	sfh.ins[i].volume = hio_read8(f);	/* Playback volume */
	sfh.ins[i].rsvd2 = hio_read8(f);	/* Reserved */
	sfh.ins[i].c2spd = hio_read16l(f);	/* C4 speed */
	sfh.ins[i].rsvd3 = hio_read32l(f);	/* Reserved */
	sfh.ins[i].paralen = hio_read16l(f);	/* Length in paragraphs */
    }

    if (!strncmp ((char *)sfh.magic, "BMOD2STM", 8))
	bmod2stm = 1;

    mod->pat = sfh.patterns;
    mod->trk = mod->pat * mod->chn;
    mod->spd = MSN (sfh.tempo);
    mod->ins = 31;
    mod->smp = mod->ins;
    m->c4rate = C4_NTSC_RATE;

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

    if (bmod2stm) {
	snprintf(mod->type, XMP_NAME_SIZE, "BMOD2STM STM");
    } else {
	snprintf(mod->type, XMP_NAME_SIZE, "Scream Tracker %d.%02d STM",
						sfh.vermaj, sfh.vermin);
    }

    MODULE_INFO();

    if (instrument_init(mod) < 0)
	return -1;

    /* Read and convert instruments and samples */
    for (i = 0; i < mod->ins; i++) {
	if (subinstrument_alloc(mod, i, 1) < 0)
	    return -1;

	mod->xxs[i].len = sfh.ins[i].length;
	mod->xxs[i].lps = sfh.ins[i].loopbeg;
	mod->xxs[i].lpe = sfh.ins[i].loopend;
	if (mod->xxs[i].lpe == 0xffff)
	    mod->xxs[i].lpe = 0;
	mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0;
	mod->xxi[i].sub[0].vol = sfh.ins[i].volume;
	mod->xxi[i].sub[0].pan = 0x80;
	mod->xxi[i].sub[0].sid = i;

	if (mod->xxs[i].len > 0)
		mod->xxi[i].nsm = 1;

	instrument_name(mod, i, sfh.ins[i].name, 12);

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

	sfh.ins[i].c2spd = 8363 * sfh.ins[i].c2spd / 8448;
	c2spd_to_note (sfh.ins[i].c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
    }

    hio_read(mod->xxo, 1, 128, f);

    for (i = 0; i < 128; i++)
	if (mod->xxo[i] >= mod->pat)
	    break;

    mod->len = i;

    D_(D_INFO "Module length: %d", mod->len);

    if (pattern_init(mod) < 0)
	return -1;

    /* Read 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);
	    b = hio_read8(f);
	    memset (event, 0, sizeof (struct xmp_event));
	    switch (b) {
	    case 251:
	    case 252:
	    case 253:
		break;
	    case 255:
		b = 0;
	    default:
		event->note = b ? 13 + LSN(b) + 12 * (2 + MSN(b)) : 0;
		b = hio_read8(f);
		event->vol = b & 0x07;
		event->ins = (b & 0xf8) >> 3;
		b = hio_read8(f);
		event->vol += (b & 0xf0) >> 1;
		if (event->vol > 0x40)
		    event->vol = 0;
		else
		    event->vol++;
		event->fxt = fx[LSN(b)];
		event->fxp = hio_read8(f);
		switch (event->fxt) {
		case FX_SPEED:
		    event->fxp = MSN (event->fxp);
		    break;
		case FX_NONE:
		    event->fxp = event->fxt = 0;
		    break;
		}
	    }
	}
    }

    /* Read samples */
    D_(D_INFO "Stored samples: %d", mod->smp);

    for (i = 0; i < mod->ins; i++) {
	if (mod->xxs[i].len > 1) {
	    if (load_sample(m, f, 0, &mod->xxs[i], NULL) < 0)
		return -1;
	} else {
	    mod->xxi[i].nsm = 0;
	}
    }

    m->quirk |= QUIRK_VSALL | QUIRKS_ST3;
    m->read_event_type = READ_EVENT_ST3;

    return 0;
}
コード例 #10
0
static void get_pbod(struct xmp_context *ctx, int size, FILE *f)
{
    struct xmp_player_context *p = &ctx->p;
    struct xmp_mod_context *m = &p->m;

    int j;
    uint16 rows;
    struct xxm_event *event;

    if (pattern >= m->xxh->pat)
	return;

    if (!pattern) {
	PATTERN_INIT();
	reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat);
    }

    rows = read16b(f);

    PATTERN_ALLOC (pattern);
    m->xxp[pattern]->rows = rows;
    TRACK_ALLOC (pattern);

    for (j = 0; j < rows * m->xxh->chn; j++) {
	uint8 note, ins;

	event = &EVENT(pattern, j % m->xxh->chn, j / m->xxh->chn);
	memset(event, 0, sizeof(struct xxm_event));

	note = read8(f);
	ins = read8(f);

	if (note) {
	    event->note = 36 + note;
	    event->ins = 1 + ins;
	}

	event->fxt = fx[read8(f)];
	event->fxp = read8(f);

	if ((event->fxt == FX_VOLSET) && (event->fxp > 0x40)) {
	    if (event->fxp <= 0x50) {
		event->fxt = FX_VOLSLIDE;
		event->fxp -= 0x40;
	    } else if (event->fxp <= 0x60) {
		event->fxt = FX_VOLSLIDE;
		event->fxp = (event->fxp - 0x50) << 4;
	    } else if (event->fxp <= 0x70) {
		event->fxt = FX_EXTENDED;
		event->fxp = (EX_F_VSLIDE_DN << 4) | (event->fxp - 0x60);
	    } else if (event->fxp <= 0x80) {
		event->fxt = FX_EXTENDED;
		event->fxp = (EX_F_VSLIDE_UP << 4) | (event->fxp - 0x70);
	    }
	}
	if (event->fxt == FX_ARPEGGIO)	/* Arpeggio fixup */
	    event->fxp = (((24 - MSN (event->fxp)) % 12) << 4) | LSN (event->fxp);
	if (event->fxt == NONE)
	    event->fxt = event->fxp = 0;
    }
    reportv(ctx, 0, ".");
    pattern++;
}
コード例 #11
0
ファイル: okt_load.c プロジェクト: yulizi1937/modo_android
static int get_pbod(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
{
    struct xmp_module *mod = &m->mod;
    struct local_data *data = (struct local_data *)parm;
    struct xmp_event *e;
    uint16 rows;
    int j;

    if (data->pattern >= mod->pat)
        return 0;

    if (!data->pattern) {
        if (pattern_init(mod) < 0)
            return -1;
        D_(D_INFO "Stored patterns: %d", mod->pat);
    }

    rows = hio_read16b(f);

    if (pattern_tracks_alloc(mod, data->pattern, rows) < 0)
        return -1;

    for (j = 0; j < rows * mod->chn; j++) {
        uint8 note, ins;

        e = &EVENT(data->pattern, j % mod->chn, j / mod->chn);
        memset(e, 0, sizeof(struct xmp_event));

        note = hio_read8(f);
        ins = hio_read8(f);

        if (note) {
            e->note = 48 + note;
            e->ins = 1 + ins;
        }

        e->fxt = fx[hio_read8(f)];
        e->fxp = hio_read8(f);

        if ((e->fxt == FX_VOLSET) && (e->fxp > 0x40)) {
            if (e->fxp <= 0x50) {
                e->fxt = FX_VOLSLIDE;
                e->fxp -= 0x40;
            } else if (e->fxp <= 0x60) {
                e->fxt = FX_VOLSLIDE;
                e->fxp = (e->fxp - 0x50) << 4;
            } else if (e->fxp <= 0x70) {
                e->fxt = FX_F_VSLIDE_DN;
                e->fxp = e->fxp - 0x60;
            } else if (e->fxp <= 0x80) {
                e->fxt = FX_F_VSLIDE_UP;
                e->fxp = e->fxp - 0x70;
            }
        }
        if (e->fxt == FX_ARPEGGIO)	/* Arpeggio fixup */
            e->fxp = (((24 - MSN(e->fxp)) % 12) << 4) | LSN(e->fxp);
        if (e->fxt == NONE)
            e->fxt = e->fxp = 0;
    }
    data->pattern++;

    return 0;
}
コード例 #12
0
static int mgt_load(struct xmp_context *ctx, FILE *f, const int start)
{
	struct xmp_player_context *p = &ctx->p;
	struct xmp_mod_context *m = &p->m;
	struct xxm_event *event;
	int i, j;
	int ver;
	int sng_ptr, seq_ptr, ins_ptr, pat_ptr, trk_ptr, smp_ptr;
	int sdata[64];

	LOAD_INIT();

	read24b(f);		/* MGT */
	ver = read8(f);
	read32b(f);		/* MCS */

	sprintf(m->type, "MGT v%d.%d (Megatracker)", MSN(ver), LSN(ver));

	m->xxh->chn = read16b(f);
	read16b(f);			/* number of songs */
	m->xxh->len = read16b(f);
	m->xxh->pat = read16b(f);
	m->xxh->trk = read16b(f);
	m->xxh->ins = m->xxh->smp = read16b(f);
	read16b(f);			/* reserved */
	read32b(f);			/* reserved */

	sng_ptr = read32b(f);
	seq_ptr = read32b(f);
	ins_ptr = read32b(f);
	pat_ptr = read32b(f);
	trk_ptr = read32b(f);
	smp_ptr = read32b(f);
	read32b(f);			/* total smp len */
	read32b(f);			/* unpacked trk size */

	fseek(f, start + sng_ptr, SEEK_SET);

	fread(m->name, 1, 32, f);
	seq_ptr = read32b(f);
	m->xxh->len = read16b(f);
	m->xxh->rst = read16b(f);
	m->xxh->bpm = read8(f);
	m->xxh->tpo = read8(f);
	read16b(f);			/* global volume */
	read8(f);			/* master L */
	read8(f);			/* master R */

	for (i = 0; i < m->xxh->chn; i++) {
		read16b(f);		/* pan */
	}
	
	MODULE_INFO();

	/* Sequence */

	fseek(f, start + seq_ptr, SEEK_SET);
	for (i = 0; i < m->xxh->len; i++)
		m->xxo[i] = read16b(f);

	/* Instruments */

	INSTRUMENT_INIT();

	fseek(f, start + ins_ptr, SEEK_SET);
	reportv(ctx, 1, "     Name                             Len  LBeg LEnd L Vol C2Spd\n");

	for (i = 0; i < m->xxh->ins; i++) {
		int c2spd, flags;

		m->xxi[i] = calloc(sizeof(struct xxm_instrument), 1);

		fread(m->xxih[i].name, 1, 32, f);
		sdata[i] = read32b(f);
		m->xxs[i].len = read32b(f);
		m->xxs[i].lps = read32b(f);
		m->xxs[i].lpe = m->xxs[i].lps + read32b(f);
		read32b(f);
		read32b(f);
		c2spd = read32b(f);
		c2spd_to_note(c2spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin);
		m->xxi[i][0].vol = read16b(f) >> 4;
		read8(f);		/* vol L */
		read8(f);		/* vol R */
		m->xxi[i][0].pan = 0x80;
		flags = read8(f);
		m->xxs[i].flg = flags & 0x03 ? WAVE_LOOPING : 0;
		m->xxs[i].flg |= flags & 0x02 ? WAVE_BIDIR_LOOP : 0;
		m->xxi[i][0].fin += 0 * read8(f);	// FIXME
		read8(f);		/* unused */
		read8(f);
		read8(f);
		read8(f);
		read16b(f);
		read32b(f);
		read32b(f);

		m->xxih[i].nsm = !!m->xxs[i].len;
		m->xxi[i][0].sid = i;
		
		if (V(1) && (strlen((char*)m->xxih[i].name) || (m->xxs[i].len > 1))) {
			report("[%2X] %-32.32s %04x %04x %04x %c V%02x %5d\n",
				i, m->xxih[i].name,
				m->xxs[i].len, m->xxs[i].lps, m->xxs[i].lpe,
				m->xxs[i].flg & WAVE_BIDIR_LOOP ? 'B' :
					m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ',
				m->xxi[i][0].vol, c2spd);
		}
	}

	/* PATTERN_INIT - alloc extra track*/
	PATTERN_INIT();

	reportv(ctx, 0, "Stored tracks  : %d ", m->xxh->trk);

	/* Tracks */

	for (i = 1; i < m->xxh->trk; i++) {
		int offset, rows;
		uint8 b;

		fseek(f, start + trk_ptr + i * 4, SEEK_SET);
		offset = read32b(f);
		fseek(f, start + offset, SEEK_SET);

		rows = read16b(f);
		m->xxt[i] = calloc(sizeof(struct xxm_track) +
				sizeof(struct xxm_event) * rows, 1);
		m->xxt[i]->rows = rows;

		//printf("\n=== Track %d ===\n\n", i);
		for (j = 0; j < rows; j++) {
			uint8 note, f2p;

			b = read8(f);
			j += b & 0x03;

			note = 0;
			event = &m->xxt[i]->event[j];
			if (b & 0x04)
				note = read8(f);
			if (b & 0x08)
				event->ins = read8(f);
			if (b & 0x10)
				event->vol = read8(f);
			if (b & 0x20)
				event->fxt = read8(f);
			if (b & 0x40)
				event->fxp = read8(f);
			if (b & 0x80)
				f2p = read8(f);

			if (note == 1)
				event->note = XMP_KEY_OFF;
			else if (note > 11) /* adjusted to play codeine.mgt */
				event->note = note - 11;

			/* effects */
			if (event->fxt < 0x10)
				/* like amiga */ ;
			else switch (event->fxt) {
			case 0x13: 
			case 0x14: 
			case 0x15: 
			case 0x17: 
			case 0x1c: 
			case 0x1d: 
			case 0x1e: 
				event->fxt = FX_EXTENDED;
				event->fxp = ((event->fxt & 0x0f) << 4) |
							(event->fxp & 0x0f);
				break;
			default:
				event->fxt = event->fxp = 0;
			}

			/* volume and volume column effects */
			if ((event->vol >= 0x10) && (event->vol <= 0x50)) {
				event->vol -= 0x0f;
				continue;
			}

			switch (event->vol >> 4) {
			case 0x06:	/* Volume slide down */
				event->f2t = FX_VOLSLIDE_2;
				event->f2p = event->vol - 0x60;
				break;
			case 0x07:	/* Volume slide up */
				event->f2t = FX_VOLSLIDE_2;
				event->f2p = (event->vol - 0x70) << 4;
				break;
			case 0x08:	/* Fine volume slide down */
				event->f2t = FX_EXTENDED;
				event->f2p = (EX_F_VSLIDE_DN << 4) |
							(event->vol - 0x80);
				break;
			case 0x09:	/* Fine volume slide up */
				event->f2t = FX_EXTENDED;
				event->f2p = (EX_F_VSLIDE_UP << 4) |
							(event->vol - 0x90);
				break;
			case 0x0a:	/* Set vibrato speed */
				event->f2t = FX_VIBRATO;
				event->f2p = (event->vol - 0xa0) << 4;
				break;
			case 0x0b:	/* Vibrato */
				event->f2t = FX_VIBRATO;
				event->f2p = event->vol - 0xb0;
				break;
			case 0x0c:	/* Set panning */
				event->f2t = FX_SETPAN;
				event->f2p = ((event->vol - 0xc0) << 4) + 8;
				break;
			case 0x0d:	/* Pan slide left */
				event->f2t = FX_PANSLIDE;
				event->f2p = (event->vol - 0xd0) << 4;
				break;
			case 0x0e:	/* Pan slide right */
				event->f2t = FX_PANSLIDE;
				event->f2p = event->vol - 0xe0;
				break;
			case 0x0f:	/* Tone portamento */
				event->f2t = FX_TONEPORTA;
				event->f2p = (event->vol - 0xf0) << 4;
				break;
			}
	
			event->vol = 0;

			/*printf("%02x  %02x %02x %02x %02x %02x\n",
				j, event->note, event->ins, event->vol,
				event->fxt, event->fxp);*/
		}

		if (V(0) && i % m->xxh->chn == 0)
			report(".");
	}
	reportv(ctx, 0, "\n");

	/* Extra track */
	m->xxt[0] = calloc(sizeof(struct xxm_track) +
			sizeof(struct xxm_event) * 64 - 1, 1);
	m->xxt[0]->rows = 64;

	/* Read and convert patterns */

	reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat);
	fseek(f, start + pat_ptr, SEEK_SET);

	for (i = 0; i < m->xxh->pat; i++) {
		PATTERN_ALLOC(i);

		m->xxp[i]->rows = read16b(f);
		for (j = 0; j < m->xxh->chn; j++) {
			m->xxp[i]->info[j].index = read16b(f) - 1;
			//printf("%3d ", m->xxp[i]->info[j].index);
		}

		reportv(ctx, 0, ".");
		//printf("\n");
	}
	reportv(ctx, 0, "\n");

	/* Read samples */

	reportv(ctx, 0, "Stored samples : %d ", m->xxh->smp);

	for (i = 0; i < m->xxh->ins; i++) {
		if (m->xxih[i].nsm == 0)
			continue;

		fseek(f, start + sdata[i], SEEK_SET);
		xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate, 0,
						&m->xxs[m->xxi[i][0].sid], NULL);
		reportv(ctx, 0, ".");
	}
	reportv(ctx, 0, "\n");

	return 0;
}
コード例 #13
0
ファイル: effects.c プロジェクト: gbraad/libxmp-4.3.0
void process_fx(struct context_data *ctx, struct channel_data *xc, int chn,
                uint8 note, uint8 fxt, uint8 fxp, int fnum)
{
    struct player_data *p = &ctx->p;
    struct module_data *m = &ctx->m;
    struct xmp_module *mod = &m->mod;
    struct flow_control *f = &p->flow;
    int h, l;

    switch (fxt) {
    case FX_ARPEGGIO:
fx_arpeggio:
        if (fxp != 0) {
            xc->arpeggio.val[0] = 0;
            xc->arpeggio.val[1] = MSN(fxp);
            xc->arpeggio.val[2] = LSN(fxp);
            xc->arpeggio.size = 3;
        }
        break;
    case FX_S3M_ARPEGGIO:
        EFFECT_MEMORY(fxp, xc->arpeggio.memory);
        goto fx_arpeggio;
#ifndef LIBXMP_CORE_PLAYER
    case FX_OKT_ARP3:
        if (fxp != 0) {
            xc->arpeggio.val[0] = -MSN(fxp);
            xc->arpeggio.val[1] = 0;
            xc->arpeggio.val[2] = LSN(fxp);
            xc->arpeggio.size = 3;
        }
        break;
    case FX_OKT_ARP4:
        if (fxp != 0) {
            xc->arpeggio.val[0] = 0;
            xc->arpeggio.val[1] = LSN(fxp);
            xc->arpeggio.val[2] = 0;
            xc->arpeggio.val[3] = -MSN(fxp);
            xc->arpeggio.size = 4;
        }
        break;
    case FX_OKT_ARP5:
        if (fxp != 0) {
            xc->arpeggio.val[0] = LSN(fxp);
            xc->arpeggio.val[1] = LSN(fxp);
            xc->arpeggio.val[2] = 0;
            xc->arpeggio.size = 3;
        }
        break;
#endif
    case FX_PORTA_UP:	/* Portamento up */
        EFFECT_MEMORY(fxp, xc->freq.memory);

        if (HAS_QUIRK(QUIRK_FINEFX)
                && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
            switch (MSN(fxp)) {
            case 0xf:
                fxp &= 0x0f;
                goto fx_f_porta_up;
            case 0xe:
                fxp &= 0x0f;
                fxp |= 0x10;
                goto fx_xf_porta;
            }
        }

        SET(PITCHBEND);

        if (fxp != 0) {
            xc->freq.slide = -fxp;
            if (HAS_QUIRK(QUIRK_UNISLD))
                xc->porta.memory = fxp;
        } else if (xc->freq.slide > 0) {
            xc->freq.slide *= -1;
        }
        break;
    case FX_PORTA_DN:	/* Portamento down */
        EFFECT_MEMORY(fxp, xc->freq.memory);

        if (HAS_QUIRK(QUIRK_FINEFX)
                && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
            switch (MSN(fxp)) {
            case 0xf:
                fxp &= 0x0f;
                goto fx_f_porta_dn;
            case 0xe:
                fxp &= 0x0f;
                fxp |= 0x20;
                goto fx_xf_porta;
            }
        }

        SET(PITCHBEND);

        if (fxp != 0) {
            xc->freq.slide = fxp;
            if (HAS_QUIRK(QUIRK_UNISLD))
                xc->porta.memory = fxp;
        } else if (xc->freq.slide < 0) {
            xc->freq.slide *= -1;
        }
        break;
    case FX_TONEPORTA:	/* Tone portamento */
        if (HAS_QUIRK(QUIRK_IGSTPOR)) {
            if (note == 0 && xc->porta.dir == 0)
                break;
        }
        if (!IS_VALID_INSTRUMENT(xc->ins))
            break;

        do_toneporta(m, xc, note);

        EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory);

        if (fxp != 0) {
            if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */
                xc->freq.memory = fxp;
            xc->porta.slide = fxp;
        }
        SET(TONEPORTA);
        break;

    case FX_VIBRATO:	/* Vibrato */
        EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

        SET(VIBRATO);
        SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp));
        break;
    case FX_FINE_VIBRATO:	/* Fine vibrato */
        EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

        SET(VIBRATO);
        SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp));
        break;

    case FX_TONE_VSLIDE:	/* Toneporta + vol slide */
        if (!IS_VALID_INSTRUMENT(xc->ins))
            break;
        do_toneporta(m, xc, note);
        SET(TONEPORTA);
        goto fx_volslide;
    case FX_VIBRA_VSLIDE:	/* Vibrato + vol slide */
        SET(VIBRATO);
        goto fx_volslide;

    case FX_TREMOLO:	/* Tremolo */
        EFFECT_MEMORY_SETONLY(fxp, xc->tremolo.memory);
        SET(TREMOLO);
        SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp));
        break;

    case FX_SETPAN:		/* Set pan */
        xc->pan.val = fxp;
        break;
    case FX_OFFSET:		/* Set sample offset */
        SET(OFFSET);
        if (fxp) {
            xc->offset_val = xc->offset = fxp << 8;
        } else {
            xc->offset_val = xc->offset;
        }
        break;
    case FX_VOLSLIDE:	/* Volume slide */
fx_volslide:
        /* S3M file volume slide note:
         * DFy  Fine volume down by y (...) If y is 0, the command will
         *      be treated as a volume slide up with a value of f (15).
         *      If a DFF command is specified, the volume will be slid
         *      up.
         */
        if (HAS_QUIRK(QUIRK_FINEFX)) {
            h = MSN(fxp);
            l = LSN(fxp);
            if (l == 0xf && h != 0) {
                xc->vol.memory = fxp;
                fxp >>= 4;
                goto fx_f_vslide_up;
            } else if (h == 0xf && l != 0) {
                xc->vol.memory = fxp;
                fxp &= 0x0f;
                goto fx_f_vslide_dn;
            }
        }
コード例 #14
0
ファイル: dbm_load.c プロジェクト: ProjectZeroSlackr/XMP
static void get_patt(struct xmp_context *ctx, int size, FILE *f)
{
	struct xmp_player_context *p = &ctx->p;
	struct xmp_mod_context *m = &p->m;
	int i, c, r, n, sz;
	struct xxm_event *event, dummy;
	uint8 x;

	PATTERN_INIT();

	reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat);

	/*
	 * Note: channel and flag bytes are inverted in the format
	 * description document
	 */

	for (i = 0; i < m->xxh->pat; i++) {
		PATTERN_ALLOC(i);
		m->xxp[i]->rows = read16b(f);
		TRACK_ALLOC(i);

		sz = read32b(f);
		//printf("rows = %d, size = %d\n", m->xxp[i]->rows, sz);

		r = 0;
		c = -1;

		while (sz > 0) {
			//printf("  offset=%x,  sz = %d, ", ftell(f), sz);
			c = read8(f);
			if (--sz <= 0) break;
			//printf("c = %02x\n", c);

			if (c == 0) {
				r++;
				c = -1;
				continue;
			}
			c--;

			n = read8(f);
			if (--sz <= 0) break;
			//printf("    n = %d\n", n);

			if (c >= m->xxh->chn || r >= m->xxp[i]->rows)
				event = &dummy;
			else
				event = &EVENT(i, c, r);

			if (n & 0x01) {
				x = read8(f);
				event->note = 1 + MSN(x) * 12 + LSN(x);
				if (--sz <= 0) break;
			}
			if (n & 0x02) {
				event->ins = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x04) {
				event->fxt = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x08) {
				event->fxp = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x10) {
				event->f2t = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x20) {
				event->f2p = read8(f);
				if (--sz <= 0) break;
			}

			if (event->fxt == 0x1c)
				event->fxt = FX_S3M_BPM;

			if (event->fxt > 0x1c)
				event->fxt = event->f2p = 0;

			if (event->f2t == 0x1c)
				event->f2t = FX_S3M_BPM;

			if (event->f2t > 0x1c)
				event->f2t = event->f2p = 0;
		}
		reportv(ctx, 0, ".");
	}
	reportv(ctx, 0, "\n");
}
コード例 #15
0
ファイル: stx_load.c プロジェクト: bithorder/libxmp
static int stx_load(struct module_data *m, xmp_file f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int c, r, i, broken = 0;
    struct xmp_event *event = 0, dummy;
    struct stx_file_header sfh;
    struct stx_instrument_header sih;
    uint8 n, b;
    uint16 x16;
    int bmod2stm = 0;
    uint16 *pp_ins;		/* Parapointers to instruments */
    uint16 *pp_pat;		/* Parapointers to patterns */

    LOAD_INIT();

    xmp_fread(&sfh.name, 20, 1, f);
    xmp_fread(&sfh.magic, 8, 1, f);
    sfh.psize = read16l(f);
    sfh.unknown1 = read16l(f);
    sfh.pp_pat = read16l(f);
    sfh.pp_ins = read16l(f);
    sfh.pp_chn = read16l(f);
    sfh.unknown2 = read16l(f);
    sfh.unknown3 = read16l(f);
    sfh.gvol = read8(f);
    sfh.tempo = read8(f);
    sfh.unknown4 = read16l(f);
    sfh.unknown5 = read16l(f);
    sfh.patnum = read16l(f);
    sfh.insnum = read16l(f);
    sfh.ordnum = read16l(f);
    sfh.unknown6 = read16l(f);
    sfh.unknown7 = read16l(f);
    sfh.unknown8 = read16l(f);
    xmp_fread(&sfh.magic2, 4, 1, f);

    /* BMOD2STM does not convert pitch */
    if (!strncmp ((char *) sfh.magic, "BMOD2STM", 8))
	bmod2stm = 1;

#if 0
    if ((strncmp ((char *) sfh.magic, "!Scream!", 8) &&
	!bmod2stm) || strncmp ((char *) sfh.magic2, "SCRM", 4))
	return -1;
#endif

    mod->ins = sfh.insnum;
    mod->pat = sfh.patnum;
    mod->trk = mod->pat * mod->chn;
    mod->len = sfh.ordnum;
    mod->spd = MSN (sfh.tempo);
    mod->smp = mod->ins;
    m->c4rate = C4_NTSC_RATE;

    /* STM2STX 1.0 released with STMIK 0.2 converts STMs with the pattern
     * length encoded in the first two bytes of the pattern (like S3M).
     */
    xmp_fseek(f, start + (sfh.pp_pat << 4), SEEK_SET);
    x16 = read16l(f);
    xmp_fseek(f, start + (x16 << 4), SEEK_SET);
    x16 = read16l(f);
    if (x16 == sfh.psize)
	broken = 1;

    strncpy(mod->name, (char *)sfh.name, 20);
    if (bmod2stm)
	set_type(m, "BMOD2STM STX");
    else
	snprintf(mod->type, XMP_NAME_SIZE, "STM2STX 1.%d", broken ? 0 : 1);

    MODULE_INFO();
 
    pp_pat = calloc (2, mod->pat);
    pp_ins = calloc (2, mod->ins);

    /* Read pattern pointers */
    xmp_fseek(f, start + (sfh.pp_pat << 4), SEEK_SET);
    for (i = 0; i < mod->pat; i++)
	pp_pat[i] = read16l(f);

    /* Read instrument pointers */
    xmp_fseek(f, start + (sfh.pp_ins << 4), SEEK_SET);
    for (i = 0; i < mod->ins; i++)
	pp_ins[i] = read16l(f);

    /* Skip channel table (?) */
    xmp_fseek(f, start + (sfh.pp_chn << 4) + 32, SEEK_SET);

    /* Read orders */
    for (i = 0; i < mod->len; i++) {
	mod->xxo[i] = read8(f);
	xmp_fseek(f, 4, SEEK_CUR);
    }
 
    INSTRUMENT_INIT();

    /* Read and convert instruments and samples */

    for (i = 0; i < mod->ins; i++) {
	mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1);
	xmp_fseek(f, start + (pp_ins[i] << 4), SEEK_SET);

	sih.type = read8(f);
	xmp_fread(&sih.dosname, 13, 1, f);
	sih.memseg = read16l(f);
	sih.length = read32l(f);
	sih.loopbeg = read32l(f);
	sih.loopend = read32l(f);
	sih.vol = read8(f);
	sih.rsvd1 = read8(f);
	sih.pack = read8(f);
	sih.flags = read8(f);
	sih.c2spd = read16l(f);
	sih.rsvd2 = read16l(f);
	xmp_fread(&sih.rsvd3, 4, 1, f);
	sih.int_gp = read16l(f);
	sih.int_512 = read16l(f);
	sih.int_last = read32l(f);
	xmp_fread(&sih.name, 28, 1, f);
	xmp_fread(&sih.magic, 4, 1, f);

	mod->xxi[i].nsm = !!(mod->xxs[i].len = sih.length);
	mod->xxs[i].lps = sih.loopbeg;
	mod->xxs[i].lpe = sih.loopend;
	if (mod->xxs[i].lpe == 0xffff)
	    mod->xxs[i].lpe = 0;
	mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0;
	mod->xxi[i].sub[0].vol = sih.vol;
	mod->xxi[i].sub[0].pan = 0x80;
	mod->xxi[i].sub[0].sid = i;

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

	D_(D_INFO "[%2X] %-14.14s %04x %04x %04x %c V%02x %5d\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, sih.c2spd);

	sih.c2spd = 8363 * sih.c2spd / 8448;
	c2spd_to_note(sih.c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
    }

    PATTERN_INIT();

    /* Read and convert patterns */
    D_(D_INFO "Stored patterns: %d", mod->pat);

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

	if (!pp_pat[i])
	    continue;

	xmp_fseek(f, start + (pp_pat[i] << 4), SEEK_SET);
	if (broken)
	    xmp_fseek(f, 2, SEEK_CUR);

	for (r = 0; r < 64; ) {
	    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) {
		n = read8(f);

		switch (n) {
		case 255:
		    n = 0;
		    break;	/* Empty note */
		case 254:
		    n = XMP_KEY_OFF;
		    break;	/* Key off */
		default:
		    n = 37 + 12 * MSN (n) + LSN (n);
		}

		event->note = n;
		event->ins = read8(f);;
	    }

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

	    if (b & S3M_FX_FOLLOWS) {
		event->fxt = fx[read8(f)];
		event->fxp = read8(f);
		switch (event->fxt) {
		case FX_SPEED:
		    event->fxp = MSN (event->fxp);
		    break;
		case FX_NONE:
		    event->fxp = event->fxt = 0;
		    break;
		}
	    }
	}

    }

    free (pp_pat);
    free (pp_ins);

    /* Read samples */
    D_(D_INFO "Stored samples: %d", mod->smp);

    for (i = 0; i < mod->ins; i++) {
	load_sample(m, f, 0, &mod->xxs[mod->xxi[i].sub[0].sid], NULL);
    }

    m->quirk |= QUIRK_VSALL | QUIRKS_ST3;
    m->read_event_type = READ_EVENT_ST3;

    return 0;
}
コード例 #16
0
ファイル: s3m_load.c プロジェクト: cmatsuoka/chiptune.js
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);
    }
コード例 #17
0
ファイル: effects.c プロジェクト: ProjectZeroSlackr/XMP
void process_fx(struct xmp_context *ctx, int chn, uint8 note, uint8 fxt, uint8 fxp, struct xmp_channel *xc)
{
    struct xmp_player_context *p = &ctx->p;
    struct xmp_mod_context *m = &p->m;
    int h, l;

    switch (fxt) {
    case FX_ARPEGGIO:
        if (!fxp)
            break;
        xc->a_val[0] = 0;
        xc->a_val[1] = 100 * MSN(fxp);
        xc->a_val[2] = 100 * LSN(fxp);
        xc->a_size = 3;
        break;
    case FX_OKT_ARP3:
        if (!fxp)
            break;
        xc->a_val[0] = -100 * MSN(fxp);
        xc->a_val[1] = 0;
        xc->a_val[2] = 100 * LSN(fxp);;
        xc->a_size = 3;
    case FX_OKT_ARP4:
        if (!fxp)
            break;
        xc->a_val[0] = 0;
        xc->a_val[1] = 100 * LSN(fxp);;
        xc->a_val[2] = 0;
        xc->a_val[3] = -100 * MSN(fxp);
        xc->a_size = 4;
        break;
    case FX_OKT_ARP5:
        if (!fxp)
            break;
        xc->a_val[0] = 100 * LSN(fxp);;
        xc->a_val[1] = 100 * LSN(fxp);;
        xc->a_val[2] = 0;
        xc->a_size = 3;
        break;
    case FX_PORTA_UP:				/* Portamento up */
fx_porta_up:
        if (m->fetch & XMP_CTL_FINEFX) {
            switch (MSN(fxp)) {
            case 0xf:
                xc->porta = fxp;
                fxp &= 0x0f;
                goto ex_f_porta_up;
            case 0xe:
                xc->porta = fxp;
                fxp &= 0x0e;
                fxp |= 0x10;
                goto fx_xf_porta;
            }
            if (!fxp) {
                if ((fxp = xc->porta) != 0)
                    goto fx_porta_up;
            }
        }
        SET(PITCHBEND);
        if ((xc->porta = fxp) != 0)
            xc->f_val = -fxp;
        else if (xc->f_val > 0)
            xc->f_val *= -1;
        break;
    case FX_PORTA_DN:				/* Portamento down */
fx_porta_dn:
        if (m->fetch & XMP_CTL_FINEFX) {
            switch (MSN(fxp)) {
            case 0xf:
                xc->porta = fxp;
                fxp &= 0x0f;
                goto ex_f_porta_dn;
            case 0xe:
                xc->porta = fxp;
                fxp &= 0x0e;
                fxp |= 0x20;
                goto fx_xf_porta;
            }
            if (!fxp) {
                if ((fxp = xc->porta) != 0)
                    goto fx_porta_dn;
            }
        }
        SET(PITCHBEND);
        if ((xc->porta = fxp) != 0)
            xc->f_val = fxp;
        else if (xc->f_val < 0)
            xc->f_val *= -1;
        break;
    case FX_TONEPORTA:				/* Tone portamento */
        if (!TEST (IS_VALID))
            break;
        DO_TONEPORTA();
        if (fxp)
            xc->s_val = fxp;
        SET(TONEPORTA);
        break;
    case FX_PER_PORTA_UP:			/* Persistent portamento up */
        SET_PER(PITCHBEND);
        xc->f_val = -fxp;
        if ((xc->porta = fxp) == 0)
            RESET_PER(PITCHBEND);
        break;
    case FX_PER_PORTA_DN:			/* Persistent portamento down */
        SET(PITCHBEND);
        xc->f_val = fxp;
        if ((xc->porta = fxp) == 0)
            RESET_PER(PITCHBEND);
        break;
    case FX_PER_TPORTA:				/* Persistent tone portamento */
        if (!TEST(IS_VALID))
            break;
        SET_PER(TONEPORTA);
        DO_TONEPORTA();
        xc->s_val = fxp;
        if (fxp == 0)
            RESET_PER(TONEPORTA);
        break;
    case FX_PER_VSLD_UP:			/* Persistent volslide up */
        SET_PER(VOL_SLIDE);
        xc->v_val = fxp;
        if (fxp == 0)
            RESET_PER(VOL_SLIDE);
        break;
    case FX_PER_VSLD_DN:			/* Persistent volslide down */
        SET_PER(VOL_SLIDE);
        xc->v_val = -fxp;
        if (fxp == 0)
            RESET_PER(VOL_SLIDE);
        break;
    case FX_TEMPO_CP:				/* Set tempo and ... */
        if (fxp)
            p->tempo = fxp;
    /* fall through */
    case FX_PER_CANCEL:				/* Cancel persistent effects */
        xc->per_flags = 0;
        break;
    case FX_VIBRATO:				/* Vibrato */
        SET(VIBRATO);
        if (LSN(fxp))
            xc->y_depth = LSN(fxp) * 4;
        if (MSN(fxp))
            xc->y_rate = MSN(fxp);
        break;
    case FX_FINE2_VIBRA:			/* Fine vibrato (2x) */
        SET(VIBRATO);
        if (LSN(fxp))
            xc->y_depth = LSN(fxp) * 2;
        if (MSN(fxp))
            xc->y_rate = MSN(fxp);
        break;
    case FX_FINE4_VIBRA:			/* Fine vibrato (4x) */
        SET(VIBRATO);
        if (LSN(fxp))
            xc->y_depth = LSN(fxp);
        if (MSN(fxp))
            xc->y_rate = MSN(fxp);
        break;
    case FX_PER_VIBRATO:			/* Persistent vibrato */
        SET_PER(VIBRATO);
        if (LSN(fxp))
            xc->y_depth = LSN(fxp) * 4;
        else
            RESET_PER(VIBRATO);
        if (MSN(fxp))
            xc->y_rate = MSN(fxp);
        break;
    case FX_TONE_VSLIDE:			/* Toneporta + vol slide */
        if (!TEST (IS_VALID))
            break;
        DO_TONEPORTA ();
        SET(TONEPORTA);
        goto fx_volslide;
    case FX_VIBRA_VSLIDE:			/* Vibrato + vol slide */
        SET(VIBRATO);
        goto fx_volslide;
    case FX_TREMOLO:				/* Tremolo */
        SET(TREMOLO);
        if (MSN(fxp))
            xc->t_rate = MSN(fxp);
        if (LSN(fxp))
            xc->t_depth = LSN(fxp);
        break;
    case FX_SETPAN:				/* Set pan */
        SET(NEW_PAN);
        xc->pan = fxp;
        break;
    case FX_OFFSET:				/* Set sample offset */
        SET(OFFSET);
        if (fxp)
            xc->offset_val = xc->offset = fxp << 8;
        else
            xc->offset_val = xc->offset;
        break;
    case FX_VOLSLIDE:				/* Volume slide */
fx_volslide:
        if (m->fetch & XMP_CTL_FINEFX) {
            h = MSN(fxp);
            l = LSN(fxp);
            if (h == 0xf && l != 0) {
                xc->volslide = fxp;
                fxp &= 0x0f;
                goto ex_f_vslide_dn;
            } else if (h == 0xe && l != 0) {
                xc->volslide = fxp;
                fxp &= 0x0f;
                goto ex_f_vslide_dn;		/* FIXME */
            } else if (l == 0xf && h != 0) {
                xc->volslide = fxp;
                fxp >>= 4;
                goto ex_f_vslide_up;
            } else if (l == 0xe && h != 0) {
コード例 #18
0
ファイル: mtm_load.c プロジェクト: GCrean/libxmp
static int mtm_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int i, j;
    struct mtm_file_header mfh;
    struct mtm_instrument_header mih;
    uint8 mt[192];
    uint16 mp[32];

    LOAD_INIT();

    hio_read(&mfh.magic, 3, 1, f);	/* "MTM" */
    mfh.version = hio_read8(f);		/* MSN=major, LSN=minor */
    hio_read(&mfh.name, 20, 1, f);	/* ASCIIZ Module name */
    mfh.tracks = hio_read16l(f);	/* Number of tracks saved */
    mfh.patterns = hio_read8(f);	/* Number of patterns saved */
    mfh.modlen = hio_read8(f);		/* Module length */
    mfh.extralen = hio_read16l(f);	/* Length of the comment field */
    mfh.samples = hio_read8(f);		/* Number of samples */
    mfh.attr = hio_read8(f);		/* Always zero */
    mfh.rows = hio_read8(f);		/* Number rows per track */
    mfh.channels = hio_read8(f);	/* Number of tracks per pattern */
    hio_read(&mfh.pan, 32, 1, f);	/* Pan positions for each channel */

#if 0
    if (strncmp ((char *)mfh.magic, "MTM", 3))
	return -1;
#endif

    mod->trk = mfh.tracks + 1;
    mod->pat = mfh.patterns + 1;
    mod->len = mfh.modlen + 1;
    mod->ins = mfh.samples;
    mod->smp = mod->ins;
    mod->chn = mfh.channels;
    mod->spd = 6;
    mod->bpm = 125;

    strncpy(mod->name, (char *)mfh.name, 20);
    set_type(m, "MultiTracker %d.%02d MTM", MSN(mfh.version), LSN(mfh.version));

    MODULE_INFO();

    if (instrument_init(mod) < 0)
	return -1;

    /* Read and convert instruments */
    for (i = 0; i < mod->ins; i++) {
	if (subinstrument_alloc(mod, i, 1) < 0)
	    return -1;

	hio_read(&mih.name, 22, 1, f);		/* Instrument name */
	mih.length = hio_read32l(f);		/* Instrument length in bytes */
	mih.loop_start = hio_read32l(f);	/* Sample loop start */
	mih.loopend = hio_read32l(f);		/* Sample loop end */
	mih.finetune = hio_read8(f);		/* Finetune */
	mih.volume = hio_read8(f);		/* Playback volume */
	mih.attr = hio_read8(f);		/* &0x01: 16bit sample */

	mod->xxs[i].len = mih.length;
	mod->xxs[i].lps = mih.loop_start;
	mod->xxs[i].lpe = mih.loopend;
	mod->xxs[i].flg = mod->xxs[i].lpe ? XMP_SAMPLE_LOOP : 0;	/* 1 == Forward loop */
	if (mfh.attr & 1) {
	    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 = mih.volume;
	mod->xxi[i].sub[0].fin = mih.finetune;
	mod->xxi[i].sub[0].pan = 0x80;
	mod->xxi[i].sub[0].sid = i;

	instrument_name(mod, i, mih.name, 22);

	if (mod->xxs[i].len > 0)
		mod->xxi[i].nsm = 1;

	D_(D_INFO "[%2X] %-22.22s %04x%c%04x %04x %c V%02x F%+03d\n", 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, mod->xxi[i].sub[0].fin - 0x80);
    }
コード例 #19
0
static void xlat_fx(int c, struct xmp_event *e, uint8 *last_fxp, int new_fx)
{
    uint8 h = MSN(e->fxp), l = LSN(e->fxp);

    switch (e->fxt = fx[e->fxt]) {
    case FX_XTND:		/* Extended effect */
	e->fxt = FX_EXTENDED;

	if (h == 0 && e->fxp == 0) {
	    e->fxp = last_fxp[c];
	    h = MSN(e->fxp);
	    l = LSN(e->fxp);
	} else {
	    last_fxp[c] = e->fxp;
	}

	switch (h) {
	case 0x1:		/* Glissando */
	    e->fxp = 0x30 | l;
	    break;
	case 0x2:		/* Finetune */
	    e->fxp = 0x50 | l;
	    break;
	case 0x3:		/* Vibrato wave */
	    e->fxp = 0x40 | l;
	    break;
	case 0x4:		/* Tremolo wave */
	    e->fxp = 0x70 | l;
	    break;
	case 0x5:		/* Panbrello wave */
	    if (l <= 3) {
	    	e->fxt = FX_PANBRELLO_WF;
	    	e->fxp = l;
	    } else {
		e->fxt = e->fxp = 0;
	    }
	    break;
	case 0x6:		/* Pattern delay */
	    e->fxp = 0xe0 | l;
	    break;
	case 0x7:		/* Instrument functions */
	    e->fxt = FX_IT_INSTFUNC;
	    e->fxp &= 0x0f;
	    break;
	case 0x8:		/* Set pan position */
	    e->fxt = FX_MASTER_PAN;
	    e->fxp = l << 4;
	    break;
	case 0x9:		/* 0x91 = set surround -- NOT IMPLEMENTED */
	    e->fxt = e->fxp = 0;
	    break;
	case 0xb:		/* Pattern loop */
	    e->fxp = 0x60 | l;
	    break;
	case 0xc:		/* Note cut */
	case 0xd:		/* Note delay */
	    if ((e->fxp = l) == 0)
		e->fxp++;	/* SD0 and SC0 becomes SD1 and SC1 */
	    e->fxp |= h << 4;
	    break;
	case 0xe:		/* Pattern row delay */
	    e->fxt = FX_IT_ROWDELAY;
	    e->fxp = l;
	    break;
	default:
	    e->fxt = e->fxp = 0;
	}
	break;
    case FX_FLT_CUTOFF:
	if (e->fxp > 0x7f && e->fxp < 0x90) {	/* Resonance */
	    e->fxt = FX_FLT_RESN;
	    e->fxp = (e->fxp - 0x80) * 16;
	} else {		/* Cutoff */
	    e->fxp *= 2;
	}
	break;
    case FX_TREMOR:
	if (!new_fx && e->fxp != 0) {
	   e->fxp = ((MSN(e->fxp) + 1) << 4) | (LSN(e->fxp) + 1);
	}
	break;
    case FX_GLOBALVOL:
	if (e->fxp > 0x80) {	/* See storlek test 16 */
		e->fxt = e->fxp = 0;
	}
	break;
    case FX_NONE:		/* No effect */
	e->fxt = e->fxp = 0;
	break;
    }
}
コード例 #20
0
ファイル: mmd_common.c プロジェクト: bithorder/libxmp
void mmd_xlat_fx(struct xmp_event *event, int bpm_on, int bpmlen, int med_8ch)
{
	if (event->fxt > 0x0f) {
		event->fxt = event->fxp = 0;
		return;
	}

	switch (event->fxt) {
	case 0x05:		/* Old vibrato */
		event->fxp = (LSN(event->fxp) << 4) | MSN(event->fxp);
		break;
	case 0x06:		/* Not defined in MED 3.2 */
	case 0x07:		/* Not defined in MED 3.2 */
		break;
	case 0x08:		/* Set hold/decay */
		break;
	case 0x09:		/* Set secondary tempo */
		event->fxt = FX_SPEED;
		break;
	case 0x0d:		/* Volume slide */
		event->fxt = FX_VOLSLIDE;
		break;
	case 0x0e:		/* Synth JMP */
		break;
	case 0x0f:
		if (event->fxp == 0x00) {	/* Jump to next block */
			event->fxt = 0x0d;
			break;
		} else if (event->fxp <= 0xf0) {
			event->fxt = FX_S3M_BPM;
                        event->fxp = med_8ch ? mmd_get_8ch_tempo(event->fxp) : (bpm_on ? event->fxp/bpmlen : event->fxp);
			break;
		} else switch (event->fxp) {
		case 0xf1:	/* Play note twice */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_RETRIG << 4) | 3;
			break;
		case 0xf2:	/* Delay note */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_DELAY << 4) | 3;
			break;
		case 0xf3:	/* Play note three times */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_RETRIG << 4) | 2;
			break;
		case 0xf8:	/* Turn filter off */
		case 0xf9:	/* Turn filter on */
		case 0xfa:	/* MIDI pedal on */
		case 0xfb:	/* MIDI pedal off */
		case 0xfd:	/* Set pitch */
		case 0xfe:	/* End of song */
			event->fxt = event->fxp = 0;
			break;
		case 0xff:	/* Note cut */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_CUT << 4) | 3;
			break;
		default:
			event->fxt = event->fxp = 0;
		}
		break;
	}
}
コード例 #21
0
ファイル: gal4_load.c プロジェクト: GenericHero/libxmp-3ds
static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
{
	struct xmp_module *mod = &m->mod;
	struct local_data *data = (struct local_data *)parm;
	int i, j;
	int srate, finetune, flags;
	int val, vwf, vra, vde, vsw, fade;
	uint8 buf[30];

	hio_read8(f);		/* 00 */
	i = hio_read8(f);		/* instrument number */

	hio_read(&mod->xxi[i].name, 1, 28, f);
	adjust_string((char *)mod->xxi[i].name);

	mod->xxi[i].nsm = hio_read8(f);

	for (j = 0; j < 108; j++) {
		mod->xxi[i].map[j].ins = hio_read8(f);
	}

	hio_seek(f, 11, SEEK_CUR);		/* unknown */
	vwf = hio_read8(f);			/* vibrato waveform */
	vsw = hio_read8(f);			/* vibrato sweep */
	hio_read8(f);			/* unknown */
	hio_read8(f);			/* unknown */
	vde = hio_read8(f);		/* vibrato depth */
	vra = hio_read16l(f) / 16;		/* vibrato speed */
	hio_read8(f);			/* unknown */

	val = hio_read8(f);			/* PV envelopes flags */
	if (LSN(val) & 0x01)
		mod->xxi[i].aei.flg |= XMP_ENVELOPE_ON;
	if (LSN(val) & 0x02)
		mod->xxi[i].aei.flg |= XMP_ENVELOPE_SUS;
	if (LSN(val) & 0x04)
		mod->xxi[i].aei.flg |= XMP_ENVELOPE_LOOP;
	if (MSN(val) & 0x01)
		mod->xxi[i].pei.flg |= XMP_ENVELOPE_ON;
	if (MSN(val) & 0x02)
		mod->xxi[i].pei.flg |= XMP_ENVELOPE_SUS;
	if (MSN(val) & 0x04)
		mod->xxi[i].pei.flg |= XMP_ENVELOPE_LOOP;

	val = hio_read8(f);			/* PV envelopes points */
	mod->xxi[i].aei.npt = LSN(val) + 1;
	mod->xxi[i].pei.npt = MSN(val) + 1;

	val = hio_read8(f);			/* PV envelopes sustain point */
	mod->xxi[i].aei.sus = LSN(val);
	mod->xxi[i].pei.sus = MSN(val);

	val = hio_read8(f);			/* PV envelopes loop start */
	mod->xxi[i].aei.lps = LSN(val);
	mod->xxi[i].pei.lps = MSN(val);

	hio_read8(f);			/* PV envelopes loop end */
	mod->xxi[i].aei.lpe = LSN(val);
	mod->xxi[i].pei.lpe = MSN(val);

	if (mod->xxi[i].aei.npt <= 0 || mod->xxi[i].aei.npt >= XMP_MAX_ENV_POINTS)
		mod->xxi[i].aei.flg &= ~XMP_ENVELOPE_ON;

	if (mod->xxi[i].pei.npt <= 0 || mod->xxi[i].pei.npt >= XMP_MAX_ENV_POINTS)
		mod->xxi[i].pei.flg &= ~XMP_ENVELOPE_ON;

	hio_read(buf, 1, 30, f);		/* volume envelope points */;
	for (j = 0; j < mod->xxi[i].aei.npt; j++) {
		mod->xxi[i].aei.data[j * 2] = readmem16l(buf + j * 3) / 16;
		mod->xxi[i].aei.data[j * 2 + 1] = buf[j * 3 + 2];
	}

	hio_read(buf, 1, 30, f);		/* pan envelope points */;
	for (j = 0; j < mod->xxi[i].pei.npt; j++) {
		mod->xxi[i].pei.data[j * 2] = readmem16l(buf + j * 3) / 16;
		mod->xxi[i].pei.data[j * 2 + 1] = buf[j * 3 + 2];
	}

	fade = hio_read8(f);		/* fadeout - 0x80->0x02 0x310->0x0c */
	hio_read8(f);			/* unknown */

	D_(D_INFO "[%2X] %-28.28s  %2d ", i, mod->xxi[i].name, mod->xxi[i].nsm);

	if (mod->xxi[i].nsm == 0)
		return 0;

	if (subinstrument_alloc(mod, i, mod->xxi[i].nsm) < 0)
		return -1;

	for (j = 0; j < mod->xxi[i].nsm; j++, data->snum++) {
		hio_read32b(f);	/* SAMP */
		hio_read32b(f);	/* size */
	
		hio_read(&mod->xxs[data->snum].name, 1, 28, f);
		adjust_string((char *)mod->xxs[data->snum].name);
	
		mod->xxi[i].sub[j].pan = hio_read8(f) * 4;
		if (mod->xxi[i].sub[j].pan == 0)	/* not sure about this */
			mod->xxi[i].sub[j].pan = 0x80;
		
		mod->xxi[i].sub[j].vol = hio_read8(f);
		flags = hio_read8(f);
		hio_read8(f);	/* unknown - 0x80 */

		mod->xxi[i].sub[j].vwf = vwf;
		mod->xxi[i].sub[j].vde = vde;
		mod->xxi[i].sub[j].vra = vra;
		mod->xxi[i].sub[j].vsw = vsw;
		mod->xxi[i].sub[j].sid = data->snum;
	
		mod->xxs[data->snum].len = hio_read32l(f);
		mod->xxs[data->snum].lps = hio_read32l(f);
		mod->xxs[data->snum].lpe = hio_read32l(f);
	
		mod->xxs[data->snum].flg = 0;
		if (flags & 0x04)
			mod->xxs[data->snum].flg |= XMP_SAMPLE_16BIT;
		if (flags & 0x08)
			mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP;
		if (flags & 0x10)
			mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP_BIDIR;
		/* if (flags & 0x80)
			mod->xxs[data->snum].flg |= ? */
	
		srate = hio_read32l(f);
		finetune = 0;
		c2spd_to_note(srate, &mod->xxi[i].sub[j].xpo, &mod->xxi[i].sub[j].fin);
		mod->xxi[i].sub[j].fin += finetune;
	
		hio_read32l(f);			/* 0x00000000 */
		hio_read32l(f);			/* unknown */
	
		D_(D_INFO "  %X: %05x%c%05x %05x %c V%02x P%02x %5d",
			j, mod->xxs[data->snum].len,
			mod->xxs[data->snum].flg & XMP_SAMPLE_16BIT ? '+' : ' ',
			mod->xxs[data->snum].lps,
			mod->xxs[data->snum].lpe,
			mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' : 
			mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
			mod->xxi[i].sub[j].vol,
			mod->xxi[i].sub[j].pan,
			srate);
	
		if (mod->xxs[data->snum].len > 1) {
			int snum = data->snum;
			if (load_sample(m, f, 0, &mod->xxs[snum], NULL) < 0)
				return -1;
		}
	}

	return 0;
}
コード例 #22
0
ファイル: dbm_load.c プロジェクト: cmatsuoka/chiptune.js
static void get_patt(struct module_data *m, int size, FILE *f, void *parm)
{
	struct xmp_module *mod = &m->mod;
	int i, c, r, n, sz;
	struct xmp_event *event, dummy;
	uint8 x;

	PATTERN_INIT();

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

	/*
	 * Note: channel and flag bytes are inverted in the format
	 * description document
	 */

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

		sz = read32b(f);
		//printf("rows = %d, size = %d\n", mod->xxp[i]->rows, sz);

		r = 0;
		c = -1;

		while (sz > 0) {
			//printf("  offset=%x,  sz = %d, ", ftell(f), sz);
			c = read8(f);
			if (--sz <= 0) break;
			//printf("c = %02x\n", c);

			if (c == 0) {
				r++;
				c = -1;
				continue;
			}
			c--;

			n = read8(f);
			if (--sz <= 0) break;
			//printf("    n = %d\n", n);

			if (c >= mod->chn || r >= mod->xxp[i]->rows)
				event = &dummy;
			else
				event = &EVENT(i, c, r);

			if (n & 0x01) {
				x = read8(f);
				event->note = 13 + MSN(x) * 12 + LSN(x);
				if (--sz <= 0) break;
			}
			if (n & 0x02) {
				event->ins = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x04) {
				event->fxt = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x08) {
				event->fxp = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x10) {
				event->f2t = read8(f);
				if (--sz <= 0) break;
			}
			if (n & 0x20) {
				event->f2p = read8(f);
				if (--sz <= 0) break;
			}

			if (event->fxt == 0x1c)
				event->fxt = FX_S3M_BPM;

			if (event->fxt > 0x1c)
				event->fxt = event->f2p = 0;

			if (event->f2t == 0x1c)
				event->f2t = FX_S3M_BPM;

			if (event->f2t > 0x1c)
				event->f2t = event->f2p = 0;
		}
	}
}
コード例 #23
0
ファイル: xm_load.c プロジェクト: GenericHero/libxmp-3ds
static int load_patterns(struct module_data *m, int version, HIO_HANDLE *f)
{
    struct xmp_module *mod = &m->mod;
    struct xm_pattern_header xph;
    struct xmp_event *event;
    uint8 *patbuf, *pat, b;
    int i, j, r;

    mod->pat++;
    if (pattern_init(mod) < 0)
	return -1;

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

    /* Endianism fixed by Miodrag Vallat <*****@*****.**>
     * Mon, 04 Jan 1999 11:17:20 +0100
     */
    for (i = 0; i < mod->pat - 1; i++) {
    	const int headsize = version > 0x0102 ? 9 : 8;

	xph.length = hio_read32l(f);
	xph.packing = hio_read8(f);
	xph.rows = version > 0x0102 ? hio_read16l(f) : hio_read8(f) + 1;

	/* Sanity check */
	if (xph.rows > 256)
	    goto err;

	xph.datasize = hio_read16l(f);
	hio_seek(f, xph.length - headsize, SEEK_CUR);
	if (hio_error(f)) {
            goto err;
	}

	r = xph.rows;
	if (r == 0)
	    r = 0x100;

	if (pattern_tracks_alloc(mod, i, r) < 0)
	    goto err;

	if (xph.datasize) {
	    int size = xph.datasize;

	    pat = patbuf = calloc(1, size);
	    if (patbuf == NULL)
		goto err;

	    hio_read(patbuf, 1, size, f);
	    for (j = 0; j < (mod->chn * r); j++) {

		/*if ((pat - patbuf) >= xph.datasize)
		    break;*/

		event = &EVENT(i, j % mod->chn, j / mod->chn);

		if (--size < 0)
		    goto err2;

		if ((b = *pat++) & XM_EVENT_PACKING) {
		    if (b & XM_EVENT_NOTE_FOLLOWS) {
			if (--size < 0)
			    goto err2;
			event->note = *pat++;
		    }
		    if (b & XM_EVENT_INSTRUMENT_FOLLOWS) {
			if (--size < 0)
			    goto err2;
			event->ins = *pat++;
		    }
		    if (b & XM_EVENT_VOLUME_FOLLOWS) {
			if (--size < 0)
			    goto err2;
			event->vol = *pat++;
		    }
		    if (b & XM_EVENT_FXTYPE_FOLLOWS) {
			if (--size < 0)
			    goto err2;
			event->fxt = *pat++;
		    }
		    if (b & XM_EVENT_FXPARM_FOLLOWS) {
			if (--size < 0)
			    goto err2;
			event->fxp = *pat++;
		    }
		} else {
                    size -=4;
		    if (size < 0)
			goto err2;
		    event->note = b;
		    event->ins = *pat++;
		    event->vol = *pat++;
		    event->fxt = *pat++;
		    event->fxp = *pat++;
		}

		/* Sanity check */
		switch (event->fxt) {
		case 18: case 19:
		case 22: case 23: case 24:
		case 26:
		case 28:
		case 30: case 31: case 32:
			event->fxt = 0;
		}
		if (event->fxt > 34) {
			event->fxt = 0;
		}

		if (event->note == 0x61) {
		    /* See OpenMPT keyoff+instr.xm test case */
		    if (event->fxt == 0x0e && MSN(event->fxp) == 0x0d) {
			event->note = XMP_KEY_OFF;
		    } else {
		    	event->note = event->ins ? XMP_KEY_FADE : XMP_KEY_OFF;
		    }
		} else if (event->note > 0) {
		    event->note += 12;
		}

		if (event->fxt == 0x0e) {
			switch (event->fxp) {
			case 0x43:
			case 0x73:
				event->fxp--;
				break;
			}
		}

		if (!event->vol)
		    continue;

		/* Volume set */
		if ((event->vol >= 0x10) && (event->vol <= 0x50)) {
		    event->vol -= 0x0f;
		    continue;
		}
		/* Volume column effects */
		switch (event->vol >> 4) {
		case 0x06:	/* Volume slide down */
		    event->f2t = FX_VOLSLIDE_2;
		    event->f2p = event->vol - 0x60;
		    break;
		case 0x07:	/* Volume slide up */
		    event->f2t = FX_VOLSLIDE_2;
		    event->f2p = (event->vol - 0x70) << 4;
		    break;
		case 0x08:	/* Fine volume slide down */
		    event->f2t = FX_EXTENDED;
		    event->f2p = (EX_F_VSLIDE_DN << 4) | (event->vol - 0x80);
		    break;
		case 0x09:	/* Fine volume slide up */
		    event->f2t = FX_EXTENDED;
		    event->f2p = (EX_F_VSLIDE_UP << 4) | (event->vol - 0x90);
		    break;
		case 0x0a:	/* Set vibrato speed */
		    event->f2t = FX_VIBRATO;
		    event->f2p = (event->vol - 0xa0) << 4;
		    break;
		case 0x0b:	/* Vibrato */
		    event->f2t = FX_VIBRATO;
		    event->f2p = event->vol - 0xb0;
		    break;
		case 0x0c:	/* Set panning */
		    event->f2t = FX_SETPAN;
		    event->f2p = (event->vol - 0xc0) << 4;
		    break;
		case 0x0d:	/* Pan slide left */
		    event->f2t = FX_PANSL_NOMEM;
		    event->f2p = (event->vol - 0xd0) << 4;
		    break;
		case 0x0e:	/* Pan slide right */
		    event->f2t = FX_PANSL_NOMEM;
		    event->f2p = event->vol - 0xe0;
		    break;
		case 0x0f:	/* Tone portamento */
		    event->f2t = FX_TONEPORTA;
		    event->f2p = (event->vol - 0xf0) << 4;

		    /* From OpenMPT TonePortamentoMemory.xm:
		     * "Another nice bug (...) is the combination of both
		     *  portamento commands (Mx and 3xx) in the same cell:
		     *  The 3xx parameter is ignored completely, and the Mx
		     *  parameter is doubled. (M2 3FF is the same as M4 000)
		     */
		    if (event->fxt == FX_TONEPORTA || event->fxt == FX_TONE_VSLIDE) {
			if (event->fxt == FX_TONEPORTA) {
			    event->fxt = 0;
			} else {
			    event->fxt = FX_VOLSLIDE;
			}
			event->fxp = 0;

			if (event->f2p < 0x80) {
				event->f2p <<= 1;
			} else {
				event->f2p = 0xff;
			}
		    }

		    /* From OpenMPT porta-offset.xm:
		     * "If there is a portamento command next to an offset
		     *  command, the offset command is ignored completely. In
		     *  particular, the offset parameter is not memorized."
		     */
		    if (event->fxt == FX_OFFSET && event->f2t == FX_TONEPORTA) {
			event->fxt = event->fxp = 0;
		    }
		    break;
		}
		event->vol = 0;
	    }
	    free(patbuf);
	}
    }
コード例 #24
0
ファイル: far_load.c プロジェクト: cmatsuoka/chiptune.js
static int far_load(struct module_data *m, FILE *f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int i, j, vib = 0;
    struct xmp_event *event;
    struct far_header ffh;
    struct far_header2 ffh2;
    struct far_instrument fih;
    uint8 sample_map[8];

    LOAD_INIT();

    read32b(f);				/* File magic: 'FAR\xfe' */
    fread(&ffh.name, 40, 1, f);		/* Song name */
    fread(&ffh.crlf, 3, 1, f);		/* 0x0d 0x0a 0x1A */
    ffh.headersize = read16l(f);	/* Remaining header size in bytes */
    ffh.version = read8(f);		/* Version MSN=major, LSN=minor */
    fread(&ffh.ch_on, 16, 1, f);	/* Channel on/off switches */
    fseek(f, 9, SEEK_CUR);		/* Current editing values */
    ffh.tempo = read8(f);		/* Default tempo */
    fread(&ffh.pan, 16, 1, f);		/* Channel pan definitions */
    read32l(f);				/* Grid, mode (for editor) */
    ffh.textlen = read16l(f);		/* Length of embedded text */

    fseek(f, ffh.textlen, SEEK_CUR);	/* Skip song text */

    fread(&ffh2.order, 256, 1, f);	/* Orders */
    ffh2.patterns = read8(f);		/* Number of stored patterns (?) */
    ffh2.songlen = read8(f);		/* Song length in patterns */
    ffh2.restart = read8(f);		/* Restart pos */
    for (i = 0; i < 256; i++)
	ffh2.patsize[i] = read16l(f);	/* Size of each pattern in bytes */

    mod->chn = 16;
    /*mod->pat=ffh2.patterns; (Error in specs? --claudio) */
    mod->len = ffh2.songlen;
    mod->spd = 6;
    mod->bpm = 8 * 60 / ffh.tempo;
    memcpy (mod->xxo, ffh2.order, mod->len);

    for (mod->pat = i = 0; i < 256; i++) {
	if (ffh2.patsize[i])
	    mod->pat = i + 1;
    }

    mod->trk = mod->chn * mod->pat;

    strncpy(mod->name, (char *)ffh.name, 40);
    set_type(m, "Farandole Composer %d.%d", MSN(ffh.version), LSN(ffh.version));

    MODULE_INFO();

    PATTERN_INIT();

    /* Read and convert patterns */
    D_(D_INFO "Comment bytes  : %d", ffh.textlen);
    D_(D_INFO "Stored patterns: %d", mod->pat);

    for (i = 0; i < mod->pat; i++) {
	uint8 brk, note, ins, vol, fxb;

	PATTERN_ALLOC(i);
	if (!ffh2.patsize[i])
	    continue;
	mod->xxp[i]->rows = (ffh2.patsize[i] - 2) / 64;
	TRACK_ALLOC(i);

	brk = read8(f) + 1;
	read8(f);

	for (j = 0; j < mod->xxp[i]->rows * mod->chn; j++) {
	    event = &EVENT(i, j % mod->chn, j / mod->chn);

	    if ((j % mod->chn) == 0 && (j / mod->chn) == brk)
		event->f2t = FX_BREAK;
	
	    note = read8(f);
	    ins = read8(f);
	    vol = read8(f);
	    fxb = read8(f);

	    if (note)
		event->note = note + 48;
	    if (event->note || ins)
		event->ins = ins + 1;

	    vol = 16 * LSN(vol) + MSN(vol);

	    if (vol)
		event->vol = vol - 0x10;	/* ? */

	    event->fxt = fx[MSN(fxb)];
	    event->fxp = LSN(fxb);

	    switch (event->fxt) {
	    case NONE:
	        event->fxt = event->fxp = 0;
		break;
	    case FX_FAR_PORTA_UP:
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_F_PORTA_UP << 4);
		break;
	    case FX_FAR_PORTA_DN:
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_F_PORTA_DN << 4);
		break;
	    case FX_FAR_RETRIG:
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_RETRIG << 4);
		break;
	    case FX_FAR_DELAY:
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_DELAY << 4);
		break;
	    case FX_FAR_SETVIBRATO:
		vib = event->fxp & 0x0f;
		event->fxt = event->fxp = 0;
		break;
	    case FX_VIBRATO:
		event->fxp = (event->fxp << 4) + vib;
		break;
	    case FX_PER_VIBRATO:
		event->fxp = (event->fxp << 4) + vib;
		break;
	    case FX_FAR_VSLIDE_UP:	/* Fine volume slide up */
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_F_VSLIDE_UP << 4);
		break;
	    case FX_FAR_VSLIDE_DN:	/* Fine volume slide down */
		event->fxt = FX_EXTENDED;
		event->fxp |= (EX_F_VSLIDE_DN << 4);
		break;
	    case FX_SPEED:
		event->fxp = 8 * 60 / event->fxp;
		break;
	    }
	}
    }

    mod->ins = -1;
    fread(sample_map, 1, 8, f);
    for (i = 0; i < 64; i++) {
	if (sample_map[i / 8] & (1 << (i % 8)))
		mod->ins = i;
    }
    mod->ins++;

    mod->smp = mod->ins;

    INSTRUMENT_INIT();

    /* Read and convert instruments and samples */

    for (i = 0; i < mod->ins; i++) {
	if (!(sample_map[i / 8] & (1 << (i % 8))))
		continue;

	mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1);

	fread(&fih.name, 32, 1, f);	/* Instrument name */
	fih.length = read32l(f);	/* Length of sample (up to 64Kb) */
	fih.finetune = read8(f);	/* Finetune (unsuported) */
	fih.volume = read8(f);		/* Volume (unsuported?) */
	fih.loop_start = read32l(f);	/* Loop start */
	fih.loopend = read32l(f);	/* Loop end */
	fih.sampletype = read8(f);	/* 1=16 bit sample */
	fih.loopmode = read8(f);

	fih.length &= 0xffff;
	fih.loop_start &= 0xffff;
	fih.loopend &= 0xffff;
	mod->xxs[i].len = fih.length;
	mod->xxi[i].nsm = fih.length > 0 ? 1 : 0;
	mod->xxs[i].lps = fih.loop_start;
	mod->xxs[i].lpe = fih.loopend;
	mod->xxs[i].flg = 0;

	if (fih.sampletype != 0) {
		mod->xxs[i].flg |= XMP_SAMPLE_16BIT;
		mod->xxs[i].len >>= 1;
		mod->xxs[i].lps >>= 1;
		mod->xxs[i].lpe >>= 1;
	}

	mod->xxs[i].flg |= fih.loopmode ? XMP_SAMPLE_LOOP : 0;
	mod->xxi[i].sub[0].vol = 0xff; /* fih.volume; */
	mod->xxi[i].sub[0].sid = i;

	copy_adjust(mod->xxi[i].name, fih.name, 32);

	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, fih.loopmode ? 'L' : ' ', mod->xxi[i].sub[0].vol);

	load_sample(f, 0, &mod->xxs[i], NULL);
    }
コード例 #25
0
ファイル: mmd_common.c プロジェクト: neuschaefer/libxmp
void mmd_xlat_fx(struct xmp_event *event, int bpm_on, int bpmlen, int med_8ch,
		 int hexvol)
{
	switch (event->fxt) {
	case 0x00:
		/* ARPEGGIO 00
		 * Changes the pitch six times between three different
		 * pitches during the duration of the note. It can create a
		 * chord sound or other special effect. Arpeggio works better
		 * with some instruments than others.
		 */
		/* fall-through */
	case 0x01:
		/* SLIDE UP 01
		 * This slides the pitch of the current track up. It decreases
		 * the period of the note by the amount of the argument on each
		 * timing pulse. OctaMED-Pro can create slides automatically,
		 * but you may want to use this function for special effects.
		 */
		/* fall-through */
	case 0x02:
		/* SLIDE DOWN 02
		 * The same as SLIDE UP, but it slides down.
		 */
		/* fall-through */
	case 0x03:
		/* PORTAMENTO 03
		 * Makes precise sliding easy.
		 */
		break;
	case 0x04:
		/* VIBRATO 04
		 * The left half of the argument is the vibrato speed, the
		 * right half is the depth. If the numbers are zeros, the
		 * previous speed and depth are used.
		 */
		/* Note: this is twice as deep as the Protracker vibrato */
		event->fxt = FX_VIBRATO2;
		break;
	case 0x05:
		/* SLIDE + FADE 05
		 * ProTracker compatible. This command is the combination of
		 * commands 0300 and 0Dxx. The argument is the fade speed.
		 * The slide will continue during this command.
		 */
		/* fall-through */
	case 0x06:
		/* VIBRATO + FADE 06
		 * ProTracker compatible. Combines commands 0400 and 0Dxx.
		 * The argument is the fade speed. The vibrato will continue
		 * during this command.
		 */
		/* fall-through */
	case 0x07:
		/* TREMOLO 07
		 * ProTracker compatible.
		 * This command is a kind of "volume vibrato". The left
		 * number is the speed of the tremolo, and the right one is
		 * the depth. The depth must be quite high before the effect
		 * is audible.
		 */
		break;
	case 0x08:
		/* HOLD and DECAY 08
		 * This command must be on the same line as the note. The
		 * left half of the argument determines the decay and the
		 * right half the hold.
		 */
		event->fxt = event->fxp = 0;
		break;
	case 0x09:
		/* SECONDARY TEMPO 09
		 * This sets the secondary tempo (the number of timing
		 * pulses per note). The argument must be from 01 to 20.
		 */
		event->fxt = FX_SPEED;
		break;
	case 0x0a:
		/* 0A not mentioned but it's Protracker-compatible */
		/* fall-through */
	case 0x0b:
		/* POSITION JUMP 0B
		 * The song plays up to this command and then jumps to
		 * another position in the play sequence. The song then
		 * loops from the point jumped to, to the end of the song
		 * forever. The purpose is to allow for introductions that
		 * play only once.
		 */
		/* fall-through */
	case 0x0c:
		/* SET VOLUME 0C
		 * Overrides the default volume of an instrument.
		 */
		if (!hexvol) {
			int p = event->fxp;
			event->fxp = (p >> 8) * 10 + (p & 0xff);
		}
		break;
	case 0x0d:
		/* VOLUME SLIDE 0D
		 * Smoothly slides the volume up or down. The left half of
		 * the argument increases the volume. The right decreases it.
		 */
		event->fxt = FX_VOLSLIDE;
		break;
	case 0x0e:
		/* SYNTH JUMP 0E
		 * When used with synthetic or hybrid instruments, it
		 * triggers a jump in the Waveform Sequence List. The argument
		 * is the jump destination (line no).
		 */
		event->fxt = event->fxp = 0;
		break;
	case 0x0f:
		/* MISCELLANEOUS 0F
		 * The effect depends upon the value of the argument.
		 */
		if (event->fxp == 0x00) {	/* Jump to next block */
			event->fxt = 0x0d;
			break;
		} else if (event->fxp <= 0xf0) {
			event->fxt = FX_S3M_BPM;
                        event->fxp = med_8ch ? get_8ch_tempo(event->fxp) : event->fxp;
			break;
		} else switch (event->fxp) {
		case 0xf1:	/* Play note twice */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_RETRIG << 4) | 3;
			break;
		case 0xf2:	/* Delay note */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_DELAY << 4) | 3;
			break;
		case 0xf3:	/* Play note three times */
			event->fxt = FX_EXTENDED;
			event->fxp = (EX_RETRIG << 4) | 2;
			break;
		case 0xf8:	/* Turn filter off */
		case 0xf9:	/* Turn filter on */
		case 0xfa:	/* MIDI pedal on */
		case 0xfb:	/* MIDI pedal off */
		case 0xfd:	/* Set pitch */
		case 0xfe:	/* End of song */
			event->fxt = event->fxp = 0;
			break;
		case 0xff:	/* Turn note off */
			event->fxt = event->fxp = 0;
			event->note = XMP_KEY_CUT;
			break;
		default:
			event->fxt = event->fxp = 0;
		}
		break;
	case 0x11:
		/* SLIDE PITCH UP (only once) 11
		 * Equivalent to ProTracker command E1x.
		 * Lets you control the pitch with great accuracy. This
		 * command changes only this occurrence of the note.
		 */
		event->fxt = FX_F_PORTA_UP;
		break;
	case 0x12:
		/* SLIDE DOWN (only once) 12
		 * Equivalent to ProTracker command E2x.
		 */
		event->fxt = FX_F_PORTA_DN;
		break;
	case 0x14:
		/* VIBRATO 14
		 * ProTracker compatible. This is similar to command 04
		 * except the depth is halved, to give greater accuracy.
		 */
		event->fxt = FX_VIBRATO;
		break;
	case 0x15:
		/* SET FINETUNE 15
		 * Set a finetune value for a note, overrides the default
		 * fine tune value of the instrument. Negative numbers must
		 * be entered as follows:
		 *   -1 => FF    -3 => FD    -5 => FB    -7 => F9
		 *   -2 => FE    -4 => FC    -6 => FA    -8 => F8
		 */
		event->fxt = FX_FINETUNE;
		event->fxp = (event->fxp + 8) << 4;
		break;
	case 0x16:
		/* LOOP 16
		 * Creates a loop within a block. 1600 marks the beginning
		 * of the loop.  The next occurrence of the 16 command
		 * designates the number of loops. Same as ProTracker E6x.
		 */
		event->fxt = FX_EXTENDED;
		if (event->fxp > 0x0f)
			event->fxp = 0x0f;
		event->fxp |= 0x60;
		break;
	case 0x18:
		/* STOP NOTE 18
		 * Cuts the note by zeroing the volume at the pulse specified
		 * in the argument value. This is the same as ProTracker
		 * command ECx.
		 */
		event->fxt = FX_EXTENDED;
		if (event->fxp > 0x0f)
			event->fxp = 0x0f;
		event->fxp |= 0xc0;
		break;
	case 0x19:
		/* SET SAMPLE START OFFSET
		 * Same as ProTracker command 9.
		 * When playing a sample, this command sets the starting
		 * offset (at steps of $100 = 256 bytes). Useful for speech
		 * samples.
		 */
		event->fxt = FX_OFFSET;
		break;
	case 0x1a:
		/* SLIDE VOLUME UP ONCE
		 * Only once ProTracker command EAx. Lets volume slide
		 * slowly once per line.
		 */
		event->fxt = FX_F_VSLIDE_UP;
		break;
	case 0x1b:
		/* VOLUME DOWN?
		 * Only once ProTracker command EBx ?
		 */
		event->fxt = FX_F_VSLIDE_DN;
		break;
	case 0x1d:
		/* JUMP TO NEXT BLOCK 1D
		 * Jumps to the next line in the PLAY SEQUENCE LIST at the
		 * specified line. ProTracker command D. This command is
		 * like F00, except that you can specify the line number of
		 * the first line to be played. The line number must be
		 * specified in HEX.
		 */
		event->fxt = FX_BREAK;
		break;
	case 0x1e:
		/* PLAY LINE x TIMES 1E
		 * Plays only commands, notes not replayed. ProTracker
		 * pattern delay.
		 */
		event->fxt = FX_PATT_DELAY;
		break;
	case 0x1f:
		/* Command 1F: NOTE DELAY AND RETRIGGER
		 * (Protracker commands EC and ED)
		 * Gives you accurate control over note playing. You can
		 * delay the note any number of ticks, and initiate fast
		 * retrigger. Level 1 = note delay value, level 2 = retrigger
		 * value.
		 */
		if (MSN(event->fxp)) {
			/* delay */
			event->fxt = FX_EXTENDED;
			event->fxp = 0xd0 | (event->fxp >> 4);
		} else if (LSN(event->fxp)) {
コード例 #26
0
ファイル: okt_load.c プロジェクト: bithorder/libxmp
static void get_pbod(struct module_data *m, int size, xmp_file f, void *parm)
{
    struct xmp_module *mod = &m->mod;
    struct local_data *data = (struct local_data *)parm;

    int j;
    uint16 rows;
    struct xmp_event *event;

    if (data->pattern >= mod->pat)
	return;

    if (!data->pattern) {
	PATTERN_INIT();
	D_(D_INFO "Stored patterns: %d", mod->pat);
    }

    rows = read16b(f);

    PATTERN_ALLOC(data->pattern);
    mod->xxp[data->pattern]->rows = rows;
    TRACK_ALLOC(data->pattern);

    for (j = 0; j < rows * mod->chn; j++) {
	uint8 note, ins;

	event = &EVENT(data->pattern, j % mod->chn, j / mod->chn);
	memset(event, 0, sizeof(struct xmp_event));

	note = read8(f);
	ins = read8(f);

	if (note) {
	    event->note = 48 + note;
	    event->ins = 1 + ins;
	}

	event->fxt = fx[read8(f)];
	event->fxp = read8(f);

	if ((event->fxt == FX_VOLSET) && (event->fxp > 0x40)) {
	    if (event->fxp <= 0x50) {
		event->fxt = FX_VOLSLIDE;
		event->fxp -= 0x40;
	    } else if (event->fxp <= 0x60) {
		event->fxt = FX_VOLSLIDE;
		event->fxp = (event->fxp - 0x50) << 4;
	    } else if (event->fxp <= 0x70) {
		event->fxt = FX_EXTENDED;
		event->fxp = (EX_F_VSLIDE_DN << 4) | (event->fxp - 0x60);
	    } else if (event->fxp <= 0x80) {
		event->fxt = FX_EXTENDED;
		event->fxp = (EX_F_VSLIDE_UP << 4) | (event->fxp - 0x70);
	    }
	}
	if (event->fxt == FX_ARPEGGIO)	/* Arpeggio fixup */
	    event->fxp = (((24 - MSN (event->fxp)) % 12) << 4) | LSN (event->fxp);
	if (event->fxt == NONE)
	    event->fxt = event->fxp = 0;
    }
    data->pattern++;
}
コード例 #27
0
ファイル: polly_load.c プロジェクト: cmatsuoka/chiptune.js
static int polly_load(struct module_data *m, FILE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_event *event;
	uint8 *buf;
	int i, j, k;

	LOAD_INIT();

	read8(f);			/* skip 0xae */
	/*
	 * File is RLE-encoded, escape is 0xAE (Aleksi Eeben's initials).
	 * Actual 0xAE is encoded as 0xAE 0x01
	 */
	if ((buf = calloc(1, 0x10000)) == NULL)
		return -1;

	decode_rle(buf, f, 0x10000);

	for (i = 0; buf[ORD_OFS + i] != 0 && i < 128; i++)
		mod->xxo[i] = buf[ORD_OFS + i] - 0xe0;
	mod->len = i;

	memcpy(mod->name, buf + ORD_OFS + 160, 16);
	/* memcpy(m->author, buf + ORD_OFS + 176, 16); */
	set_type(m, "Polly Tracker");
	MODULE_INFO();

	mod->spd = 0x03;
	mod->bpm = 0x7d * buf[ORD_OFS + 193] / 0x88;
#if 0
	for (i = 0; i < 1024; i++) {
		if ((i % 16) == 0) printf("\n");
		printf("%02x ", buf[ORD_OFS + i]);
	}
#endif

	mod->pat = 0;
	for (i = 0; i < mod->len; i++) {
		if (mod->xxo[i] > mod->pat)
			mod->pat = mod->xxo[i];
	}
	mod->pat++;
	
	mod->chn = 4;
	mod->trk = mod->pat * mod->chn;

	PATTERN_INIT();

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

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

		for (j = 0; j < 64; j++) {
			for (k = 0; k < 4; k++) {
				uint8 x = buf[i * PAT_SIZE + j * 4 + k];
				event = &EVENT(i, k, j);
				if (x == 0xf0) {
					event->fxt = FX_BREAK;
					event->fxp = 0;
					continue;
				}
				event->note = LSN(x);
				if (event->note)
					event->note += 48;
				event->ins = MSN(x);
			}
		}
	}

	mod->ins = mod->smp = 15;
	INSTRUMENT_INIT();

	for (i = 0; i < 15; i++) {
		mod->xxi[i].sub = calloc(sizeof (struct xmp_subinstrument), 1);
		mod->xxs[i].len = buf[ORD_OFS + 129 + i] < 0x10 ? 0 :
					256 * buf[ORD_OFS + 145 + i];
		mod->xxi[i].sub[0].fin = 0;
		mod->xxi[i].sub[0].vol = 0x40;
		mod->xxs[i].lps = 0;
		mod->xxs[i].lpe = 0;
		mod->xxs[i].flg = 0;
		mod->xxi[i].sub[0].pan = 0x80;
		mod->xxi[i].sub[0].sid = i;
		mod->xxi[i].nsm = !!(mod->xxs[i].len);
		mod->xxi[i].rls = 0xfff;

                D_(D_INFO "[%2X] %04x %04x %04x %c V%02x",
                       		i, mod->xxs[i].len, mod->xxs[i].lps,
                        	mod->xxs[i].lpe, ' ', mod->xxi[i].sub[0].vol);
	}

	/* Convert samples from 6 to 8 bits */
	for (i = SMP_OFS; i < 0x10000; i++)
		buf[i] = buf[i] << 2;

	/* Read samples */
	D_(D_INFO "Loading samples: %d", mod->ins);

	for (i = 0; i < mod->ins; i++) {
		if (mod->xxs[i].len == 0)
			continue;
		load_sample(NULL, SAMPLE_FLAG_NOLOAD | SAMPLE_FLAG_UNS,
				&mod->xxs[mod->xxi[i].sub[0].sid],
				(char*)buf + ORD_OFS + 256 +
					256 * (buf[ORD_OFS + 129 + i] - 0x10));
	}

	free(buf);

	/* make it mono */
	for (i = 0; i < mod->chn; i++)
		mod->xxc[i].pan = 0x80;

	m->quirk |= QUIRK_MODRNG;

	return 0;
}
コード例 #28
0
ファイル: psm_load.c プロジェクト: cmatsuoka/libxmp
static int psm_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	int c, r, i;
	struct xmp_event *event;
	uint8 buf[1024];
	uint32 p_ord, p_chn, p_pat, p_ins;
	uint32 p_smp[64];
	int type, ver /*, mode*/;
 
	LOAD_INIT();

	hio_read32b(f);

	hio_read(buf, 1, 60, f);
	strncpy(mod->name, (char *)buf, 60);

	type = hio_read8(f);		/* song type */
	ver = hio_read8(f);		/* song version */
	/*mode =*/ hio_read8(f);	/* pattern version */

	if (type & 0x01)		/* song mode not supported */
		return -1;

	libxmp_set_type(m, "Protracker Studio PSM %d.%02d", MSN(ver), LSN(ver));

	mod->spd = hio_read8(f);
	mod->bpm = hio_read8(f);
	hio_read8(f);			/* master volume */
	hio_read16l(f);			/* song length */
	mod->len = hio_read16l(f);
	mod->pat = hio_read16l(f);
	mod->ins = hio_read16l(f);
	hio_read16l(f);			/* ignore channels to play */
	mod->chn = hio_read16l(f);	/* use channels to proceed */
	mod->smp = mod->ins;
	mod->trk = mod->pat * mod->chn;

	/* Sanity check */
	if (mod->len > 256 || mod->pat > 256 || mod->ins > 255 ||
	    mod->chn > XMP_MAX_CHANNELS) {
		return -1;
        }

	p_ord = hio_read32l(f);
	p_chn = hio_read32l(f);
	p_pat = hio_read32l(f);
	p_ins = hio_read32l(f);

	/* should be this way but fails with Silverball song 6 */
	//mod->flg |= ~type & 0x02 ? XXM_FLG_MODRNG : 0;

	m->c4rate = C4_NTSC_RATE;

	MODULE_INFO();

	hio_seek(f, start + p_ord, SEEK_SET);
	hio_read(mod->xxo, 1, mod->len, f);

	hio_seek(f, start + p_chn, SEEK_SET);
	hio_read(buf, 1, 16, f);

	if (libxmp_init_instrument(m) < 0)
		return -1;

	hio_seek(f, start + p_ins, SEEK_SET);
	for (i = 0; i < mod->ins; i++) {
		uint16 flags, c2spd;
		int finetune;

		if (libxmp_alloc_subinstrument(mod, i, 1) < 0)
			return -1;

		hio_read(buf, 1, 13, f);	/* sample filename */
		hio_read(buf, 1, 24, f);	/* sample description */
		buf[24] = 0;			/* add string termination */
		strncpy((char *)mod->xxi[i].name, (char *)buf, 24);
		p_smp[i] = hio_read32l(f);
		hio_read32l(f);			/* memory location */
		hio_read16l(f);			/* sample number */
		flags = hio_read8(f);		/* sample type */
		mod->xxs[i].len = hio_read32l(f); 
		mod->xxs[i].lps = hio_read32l(f);
		mod->xxs[i].lpe = hio_read32l(f);
		finetune = (int8)(hio_read8(f) << 4);
		mod->xxi[i].sub[0].vol = hio_read8(f);
		c2spd = hio_read16l(f);
		mod->xxi[i].sub[0].pan = 0x80;
		mod->xxi[i].sub[0].sid = i;
		mod->xxs[i].flg = flags & 0x80 ? XMP_SAMPLE_LOOP : 0;
		mod->xxs[i].flg |= flags & 0x20 ? XMP_SAMPLE_LOOP_BIDIR : 0;

		libxmp_c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo,
						&mod->xxi[i].sub[0].fin);
		mod->xxi[i].sub[0].fin += finetune;

		if (mod->xxs[i].len > 0)
			mod->xxi[i].nsm = 1;

		D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %5d",
			i, mod->xxi[i].name, mod->xxs[i].len, mod->xxs[i].lps,
			mod->xxs[i].lpe, mod->xxs[i].flg & XMP_SAMPLE_LOOP ?
			'L' : ' ', mod->xxi[i].sub[0].vol, c2spd);
	}
	
	if (libxmp_init_pattern(mod) < 0)
		return -1;

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

	hio_seek(f, start + p_pat, SEEK_SET);
	for (i = 0; i < mod->pat; i++) {
		int len;
		uint8 b, rows, chan;

		len = hio_read16l(f) - 4;
		rows = hio_read8(f);
		if (rows > 64) {
			return -1;
		}
		chan = hio_read8(f);
		if (chan > 32) {
			return -1;
		}

		if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0)
			return -1;

		for (r = 0; r < rows; r++) {
			while (len > 0) {
				b = hio_read8(f);
				len--;

				if (b == 0)
					break;
	
				c = b & 0x0f;
				if (c >= mod->chn)
					return -1;
				event = &EVENT(i, c, r);
	
				if (b & 0x80) {
					event->note = hio_read8(f) + 36 + 1;
					event->ins = hio_read8(f);
					len -= 2;
				}
	
				if (b & 0x40) {
					event->vol = hio_read8(f) + 1;
					len--;
				}
	
				if (b & 0x20) {
					event->fxt = hio_read8(f);
					event->fxp = hio_read8(f);
					len -= 2;
				}
			}
		}

		if (len > 0)
			hio_seek(f, len, SEEK_CUR);
	}

	/* Read samples */

	D_(D_INFO "Stored samples: %d", mod->smp);

	for (i = 0; i < mod->ins; i++) {
		hio_seek(f, start + p_smp[i], SEEK_SET);
		if (libxmp_load_sample(m, f, SAMPLE_FLAG_DIFF,
				&mod->xxs[mod->xxi[i].sub[0].sid], NULL) < 0)
			return -1;
	}

	return 0;
}
コード例 #29
0
ファイル: ptm_load.c プロジェクト: ProjectZeroSlackr/XMP
static int ptm_load(struct xmp_context *ctx, FILE *f, const int start)
{
    struct xmp_player_context *p = &ctx->p;
    struct xmp_mod_context *m = &p->m;
    int c, r, i, smp_ofs[256];
    struct xxm_event *event;
    struct ptm_file_header pfh;
    struct ptm_instrument_header pih;
    uint8 n, b;

    LOAD_INIT();

    /* Load and convert header */

    fread(&pfh.name, 28, 1, f);		/* Song name */
    pfh.doseof = read8(f);		/* 0x1a */
    pfh.vermin = read8(f);		/* Minor version */
    pfh.vermaj = read8(f);		/* Major type */
    pfh.rsvd1 = read8(f);		/* Reserved */
    pfh.ordnum = read16l(f);		/* Number of orders (must be even) */
    pfh.insnum = read16l(f);		/* Number of instruments */
    pfh.patnum = read16l(f);		/* Number of patterns */
    pfh.chnnum = read16l(f);		/* Number of channels */
    pfh.flags = read16l(f);		/* Flags (set to 0) */
    pfh.rsvd2 = read16l(f);		/* Reserved */
    pfh.magic = read32b(f); 		/* 'PTMF' */

#if 0
    if (pfh.magic != MAGIC_PTMF)
	return -1;
#endif

    fread(&pfh.rsvd3, 16, 1, f);	/* Reserved */
    fread(&pfh.chset, 32, 1, f);	/* Channel settings */
    fread(&pfh.order, 256, 1, f);	/* Orders */
    for (i = 0; i < 128; i++)
	pfh.patseg[i] = read16l(f);

    m->xxh->len = pfh.ordnum;
    m->xxh->ins = pfh.insnum;
    m->xxh->pat = pfh.patnum;
    m->xxh->chn = pfh.chnnum;
    m->xxh->trk = m->xxh->pat * m->xxh->chn;
    m->xxh->smp = m->xxh->ins;
    m->xxh->tpo = 6;
    m->xxh->bpm = 125;
    memcpy (m->xxo, pfh.order, 256);

    m->c4rate = C4_NTSC_RATE;

    copy_adjust((uint8 *)m->name, pfh.name, 28);
    sprintf(m->type, "PTMF %d.%02x (Poly Tracker)",
	pfh.vermaj, pfh.vermin);

    MODULE_INFO();

    INSTRUMENT_INIT();

    /* Read and convert instruments and samples */

    reportv(ctx, 1, "     Instrument name              Len   LBeg  LEnd  L Vol C4Spd\n");

    for (i = 0; i < m->xxh->ins; i++) {
	m->xxi[i] = calloc (sizeof (struct xxm_instrument), 1);

	pih.type = read8(f);			/* Sample type */
	fread(&pih.dosname, 12, 1, f);		/* DOS file name */
	pih.vol = read8(f);			/* Volume */
	pih.c4spd = read16l(f);			/* C4 speed */
	pih.smpseg = read16l(f);		/* Sample segment (not used) */
	pih.smpofs = read32l(f);		/* Sample offset */
	pih.length = read32l(f);		/* Length */
	pih.loopbeg = read32l(f);		/* Loop begin */
	pih.loopend = read32l(f);		/* Loop end */
	pih.gusbeg = read32l(f);		/* GUS begin address */
	pih.guslps = read32l(f);		/* GUS loop start address */
	pih.guslpe = read32l(f);		/* GUS loop end address */
	pih.gusflg = read8(f);			/* GUS loop flags */
	pih.rsvd1 = read8(f);			/* Reserved */
	fread(&pih.name, 28, 1, f);		/* Instrument name */
	pih.magic = read32b(f);			/* 'PTMS' */

	if ((pih.type & 3) != 1)
	    continue;

	smp_ofs[i] = pih.smpofs;
	m->xxih[i].nsm = !!(m->xxs[i].len = pih.length);
	m->xxs[i].lps = pih.loopbeg;
	m->xxs[i].lpe = pih.loopend;
	if (m->xxs[i].lpe)
		m->xxs[i].lpe--;
	m->xxs[i].flg = pih.type & 0x04 ? WAVE_LOOPING : 0;
	m->xxs[i].flg |= pih.type & 0x08 ? WAVE_LOOPING | WAVE_BIDIR_LOOP : 0;
	m->xxs[i].flg |= pih.type & 0x10 ? WAVE_16_BITS : 0;
	m->xxi[i][0].vol = pih.vol;
	m->xxi[i][0].pan = 0x80;
	m->xxi[i][0].sid = i;
	pih.magic = 0;

	copy_adjust(m->xxih[i].name, pih.name, 28);

	if ((V(1)) && (strlen((char *)m->xxih[i].name) || m->xxs[i].len))
	    report ("[%2X] %-28.28s %05x%c%05x %05x %c V%02x %5d\n",
		i, m->xxih[i].name, m->xxs[i].len, pih.type & 0x10 ? '+' : ' ',
		m->xxs[i].lps, m->xxs[i].lpe, m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ',
		m->xxi[i][0].vol, pih.c4spd);

	/* Convert C4SPD to relnote/finetune */
	c2spd_to_note (pih.c4spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin);
    }

    PATTERN_INIT();

    /* Read patterns */
    reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat);

    for (i = 0; i < m->xxh->pat; i++) {
	if (!pfh.patseg[i])
	    continue;
	PATTERN_ALLOC (i);
	m->xxp[i]->rows = 64;
	TRACK_ALLOC (i);
	fseek(f, start + 16L * pfh.patseg[i], SEEK_SET);
	r = 0;
	while (r < 64) {
	    fread (&b, 1, 1, f);
	    if (!b) {
		r++;
		continue;
	    }

	    c = b & PTM_CH_MASK;
	    if (c >= m->xxh->chn)
		continue;

	    event = &EVENT (i, c, r);
	    if (b & PTM_NI_FOLLOW) {
		fread (&n, 1, 1, f);
		switch (n) {
		case 255:
		    n = 0;
		    break;	/* Empty note */
		case 254:
		    n = XMP_KEY_OFF;
		    break;	/* Key off */
		}
		event->note = n;
		fread (&n, 1, 1, f);
		event->ins = n;
	    }
	    if (b & PTM_FX_FOLLOWS) {
		event->fxt = read8(f);
		event->fxp = read8(f);

		if (event->fxt > 0x17)
			event->fxt = event->fxp = 0;

		switch (event->fxt) {
		case 0x0e:	/* Extended effect */
		    if (MSN(event->fxp) == 0x8) {	/* Pan set */
			event->fxt = FX_SETPAN;
			event->fxp = LSN (event->fxp) << 4;
		    }
		    break;
		case 0x10:	/* Set global volume */
		    event->fxt = FX_GLOBALVOL;
		    break;
		case 0x11:	/* Multi retrig */
		    event->fxt = FX_MULTI_RETRIG;
		    break;
		case 0x12:	/* Fine vibrato */
		    event->fxt = FX_FINE4_VIBRA;
		    break;
		case 0x13:	/* Note slide down */
		    event->fxt = FX_NSLIDE_DN;
		    break;
		case 0x14:	/* Note slide up */
		    event->fxt = FX_NSLIDE_UP;
		    break;
		case 0x15:	/* Note slide down + retrig */
		    event->fxt = FX_NSLIDE_R_DN;
		    break;
		case 0x16:	/* Note slide up + retrig */
		    event->fxt = FX_NSLIDE_R_UP;
		    break;
		case 0x17:	/* Reverse sample */
		    event->fxt = event->fxp = 0;
		    break;
		}
	    }
	    if (b & PTM_VOL_FOLLOWS) {
		event->vol = read8(f) + 1;
	    }
	}
	reportv(ctx, 0, ".");
    }

    reportv(ctx, 0, "\nStored samples : %d ", m->xxh->smp);

    for (i = 0; i < m->xxh->smp; i++) {
	if (!m->xxs[i].len)
	    continue;
	fseek(f, start + smp_ofs[m->xxi[i][0].sid], SEEK_SET);
	xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate,
			XMP_SMP_8BDIFF, &m->xxs[m->xxi[i][0].sid], NULL);
	reportv(ctx, 0, ".");
    }
    reportv(ctx, 0, "\n");

    m->vol_xlat = ptm_vol;

    for (i = 0; i < m->xxh->chn; i++)
	m->xxc[i].pan = pfh.chset[i] << 4;

    return 0;
}
コード例 #30
0
ファイル: gdm_load.c プロジェクト: ProjectZeroSlackr/XMP
static int gdm_load(struct xmp_context *ctx, FILE *f, const int start)
{
	struct xmp_player_context *p = &ctx->p;
	struct xmp_mod_context *m = &p->m;
	struct xxm_event *event;
	int vermaj, vermin, tvmaj, tvmin, tracker;
	int origfmt, ord_ofs, pat_ofs, ins_ofs, smp_ofs;
	uint8 buffer[32], panmap[32];
	int i;

	LOAD_INIT();

	read32b(f);		/* skip magic */
	fread(m->name, 1, 32, f);
	fread(m->author, 1, 32, f);

	fseek(f, 7, SEEK_CUR);

	vermaj = read8(f);
	vermin = read8(f);
	tracker = read16l(f);
	tvmaj = read8(f);
	tvmin = read8(f);

	if (tracker == 0) {
		sprintf(m->type, "GDM %d.%02d, (2GDM %d.%02d)",
					vermaj, vermin, tvmaj, tvmin);
	} else {
		sprintf(m->type, "GDM %d.%02d (unknown tracker %d.%02d)",
					vermaj, vermin, tvmaj, tvmin);
	}

	fread(panmap, 32, 1, f);
	for (i = 0; i < 32; i++) {
		if (panmap[i] != 0xff)
			m->xxh->chn = i + 1;
		if (panmap[i] == 16)
			panmap[i] = 8;
		m->xxc[i].pan = 0x80 + (panmap[i] - 8) * 16;
	}

	m->xxh->gvl = read8(f);
	m->xxh->tpo = read8(f);
	m->xxh->bpm = read8(f);
	origfmt = read16l(f);
	ord_ofs = read32l(f);
	m->xxh->len = read8(f);
	pat_ofs = read32l(f);
	m->xxh->pat = read8(f);
	ins_ofs = read32l(f);
	smp_ofs = read32l(f);
	m->xxh->ins = m->xxh->smp = read8(f);
	m->xxh->trk = m->xxh->pat * m->xxh->chn;
	
	MODULE_INFO();

	if (origfmt > 9)
		origfmt = 9;
	reportv(ctx, 0, "Orig format    : %s\n", fmt[origfmt]);

	fseek(f, start + ord_ofs, SEEK_SET);

	for (i = 0; i < m->xxh->len; i++)
		m->xxo[i] = read8(f);

	/* Read instrument data */

	fseek(f, start + ins_ofs, SEEK_SET);

	INSTRUMENT_INIT();

	reportv(ctx, 1, "     Name                             Len   LBeg  LEnd  L Vol Pan C4Spd\n");

	for (i = 0; i < m->xxh->ins; i++) {
		int flg, c4spd, vol, pan;

		m->xxi[i] = calloc(sizeof(struct xxm_instrument), 1);
		fread(buffer, 32, 1, f);
		copy_adjust(m->xxih[i].name, buffer, 32);
		fseek(f, 12, SEEK_CUR);		/* skip filename */
		read8(f);			/* skip EMS handle */
		m->xxs[i].len = read32l(f);
		m->xxs[i].lps = read32l(f);
		m->xxs[i].lpe = read32l(f);
		flg = read8(f);
		c4spd = read16l(f);
		vol = read8(f);
		pan = read8(f);
		
		m->xxi[i][0].vol = vol > 0x40 ? 0x40 : vol;
		m->xxi[i][0].pan = pan > 15 ? 0x80 : 0x80 + (pan - 8) * 16;
		c2spd_to_note(c4spd, &m->xxi[i][0].xpo, &m->xxi[i][0].fin);

		m->xxih[i].nsm = !!(m->xxs[i].len);
		m->xxi[i][0].sid = i;
		m->xxs[i].flg = 0;

		if (flg & 0x01)
			m->xxs[i].flg |= WAVE_LOOPING;
		if (flg & 0x02)
			m->xxs[i].flg |= WAVE_16_BITS;

		if (V(1) && (strlen((char*)m->xxih[i].name) || (m->xxs[i].len > 1))) {
			report("[%2X] %-32.32s %05x%c%05x %05x %c V%02x P%02x %5d\n",
				i, m->xxih[i].name,
				m->xxs[i].len,
				m->xxs[i].flg & WAVE_16_BITS ? '+' : ' ',
				m->xxs[i].lps,
				m->xxs[i].lpe,
				m->xxs[i].flg & WAVE_LOOPING ? 'L' : ' ',
				m->xxi[i][0].vol,
				m->xxi[i][0].pan,
				c4spd);
		}


	}

	/* Read and convert patterns */

	fseek(f, start + pat_ofs, SEEK_SET);

	PATTERN_INIT();

	reportv(ctx, 0, "Stored patterns: %d ", m->xxh->pat);

	for (i = 0; i < m->xxh->pat; i++) {
		int len, c, r, k;

		PATTERN_ALLOC(i);
		m->xxp[i]->rows = 64;
		TRACK_ALLOC(i);

		len = read16l(f);
		len -= 2;

		for (r = 0; len > 0; ) {
			c = read8(f);
			len--;

			if (c == 0) {
				r++;
				continue;
			}

			assert((c & 0x1f) < m->xxh->chn);
			event = &EVENT (i, c & 0x1f, r);

			if (c & 0x20) {		/* note and sample follows */
				k = read8(f);
				event->note = 12 * MSN(k & 0x7f) + LSN(k);
				event->ins = read8(f);
				len -= 2;
			}

			if (c & 0x40) {		/* effect(s) follow */
				do {
					k = read8(f);
					len--;
					switch ((k & 0xc0) >> 6) {
					case 0:
						event->fxt = k & 0x1f;
						event->fxp = read8(f);
						len--;
						fix_effect(&event->fxt, &event->fxp);
						break;
					case 1:
						event->f2t = k & 0x1f;
						event->f2p = read8(f);
						len--;
						fix_effect(&event->f2t, &event->f2p);
						break;
					case 2:
						read8(f);
						len--;
					}
				} while (k & 0x20);
			}
		}
		
		reportv(ctx, 0, ".");
	}
	reportv(ctx, 0, "\n");

	/* Read samples */

	fseek(f, start + smp_ofs, SEEK_SET);

	reportv(ctx, 0, "Stored samples : %d ", m->xxh->smp);
	for (i = 0; i < m->xxh->ins; i++) {
		xmp_drv_loadpatch(ctx, f, m->xxi[i][0].sid, m->c4rate,
				XMP_SMP_UNS, &m->xxs[m->xxi[i][0].sid], NULL);
		reportv(ctx, 0, ".");
	}
	reportv(ctx, 0, "\n");

	return 0;
}