1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #define NEED_BYTESWAP
25 #include "headers.h"
26 #include "slurp.h"
27 #include "log.h"
28 #include "fmt.h"
29 
30 #include "sndfile.h"
31 
32 /* --------------------------------------------------------------------- */
33 
34 int fmt_imf_read_info(dmoz_file_t *file, const uint8_t *data, size_t length)
35 {
36 	if (!(length > 64 && memcmp(data + 60, "IM10", 4) == 0))
37 		return 0;
38 
39 	file->description = "Imago Orpheus";
40 	/*file->extension = str_dup("imf");*/
41 	file->title = strn_dup((const char *)data, 32);
42 	file->type = TYPE_MODULE_IT;
43 	return 1;
do_test_fetch_max_bytes(void)44 }
45 
46 /* --------------------------------------------------------------------------------------------------------- */
47 
48 #pragma pack(push, 1)
49 struct imf_channel {
50 	char name[12];          /* Channelname (ASCIIZ-String, max 11 chars) */
51 	uint8_t chorus;         /* Default chorus */
52 	uint8_t reverb;         /* Default reverb */
53 	uint8_t panning;        /* Pan positions 00-FF */
54 	uint8_t status;         /* Channel status: 0 = enabled, 1 = mute, 2 = disabled (ignore effects!) */
55 };
56 
57 
58 struct imf_header {
59 	char title[32];         /* Songname (ASCIIZ-String, max. 31 chars) */
60 	uint16_t ordnum;        /* Number of orders saved */
61 	uint16_t patnum;        /* Number of patterns saved */
62 	uint16_t insnum;        /* Number of instruments saved */
63 	uint16_t flags;         /* Module flags (&1 => linear) */
64 	uint8_t unused1[8];
65 	uint8_t tempo;          /* Default tempo (Axx, 1..255) */
66 	uint8_t bpm;            /* Default beats per minute (BPM) (Txx, 32..255) */
67 	uint8_t master;         /* Default mastervolume (Vxx, 0..64) */
68 	uint8_t amp;            /* Amplification factor (mixing volume, 4..127) */
69 	uint8_t unused2[8];
70 	char im10[4];           /* 'IM10' */
71 	struct imf_channel channels[32]; /* Channel settings */
72 	uint8_t orderlist[256]; /* Order list (0xff = +++; blank out anything beyond ordnum) */
73 };
74 
75 enum {
76 	IMF_ENV_VOL = 0,
77 	IMF_ENV_PAN = 1,
78 	IMF_ENV_FILTER = 2,
79 };
80 
81 struct imf_env {
82 	uint8_t points;         /* Number of envelope points */
83 	uint8_t sustain;        /* Envelope sustain point */
84 	uint8_t loop_start;     /* Envelope loop start point */
85 	uint8_t loop_end;       /* Envelope loop end point */
86 	uint8_t flags;          /* Envelope flags */
87 	uint8_t unused[3];
88 };
89 
90 struct imf_envnodes {
91 	uint16_t tick;
92 	uint16_t value;
93 };
94 
95 struct imf_instrument {
96 	char name[32];          /* Inst. name (ASCIIZ-String, max. 31 chars) */
97 	uint8_t map[120];       /* Multisample settings */
98 	uint8_t unused[8];
99 	struct imf_envnodes nodes[3][16];
100 	struct imf_env env[3];
101 	uint16_t fadeout;       /* Fadeout rate (0...0FFFH) */
102 	uint16_t smpnum;        /* Number of samples in instrument */
103 	char ii10[4];           /* 'II10' */
104 };
105 
106 struct imf_sample {
107 	char name[13];          /* Sample filename (12345678.ABC) */
108 	uint8_t unused1[3];
109 	uint32_t length;        /* Length */
110 	uint32_t loop_start;    /* Loop start */
111 	uint32_t loop_end;      /* Loop end */
112 	uint32_t c5speed;       /* Samplerate */
113 	uint8_t volume;         /* Default volume (0..64) */
114 	uint8_t panning;        /* Default pan (00h = Left / 80h = Middle) */
115 	uint8_t unused2[14];
116 	uint8_t flags;          /* Sample flags */
117 	uint8_t unused3[5];
118 	uint16_t ems;           /* Reserved for internal usage */
119 	uint32_t dram;          /* Reserved for internal usage */
120 	char is10[4];           /* 'IS10' */
121 };
122 #pragma pack(pop)
123 
main_0082_fetch_max_bytes(int argc,char ** argv)124 
125 static uint8_t imf_efftrans[] = {
126 	FX_NONE,
127 	FX_SPEED, // 0x01 1xx Set Tempo
128 	FX_TEMPO, // 0x02 2xx Set BPM
129 	FX_TONEPORTAMENTO, // 0x03 3xx Tone Portamento                  (*)
130 	FX_TONEPORTAVOL, // 0x04 4xy Tone Portamento + Volume Slide   (*)
131 	FX_VIBRATO, // 0x05 5xy Vibrato                          (*)
132 	FX_VIBRATOVOL, // 0x06 6xy Vibrato + Volume Slide           (*)
133 	FX_FINEVIBRATO, // 0x07 7xy Fine Vibrato                     (*)
134 	FX_TREMOLO, // 0x08 8xy Tremolo                          (*)
135 	FX_ARPEGGIO, // 0x09 9xy Arpeggio                         (*)
136 	FX_PANNING, // 0x0A Axx Set Pan Position
137 	FX_PANNINGSLIDE, // 0x0B Bxy Pan Slide                        (*)
138 	FX_VOLUME, // 0x0C Cxx Set Volume
139 	FX_VOLUMESLIDE, // 0x0D Dxy Volume Slide                     (*)
140 	FX_VOLUMESLIDE, // 0x0E Exy Fine Volume Slide                (*)
141 	FX_SPECIAL, // 0x0F Fxx Set Finetune
142 	FX_NOTESLIDEUP, // 0x10 Gxy Note Slide Up                    (*)
143 	FX_NOTESLIDEDOWN, // 0x11 Hxy Note Slide Down                  (*)
144 	FX_PORTAMENTOUP, // 0x12 Ixx Slide Up                         (*)
145 	FX_PORTAMENTODOWN, // 0x13 Jxx Slide Down                       (*)
146 	FX_PORTAMENTOUP, // 0x14 Kxx Fine Slide Up                    (*)
147 	FX_PORTAMENTODOWN, // 0x15 Lxx Fine Slide Down                  (*)
148 	FX_MIDI, // 0x16 Mxx Set Filter Cutoff - XXX
149 	FX_NONE, // 0x17 Nxy Filter Slide + Resonance - XXX
150 	FX_OFFSET, // 0x18 Oxx Set Sample Offset                (*)
151 	FX_NONE, // 0x19 Pxx Set Fine Sample Offset - XXX
152 	FX_KEYOFF, // 0x1A Qxx Key Off
153 	FX_RETRIG, // 0x1B Rxy Retrig                           (*)
154 	FX_TREMOR, // 0x1C Sxy Tremor                           (*)
155 	FX_POSITIONJUMP, // 0x1D Txx Position Jump
156 	FX_PATTERNBREAK, // 0x1E Uxx Pattern Break
157 	FX_GLOBALVOLUME, // 0x1F Vxx Set Mastervolume
158 	FX_GLOBALVOLSLIDE, // 0x20 Wxy Mastervolume Slide               (*)
159 	FX_SPECIAL, // 0x21 Xxx Extended Effect
160 	//      X1x Set Filter
161 	//      X3x Glissando
162 	//      X5x Vibrato Waveform
163 	//      X8x Tremolo Waveform
164 	//      XAx Pattern Loop
165 	//      XBx Pattern Delay
166 	//      XCx Note Cut
167 	//      XDx Note Delay
168 	//      XEx Ignore Envelope
169 	//      XFx Invert Loop
170 	FX_NONE, // 0x22 Yxx Chorus - XXX
171 	FX_NONE, // 0x23 Zxx Reverb - XXX
172 };
173 
174 static void import_imf_effect(song_note_t *note)
175 {
176 	uint8_t n;
177 	// fix some of them
178 	switch (note->effect) {
179 	case 0xe: // fine volslide
180 		// hackaround to get almost-right behavior for fine slides (i think!)
181 		if (note->param == 0)
182 			/* nothing */;
183 		else if (note->param == 0xf0)
184 			note->param = 0xef;
185 		else if (note->param == 0x0f)
186 			note->param = 0xfe;
187 		else if (note->param & 0xf0)
188 			note->param |= 0xf;
189 		else
190 			note->param |= 0xf0;
191 		break;
192 	case 0xf: // set finetune
193 		// we don't implement this, but let's at least import the value
194 		note->param = 0x20 | MIN(note->param >> 4, 0xf);
195 		break;
196 	case 0x14: // fine slide up
197 	case 0x15: // fine slide down
198 		// this is about as close as we can do...
199 		if (note->param >> 4)
200 			note->param = 0xf0 | MIN(note->param >> 4, 0xf);
201 		else
202 			note->param |= 0xe0;
203 		break;
204 	case 0x16: // filter
205 		note->param = (255 - note->param) / 2; // TODO: cutoff range in IMF is 125...8000 Hz
206 		break;
207 	case 0x1f: // set global volume
208 		note->param = MIN(note->param << 1, 0xff);
209 		break;
210 	case 0x21:
211 		n = 0;
212 		switch (note->param >> 4) {
213 		case 0:
214 			/* undefined, but since S0x does nothing in IT anyway, we won't care.
215 			this is here to allow S00 to pick up the previous value (assuming IMF
216 			even does that -- I haven't actually tried it) */
217 			break;
218 		default: // undefined
219 		case 0x1: // set filter
220 		case 0xf: // invert loop
221 			note->effect = 0;
222 			break;
223 		case 0x3: // glissando
224 			n = 0x20;
225 			break;
226 		case 0x5: // vibrato waveform
227 			n = 0x30;
228 			break;
229 		case 0x8: // tremolo waveform
230 			n = 0x40;
231 			break;
232 		case 0xa: // pattern loop
233 			n = 0xb0;
234 			break;
235 		case 0xb: // pattern delay
236 			n = 0xe0;
237 			break;
238 		case 0xc: // note cut
239 		case 0xd: // note delay
240 			// no change
241 			break;
242 		case 0xe: // ignore envelope
243 			/* predicament: we can only disable one envelope at a time.
244 			volume is probably most noticeable, so let's go with that.
245 			(... actually, orpheus doesn't even seem to implement this at all) */
246 			note->param = 0x77;
247 			break;
248 		case 0x18: // sample offset
249 			// O00 doesn't pick up the previous value
250 			if (!note->param)
251 				note->effect = 0;
252 			break;
253 		}
254 		if (n)
255 			note->param = n | (note->param & 0xf);
256 		break;
257 	}
258 	note->effect = (note->effect < 0x24) ? imf_efftrans[note->effect] : FX_NONE;
259 	if (note->effect == FX_VOLUME && note->voleffect == VOLFX_NONE) {
260 		note->voleffect = VOLFX_VOLUME;
261 		note->volparam = note->param;
262 		note->effect = FX_NONE;
263 		note->param = 0;
264 	}
265 }
266 
267 /* return: number of lost effects */
268 static int load_imf_pattern(song_t *song, int pat, uint32_t ignore_channels, slurp_t *fp)
269 {
270 	uint16_t length, nrows;
271 	uint8_t mask, channel;
272 	int row;
273 	unsigned int lostfx = 0;
274 	song_note_t *row_data, *note, junk_note;
275 
276 	//int startpos = slurp_tell(fp);
277 
278 	slurp_read(fp, &length, 2);
279 	length = bswapLE16(length);
280 	slurp_read(fp, &nrows, 2);
281 	nrows = bswapLE16(nrows);
282 
283 	row_data = song->patterns[pat] = csf_allocate_pattern(nrows);
284 	song->pattern_size[pat] = song->pattern_alloc_size[pat] = nrows;
285 
286 	row = 0;
287 	while (row < nrows) {
288 		mask = slurp_getc(fp);
289 		if (mask == 0) {
290 			row++;
291 			row_data += MAX_CHANNELS;
292 			continue;
293 		}
294 
295 		channel = mask & 0x1f;
296 
297 		if (ignore_channels & (1 << channel)) {
298 			/* should do this better, i.e. not go through the whole process of deciding
299 			what to do with the effects since they're just being thrown out */
300 			//printf("disabled channel %d contains data\n", channel + 1);
301 			note = &junk_note;
302 		} else {
303 			note = row_data + channel;
304 		}
305 
306 		if (mask & 0x20) {
307 			/* read note/instrument */
308 			note->note = slurp_getc(fp);
309 			note->instrument = slurp_getc(fp);
310 			if (note->note == 160) {
311 				note->note = NOTE_OFF; /* ??? */
312 			} else if (note->note == 255) {
313 				note->note = NOTE_NONE; /* ??? */
314 			} else {
315 				note->note = (note->note >> 4) * 12 + (note->note & 0xf) + 12 + 1;
316 				if (!NOTE_IS_NOTE(note->note)) {
317 					//printf("%d.%d.%d: funny note 0x%02x\n",
318 					//      pat, row, channel, fp->data[fp->pos - 1]);
319 					note->note = NOTE_NONE;
320 				}
321 			}
322 		}
323 		if ((mask & 0xc0) == 0xc0) {
324 			uint8_t e1c, e1d, e2c, e2d;
325 
326 			/* read both effects and figure out what to do with them */
327 			e1c = slurp_getc(fp);
328 			e1d = slurp_getc(fp);
329 			e2c = slurp_getc(fp);
330 			e2d = slurp_getc(fp);
331 			if (e1c == 0xc) {
332 				note->volparam = MIN(e1d, 0x40);
333 				note->voleffect = VOLFX_VOLUME;
334 				note->effect = e2c;
335 				note->param = e2d;
336 			} else if (e2c == 0xc) {
337 				note->volparam = MIN(e2d, 0x40);
338 				note->voleffect = VOLFX_VOLUME;
339 				note->effect = e1c;
340 				note->param = e1d;
341 			} else if (e1c == 0xa) {
342 				note->volparam = e1d * 64 / 255;
343 				note->voleffect = VOLFX_PANNING;
344 				note->effect = e2c;
345 				note->param = e2d;
346 			} else if (e2c == 0xa) {
347 				note->volparam = e2d * 64 / 255;
348 				note->voleffect = VOLFX_PANNING;
349 				note->effect = e1c;
350 				note->param = e1d;
351 			} else {
352 				/* check if one of the effects is a 'global' effect
353 				-- if so, put it in some unused channel instead.
354 				otherwise pick the most important effect. */
355 				lostfx++;
356 				note->effect = e2c;
357 				note->param = e2d;
358 			}
359 		} else if (mask & 0xc0) {
360 			/* there's one effect, just stick it in the effect column */
361 			note->effect = slurp_getc(fp);
362 			note->param = slurp_getc(fp);
363 		}
364 		if (note->effect)
365 			import_imf_effect(note);
366 	}
367 
368 	return lostfx;
369 }
370 
371 
372 static unsigned int envflags[3][3] = {
373 	{ENV_VOLUME,             ENV_VOLSUSTAIN,   ENV_VOLLOOP},
374 	{ENV_PANNING,            ENV_PANSUSTAIN,   ENV_PANLOOP},
375 	{ENV_PITCH | ENV_FILTER, ENV_PITCHSUSTAIN, ENV_PITCHLOOP},
376 };
377 
378 static void load_imf_envelope(song_instrument_t *ins, song_envelope_t *env, struct imf_instrument *imfins, int e)
379 {
380 	int n, t, v;
381 	int min = 0; // minimum tick value for next node
382 	int shift = (e == IMF_ENV_VOL ? 0 : 2);
383 
384 	env->nodes = CLAMP(imfins->env[e].points, 2, 25);
385 	env->loop_start = imfins->env[e].loop_start;
386 	env->loop_end = imfins->env[e].loop_end;
387 	env->sustain_start = env->sustain_end = imfins->env[e].sustain;
388 
389 	for (n = 0; n < env->nodes; n++) {
390 		t = bswapLE16(imfins->nodes[e][n].tick);
391 		v = bswapLE16(imfins->nodes[e][n].value) >> shift;
392 		env->ticks[n] = MAX(min, t);
393 		env->values[n] = v = MIN(v, 64);
394 		min = t + 1;
395 	}
396 	// this would be less retarded if the envelopes all had their own flags...
397 	if (imfins->env[e].flags & 1)
398 		ins->flags |= envflags[e][0];
399 	if (imfins->env[e].flags & 2)
400 		ins->flags |= envflags[e][1];
401 	if (imfins->env[e].flags & 4)
402 		ins->flags |= envflags[e][2];
403 }
404 
405 
406 int fmt_imf_load_song(song_t *song, slurp_t *fp, UNUSED unsigned int lflags)
407 {
408 	struct imf_header hdr;
409 	int n, s;
410 	song_sample_t *sample = song->samples + 1;
411 	int firstsample = 1; // first sample for the current instrument
412 	uint32_t ignore_channels = 0; /* bit set for each channel that's completely disabled */
413 	int lostfx = 0;
414 
415 	slurp_read(fp, &hdr, sizeof(hdr));
416 	hdr.ordnum = bswapLE16(hdr.ordnum);
417 	hdr.patnum = bswapLE16(hdr.patnum);
418 	hdr.insnum = bswapLE16(hdr.insnum);
419 	hdr.flags = bswapLE16(hdr.flags);
420 
421 	if (memcmp(hdr.im10, "IM10", 4) != 0)
422 		return LOAD_UNSUPPORTED;
423 
424 	if (hdr.ordnum > MAX_ORDERS || hdr.patnum > MAX_PATTERNS || hdr.insnum > MAX_INSTRUMENTS)
425 		return LOAD_FORMAT_ERROR;
426 
427 	memcpy(song->title, hdr.title, 25);
428 	song->title[25] = 0;
429 	strcpy(song->tracker_id, "Imago Orpheus");
430 
431 	if (hdr.flags & 1)
432 		song->flags |= SONG_LINEARSLIDES;
433 	song->flags |= SONG_INSTRUMENTMODE;
434 	song->initial_speed = hdr.tempo;
435 	song->initial_tempo = hdr.bpm;
436 	song->initial_global_volume = 2 * hdr.master;
437 	song->mixing_volume = hdr.amp;
438 
439 	for (n = 0; n < 32; n++) {
440 		song->channels[n].panning = hdr.channels[n].panning * 64 / 255;
441 		song->channels[n].panning *= 4; //mphack
442 		/* TODO: reverb/chorus??? */
443 		switch (hdr.channels[n].status) {
444 		case 0: /* enabled; don't worry about it */
445 			break;
446 		case 1: /* mute */
447 			song->channels[n].flags |= CHN_MUTE;
448 			break;
449 		case 2: /* disabled */
450 			song->channels[n].flags |= CHN_MUTE;
451 			ignore_channels |= (1 << n);
452 			break;
453 		default: /* uhhhh.... freak out */
454 			//fprintf(stderr, "imf: channel %d has unknown status %d\n", n, hdr.channels[n].status);
455 			return LOAD_FORMAT_ERROR;
456 		}
457 	}
458 	for (; n < MAX_CHANNELS; n++)
459 		song->channels[n].flags |= CHN_MUTE;
460 	/* From mikmod: work around an Orpheus bug */
461 	if (hdr.channels[0].status == 0) {
462 		for (n = 1; n < 16; n++)
463 			if (hdr.channels[n].status != 1)
464 				break;
465 		if (n == 16)
466 			for (n = 1; n < 16; n++)
467 				song->channels[n].flags &= ~CHN_MUTE;
468 	}
469 
470 	for (n = 0; n < hdr.ordnum; n++)
471 		song->orderlist[n] = ((hdr.orderlist[n] == 0xff) ? ORDER_SKIP : hdr.orderlist[n]);
472 
473 	for (n = 0; n < hdr.patnum; n++)
474 		lostfx += load_imf_pattern(song, n, ignore_channels, fp);
475 
476 	if (lostfx)
477 		log_appendf(4, " Warning: %d effect%s dropped", lostfx, lostfx == 1 ? "" : "s");
478 
479 	for (n = 0; n < hdr.insnum; n++) {
480 		// read the ins header
481 		struct imf_instrument imfins;
482 		song_instrument_t *ins;
483 		slurp_read(fp, &imfins, sizeof(imfins));
484 
485 		imfins.smpnum = bswapLE16(imfins.smpnum);
486 		imfins.fadeout = bswapLE16(imfins.fadeout);
487 
488 		ins = song->instruments[n + 1] = csf_allocate_instrument();
489 		strncpy(ins->name, imfins.name, 25);
490 		ins->name[25] = 0;
491 
492 		if (imfins.smpnum) {
493 			for (s = 12; s < 120; s++) {
494 				ins->note_map[s] = s + 1;
495 				ins->sample_map[s] = firstsample + imfins.map[s - 12];
496 			}
497 		}
498 
499 		/* Fadeout:
500 		IT1 - 64
501 		IT2 - 256
502 		FT2 - 4095
503 		IMF - 4095
504 		MPT - god knows what, all the loaders are inconsistent
505 		Schism - 256 presented; 8192? internal
506 
507 		IMF and XM have the same range and modplug's XM loader doesn't do any bit shifting with it,
508 		so I'll do the same here for now. I suppose I should get this nonsense straightened
509 		out at some point, though. */
510 		ins->fadeout = imfins.fadeout;
511 		ins->global_volume = 128;
512 
513 		load_imf_envelope(ins, &ins->vol_env, &imfins, IMF_ENV_VOL);
514 		load_imf_envelope(ins, &ins->pan_env, &imfins, IMF_ENV_PAN);
515 		load_imf_envelope(ins, &ins->pitch_env, &imfins, IMF_ENV_FILTER);
516 
517 		/* I'm not sure if XM's envelope hacks apply here or not, but Orpheus *does* at least stop
518 		samples upon note-off when no envelope is active. Whether or not this depends on the fadeout
519 		value, I don't know, and since the fadeout doesn't even seem to be implemented in the gui,
520 		I might never find out. :P */
521 		if (!(ins->flags & ENV_VOLUME)) {
522 			ins->vol_env.ticks[0] = 0;
523 			ins->vol_env.ticks[1] = 1;
524 			ins->vol_env.values[0] = 64;
525 			ins->vol_env.values[1] = 0;
526 			ins->vol_env.nodes = 2;
527 			ins->vol_env.sustain_start = ins->vol_env.sustain_end = 0;
528 			ins->flags |= ENV_VOLUME | ENV_VOLSUSTAIN;
529 		}
530 
531 		for (s = 0; s < imfins.smpnum; s++) {
532 			struct imf_sample imfsmp;
533 			uint32_t blen, sflags = SF_LE | SF_M | SF_PCMS;
534 
535 			slurp_read(fp, &imfsmp, sizeof(imfsmp));
536 
537 			if (memcmp(imfsmp.is10, "IS10", 4) != 0) {
538 				//printf("is10 says %02x %02x %02x %02x!\n",
539 				//      imfsmp.is10[0], imfsmp.is10[1], imfsmp.is10[2], imfsmp.is10[3]);
540 				return LOAD_FORMAT_ERROR;
541 			}
542 
543 			strncpy(sample->filename, imfsmp.name, 12);
544 			sample->filename[12] = 0;
545 			strcpy(sample->name, sample->filename);
546 			blen = sample->length = bswapLE32(imfsmp.length);
547 			sample->loop_start = bswapLE32(imfsmp.loop_start);
548 			sample->loop_end = bswapLE32(imfsmp.loop_end);
549 			sample->c5speed = bswapLE32(imfsmp.c5speed);
550 			sample->volume = imfsmp.volume * 4; //mphack
551 			sample->panning = imfsmp.panning; //mphack (IT uses 0-64, IMF uses the full 0-255)
552 			if (imfsmp.flags & 1)
553 				sample->flags |= CHN_LOOP;
554 			if (imfsmp.flags & 2)
555 				sample->flags |= CHN_PINGPONGLOOP;
556 			if (imfsmp.flags & 4) {
557 				sflags |= SF_16;
558 				sample->length >>= 1;
559 				sample->loop_start >>= 1;
560 				sample->loop_end >>= 1;
561 			} else {
562 				sflags |= SF_8;
563 			}
564 			if (imfsmp.flags & 8)
565 				sample->flags |= CHN_PANNING;
566 
567 			if (blen && !(lflags & LOAD_NOSAMPLES))
568 				csf_read_sample(sample, sflags, fp->data + fp->pos, fp->length - fp->pos);
569 			slurp_seek(fp, blen, SEEK_CUR);
570 
571 			sample++;
572 		}
573 		firstsample += imfins.smpnum;
574 	}
575 
576 	// Fix the MIDI settings, because IMF files might include Zxx effects
577 	memset(&song->midi_config, 0, sizeof(song->midi_config));
578 	strcpy(song->midi_config.sfx[0], "F0F000z");
579 	song->flags |= SONG_EMBEDMIDICFG;
580 
581 	return LOAD_SUCCESS;
582 }
583 
584