コード例 #1
0
ファイル: mmd_common.c プロジェクト: visy/turha
int mmd_load_hybrid_instrument(HIO_HANDLE *f, struct module_data *m, int i,
			int smp_idx, struct SynthInstr *synth,
			struct InstrExt *exp_smp, struct MMD0sample *sample)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_instrument *xxi = &mod->xxi[i];
	struct xmp_subinstrument *sub;
	struct xmp_sample *xxs;
	int length, type;
	int pos = hio_tell(f);

	synth->defaultdecay = hio_read8(f);
	hio_seek(f, 3, SEEK_CUR);
	synth->rep = hio_read16b(f);
	synth->replen = hio_read16b(f);
	synth->voltbllen = hio_read16b(f);
	synth->wftbllen = hio_read16b(f);
	synth->volspeed = hio_read8(f);
	synth->wfspeed = hio_read8(f);
	synth->wforms = hio_read16b(f);
	hio_read(synth->voltbl, 1, 128, f);;
	hio_read(synth->wftbl, 1, 128, f);;

	hio_seek(f, pos - 6 + hio_read32b(f), SEEK_SET);
	length = hio_read32b(f);
	type = hio_read16b(f);

	if (med_new_instrument_extras(xxi) != 0)
		return -1;

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

	MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed;
	MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed;

	sub = &xxi->sub[0];

	sub->pan = 0x80;
	sub->vol = sample->svol;
	sub->xpo = sample->strans;
	sub->sid = smp_idx;
	sub->fin = exp_smp->finetune;

	xxs = &mod->xxs[smp_idx];

	xxs->len = length;
	xxs->lps = 2 * sample->rep;
	xxs->lpe = xxs->lps + 2 * sample->replen;
	xxs->flg = sample->replen > 1 ?  XMP_SAMPLE_LOOP : 0;

	if (load_sample(m, f, 0, xxs, NULL) < 0)
		return -1;

	return 0;
}
コード例 #2
0
ファイル: sample.c プロジェクト: visy/turha
int load_sample(struct module_data *m, HIO_HANDLE *f, int flags, struct xmp_sample *xxs, void *buffer)
{
	int bytelen, extralen, unroll_extralen, i;

	/* Adlib FM patches */
	if (flags & SAMPLE_FLAG_ADLIB) {
		const int size = 11;

		if (flags & SAMPLE_FLAG_HSC) {
			convert_hsc_to_sbi(buffer);
		}

		xxs->data = malloc(size + 4);
		if (xxs->data == NULL)
			return -1;

		*(uint32 *)xxs->data = 0;
		xxs->data += 4;

		memcpy(xxs->data, buffer, size);

		xxs->flg |= XMP_SAMPLE_SYNTH;
		xxs->len = size;

		return 0;
	}

	/* Empty samples
	 */
	if (xxs->len == 0) {
		return 0;
	}

	/* Skip sample loading
	 * FIXME: fails for ADPCM samples
	 */
	if (m && m->smpctl & XMP_SMPCTL_SKIP) {
		if (~flags & SAMPLE_FLAG_NOLOAD)
			hio_seek(f, xxs->len, SEEK_CUR);
		return 0;
	}

	/* Loop parameters sanity check
	 */
	if (xxs->lpe > xxs->len) {
		xxs->lpe = xxs->len;
	}
	if (xxs->lps >= xxs->len || xxs->lps >= xxs->lpe) {
		xxs->lps = xxs->lpe = 0;
		xxs->flg &= ~(XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR);
	}

	/* Patches with samples
	 * Allocate extra sample for interpolation.
	 */
	bytelen = xxs->len;
	extralen = 4;
	unroll_extralen = 0;

	/* Disable birectional loop flag if sample is not looped
	 */
	if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
		if (~xxs->flg & XMP_SAMPLE_LOOP)
			xxs->flg &= ~XMP_SAMPLE_LOOP_BIDIR;
	}
	/* Unroll bidirectional loops
	 */
	if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
		unroll_extralen = (xxs->lpe - xxs->lps) -
				(xxs->len - xxs->lpe);

		if (unroll_extralen < 0) {
			unroll_extralen = 0;
		}
	}

	if (xxs->flg & XMP_SAMPLE_16BIT) {
		bytelen *= 2;
		extralen *= 2;
		unroll_extralen *= 2;
	}

	/* add guard bytes before the buffer for higher order interpolation */
	xxs->data = malloc(bytelen + extralen + unroll_extralen + 4);
	if (xxs->data == NULL)
		return -1;

	*(uint32 *)xxs->data = 0;
	xxs->data += 4;

	if (flags & SAMPLE_FLAG_NOLOAD) {
		memcpy(xxs->data, buffer, bytelen);
	} else {
		uint8 buf[5];
		long pos = hio_tell(f);
		int num = hio_read(buf, 1, 5, f);

		hio_seek(f, pos, SEEK_SET);

		if (num == 5 && !memcmp(buf, "ADPCM", 5)) {
			int x2 = bytelen >> 1;
			char table[16];

			hio_seek(f, 5, SEEK_CUR);	/* Skip "ADPCM" */
			hio_read(table, 1, 16, f);
			hio_read(xxs->data + x2, 1, x2, f);
			adpcm4_decoder((uint8 *)xxs->data + x2,
				       (uint8 *)xxs->data, table, bytelen);
		} else {
コード例 #3
0
ファイル: mfp_load.c プロジェクト: vitamin-caig/zxtune
static int mfp_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	int i, j, k, x, y;
	struct xmp_event *event;
	struct stat st;
	char smp_filename[PATH_MAX];
	HIO_HANDLE *s;
	int size1, size2;
	int pat_addr, pat_table[128][4];
	uint8 buf[1024], mod_event[4];
	int row;

	LOAD_INIT();

	set_type(m, "Magnetic Fields Packer");
	MODULE_INFO();

	mod->chn = 4;
	mod->ins = mod->smp = 31;

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

	for (i = 0; i < 31; i++) {
		int loop_size;

		if (subinstrument_alloc(mod, i, 1) < 0)
			return -1;
		
		mod->xxs[i].len = 2 * hio_read16b(f);
		mod->xxi[i].sub[0].fin = (int8)(hio_read8(f) << 4);
		mod->xxi[i].sub[0].vol = hio_read8(f);
		mod->xxs[i].lps = 2 * hio_read16b(f);
		loop_size = hio_read16b(f);

		mod->xxs[i].lpe = mod->xxs[i].lps + 2 * loop_size;
		mod->xxs[i].flg = loop_size > 1 ? XMP_SAMPLE_LOOP : 0;
		mod->xxi[i].sub[0].pan = 0x80;
		mod->xxi[i].sub[0].sid = i;
		mod->xxi[i].rls = 0xfff;

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

               	D_(D_INFO "[%2X] %04x %04x %04x %c V%02x %+d",
                       	i, mod->xxs[i].len, mod->xxs[i].lps,
                       	mod->xxs[i].lpe,
			loop_size > 1 ? 'L' : ' ',
                       	mod->xxi[i].sub[0].vol, mod->xxi[i].sub[0].fin >> 4);
	}

	mod->len = mod->pat = hio_read8(f);
	hio_read8(f);		/* restart */

	for (i = 0; i < 128; i++)
		mod->xxo[i] = hio_read8(f);

#if 0
	for (i = 0; i < 128; i++) {
		mod->xxo[i] = hio_read8(f);
		if (mod->xxo[i] > mod->pat)
			mod->pat = mod->xxo[i];
	}
	mod->pat++;
#endif

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

	/* Read and convert patterns */

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

	size1 = hio_read16b(f);
	size2 = hio_read16b(f);

	for (i = 0; i < size1; i++) {		/* Read pattern table */
		for (j = 0; j < 4; j++) {
			pat_table[i][j] = hio_read16b(f);
		}
	}

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

	pat_addr = hio_tell(f);

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

		for (j = 0; j < 4; j++) {
			hio_seek(f, pat_addr + pat_table[i][j], SEEK_SET);

			hio_read(buf, 1, 1024, f);

			for (row = k = 0; k < 4; k++) {
				for (x = 0; x < 4; x++) {
					for (y = 0; y < 4; y++, row++) {
						event = &EVENT(i, j, row);
						memcpy(mod_event, &buf[buf[buf[buf[k] + x] + y] * 2], 4);
						decode_protracker_event(event, mod_event);
					}
				}
			}
		}
	}

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

	/* first check smp.filename */
	if (strlen(m->basename) < 5 || m->basename[3] != '.') {
		fprintf(stderr, "libxmp: invalid filename %s\n", m->basename);
		goto err;
	}

	m->basename[0] = 's';
	m->basename[1] = 'm';
	m->basename[2] = 'p';
	snprintf(smp_filename, sizeof(smp_filename), "%s%s", m->dirname, m->basename);
	if (stat(smp_filename, &st) < 0) {
		/* handle .set filenames like in Kid Chaos*/
		char *x;
		if (strchr(m->basename, '-')) {
			if ((x = strrchr(smp_filename, '-')))
				strcpy(x, ".set");
		}
		if (stat(smp_filename, &st) < 0) {
			fprintf(stderr, "libxmp: missing file %s\n",
								smp_filename);
			goto err;
		}
	}
	if ((s = hio_open_file(smp_filename, "rb")) == NULL) {
		fprintf(stderr, "libxmp: can't open sample file %s\n",
								smp_filename);
		goto err;
	}

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

	hio_close(s);

	m->quirk |= QUIRK_MODRNG;

	return 0;

    err:
	for (i = 0; i < mod->ins; i++) {
		mod->xxi[i].nsm = 0;
		memset(&mod->xxs[i], 0, sizeof(struct xmp_sample));
	}

	return 0;
}
コード例 #4
0
ファイル: mmd_common.c プロジェクト: visy/turha
int mmd_load_synth_instrument(HIO_HANDLE *f, struct module_data *m, int i,
			int smp_idx, struct SynthInstr *synth,
			struct InstrExt *exp_smp, struct MMD0sample *sample)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_instrument *xxi = &mod->xxi[i];
	int pos = hio_tell(f);
	int j;

	synth->defaultdecay = hio_read8(f);
	hio_seek(f, 3, SEEK_CUR);
	synth->rep = hio_read16b(f);
	synth->replen = hio_read16b(f);
	synth->voltbllen = hio_read16b(f);
	synth->wftbllen = hio_read16b(f);
	synth->volspeed = hio_read8(f);
	synth->wfspeed = hio_read8(f);
	synth->wforms = hio_read16b(f);
	hio_read(synth->voltbl, 1, 128, f);;
	hio_read(synth->wftbl, 1, 128, f);;
	for (j = 0; j < 64; j++)
		synth->wf[j] = hio_read32b(f);

	D_(D_INFO "  VS:%02x WS:%02x WF:%02x %02x %+3d %+1d",
			synth->volspeed, synth->wfspeed,
			synth->wforms & 0xff,
			sample->svol,
			sample->strans,
			exp_smp->finetune);

	if (synth->wforms == 0xffff)	
		return 1;
	if (synth->wforms > 64)
	  return -1;

	if (med_new_instrument_extras(&mod->xxi[i]) != 0)
		return -1;

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

	MED_INSTRUMENT_EXTRAS((*xxi))->vts = synth->volspeed;
	MED_INSTRUMENT_EXTRAS((*xxi))->wts = synth->wfspeed;

	for (j = 0; j < synth->wforms; j++) {
		struct xmp_subinstrument *sub = &xxi->sub[j];
		struct xmp_sample *xxs = &mod->xxs[smp_idx];

		sub->pan = 0x80;
		sub->vol = sample->svol;
		sub->xpo = sample->strans - 24;
		sub->sid = smp_idx;
		sub->fin = exp_smp->finetune;

		hio_seek(f, pos - 6 + synth->wf[j], SEEK_SET);

		xxs->len = hio_read16b(f) * 2;
		xxs->lps = 0;
		xxs->lpe = mod->xxs[smp_idx].len;
		xxs->flg = XMP_SAMPLE_LOOP;

		if (load_sample(m, f, 0, xxs, NULL) < 0)
			return -1;

		smp_idx++;
	}

	return 0;
}
コード例 #5
0
ファイル: gal4_load.c プロジェクト: GenericHero/libxmp-3ds
static int gal4_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	iff_handle handle;
	int i, ret, offset;
	struct local_data data;

	LOAD_INIT();

	hio_read32b(f);	/* Skip RIFF */
	hio_read32b(f);	/* Skip size */
	hio_read32b(f);	/* Skip AM   */

	offset = hio_tell(f);

	mod->smp = mod->ins = 0;

	handle = iff_new();
	if (handle == NULL)
		return -1;

	/* IFF chunk IDs */
	ret = iff_register(handle, "MAIN", get_main);
	ret |= iff_register(handle, "ORDR", get_ordr);
	ret |= iff_register(handle, "PATT", get_patt_cnt);
	ret |= iff_register(handle, "INST", get_inst_cnt);

	if (ret != 0)
		return -1;

	iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
	iff_set_quirk(handle, IFF_CHUNK_TRUNC4);

	/* Load IFF chunks */
	if (iff_load(handle, m, f, &data) < 0) {
		iff_release(handle);
		return -1;
	}

	iff_release(handle);

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

	MODULE_INFO();

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

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

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

	hio_seek(f, start + offset, SEEK_SET);
	data.snum = 0;

	handle = iff_new();
	if (handle == NULL)
		return -1;

	/* IFF chunk IDs */
	ret = iff_register(handle, "PATT", get_patt);
	ret |= iff_register(handle, "INST", get_inst);

	if (ret != 0)
		return -1;

	iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
	iff_set_quirk(handle, IFF_CHUNK_TRUNC4);

	/* Load IFF chunks */
	if (iff_load(handle, m, f, &data) < 0) {
		iff_release(handle);
		return -1;
	}

	iff_release(handle);

	/* Alloc missing patterns */
	for (i = 0; i < mod->pat; i++) {
		if (mod->xxp[i] == NULL) {
			if (pattern_tracks_alloc(mod, i, 64) < 0) {
				return -1;
			}
		}
	}

	for (i = 0; i < mod->chn; i++) {
		mod->xxc[i].pan = 0x80;
	}

	m->quirk |= QUIRKS_FT2;
	m->read_event_type = READ_EVENT_FT2;

	return 0;
}
コード例 #6
0
ファイル: amf_load.c プロジェクト: B0rschti/libxmp-4.3.0
static int amf_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	int i, j;
	struct xmp_event *event;
	uint8 buf[1024];
	int *trkmap, newtrk;
	int ver;

	LOAD_INIT();

	hio_read(buf, 1, 3, f);
	ver = hio_read8(f);

	hio_read(buf, 1, 32, f);
	strncpy(mod->name, (char *)buf, 32);
	set_type(m, "DSMI %d.%d AMF", ver / 10, ver % 10);

	mod->ins = hio_read8(f);
	mod->len = hio_read8(f);
	mod->trk = hio_read16l(f);
	mod->chn = hio_read8(f);

	mod->smp = mod->ins;
	mod->pat = mod->len;

	if (ver == 0x0a)
		hio_read(buf, 1, 16, f);	/* channel remap table */

	if (ver >= 0x0d) {
		hio_read(buf, 1, 32, f);	/* panning table */
		for (i = 0; i < 32; i++) {
			mod->xxc->pan = 0x80 + 2 * (int8)buf[i];
		}
		mod->bpm = hio_read8(f);
		mod->spd = hio_read8(f);
	} else if (ver >= 0x0b) {
		hio_read(buf, 1, 16, f);
	}

	MODULE_INFO();
 

	/* Orders */

	/*
	 * Andre Timmermans <*****@*****.**> says:
	 *
	 * Order table: track numbers in this table are not explained,
	 * but as you noticed you have to perform -1 to obtain the index
	 * in the track table. For value 0, found in some files, I think
	 * it means an empty track.
	 */

	for (i = 0; i < mod->len; i++)
		mod->xxo[i] = i;

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

	mod->xxp = calloc(sizeof(struct xmp_pattern *), mod->pat + 1);
	if (mod->xxp == NULL)
		return -1;

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

		mod->xxp[i]->rows = ver >= 0x0e ? hio_read16l(f) : 64;

		for (j = 0; j < mod->chn; j++) {
			uint16 t = hio_read16l(f);
			mod->xxp[i]->index[j] = t;
		}
	}

	/* Instruments */

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

	/* Probe for 2-byte loop start 1.0 format
	 * in facing_n.amf and sweetdrm.amf have only the sample
	 * loop start specified in 2 bytes
	 */
	if (ver <= 0x0a) {
		uint8 b;
		uint32 len, start, end;
		long pos = hio_tell(f);
		for (i = 0; i < mod->ins; i++) {
			b = hio_read8(f);
			if (b != 0 && b != 1) {
				ver = 0x09;
				break;
			}
			hio_seek(f, 32 + 13, SEEK_CUR);
			if (hio_read32l(f) > 0x100000) { /* check index */
				ver = 0x09;
				break;
			}
			len = hio_read32l(f);
			if (len > 0x100000) {		/* check len */
				ver = 0x09;
				break;
			}
			if (hio_read16l(f) == 0x0000) {	/* check c2spd */
				ver = 0x09;
				break;
			}
			if (hio_read8(f) > 0x40) {	/* check volume */
				ver = 0x09;
				break;
			}
			start = hio_read32l(f);
			if (start > len) {		/* check loop start */
				ver = 0x09;
				break;
			}
			end = hio_read32l(f);
			if (end > len) {		/* check loop end */
				ver = 0x09;
				break;
			}
		}
		hio_seek(f, pos, SEEK_SET);
	}

	for (i = 0; i < mod->ins; i++) {
		/*uint8 b;*/
		int c2spd;

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

		/*b =*/ hio_read8(f);

		hio_read(buf, 1, 32, f);
		instrument_name(mod, i, buf, 32);

		hio_read(buf, 1, 13, f);	/* sample name */
		hio_read32l(f);			/* sample index */

		mod->xxi[i].nsm = 1;
		mod->xxi[i].sub[0].sid = i;
		mod->xxi[i].sub[0].pan = 0x80;
		mod->xxs[i].len = hio_read32l(f);
		c2spd = hio_read16l(f);
		c2spd_to_note(c2spd, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
		mod->xxi[i].sub[0].vol = hio_read8(f);

		/*
		 * Andre Timmermans <*****@*****.**> says:
		 *
		 * [Miodrag Vallat's] doc tells that in version 1.0 only
		 * sample loop start is present (2 bytes) but the files I
		 * have tells both start and end are present (2*4 bytes).
		 * Maybe it should be read as version < 1.0.
		 *
		 * CM: confirmed with Maelcum's "The tribal zone"
		 */

		if (ver < 0x0a) {
			mod->xxs[i].lps = hio_read16l(f);
			mod->xxs[i].lpe = mod->xxs[i].len;
		} else {
			mod->xxs[i].lps = hio_read32l(f);
			mod->xxs[i].lpe = hio_read32l(f);
		}

		if (ver < 0x0a) {
			mod->xxs[i].flg = mod->xxs[i].lps > 0 ? XMP_SAMPLE_LOOP : 0;
		} else {
			mod->xxs[i].flg = mod->xxs[i].lpe > mod->xxs[i].lps ?
							XMP_SAMPLE_LOOP : 0;
		}

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

	/* Tracks */

	trkmap = calloc(sizeof(int), mod->trk);
	if (trkmap == NULL)
		return -1;
	newtrk = 0;

	for (i = 0; i < mod->trk; i++) {		/* read track table */
		uint16 t;
		t = hio_read16l(f);
		trkmap[i] = t;
		if (t > newtrk) newtrk = t;
/*printf("%d -> %d\n", i, t);*/
	}

	for (i = 0; i < mod->pat; i++) {		/* read track table */
		for (j = 0; j < mod->chn; j++) {
			int k = mod->xxp[i]->index[j] - 1;

			/* Use empty track if an invalid track is requested
			 * (such as in Lasse Makkonen "faster and louder")
			 */
			if (k < 0 || k >= mod->trk)
				k = 0;
			mod->xxp[i]->index[j] = trkmap[k];
/*printf("mod->xxp[%d]->info[%d].index = %d (k = %d)\n", i, j, trkmap[k], k);*/
		}
	}

	mod->trk = newtrk;		/* + empty track */
	free(trkmap);

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

	mod->trk++;
	mod->xxt = calloc (sizeof (struct xmp_track *), mod->trk);
	if (mod->xxt == NULL)
		return -1;

	/* Alloc track 0 as empty track */
	if (track_alloc(mod, 0, 64) < 0)
		return -1;

	/* Alloc rest of the tracks */
	for (i = 1; i < mod->trk; i++) {
		uint8 t1, t2, t3;
		int size;

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

		size = hio_read24l(f);
/*printf("TRACK %d SIZE %d\n", i, size);*/

		for (j = 0; j < size; j++) {
			t1 = hio_read8(f);			/* row */
			t2 = hio_read8(f);			/* type */
			t3 = hio_read8(f);			/* parameter */
/*printf("track %d row %d: %02x %02x %02x\n", i, t1, t1, t2, t3);*/

			if (t1 == 0xff && t2 == 0xff && t3 == 0xff)
				break;

			event = &mod->xxt[i]->event[t1];

			if (t2 < 0x7f) {		/* note */
				if (t2 > 0)
					event->note = t2 + 1;
				event->vol = t3;
			} else if (t2 == 0x7f) {	/* copy previous */
				memcpy(event, &mod->xxt[i]->event[t1 - 1],
					sizeof(struct xmp_event));
			} else if (t2 == 0x80) {	/* instrument */
				event->ins = t3 + 1;
			} else  {			/* effects */
				uint8 fxp, fxt;

				fxp = fxt = 0;

				switch (t2) {
				case 0x81:
					fxt = FX_SPEED;
					fxp = t3;
					break;
				case 0x82:
					if ((int8)t3 > 0) {
						fxt = FX_VOLSLIDE;
						fxp = t3 << 4;
					} else {
						fxt = FX_VOLSLIDE;
						fxp = -(int8)t3 & 0x0f;
					}
					break;
				case 0x83:
					event->vol = t3;
					break;
				case 0x84:
					/* AT: Not explained for 0x84, pitch
					 * slide, value 0x00 corresponds to
					 * S3M E00 and 0x80 stands for S3M F00
					 * (I checked with M2AMF)
					 */
					if ((int8)t3 >= 0) {
						fxt = FX_PORTA_DN;
						fxp = t3;
					} else if (t3 == 0x80) {
						fxt = FX_PORTA_UP;
						fxp = 0;
					} else {
						fxt = FX_PORTA_UP;
						fxp = -(int8)t3;
					}
					break;
				case 0x85:
					/* porta abs -- unknown */
					break;
				case 0x86:
					fxt = FX_TONEPORTA;
					fxp = t3;
					break;

				/* AT: M2AMF maps both tremolo and tremor to
				 * 0x87. Since tremor is only found in certain
				 * formats, maybe it would be better to
				 * consider it is a tremolo.
				 */
				case 0x87:
					fxt = FX_TREMOLO;
					fxp = t3;
					break;
				case 0x88:
					fxt = FX_ARPEGGIO;
					fxp = t3;
					break;
				case 0x89:
					fxt = FX_VIBRATO;
					fxp = t3;
					break;
				case 0x8a:
					if ((int8)t3 > 0) {
						fxt = FX_TONE_VSLIDE;
						fxp = t3 << 4;
					} else {
						fxt = FX_TONE_VSLIDE;
						fxp = -(int8)t3 & 0x0f;
					}
					break;
				case 0x8b:
					if ((int8)t3 > 0) {
						fxt = FX_VIBRA_VSLIDE;
						fxp = t3 << 4;
					} else {
						fxt = FX_VIBRA_VSLIDE;
						fxp = -(int8)t3 & 0x0f;
					}
					break;
				case 0x8c:
					fxt = FX_BREAK;
					fxp = t3;
					break;
				case 0x8d:
					fxt = FX_JUMP;
					fxp = t3;
					break;
				case 0x8e:
					/* sync -- unknown */
					break;
				case 0x8f:
					fxt = FX_EXTENDED;
					fxp = (EX_RETRIG << 4) | (t3 & 0x0f);
					break;
				case 0x90:
					fxt = FX_OFFSET;
					fxp = t3;
					break;
				case 0x91:
					if ((int8)t3 > 0) {
						fxt = FX_EXTENDED;
						fxp = (EX_F_VSLIDE_UP << 4) |
							(t3 & 0x0f);
					} else {
						fxt = FX_EXTENDED;
						fxp = (EX_F_VSLIDE_DN << 4) |
							(t3 & 0x0f);
					}
					break;
				case 0x92:
					if ((int8)t3 > 0) {
						fxt = FX_PORTA_DN;
						fxp = 0xf0 | (fxp & 0x0f);
					} else {
						fxt = FX_PORTA_UP;
						fxp = 0xf0 | (fxp & 0x0f);
					}
					break;
				case 0x93:
					fxt = FX_EXTENDED;
					fxp = (EX_DELAY << 4) | (t3 & 0x0f);
					break;
				case 0x94:
					fxt = FX_EXTENDED;
					fxp = (EX_CUT << 4) | (t3 & 0x0f);
					break;
				case 0x95:
					fxt = FX_SPEED;
					if (t3 < 0x21)
						t3 = 0x21;
					fxp = t3;
					break;
				case 0x96:
					if ((int8)t3 > 0) {
						fxt = FX_PORTA_DN;
						fxp = 0xe0 | (fxp & 0x0f);
					} else {
						fxt = FX_PORTA_UP;
						fxp = 0xe0 | (fxp & 0x0f);
					}
					break;
				case 0x97:
					fxt = FX_SETPAN;
					fxp = 0x80 + 2 * (int8)t3;
					break;
				}

				event->fxt = fxt;
				event->fxp = fxp;
			}

		}
	}


	/* Samples */

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

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

	m->quirk |= QUIRK_FINEFX;

	return 0;
}
コード例 #7
0
ファイル: gal5_load.c プロジェクト: cmatsuoka/libxmp
static int gal5_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	iff_handle handle;
	int i, ret, offset;
	struct local_data data;

	LOAD_INIT();

	hio_read32b(f);	/* Skip RIFF */
	hio_read32b(f);	/* Skip size */
	hio_read32b(f);	/* Skip AM   */

	offset = hio_tell(f);

	mod->smp = mod->ins = 0;

	handle = libxmp_iff_new();
	if (handle == NULL)
		return -1;

	m->c4rate = C4_NTSC_RATE;

	/* IFF chunk IDs */
	ret = libxmp_iff_register(handle, "INIT", get_init);		/* Galaxy 5.0 */
	ret |= libxmp_iff_register(handle, "ORDR", get_ordr);
	ret |= libxmp_iff_register(handle, "PATT", get_patt_cnt);
	ret |= libxmp_iff_register(handle, "INST", get_inst_cnt);

	if (ret != 0)
		return -1;

	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
	libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED);
	libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2);

	/* Load IFF chunks */
	if (libxmp_iff_load(handle, m, f, &data) < 0) {
		libxmp_iff_release(handle);
		return -1;
	}

	libxmp_iff_release(handle);

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

	MODULE_INFO();

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

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

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

	hio_seek(f, start + offset, SEEK_SET);

	handle = libxmp_iff_new();
	if (handle == NULL)
		return -1;

	/* IFF chunk IDs */
	ret = libxmp_iff_register(handle, "PATT", get_patt);
	ret |= libxmp_iff_register(handle, "INST", get_inst);

	if (ret != 0)
		return -1;

	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
	libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED);
	libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2);

	/* Load IFF chunks */
	if (libxmp_iff_load(handle, m, f, &data) < 0) {
		libxmp_iff_release(handle);
		return -1;
	}

	libxmp_iff_release(handle);

	/* Alloc missing patterns */
	for (i = 0; i < mod->pat; i++) {
		if (mod->xxp[i] == NULL) {
			if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) {
				return -1;
			}
		}
	}

	for (i = 0; i < mod->chn; i++) {
		mod->xxc[i].pan = data.chn_pan[i] * 2;
	}

	m->quirk |= QUIRKS_FT2;
	m->read_event_type = READ_EVENT_FT2;

	return 0;
}
コード例 #8
0
ファイル: skyt.c プロジェクト: Sappharad/modizer
static int depack_skyt(HIO_HANDLE *in, FILE *out)
{
	uint8 c1, c2, c3, c4;
	uint8 ptable[128];
	uint8 pat_pos;
	uint8 pat[1024];
	int i = 0, j = 0, k = 0;
	int trkval[128][4];
	int trk_addr;
	int size, ssize = 0;

	memset(ptable, 0, 128);
	memset(trkval, 0, 128 * 4);

	pw_write_zero(out, 20);			/* write title */

	/* read and write sample descriptions */
	for (i = 0; i < 31; i++) {
		pw_write_zero(out, 22);			/*sample name */
		write16b(out, size = hio_read16b(in));	/* sample size */
		ssize += size * 2;
		write8(out, hio_read8(in));			/* finetune */
		write8(out, hio_read8(in));			/* volume */
		write16b(out, hio_read16b(in));		/* loop start */
		write16b(out, hio_read16b(in));		/* loop size */
	}

	hio_read32b(in);			/* bypass 8 empty bytes */
	hio_read32b(in);
	hio_read32b(in);			/* bypass "SKYT" ID */

	pat_pos = hio_read8(in) + 1;		/* pattern table lenght */
	if (pat_pos >= 128) {
		return -1;
	}
	write8(out, pat_pos);
	write8(out, 0x7f);			/* write NoiseTracker byte */

	/* read track numbers ... and deduce pattern list */
	for (i = 0; i < pat_pos; i++) {
		for (j = 0; j < 4; j++) {
			trkval[i][j] = hio_read16b(in);
		}
	}

	/* write pseudo pattern list */
	for (i = 0; i < 128; i++) {
		write8(out, i < pat_pos ? i : 0);
	}

	write32b(out, PW_MOD_MAGIC);		/* write ptk's ID */

	hio_read8(in);				/* bypass $00 unknown byte */

	/* get track address */
	trk_addr = hio_tell(in);

	/* track data */
	for (i = 0; i < pat_pos; i++) {
		memset(pat, 0, 1024);
		for (j = 0; j < 4; j++) {
			hio_seek(in, trk_addr + ((trkval[i][j] - 1)<<8), SEEK_SET);
			for (k = 0; k < 64; k++) {
				int x = k * 16 + j * 4;

				c1 = hio_read8(in);
				c2 = hio_read8(in);
				c3 = hio_read8(in);
				c4 = hio_read8(in);

				pat[x] = (c2 & 0xf0) | ptk_table[c1][0];
				pat[x + 1] = ptk_table[c1][1];
				pat[x + 2] = ((c2 << 4) & 0xf0) | c3;
				pat[x + 3] = c4;
			}
		}
		fwrite(pat, 1024, 1, out);
	}

	/* sample data */
	pw_move_data(out, in, ssize);

	return 0;
}
コード例 #9
0
ファイル: mod_load.c プロジェクト: GCrean/libxmp
static int mod_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
    struct xmp_module *mod = &m->mod;
    int i, j;
    int smp_size, pat_size, wow, ptsong = 0;
    struct xmp_event *event;
    struct mod_header mh;
    uint8 mod_event[4];
    char *x, pathname[PATH_MAX] = "", *tracker = "";
    int detected = 0;
    char magic[8], idbuffer[32];
    int ptkloop = 0;			/* Protracker loop */
    int tracker_id = TRACKER_PROTRACKER;

    LOAD_INIT();

    mod->ins = 31;
    mod->smp = mod->ins;
    mod->chn = 0;
    smp_size = 0;
    pat_size = 0;

    m->quirk |= QUIRK_MODRNG;

    hio_read(&mh.name, 20, 1, f);
    for (i = 0; i < 31; i++) {
	hio_read(&mh.ins[i].name, 22, 1, f);	/* Instrument name */
	mh.ins[i].size = hio_read16b(f);	/* Length in 16-bit words */
	mh.ins[i].finetune = hio_read8(f);	/* Finetune (signed nibble) */
	mh.ins[i].volume = hio_read8(f);	/* Linear playback volume */
	mh.ins[i].loop_start = hio_read16b(f);	/* Loop start in 16-bit words */
	mh.ins[i].loop_size = hio_read16b(f);	/* Loop size in 16-bit words */

	smp_size += 2 * mh.ins[i].size;
    }
    mh.len = hio_read8(f);
    mh.restart = hio_read8(f);
    hio_read(&mh.order, 128, 1, f);
    memset(magic, 0, 8);
    hio_read(magic, 4, 1, f);

    for (i = 0; mod_magic[i].ch; i++) {
	if (!(strncmp (magic, mod_magic[i].magic, 4))) {
	    mod->chn = mod_magic[i].ch;
	    tracker_id = mod_magic[i].id;
	    detected = mod_magic[i].flag;
	    break;
	}
    }

    if (!mod->chn) {
	if (!strncmp(magic + 2, "CH", 2) &&
	    isdigit((int)magic[0]) && isdigit((int)magic[1])) {
	    mod->chn = (*magic - '0') * 10 + magic[1] - '0';
	} else if (!strncmp(magic + 1, "CHN", 3) && isdigit((int)*magic)) {
	    mod->chn = *magic - '0';
	} else {
	    return -1;
	}
	tracker_id = mod->chn & 1 ? TRACKER_TAKETRACKER : TRACKER_FASTTRACKER2;
	detected = 1;
	m->quirk &= ~QUIRK_MODRNG;
    }

    strncpy(mod->name, (char *) mh.name, 20);

    mod->len = mh.len;
    /* mod->rst = mh.restart; */

    if (mod->rst >= mod->len)
	mod->rst = 0;
    memcpy(mod->xxo, mh.order, 128);

    for (i = 0; i < 128; i++) {
	/* This fixes dragnet.mod (garbage in the order list) */
	if (mod->xxo[i] > 0x7f)
		break;
	if (mod->xxo[i] > mod->pat)
	    mod->pat = mod->xxo[i];
    }
    mod->pat++;

    pat_size = 256 * mod->chn * mod->pat;

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

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

	mod->xxs[i].len = 2 * mh.ins[i].size;
	mod->xxs[i].lps = 2 * mh.ins[i].loop_start;
	mod->xxs[i].lpe = mod->xxs[i].lps + 2 * mh.ins[i].loop_size;
	if (mod->xxs[i].lpe > mod->xxs[i].len)
		mod->xxs[i].lpe = mod->xxs[i].len;
	mod->xxs[i].flg = (mh.ins[i].loop_size > 1 && mod->xxs[i].lpe >= 4) ?
		XMP_SAMPLE_LOOP : 0;
	mod->xxi[i].sub[0].fin = (int8)(mh.ins[i].finetune << 4);
	mod->xxi[i].sub[0].vol = mh.ins[i].volume;
	mod->xxi[i].sub[0].pan = 0x80;
	mod->xxi[i].sub[0].sid = i;
	instrument_name(mod, i, mh.ins[i].name, 22);

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

    /*
     * Experimental tracker-detection routine
     */ 

    if (detected)
	goto skip_test;

    /* Test for Flextrax modules
     *
     * FlexTrax is a soundtracker for Atari Falcon030 compatible computers.
     * FlexTrax supports the standard MOD file format (up to eight channels)
     * for compatibility reasons but also features a new enhanced module
     * format FLX. The FLX format is an extended version of the standard
     * MOD file format with support for real-time sound effects like reverb
     * and delay.
     */

    if (0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size < m->size) {
	int pos = hio_tell(f);
	hio_seek(f, start + 0x43c + mod->pat * 4 * mod->chn * 0x40 + smp_size, SEEK_SET);
	hio_read(idbuffer, 1, 4, f);
	hio_seek(f, start + pos, SEEK_SET);

	if (!memcmp(idbuffer, "FLEX", 4)) {
	    tracker_id = TRACKER_FLEXTRAX;
	    goto skip_test;
	}
    }

    /* Test for Mod's Grave WOW modules
     *
     * Stefan Danes <*****@*****.**> said:
     * This weird format is identical to '8CHN' but still uses the 'M.K.' ID.
     * You can only test for WOW by calculating the size of the module for 8 
     * channels and comparing this to the actual module length. If it's equal, 
     * the module is an 8 channel WOW.
     */

    if ((wow = (!strncmp(magic, "M.K.", 4) &&
		(0x43c + mod->pat * 32 * 0x40 + smp_size == m->size)))) {
	mod->chn = 8;
	tracker_id = TRACKER_MODSGRAVE;
	goto skip_test;
    }

    /* Test for Protracker song files
     */
    else if ((ptsong = (!strncmp((char *)magic, "M.K.", 4) &&
		(0x43c + mod->pat * 0x400 == m->size)))) {
	tracker_id = TRACKER_PROTRACKER;
	goto skip_test;
    }

    /* Test Protracker-like files
     */
    if (mod->chn == 4 && mh.restart == mod->pat) {
	tracker_id = TRACKER_SOUNDTRACKER;
    } else if (mod->chn == 4 && mh.restart == 0x78) {
        tracker_id = TRACKER_NOISETRACKER;
    } else if (mh.restart < 0x7f) {
	if (mod->chn == 4) {
	    tracker_id = TRACKER_NOISETRACKER;
	} else {
	    tracker_id = TRACKER_UNKNOWN;
	}
	mod->rst = mh.restart;
    }

    if (mod->chn != 4 && mh.restart == 0x7f) {
	tracker_id = TRACKER_SCREAMTRACKER3;
	m->quirk &= ~QUIRK_MODRNG;
	m->read_event_type = READ_EVENT_ST3;
    }

    if (mod->chn == 4 && mh.restart == 0x7f) {
	for (i = 0; i < 31; i++) {
	    if (mh.ins[i].loop_size == 0)
		break;
	}
	if (i < 31) {
	    tracker_id = TRACKER_CLONE;
	}
    }

    if (mh.restart != 0x78 && mh.restart < 0x7f) {
	for (i = 0; i < 31; i++) {
	    if (mh.ins[i].loop_size == 0)
		break;
	}
	if (i == 31) {	/* All loops are size 2 or greater */
	    for (i = 0; i < 31; i++) {
		if (mh.ins[i].size == 1 && mh.ins[i].volume == 0) {
		    tracker_id = TRACKER_CONVERTED;
		    goto skip_test;
		}
	    }

	    for (i = 0; i < 31; i++) {
	        if (is_st_ins((char *)mh.ins[i].name))
		    break;
	    }
	    if (i == 31) {	/* No st- instruments */
	        for (i = 0; i < 31; i++) {
		    if (mh.ins[i].size == 0 && mh.ins[i].loop_size == 1) {
			switch (mod->chn) {
			case 4:
			    tracker_id = TRACKER_NOISETRACKER;	/* or Octalyser */
			    break;
			case 6:
			case 8:
		            tracker_id = TRACKER_OCTALYSER;
			    break;
			default:
		            tracker_id = TRACKER_UNKNOWN;
			}
		        goto skip_test;
		    }
	        }

		if (mod->chn == 4) {
	    	    tracker_id = TRACKER_PROTRACKER;
		} else if (mod->chn == 6 || mod->chn == 8) {
	    	    tracker_id = TRACKER_FASTTRACKER;	/* FastTracker 1.01? */
		    m->quirk &= ~QUIRK_MODRNG;
		} else {
	    	    tracker_id = TRACKER_UNKNOWN;
		}
	    }
	} else {	/* Has loops with 0 size */
	    for (i = 15; i < 31; i++) {
	        if (strlen((char *)mh.ins[i].name) || mh.ins[i].size > 0)
		    break;
	    }
	    if (i == 31 && is_st_ins((char *)mh.ins[14].name)) {
		tracker_id = TRACKER_CONVERTEDST;
		goto skip_test;
	    }

	    /* Assume that Fast Tracker modules won't have ST- instruments */
	    for (i = 0; i < 31; i++) {
	        if (is_st_ins((char *)mh.ins[i].name))
		    break;
	    }
	    if (i < 31) {
		tracker_id = TRACKER_UNKNOWN_CONV;
		goto skip_test;
	    }

	    if (mod->chn == 4 || mod->chn == 6 || mod->chn == 8) {
	    	tracker_id = TRACKER_FASTTRACKER;
	        m->quirk &= ~QUIRK_MODRNG;
		goto skip_test;
	    }

	    tracker_id = TRACKER_UNKNOWN;	/* ??!? */
	}
    }

skip_test:

    switch (tracker_id) {
    case TRACKER_PROTRACKER:
	tracker = "Protracker";
	ptkloop = 1;
	break;
    case TRACKER_NOISETRACKER:
	tracker = "Noisetracker";
	ptkloop = 1;
	break;
    case TRACKER_SOUNDTRACKER:
	tracker = "Soundtracker";
	ptkloop = 1;
	break;
    case TRACKER_FASTTRACKER:
	tracker = "Fast Tracker";
	break;
    case TRACKER_FASTTRACKER2:
	tracker = "FastTracker 2";
	break;
    case TRACKER_OCTALYSER:
	tracker = "Octalyser";
	break;
    case TRACKER_TAKETRACKER:
	tracker = "TakeTracker";
	break;
    case TRACKER_DIGITALTRACKER:
	tracker = "Digital Tracker";
	break;
    case TRACKER_FLEXTRAX:
	tracker = "Flextrax";
	break;
    case TRACKER_MODSGRAVE:
	tracker = "Mod's Grave";
	break;
    case TRACKER_SCREAMTRACKER3:
	tracker = "Scream Tracker III";
	break;
    case TRACKER_UNKNOWN_CONV:
	tracker = "unknown or converted";
	break;
    case TRACKER_CONVERTEDST:
	tracker = "converted ST2.2 or earlier";
	break;
    case TRACKER_CONVERTED:
	tracker = "converted";
	break;
    case TRACKER_CLONE:
	tracker = "Protracker clone";
	break;
    default:
    case TRACKER_UNKNOWN:
	tracker = "unknown";
	break;
    }

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

    snprintf(mod->type, XMP_NAME_SIZE, "%s (%s)", tracker, magic);
    MODULE_INFO();

    for (i = 0; i < mod->ins; i++) {
	D_(D_INFO "[%2X] %-22.22s %04x %04x %04x %c V%02x %+d %c\n",
		i, mod->xxi[i].name,
		mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe,
		(mh.ins[i].loop_size > 1 && mod->xxs[i].lpe > 8) ?
			'L' : ' ', mod->xxi[i].sub[0].vol,
		mod->xxi[i].sub[0].fin >> 4,
		ptkloop && mod->xxs[i].lps == 0 && mh.ins[i].loop_size > 1 &&
			mod->xxs[i].len > mod->xxs[i].lpe ? '!' : ' ');
    }

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

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

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

	for (j = 0; j < (64 * mod->chn); j++) {
	    event = &EVENT (i, j % mod->chn, j / mod->chn);
	    hio_read (mod_event, 1, 4, f);

	    switch (tracker_id) {
	    case TRACKER_NOISETRACKER:
		decode_noisetracker_event(event, mod_event);
		break;
	    case TRACKER_PROTRACKER:
	    default:
		decode_protracker_event(event, mod_event);
		break;
	    }
	}
    }

    /* Load samples */

    if (m->filename && (x = strrchr(m->filename, '/')))
	strncpy(pathname, m->filename, x - m->filename);

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

    for (i = 0; i < mod->smp; i++) {
	int flags;

	if (!mod->xxs[i].len)
	    continue;

	flags = ptkloop ? SAMPLE_FLAG_FULLREP : 0;

	if (ptsong) {
	    HIO_HANDLE *s;
	    char sn[256];
	    snprintf(sn, XMP_NAME_SIZE, "%s%s", pathname, mod->xxi[i].name);
	
	    if ((s = hio_open_file(sn, "rb"))) {
	        if (load_sample(m, s, flags, &mod->xxs[i], NULL) < 0) {
		    hio_close(s);
		    return -1;
		}
		hio_close(s);
	    }
	} else {
	    if (load_sample(m, f, flags, &mod->xxs[i], NULL) < 0)
		return -1;
	}
    }

    if (mod->chn > 4) {
	m->quirk &= ~QUIRK_MODRNG;
	m->quirk |= QUIRKS_FT2;
	m->read_event_type = READ_EVENT_FT2;
    } else if (strcmp(tracker, "Protracker") == 0) {
	m->quirk |= QUIRK_INVLOOP;
    }

    return 0;
}
コード例 #10
0
ファイル: pha.c プロジェクト: Sappharad/modizer
static int depack_pha(HIO_HANDLE *in, FILE *out)
{
	uint8 c1, c2;
	uint8 pnum[128];
	uint8 pnum1[128];
	uint8 nop;
	uint8 *pdata;
	uint8 *pat;
	uint8 onote[4][4];
	uint8 note, ins, fxt, fxp;
	uint8 npat = 0x00;
	int paddr[128];
	int i, j, k;
	int paddr1[128];
	int paddr2[128];
	int tmp_ptr, tmp;
	int pat_addr;
	int psize;
	int size, ssize = 0;
	int smp_addr;
	short ocpt[4];

	memset(paddr, 0, 128 * 4);
	memset(paddr1, 0, 128 * 4);
	memset(paddr2, 0, 128 * 4);
	memset(pnum, 0, 128);
	memset(pnum1, 0, 128);
	memset(onote, 0, 4 * 4);
	memset(ocpt, 0, 4 * 2);

	pw_write_zero(out, 20);				/* title */

	for (i = 0; i < 31; i++) {
		int vol, fin, lps, lsz;

		pw_write_zero(out, 22);			/* sample name */
		write16b(out, size = hio_read16b(in));	/* size */
		ssize += size * 2;
		hio_read8(in);				/* ??? */
		
		vol = hio_read8(in);			/* volume */
		lps = hio_read16b(in);			/* loop start */
		lsz = hio_read16b(in);			/* loop size */
		hio_read32b(in);			/* sample address */
		hio_read8(in);				/* ??? */

		fin = hio_read8(in);			/* finetune - 11 */
		if (fin != 0) {
			fin += 11;
		}
		write8(out, fin);
		write8(out, vol);
		write16b(out, lps);
		write16b(out, lsz);

	}

	hio_seek(in, 14, SEEK_CUR);		/* bypass unknown 14 bytes */

	for (i = 0; i < 128; i++)
		paddr[i] = hio_read32b(in);

	/* ordering of patterns addresses */

	tmp_ptr = 0;
	for (i = 0; i < 128; i++) {
		if (i == 0) {
			pnum[0] = 0;
			tmp_ptr++;
			continue;
		}

		for (j = 0; j < i; j++) {
			if (paddr[i] == paddr[j]) {
				pnum[i] = pnum[j];
				break;
			}
		}
		if (j == i)
			pnum[i] = tmp_ptr++;
	}

	/* correct re-order */
	for (i = 0; i < 128; i++)
		paddr1[i] = paddr[i];

restart:
	for (i = 0; i < 128; i++) {
		for (j = 0; j < i; j++) {
			if (paddr1[i] < paddr1[j]) {
				tmp = pnum[j];
				pnum[j] = pnum[i];
				pnum[i] = tmp;

				tmp = paddr1[j];
				paddr1[j] = paddr1[i];
				paddr1[i] = tmp;
				goto restart;
			}
		}
	}

	j = 0;
	for (i = 0; i < 128; i++) {
		if (i == 0) {
			paddr2[j] = paddr1[i];
			continue;
		}

		if (paddr1[i] == paddr2[j])
			continue;
		paddr2[++j] = paddr1[i];
	}

	/* try to take care of unused patterns ... HARRRRRRD */
	memset(paddr1, 0, 128 * 4);
	j = 0;
	k = paddr[0];
	/* 120 ... leaves 8 unused ptk_tableible patterns .. */
	for (i = 0; i < 120; i++) {
		paddr1[j] = paddr2[i];
		j += 1;
		if ((paddr2[i + 1] - paddr2[i]) > 1024) {
			paddr1[j] = paddr2[i] + 1024;
			j += 1;
		}
	}

	for (c1 = 0; c1 < 128; c1++) {
		for (c2 = 0; c2 < 128; c2++) {
			if (paddr[c1] == paddr1[c2]) {
				pnum1[c1] = c2;
			}
		}
	}

	memset(pnum, 0, 128);
	pat_addr = 999999l;
	for (i = 0; i < 128; i++) {
		pnum[i] = pnum1[i];
		if (paddr[i] < pat_addr)
			pat_addr = paddr[i];
	}

	/* try to get the number of pattern in pattern list */
	for (nop = 128; nop > 0; nop--) {
		if (pnum[nop - 1] != 0)
			break;
	}

	/* write this value */
	write8(out, nop);

	/* get highest pattern number */
	for (i = 0; i < nop; i++)
		if (pnum[i] > npat)
			npat = pnum[i];

	write8(out, 0x7f);			/* ntk restart byte */

	for (i = 0; i < 128; i++)		/* write pattern list */
		write8(out, pnum[i]);

	write32b(out, PW_MOD_MAGIC);		/* ID string */

	smp_addr = hio_tell(in);
	hio_seek(in, pat_addr, SEEK_SET);

	/* pattern datas */
	/* read ALL pattern data */

/* FIXME: shouldn't use file size */
#if 0
	j = ftell (in);
	fseek (in, 0, 2);	/* SEEK_END */
	psize = ftell (in) - j;
	fseek (in, j, 0);	/* SEEK_SET */
#endif
	psize = npat * 1024;
	pdata = (uint8 *) malloc (psize);
	psize = hio_read(pdata, 1, psize, in);
	npat += 1;		/* coz first value is $00 */
	pat = (uint8 *)malloc(npat * 1024);
	memset(pat, 0, npat * 1024);

	j = 0;
	for (i = 0; j < psize; i++) {
		if (pdata[i] == 0xff) {
			i += 1;
			ocpt[(k + 3) % 4] = 0xff - pdata[i];
			continue;
		}
		if (ocpt[k % 4] != 0) {
			ins = onote[k % 4][0];
			note = onote[k % 4][1];
			fxt = onote[k % 4][2];
			fxp = onote[k % 4][3];
			ocpt[k % 4] -= 1;

			pat[j] = ins & 0xf0;
			pat[j] |= ptk_table[(note / 2)][0];
			pat[j + 1] = ptk_table[(note / 2)][1];
			pat[j + 2] = (ins << 4) & 0xf0;
			pat[j + 2] |= fxt;
			pat[j + 3] = fxp;
			k += 1;
			j += 4;
			i -= 1;
			continue;
		}
		ins = pdata[i];
		note = pdata[i + 1];
		fxt = pdata[i + 2];
		fxp = pdata[i + 3];
		onote[k % 4][0] = ins;
		onote[k % 4][1] = note;
		onote[k % 4][2] = fxt;
		onote[k % 4][3] = fxp;
		i += 3;
		pat[j] = ins & 0xf0;
		pat[j] |= ptk_table[(note / 2)][0];
		pat[j + 1] = ptk_table[(note / 2)][1];
		pat[j + 2] = (ins << 4) & 0xf0;
		pat[j + 2] |= fxt;
		pat[j + 3] = fxp;
		k += 1;
		j += 4;
	}
	fwrite(pat, npat * 1024, 1, out);
	free(pdata);
	free(pat);

	/* Sample data */
	hio_seek(in, smp_addr, SEEK_SET);
	pw_move_data(out, in, ssize);

	return 0;
}
コード例 #11
0
ファイル: mmd3_load.c プロジェクト: duongbaoduy/libxmp
static int mmd3_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	int i, j, k;
	struct MMD0 header;
	struct MMD2song song;
	struct MMD1Block block;
	struct InstrHdr instr;
	struct SynthInstr synth;
	struct InstrExt exp_smp;
	struct MMD0exp expdata;
	struct xmp_event *event;
	int ver = 0;
	int smp_idx = 0;
	uint8 e[4];
	int song_offset;
	int seqtable_offset;
	int trackvols_offset;
	int trackpans_offset;
	int blockarr_offset;
	int smplarr_offset;
	int expdata_offset;
	int expsmp_offset;
	int songname_offset;
	int iinfo_offset;
	int playseq_offset;
	int pos;
	int bpm_on, bpmlen, med_8ch;

	LOAD_INIT();

	hio_read(&header.id, 4, 1, f);

	ver = *((char *)&header.id + 3) - '1' + 1;

	D_(D_WARN "load header");
	header.modlen = hio_read32b(f);
	song_offset = hio_read32b(f);
	D_(D_INFO "song_offset = 0x%08x", song_offset);
	hio_read16b(f);
	hio_read16b(f);
	blockarr_offset = hio_read32b(f);
	D_(D_INFO "blockarr_offset = 0x%08x", blockarr_offset);
	hio_read32b(f);
	smplarr_offset = hio_read32b(f);
	D_(D_INFO "smplarr_offset = 0x%08x", smplarr_offset);
	hio_read32b(f);
	expdata_offset = hio_read32b(f);
	D_(D_INFO "expdata_offset = 0x%08x", expdata_offset);
	hio_read32b(f);
	header.pstate = hio_read16b(f);
	header.pblock = hio_read16b(f);
	header.pline = hio_read16b(f);
	header.pseqnum = hio_read16b(f);
	header.actplayline = hio_read16b(f);
	header.counter = hio_read8(f);
	header.extra_songs = hio_read8(f);

	/*
	 * song structure
	 */
	D_(D_WARN "load song");
	hio_seek(f, start + song_offset, SEEK_SET);
	for (i = 0; i < 63; i++) {
		song.sample[i].rep = hio_read16b(f);
		song.sample[i].replen = hio_read16b(f);
		song.sample[i].midich = hio_read8(f);
		song.sample[i].midipreset = hio_read8(f);
		song.sample[i].svol = hio_read8(f);
		song.sample[i].strans = hio_read8s(f);
	}
	song.numblocks = hio_read16b(f);
	song.songlen = hio_read16b(f);
	D_(D_INFO "song.songlen = %d", song.songlen);
	seqtable_offset = hio_read32b(f);
	hio_read32b(f);
	trackvols_offset = hio_read32b(f);
	song.numtracks = hio_read16b(f);
	song.numpseqs = hio_read16b(f);
	trackpans_offset = hio_read32b(f);
	song.flags3 = hio_read32b(f);
	song.voladj = hio_read16b(f);
	song.channels = hio_read16b(f);
	song.mix_echotype = hio_read8(f);
	song.mix_echodepth = hio_read8(f);
	song.mix_echolen = hio_read16b(f);
	song.mix_stereosep = hio_read8(f);

	hio_seek(f, 223, SEEK_CUR);

	song.deftempo = hio_read16b(f);
	song.playtransp = hio_read8(f);
	song.flags = hio_read8(f);
	song.flags2 = hio_read8(f);
	song.tempo2 = hio_read8(f);
	for (i = 0; i < 16; i++)
		hio_read8(f);		/* reserved */
	song.mastervol = hio_read8(f);
	song.numsamples = hio_read8(f);

	/*
	 * read sequence
	 */
	hio_seek(f, start + seqtable_offset, SEEK_SET);
	playseq_offset = hio_read32b(f);
	hio_seek(f, start + playseq_offset, SEEK_SET);
	hio_seek(f, 32, SEEK_CUR);	/* skip name */
	hio_read32b(f);
	hio_read32b(f);
	mod->len = hio_read16b(f);
	for (i = 0; i < mod->len; i++)
		mod->xxo[i] = hio_read16b(f);

	/*
	 * convert header
	 */
	m->c4rate = C4_NTSC_RATE;
	m->quirk |= song.flags & FLAG_STSLIDE ? 0 : QUIRK_VSALL | QUIRK_PBALL;
	med_8ch = song.flags & FLAG_8CHANNEL;
	bpm_on = song.flags2 & FLAG2_BPM;
	bpmlen = 1 + (song.flags2 & FLAG2_BMASK);
	m->time_factor = MED_TIME_FACTOR;

	mmd_set_bpm(m, med_8ch, song.deftempo, bpm_on, bpmlen);

	mod->spd = song.tempo2;
	mod->pat = song.numblocks;
	mod->ins = song.numsamples;
	mod->rst = 0;
	mod->chn = 0;
	mod->name[0] = 0;

	/*
	 * Obtain number of samples from each instrument
	 */
	mod->smp = 0;
	for (i = 0; i < mod->ins; i++) {
		uint32 smpl_offset;
		int16 type;
		hio_seek(f, start + smplarr_offset + i * 4, SEEK_SET);
		smpl_offset = hio_read32b(f);
		if (smpl_offset == 0)
			continue;
		hio_seek(f, start + smpl_offset, SEEK_SET);
		hio_read32b(f);				/* length */
		type = hio_read16b(f);
		if (type == -1) {			/* type is synth? */
			hio_seek(f, 14, SEEK_CUR);
			mod->smp += hio_read16b(f);		/* wforms */
		} else {
			mod->smp++;
		}
	}

	/*
	 * expdata
	 */
	D_(D_WARN "load expdata");
	expdata.s_ext_entries = 0;
	expdata.s_ext_entrsz = 0;
	expdata.i_ext_entries = 0;
	expdata.i_ext_entrsz = 0;
	expsmp_offset = 0;
	iinfo_offset = 0;
	if (expdata_offset) {
		hio_seek(f, start + expdata_offset, SEEK_SET);
		hio_read32b(f);
		expsmp_offset = hio_read32b(f);
		D_(D_INFO "expsmp_offset = 0x%08x", expsmp_offset);
		expdata.s_ext_entries = hio_read16b(f);
		expdata.s_ext_entrsz = hio_read16b(f);
		hio_read32b(f);
		hio_read32b(f);
		iinfo_offset = hio_read32b(f);
		D_(D_INFO "iinfo_offset = 0x%08x", iinfo_offset);
		expdata.i_ext_entries = hio_read16b(f);
		expdata.i_ext_entrsz = hio_read16b(f);
		hio_read32b(f);
		hio_read32b(f);
		hio_read32b(f);
		hio_read32b(f);
		songname_offset = hio_read32b(f);
		D_(D_INFO "songname_offset = 0x%08x", songname_offset);
		expdata.songnamelen = hio_read32b(f);
		hio_seek(f, start + songname_offset, SEEK_SET);
		D_(D_INFO "expdata.songnamelen = %d", expdata.songnamelen);
		for (i = 0; i < expdata.songnamelen; i++) {
			if (i >= XMP_NAME_SIZE)
				break;
			mod->name[i] = hio_read8(f);
		}
	}

	/*
	 * Quickly scan patterns to check the number of channels
	 */
	D_(D_WARN "find number of channels");

	for (i = 0; i < mod->pat; i++) {
		int block_offset;

		hio_seek(f, start + blockarr_offset + i * 4, SEEK_SET);
		block_offset = hio_read32b(f);
		D_(D_INFO "block %d block_offset = 0x%08x", i, block_offset);
		if (block_offset == 0)
			continue;
		hio_seek(f, start + block_offset, SEEK_SET);

		block.numtracks = hio_read16b(f);
		block.lines = hio_read16b(f);

		if (block.numtracks > mod->chn)
			mod->chn = block.numtracks;
	}

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

	if (ver == 2)
	    set_type(m, "OctaMED v5 MMD2");
	else
	    set_type(m, "OctaMED Soundstudio MMD%c", '0' + ver);

	MODULE_INFO();

	D_(D_INFO "BPM mode: %s (length = %d)", bpm_on ? "on" : "off", bpmlen);
	D_(D_INFO "Song transpose : %d", song.playtransp);
	D_(D_INFO "Stored patterns: %d", mod->pat);

	/*
	 * Read and convert patterns
	 */
	D_(D_WARN "read patterns");

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

	for (i = 0; i < mod->pat; i++) {
		int block_offset;

		hio_seek(f, start + blockarr_offset + i * 4, SEEK_SET);
		block_offset = hio_read32b(f);
		if (block_offset == 0)
			continue;
		hio_seek(f, start + block_offset, SEEK_SET);

		block.numtracks = hio_read16b(f);
		block.lines = hio_read16b(f);
		hio_read32b(f);

		if (pattern_tracks_alloc(mod, i, block.lines + 1) < 0)
			return -1;

		for (j = 0; j < mod->xxp[i]->rows; j++) {
			for (k = 0; k < block.numtracks; k++) {
				e[0] = hio_read8(f);
				e[1] = hio_read8(f);
				e[2] = hio_read8(f);
				e[3] = hio_read8(f);

				event = &EVENT(i, k, j);
				event->note = e[0] & 0x7f;
				if (event->note) {
					event->note += song.playtransp;
					if (ver == 2)
						event->note += 12;
					else
						event->note -= 12;
				};

				if (event->note < 0 || event->note >=
								XMP_MAX_KEYS)
					event->note = 0;

				event->ins = e[1] & 0x3f;

				/* Decay */
				if (event->ins && !event->note) {
					event->f2t = FX_MED_HOLD;
				}

				event->fxt = e[2];
				event->fxp = e[3];
				mmd_xlat_fx(event, bpm_on, bpmlen, med_8ch);
			}
		}
	}

	if (med_new_module_extras(m) != 0)
		return -1;

	/*
	 * Read and convert instruments and samples
	 */
	D_(D_WARN "read instruments");

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

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

	for (smp_idx = i = 0; i < mod->ins; i++) {
		int smpl_offset;
		char name[40] = "";

		hio_seek(f, start + smplarr_offset + i * 4, SEEK_SET);
		smpl_offset = hio_read32b(f);

		D_(D_INFO "sample %d smpl_offset = 0x%08x", i, smpl_offset);

		if (smpl_offset == 0)
			continue;

		hio_seek(f, start + smpl_offset, SEEK_SET);
		instr.length = hio_read32b(f);
		instr.type = hio_read16b(f);

		pos = hio_tell(f);

		if (expdata_offset && i < expdata.i_ext_entries) {
			hio_seek(f, iinfo_offset + i * expdata.i_ext_entrsz,
								SEEK_SET);
			hio_read(name, 40, 1, f);
			D_(D_INFO "[%2x] %-40.40s %d", i, name, instr.type);
		}

		exp_smp.finetune = 0;
		if (expdata_offset && i < expdata.s_ext_entries) {
			hio_seek(f, expsmp_offset + i * expdata.s_ext_entrsz,
							SEEK_SET);
			exp_smp.hold = hio_read8(f);
			exp_smp.decay = hio_read8(f);
			exp_smp.suppress_midi_off = hio_read8(f);
			exp_smp.finetune = hio_read8(f);

			if (expdata.s_ext_entrsz > 4) {	/* Octamed V5 */
				exp_smp.default_pitch = hio_read8(f);
				exp_smp.instr_flags = hio_read8(f);
			}
		}

		hio_seek(f, pos, SEEK_SET);

		if (instr.type == -2) {			/* Hybrid */
			int ret = mmd_load_hybrid_instrument(f, m, i,
				smp_idx, &synth, &exp_smp, &song.sample[i]);

			if (ret < 0)
				return -1;

			smp_idx++;

			if (mmd_alloc_tables(m, i, &synth) != 0)
				return -1;

			continue;
		}

		if (instr.type == -1) {			/* Synthetic */
			int ret = mmd_load_synth_instrument(f, m, i, smp_idx,
				&synth, &exp_smp, &song.sample[i]);

			if (ret > 0)
				continue;

			if (ret < 0)
				return -1;

			smp_idx += synth.wforms;

			if (mmd_alloc_tables(m, i, &synth) != 0)
				return -1;

			continue;
		}

		if (instr.type >= 1 && instr.type <= 6) {	/* IFFOCT */
			int ret;
			const int oct = num_oct[instr.type - 1];

			hio_seek(f, start + smpl_offset + 6, SEEK_SET);

			ret = mmd_load_iffoct_instrument(f, m, i, smp_idx,
				&instr, oct, &exp_smp, &song.sample[i]);

			if (ret < 0)
				return -1;

			smp_idx += oct;

			continue;
		}

		/* Filter out stereo samples */
		if ((instr.type & ~(S_16 | STEREO)) != 0)
			continue;

		if (instr.type == 0) {			/* Sample */
			int ret;

			hio_seek(f, start + smpl_offset + 6, SEEK_SET);

			ret = mmd_load_sampled_instrument(f, m, i, smp_idx,
				&instr, &expdata, &exp_smp, &song.sample[i],
				ver);

			if (ret < 0)
				return -1;

			smp_idx++;

			continue;
		}
	}

	hio_seek(f, start + trackvols_offset, SEEK_SET);
	for (i = 0; i < mod->chn; i++)
		mod->xxc[i].vol = hio_read8(f);;

	if (trackpans_offset) {
		hio_seek(f, start + trackpans_offset, SEEK_SET);
		for (i = 0; i < mod->chn; i++) {
			int p = 8 * hio_read8s(f);
			mod->xxc[i].pan = 0x80 + (p > 127 ? 127 : p);
		}
	} else {
		for (i = 0; i < mod->chn; i++)
			mod->xxc[i].pan = 0x80;
	}

	m->read_event_type = READ_EVENT_MED;

	return 0;
}
コード例 #12
0
ファイル: abk_load.c プロジェクト: Nlcke/gideros
/**
 * @brief reads an ABK pattern into a xmp_event structure. 
 * @param f stream to read data from.
 * @param events events object to populate.
 * @param pattern_offset_abs the absolute file offset to the start of the patter to read.
 * @return returns the size of the pattern.
 */
static int read_abk_pattern(HIO_HANDLE *f, struct xmp_event *events, uint32 pattern_offset_abs)
{
    uint8 position;
    uint8 command;
    uint8 param;
    uint8 inst = 0;
    uint8 jumped = 0;
    uint8 per_command = 0;
    uint8 per_param = 0;

    uint16 delay;
    uint16 patdata;

    uint32 storepos;
    storepos = hio_tell(f);

    /* count how many abk positions are used in this pattern */
    position = 0;

    hio_seek(f, pattern_offset_abs, SEEK_SET);

    /* read the first bit of pattern data */
    patdata = hio_read16b(f);

    while ((patdata != 0x8000) && (jumped == 0))
    {
        if (patdata == 0x9100)
        {
            break;
        }

        if (patdata & 0x8000)
        {
            command = (patdata >> 8) & 0x7F;
            param = patdata & 0x007F;

            if (command != 0x03 && command != 0x09 && command != 0x0b && command != 0x0c && command != 0x0d && command < 0x10) {
                per_command = 0;
                per_param = 0;
            }

            switch (command)
            {
            case 0x01:		/* portamento up */
            case 0x0e:
                events[position].fxt = FX_PORTA_UP;
                events[position].fxp = param;
                break;
            case 0x02:		/* portamento down */
            case 0x0f:
                events[position].fxt = FX_PORTA_DN;
                events[position].fxp = param;
                break;
            case 0x03:		/* set volume */
                events[position].fxt = FX_VOLSET;
                events[position].fxp = param;
                break;
            case 0x04:		/* stop effect */
                break;
            case 0x05:		/* repeat */
                events[position].fxt = FX_EXTENDED;
                if (param == 0) {
                    events[position].fxp = 0x50;
                } else {
                    events[position].fxp = 0x60 | (param & 0x0f);
                }
                break;
            case 0x06:		/* lowpass filter off */
                events[position].fxt = FX_EXTENDED;
                events[position].fxp = 0x00;
                break;
            case 0x07:		/* lowpass filter on */
                events[position].fxt = FX_EXTENDED;
                events[position].fxp = 0x01;
                break;
            case 0x08:		/* set tempo */
                if (param > 0) {
                    events[position].fxt = FX_SPEED;
                    events[position].fxp = 100/param;
                }
                break;
            case 0x09:		/* set instrument */
                inst = param + 1;
                break;
            case 0x0a:		/* arpeggio */
                per_command = FX_ARPEGGIO;
                per_param = param;
                break;
            case 0x0b:		/* tone portamento */
                per_command = FX_TONEPORTA;
                per_param = param;
                break;
            case 0x0c:		/* vibrato */
                per_command = FX_VIBRATO;
                per_param = param;
                break;
            case 0x0d:		/* volume slide */
		if (param != 0) {
                    per_command = FX_VOLSLIDE;
                    per_param = param;
                } else {
                    per_command = 0;
                    per_param = 0;
                }
                break;
            case 0x10:		/* delay */
                if (per_command != 0 || per_param != 0) {
                    int i;
                    for (i = 0; i < param && position < 64; i++) {
                        events[position].fxt = per_command;
                        events[position].fxp = per_param;
                        position++;
                    }
                } else {
		    position += param;
		}
		if (position >= 64) {
		    jumped = 1;
		}
                break;
            case 0x11:		/* position jump */
                events[position].fxt = FX_JUMP;
                events[position].fxp = param;
                /* break out of the loop because we've jumped.*/
                jumped = 1;
                break;
            default:
#if 0
                /* write out an error for any unprocessed commands.*/
                D_(D_WARN "ABK UNPROCESSED COMMAND: %x,%x\n", command, param);
                break;
#else
		return -1;
#endif
            }
        }
        else
        {
            if (patdata & 0x4000)
コード例 #13
0
ファイル: heatseek.c プロジェクト: Acidburn0zzz/libxmp
static int depack_crb(HIO_HANDLE *in, FILE *out)
{
	uint8 c1;
	uint8 ptable[128];
	uint8 pat_pos, pat_max;
	uint8 pat[1024];
	int taddr[512];
	int i, j, k, l, m;
	int size, ssize = 0;

	memset(ptable, 0, 128);
	memset(taddr, 0, 512 * 4);

	pw_write_zero(out, 20);				/* write title */

	/* read and write sample descriptions */
	for (i = 0; i < 31; i++) {
		pw_write_zero(out, 22);			/*sample name */
		write16b(out, size = hio_read16b(in));	/* size */
		ssize += size * 2;
		write8(out, hio_read8(in));			/* finetune */
		write8(out, hio_read8(in));			/* volume */
		write16b(out, hio_read16b(in));		/* loop start */
		size = hio_read16b(in);			/* loop size */
		write16b(out, size ? size : 1);
	}

	write8(out, pat_pos = hio_read8(in));		/* pat table length */
	write8(out, hio_read8(in)); 			/* NoiseTracker byte */

	/* read and write pattern list and get highest patt number */
	for (pat_max = i = 0; i < 128; i++) {
		write8(out, c1 = hio_read8(in));
		if (c1 > pat_max)
			pat_max = c1;
	}
	pat_max++;

	/* write ptk's ID */
	write32b(out, PW_MOD_MAGIC);

	/* pattern data */
	for (i = 0; i < pat_max; i++) {
		memset(pat, 0, 1024);
		for (j = 0; j < 4; j++) {
			int x = hio_tell(in);
			if (x < 0) {
				return -1;
			}
			taddr[i * 4 + j] = x;
			for (k = 0; k < 64; k++) {
				int y = k * 16 + j * 4;

				c1 = hio_read8(in);
				if (c1 == 0x80) {
					k += hio_read24b(in);
					continue;
				}
				if (c1 == 0xc0) {
					m = hio_read24b(in);
					l = hio_tell(in);

					/* Sanity check */
					if (l < 0 || m >= 2048)
						return -1;

					hio_seek(in, taddr[m >> 2], SEEK_SET);
					for (m = 0; m < 64; m++) {
						int x = m * 16 + j * 4;

						c1 = hio_read8(in);
						if (c1 == 0x80) {
							m += hio_read24b(in);
							continue;
						}
						pat[x] = c1;
						pat[x + 1] = hio_read8(in);
						pat[x + 2] = hio_read8(in);
						pat[x + 3] = hio_read8(in);
					}
					hio_seek(in, l, SEEK_SET);
					k += 100;
					continue;
				}
				pat[y] = c1;
				pat[y + 1] = hio_read8(in);
				pat[y + 2] = hio_read8(in);
				pat[y + 3] = hio_read8(in);
			}
		}
		fwrite (pat, 1024, 1, out);
	}
コード例 #14
0
ファイル: tcb_load.c プロジェクト: Sappharad/modizer
static int tcb_load(struct module_data *m, HIO_HANDLE *f, const int start)
{
	struct xmp_module *mod = &m->mod;
	struct xmp_event *event;
	int i, j, k;
	uint8 buffer[10];
	int base_offs, soffs[16];
	uint8 unk1[16], unk2[16], unk3[16];

	LOAD_INIT();

	hio_read(buffer, 8, 1, f);

	libxmp_set_type(m, "TCB Tracker", buffer);

	hio_read16b(f);	/* ? */
	mod->pat = hio_read16b(f);
	mod->ins = 16;
	mod->smp = mod->ins;
	mod->chn = 4;
	mod->trk = mod->pat * mod->chn;

	m->quirk |= QUIRK_MODRNG;

	hio_read16b(f);	/* ? */

	for (i = 0; i < 128; i++)
		mod->xxo[i] = hio_read8(f);

	mod->len = hio_read8(f);
	hio_read8(f);	/* ? */
	hio_read16b(f);	/* ? */

	MODULE_INFO();

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

	/* Read instrument names */
	for (i = 0; i < mod->ins; i++) {
		if (libxmp_alloc_subinstrument(mod, i, 1) < 0)
			return -1;
		hio_read(buffer, 8, 1, f);
		libxmp_instrument_name(mod, i, buffer, 8);
	}

	hio_read16b(f);	/* ? */
	for (i = 0; i < 5; i++)
		hio_read16b(f);
	for (i = 0; i < 5; i++)
		hio_read16b(f);
	for (i = 0; i < 5; i++)
		hio_read16b(f);

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

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

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

		for (j = 0; j < mod->xxp[i]->rows; j++) {
			for (k = 0; k < mod->chn; k++) {
				int b;
				event = &EVENT (i, k, j);

				b = hio_read8(f);
				if (b) {
					event->note = 12 * (b >> 4);
					event->note += (b & 0xf) + 36;
				}
				b = hio_read8(f);
				event->ins = b >> 4;
				if (event->ins)
					event->ins += 1;
				if (b &= 0x0f) {
					switch (b) {
					case 0xd:
						event->fxt = FX_BREAK;
						event->fxp = 0;
						break;
					default:
						printf("---> %02x\n", b);
					}
				}
			}
		}
	}

	base_offs = hio_tell(f);
	hio_read32b(f);	/* remaining size */

	/* Read instrument data */

	for (i = 0; i < mod->ins; i++) {
		mod->xxi[i].sub[0].vol = hio_read8(f) / 2;
		mod->xxi[i].sub[0].pan = 0x80;
		unk1[i] = hio_read8(f);
		unk2[i] = hio_read8(f);
		unk3[i] = hio_read8(f);
	}


	for (i = 0; i < mod->ins; i++) {
		soffs[i] = hio_read32b(f);
		mod->xxs[i].len = hio_read32b(f);
	}

	hio_read32b(f);
	hio_read32b(f);
	hio_read32b(f);
	hio_read32b(f);

	for (i = 0; i < mod->ins; i++) {
		mod->xxi[i].nsm = !!(mod->xxs[i].len);
		mod->xxs[i].lps = 0;
		mod->xxs[i].lpe = 0;
		mod->xxs[i].flg = mod->xxs[i].lpe > 0 ? XMP_SAMPLE_LOOP : 0;
		mod->xxi[i].sub[0].fin = 0;
		mod->xxi[i].sub[0].pan = 0x80;
		mod->xxi[i].sub[0].sid = i;

		D_(D_INFO "[%2X] %-8.8s  %04x %04x %04x %c "
						"V%02x  %02x %02x %02x\n",
				i, mod->xxi[i].name,
				mod->xxs[i].len, mod->xxs[i].lps, mod->xxs[i].lpe,
				mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
				mod->xxi[i].sub[0].vol, unk1[i], unk2[i], unk3[i]);
	}

	/* Read samples */

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

	for (i = 0; i < mod->ins; i++) {
		hio_seek(f, start + base_offs + soffs[i], SEEK_SET);
		if (libxmp_load_sample(m, f, SAMPLE_FLAG_UNS, &mod->xxs[i], NULL) < 0)
			return -1;
	}

	return 0;
}