1 /* Extended Module Player
2  * Copyright (C) 1996-2021 Claudio Matsuoka and Hipolito Carraro Jr
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 /*
24  * Originally based on the PSM loader from Modplug by Olivier Lapicque and
25  * fixed comparing the One Must Fall! PSMs with Kenny Chou's MTM files.
26  */
27 
28 /*
29  * From EPICTEST Readme.1st:
30  *
31  * The Music And Sound Interface, MASI, is the basis behind all new Epic
32  * games. MASI uses its own proprietary file format, PSM, for storing
33  * its music.
34  */
35 
36 /*
37  * kode54's comment on Sinaria PSMs in the foo_dumb hydrogenaudio forum:
38  *
39  * "The Sinaria variant uses eight character pattern and instrument IDs,
40  * the sample headers are laid out slightly different, and the patterns
41  * use a different format for the note values, and also different effect
42  * scales for certain commands.
43  *
44  * [Epic] PSM uses high nibble for octave and low nibble for note, for
45  * a valid range up to 0x7F, for a range of D-1 through D#9 compared to
46  * IT. (...) Sinaria PSM uses plain note values, from 1 - 83, for a
47  * range of C-3 through B-9.
48  *
49  * [Epic] PSM also uses an effect scale for portamento, volume slides,
50  * and vibrato that is about four times as sensitive as the IT equivalents.
51  * Sinaria does not. This seems to coincide with the MOD/S3M to PSM
52  * converter that Joshua Jensen released in the EPICTEST.ZIP file which
53  * can still be found on a few FTP sites. It converted effects literally,
54  * even though the bundled players behaved as the libraries used with
55  * Epic's games did and made the effects sound too strong."
56  */
57 
58 /*
59  * Claudio's note: Sinaria seems to have a finetune byte just before
60  * volume and some kind of (stereo?) interleaved sample, with 16-byte
61  * frames (see Sinaria songs 5 and 8). Sinaria song 10 still sounds
62  * ugly, maybe caused by finetune issues?
63  */
64 
65 #include <limits.h>
66 #include "loader.h"
67 #include "iff.h"
68 #include "period.h"
69 
70 #define MAGIC_PSM_	MAGIC4('P','S','M',' ')
71 #define MAGIC_FILE	MAGIC4('F','I','L','E')
72 #define MAGIC_TITL	MAGIC4('T','I','T','L')
73 #define MAGIC_OPLH	MAGIC4('O','P','L','H')
74 #define MAGIC_PPAN	MAGIC4('P','P','A','N')
75 
76 
77 static int masi_test (HIO_HANDLE *, char *, const int);
78 static int masi_load (struct module_data *, HIO_HANDLE *, const int);
79 
80 const struct format_loader libxmp_loader_masi = {
81 	"Epic MegaGames MASI",
82 	masi_test,
83 	masi_load
84 };
85 
masi_test(HIO_HANDLE * f,char * t,const int start)86 static int masi_test(HIO_HANDLE *f, char *t, const int start)
87 {
88 	int val;
89 
90 	if (hio_read32b(f) != MAGIC_PSM_)
91 		return -1;
92 
93 	hio_read8(f);
94 	hio_read8(f);
95 	hio_read8(f);
96 	if (hio_read8(f) != 0)
97 		return -1;
98 
99 	if (hio_read32b(f) != MAGIC_FILE)
100 		return -1;
101 
102 	hio_read32b(f);
103 	val = hio_read32l(f);
104 	hio_seek(f, val, SEEK_CUR);
105 
106 	if (hio_read32b(f) == MAGIC_TITL) {
107 		val = hio_read32l(f);
108 		libxmp_read_title(f, t, val);
109 	} else {
110 		libxmp_read_title(f, t, 0);
111 	}
112 
113 	return 0;
114 }
115 
116 struct local_data {
117 	int sinaria;
118 	int cur_pat;
119 	int cur_ins;
120 	uint8 *pnam;
121 	uint8 *pord;
122 };
123 
get_sdft(struct module_data * m,int size,HIO_HANDLE * f,void * parm)124 static int get_sdft(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
125 {
126 	return 0;
127 }
128 
get_titl(struct module_data * m,int size,HIO_HANDLE * f,void * parm)129 static int get_titl(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
130 {
131 	struct xmp_module *mod = &m->mod;
132 	char buf[40];
133 
134 	hio_read(buf, 1, 40, f);
135 	size = size > 32 ? 32 : size;
136 	strncpy(mod->name, buf, size);
137 	mod->name[size] = '\0';
138 
139 	return 0;
140 }
141 
get_dsmp_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)142 static int get_dsmp_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
143 {
144 	struct xmp_module *mod = &m->mod;
145 
146 	mod->ins++;
147 	mod->smp = mod->ins;
148 
149 	return 0;
150 }
151 
get_pbod_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)152 static int get_pbod_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
153 {
154 	struct xmp_module *mod = &m->mod;
155 	struct local_data *data = (struct local_data *)parm;
156 	char buf[20];
157 
158 	mod->pat++;
159 	if (hio_read(buf, 1, 20, f) < 20) {
160 		D_(D_CRIT "read error at pat %d", mod->pat - 1);
161 		return -1;
162 	}
163 	if (buf[9] != 0 && buf[13] == 0)
164 		data->sinaria = 1;
165 
166 	return 0;
167 }
168 
169 
get_dsmp(struct module_data * m,int size,HIO_HANDLE * f,void * parm)170 static int get_dsmp(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
171 {
172 	struct xmp_module *mod = &m->mod;
173 	struct xmp_instrument *xxi;
174 	struct xmp_subinstrument *sub;
175 	struct xmp_sample *xxs;
176 	struct local_data *data = (struct local_data *)parm;
177 	int i, srate, flags;
178 	int finetune;
179 
180 	flags = hio_read8(f);				/* flags */
181 	hio_seek(f, 8, SEEK_CUR);			/* songname */
182 	hio_seek(f, data->sinaria ? 8 : 4, SEEK_CUR);	/* smpid */
183 
184 	i = data->cur_ins;
185 	if (libxmp_alloc_subinstrument(mod, i, 1) < 0)
186 		return -1;
187 
188 	xxi = &mod->xxi[i];
189 	sub = &xxi->sub[0];
190 	xxs = &mod->xxs[i];
191 
192 	hio_read(xxi->name, 1, 31, f);
193 	hio_seek(f, 8, SEEK_CUR);
194 	hio_read8(f);		/* insno */
195 	hio_read8(f);
196 	xxs->len = hio_read32l(f);
197 	xxs->lps = hio_read32l(f);
198 	xxs->lpe = hio_read32l(f);
199 	xxs->flg = flags & 0x80 ? XMP_SAMPLE_LOOP : 0;
200 	hio_read16l(f);
201 
202 	if ((int32)xxs->lpe < 0)
203 		xxs->lpe = 0;
204 
205 	if (xxs->len > 0)
206 		xxi->nsm = 1;
207 
208 	finetune = 0;
209 	if (data->sinaria) {
210 		finetune = (int8)(hio_read8s(f) << 4);
211 	}
212 
213 	sub->vol = hio_read8(f) / 2 + 1;
214 	hio_read32l(f);
215 	sub->pan = 0x80;
216 	sub->sid = i;
217 	srate = hio_read16l(f);
218 
219 	D_(D_INFO "[%2X] %-32.32s %05x %05x %05x %c V%02x %+04d %5d", i,
220 		xxi->name, xxs->len, xxs->lps, xxs->lpe,
221 		xxs->flg & XMP_SAMPLE_LOOP ?  'L' : ' ',
222 		sub->vol, finetune, srate);
223 
224 	libxmp_c2spd_to_note(srate, &sub->xpo, &sub->fin);
225 	sub->fin += finetune;
226 
227 	hio_seek(f, 16, SEEK_CUR);
228 	if (libxmp_load_sample(m, f, SAMPLE_FLAG_8BDIFF, xxs, NULL) < 0)
229 		return -1;
230 
231 	data->cur_ins++;
232 
233 	return 0;
234 }
235 
236 
convert_porta(uint8 param,int sinaria)237 static uint8 convert_porta(uint8 param, int sinaria)
238 {
239 	if (sinaria) {
240 		return param;
241 	}
242 
243 	if (param < 4) {
244 		return param | 0xf0;
245 	} else {
246 		return param >> 2;
247 	}
248 }
249 
get_pbod(struct module_data * m,int size,HIO_HANDLE * f,void * parm)250 static int get_pbod(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
251 {
252 	struct xmp_module *mod = &m->mod;
253 	struct local_data *data = (struct local_data *)parm;
254 	int i, r;
255 	struct xmp_event *event, dummy;
256 	uint8 flag, chan;
257 	/* uint32 len; */
258 	int rows, rowlen;
259 
260 	i = data->cur_pat;
261 
262 	/*len =*/ hio_read32l(f);
263 	hio_read(data->pnam + i * 8, 1, data->sinaria ? 8 : 4, f);
264 
265 	rows = hio_read16l(f);
266 	if (hio_error(f)) {
267 		return -1;
268 	}
269 
270 	if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0)
271 		return -1;
272 
273 	r = 0;
274 
275 	do {
276 		rowlen = hio_read16l(f) - 2;
277 		if (hio_error(f)) {
278 			return -1;
279 		}
280 		while (rowlen > 0) {
281 			flag = hio_read8(f);
282 
283 			if (rowlen == 1)
284 				break;
285 
286 			chan = hio_read8(f);
287 			rowlen -= 2;
288 
289 			event = chan < mod->chn ? &EVENT(i, chan, r) : &dummy;
290 
291 			if (flag & 0x80) {
292 				uint8 note = hio_read8(f);
293 				rowlen--;
294 				if (data->sinaria)
295 					note += 36;
296 				else
297 					note = (note >> 4) * 12 + (note & 0x0f) + 1 + 12;
298 				event->note = note;
299 			}
300 
301 			if (flag & 0x40) {
302 				event->ins = hio_read8(f) + 1;
303 				rowlen--;
304 			}
305 
306 			if (flag & 0x20) {
307 				event->vol = hio_read8(f) / 2 + 1;
308 				rowlen--;
309 			}
310 
311 			if (flag & 0x10) {
312 				uint8 fxt = hio_read8(f);
313 				uint8 fxp = hio_read8(f);
314 				rowlen -= 2;
315 
316 #if 0
317 				/* compressed events */
318 				if (fxt >= 0x40) {
319 					switch (fxp >> 4) {
320 					case 0x0: {
321 						uint8 note;
322 						note = (fxt>>4)*12 +
323 							(fxt & 0x0f) + 1;
324 						event->note = note;
325 						fxt = FX_TONEPORTA;
326 						fxp = (fxp + 1) * 2;
327 						break; }
328 					default:
329 D_(D_CRIT "p%d r%d c%d: compressed event %02x %02x\n", i, r, chan, fxt, fxp);
330 						return -1;
331 					}
332 				} else
333 #endif
334 
335 				switch (fxt) {
336 
337 				/* Volume slide */
338 				case 0x01:		/* fine volslide up */
339 					fxt = FX_EXTENDED;
340 					fxp = (EX_F_VSLIDE_UP << 4) |
341 						((fxp / 2) & 0x0f);
342 					break;
343 				case 0x02:		/* volslide up */
344 					fxt = FX_VOLSLIDE;
345 					fxp = (fxp / 2) << 4;
346 					break;
347 				case 0x03:		/* fine volslide down */
348 					fxt = FX_EXTENDED;
349 					fxp = (EX_F_VSLIDE_DN << 4) |
350 						((fxp / 2) & 0x0f);
351 					break;
352 				case 0x04: 		/* volslide down */
353 					fxt = FX_VOLSLIDE;
354 					fxp /= 2;
355 					break;
356 
357 				/* Portamento */
358 				case 0x0b:		/* fine portamento up */
359 					fxt = FX_PORTA_UP;
360 					fxp = (EX_F_PORTA_UP << 4) |
361 						convert_porta(fxp, data->sinaria);
362 					break;
363 				case 0x0c:		/* portamento up */
364 					fxt = FX_PORTA_UP;
365 					fxp = convert_porta(fxp, data->sinaria);
366 					break;
367 				case 0x0d:		/* fine portamento up */
368 					fxt = FX_PORTA_DN;
369 					fxp = (EX_F_PORTA_DN << 4) |
370 						convert_porta(fxp, data->sinaria);
371 					break;
372 				case 0x0e:		/* portamento down */
373 					fxt = FX_PORTA_DN;
374 					fxp = convert_porta(fxp, data->sinaria);
375 					break;
376 				case 0x0f:		/* tone portamento */
377 					fxt = FX_TONEPORTA;
378 					fxp >>= 2;
379 					break;
380 				case 0x10:		/* toneporta + vslide up */
381 					fxt = FX_TONE_VSLIDE;
382 					fxp = fxt & 0xf0;
383 					break;
384 				case 0x11:		/* glissando */
385 					fxt = FX_EXTENDED;
386 					fxp = (EX_GLISS << 4) | (fxp & 0x0f);
387 					break;
388 				case 0x12:		/* toneporta + vslide down */
389 					fxt = FX_TONE_VSLIDE;
390 					fxp >>= 4;
391 					break;
392 
393 				/* 0x13: S3M S: crashes MASI */
394 
395 				/* Vibrato */
396 				case 0x15:		/* vibrato */
397 					fxt = data->sinaria ?
398 						FX_VIBRATO : FX_FINE_VIBRATO;
399 					/* fxp remains the same */
400 					break;
401 				case 0x16:		/* vibrato waveform */
402 					fxt = FX_EXTENDED;
403 					fxp = (EX_VIBRATO_WF << 4) | (fxp & 0x0f);
404 					break;
405 				case 0x17:		/* vibrato + vslide up */
406 					fxt = FX_VIBRA_VSLIDE;
407 					fxp >>= 4;
408 					break;
409 				case 0x18:		/* vibrato + vslide down */
410 					fxt = FX_VIBRA_VSLIDE;
411 					fxp = fxp & 0x0f;
412 					break;
413 
414 				/* Tremolo */
415 				case 0x1f:		/* tremolo */
416 					fxt = FX_TREMOLO;
417 					/* fxp remains the same */
418 					break;
419 				case 0x20:		/* tremolo waveform */
420 					fxt = FX_EXTENDED;
421 					fxp = (EX_TREMOLO_WF << 4) | (fxp & 0x0f);
422 					break;
423 
424 				/* Sample commands */
425 				case 0x29:		/* 3-byte offset */
426 					fxt = FX_OFFSET;
427 					/* use only the middle byte */
428 					fxp = hio_read8(f);
429 					hio_read8(f);
430 					rowlen -= 2;
431 					break;
432 				case 0x2a:		/* retrig note */
433 					fxt = FX_EXTENDED;
434 					fxp = (EX_RETRIG << 4) | (fxp & 0x0f);
435 					break;
436 				case 0x2b:		/* note cut */
437 					fxt = FX_EXTENDED;
438 					fxp = (EX_CUT << 4) | (fxp & 0x0f);
439 					break;
440 				case 0x2c:		/* note delay */
441 					fxt = FX_EXTENDED;
442 					fxp = (EX_DELAY << 4) | (fxp & 0x0f);
443 					break;
444 
445 				/* Position change */
446 				case 0x33:		/* position jump */
447 					/* not used in MASI */
448 					fxt = FX_JUMP;
449 					fxp >>= 1;
450 					hio_read8(f);
451 					rowlen--;
452 					break;
453 				case 0x34:		/* pattern break */
454 					/* not used in MASI */
455 					fxt = FX_BREAK;
456 					break;
457 				case 0x35:		/* pattern loop */
458 					fxt = FX_EXTENDED;
459 					fxp = (EX_PATTERN_LOOP << 4) | (fxp & 0x0f);
460 					break;
461 				case 0x36:		/* pattern delay */
462 					fxt = FX_EXTENDED;
463 					fxp = (EX_PATT_DELAY << 4) | (fxp & 0x0f);
464 					break;
465 
466 				/* Speed change */
467 				case 0x3d:		/* speed */
468 					fxt = FX_SPEED;
469 					break;
470 				case 0x3e:		/* tempo */
471 					fxt = FX_SPEED;
472 					break;
473 
474 				/* Other */
475 				case 0x47:		/* arpeggio */
476 					fxt = FX_S3M_ARPEGGIO;
477 					break;
478 				case 0x48:		/* set finetune */
479 					fxt = FX_EXTENDED;
480 					fxp = (EX_FINETUNE << 4) | (fxp & 0x0f);
481 					break;
482 				case 0x49:		/* set pan */
483 					fxt = FX_SETPAN;
484 					fxp <<= 4;
485 					break;
486 
487 				default:
488 D_(D_CRIT "p%d r%d c%d: unknown effect %02x %02x\n", i, r, chan, fxt, fxp);
489 					fxt = fxp = 0;
490 				}
491 
492 				event->fxt = fxt;
493 				event->fxp = fxp;
494 			}
495 		}
496 		r++;
497 	} while (r < rows);
498 
499 	data->cur_pat++;
500 
501 	return 0;
502 }
503 
get_song(struct module_data * m,int size,HIO_HANDLE * f,void * parm)504 static int get_song(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
505 {
506 	struct xmp_module *mod = &m->mod;
507 
508 	hio_seek(f, 10, SEEK_CUR);
509 	mod->chn = hio_read8(f);
510 
511 	return 0;
512 }
513 
subchunk_oplh(struct module_data * m,int size,HIO_HANDLE * f,void * parm)514 static int subchunk_oplh(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
515 {
516 	struct xmp_module *mod = &m->mod;
517 	struct local_data *data = (struct local_data *)parm;
518 	int first_order_chunk = INT_MAX;
519 	int num_chunk, i;
520 
521 	/* First two bytes = Number of chunks that follow */
522 	num_chunk = hio_read16l(f);
523 
524 	/* Sub sub chunks */
525 	for (i = 0; i < num_chunk && size > 0; i++) {
526 		int opcode = hio_read8(f);
527 
528 		size--;
529 
530 		if (opcode == 0) {	/* last sub sub chunk */
531 			break;
532 		}
533 
534 		/* Saga Musix's note in OpenMPT:
535 		 *
536 		 * "This is more like a playlist than a collection of global
537 		 *  values. In theory, a tempo item inbetween two order items
538 		 *  should modify the tempo when switching patterns. No module
539 		 *  uses this feature in practice though, so we can keep our
540 		 *  loader simple. Unimplemented opcodes do nothing or freeze
541 		 *  MASI."
542 		 */
543 		switch (opcode) {
544 		case 0x01:			/* Play order list item */
545 			if (mod->len >= XMP_MAX_MOD_LENGTH) {
546 				return -1;
547 			}
548 			hio_read(data->pord + mod->len * 8, 1, data->sinaria ? 8 : 4, f);
549 			size -= data->sinaria ? 8 : 4;
550 			mod->len++;
551 			if (first_order_chunk == INT_MAX) {
552 				first_order_chunk = i;
553 			}
554 			break;
555 
556 		/* 0x02: Play range */
557 		/* 0x03: Jump loop */
558 
559 		case 0x04: {			/* Jump line (restart position) */
560 			int restart_chunk = hio_read16l(f);
561 			size -= 2;
562 
563 			/* This jumps to the command line, but since we're converting
564 			 * play order list items to our order list, only change the
565 			 * restart position if it's after the first order chunk.
566 			 */
567 
568 			if (restart_chunk >= first_order_chunk) {
569 				mod->rst = restart_chunk - first_order_chunk;
570 			}
571 
572 			break; }
573 
574 		/* 0x05: Channel flip */
575 		/* 0x06: Transpose */
576 
577 		case 0x07:			/* Default speed */
578 			mod->spd = hio_read8(f);
579 			size--;
580 			break;
581 		case 0x08:			/* Default tempo */
582 			mod->bpm = hio_read8(f);
583 			size--;
584 			break;
585 		case 0x0c:			/* Sample map table */
586 			hio_read16l(f);
587 			hio_read16l(f);
588 			hio_read16l(f);
589 			size -= 6;
590 			break;
591 		case 0x0d: {			/* Channel panning table */
592 			int chn = hio_read8(f);
593 			int pan = hio_read8(f);
594 			int type = hio_read8(f);
595 			struct xmp_channel *xxc;
596 
597 			if (chn >= XMP_MAX_CHANNELS) {
598 				break;
599 			}
600 
601 			xxc = &mod->xxc[chn];
602 
603 			size -= 3;
604 
605 			switch (type) {
606 			case 0:		/* use panning */
607 				xxc->pan = pan ^ 0x80;
608 				break;
609 			case 2:		/* surround */
610 				xxc->pan = 0x80;
611                         	xxc->flg |= XMP_CHANNEL_SURROUND;
612 				break;
613 			case 4:		/* center */
614 				xxc->pan = 0x80;
615 				break;
616 			}
617 			break; }
618 		case 0x0e: {			/* Channel volume table */
619 			int chn = hio_read8(f);
620 			int vol = hio_read8(f);
621 			struct xmp_channel *xxc;
622 
623 			if (chn >= XMP_MAX_CHANNELS) {
624 				break;
625 			}
626 
627 			xxc = &mod->xxc[chn];
628 
629 			size -= 2;
630 
631 			xxc->vol = (vol >> 2) + 1;
632 			break; }
633 		default:
634 			/*printf("channel %d: %02x %02x\n", i, c, hio_read8(f));*/
635 			return -1;
636 		}
637 	}
638 
639 	return 0;
640 }
641 
642 /* Sinaria channel panning table */
subchunk_ppan(struct module_data * m,int size,HIO_HANDLE * f,void * parm)643 static int subchunk_ppan(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
644 {
645 	struct xmp_module *mod = &m->mod;
646 	int i;
647 
648 	for (i = 0; i < XMP_MAX_CHANNELS && size > 0; i++) {
649 		struct xmp_channel *xxc = &mod->xxc[i];
650 		int type = hio_read8(f);
651 		int pan = hio_read8(f);
652 
653 		size -= 2;
654 
655 		switch (type) {
656 		case 0:		/* use panning */
657 			xxc->pan = pan ^ 0x80;
658 			break;
659 		case 2:		/* surround */
660 			xxc->pan = 0x80;
661                        	xxc->flg |= XMP_CHANNEL_SURROUND;
662 			break;
663 		case 4:		/* center */
664 			xxc->pan = 0x80;
665 			break;
666 		}
667 	}
668 
669 	return 0;
670 }
671 
672 /* Subchunk loader based on OpenMPT LoadPSM.cpp */
get_song_2(struct module_data * m,int size,HIO_HANDLE * f,void * parm)673 static int get_song_2(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
674 {
675 	uint32 magic;
676 	char buf[20];
677 
678 	hio_read(buf, 1, 9, f);
679 	hio_read16l(f);
680 	size -= 11;
681 
682 	D_(D_INFO "Subsong title: %-9.9s", buf);
683 
684 	/* Iterate over subchunks. We want OPLH and PPAN */
685 	while (size > 0) {
686 		int subchunk_size;
687 
688 		magic = hio_read32b(f);
689 		subchunk_size = hio_read32l(f);
690 		if (subchunk_size <= 0 || hio_error(f)) {
691 			return -1;
692 		}
693 
694 		size -= subchunk_size;
695 
696 		switch (magic) {
697 		case MAGIC_OPLH:
698 			if (subchunk_oplh(m, size, f, parm) < 0) {
699 				return -1;
700 			}
701 			break;
702 
703 		case MAGIC_PPAN:
704 			if (subchunk_ppan(m, size, f, parm) < 0) {
705 				return -1;
706 			}
707 			break;
708 
709 		default:
710 			hio_seek(f, subchunk_size, SEEK_CUR);
711 		}
712 	}
713 
714 	return 0;
715 }
716 
masi_load(struct module_data * m,HIO_HANDLE * f,const int start)717 static int masi_load(struct module_data *m, HIO_HANDLE *f, const int start)
718 {
719 	struct xmp_module *mod = &m->mod;
720 	iff_handle handle;
721 	int ret, offset;
722 	int i, j;
723 	struct local_data data;
724 
725 	LOAD_INIT();
726 
727 	hio_read32b(f);
728 
729 	data.sinaria = 0;
730 	mod->name[0] = 0;
731 
732 	hio_seek(f, 8, SEEK_CUR);		/* skip file size and FILE */
733 	mod->smp = mod->ins = 0;
734 	data.cur_pat = 0;
735 	data.cur_ins = 0;
736 	offset = hio_tell(f);
737 
738 	handle = libxmp_iff_new();
739 	if (handle == NULL)
740 		goto err;
741 
742 	/* IFF chunk IDs */
743 	ret = libxmp_iff_register(handle, "TITL", get_titl);
744 	ret |= libxmp_iff_register(handle, "SDFT", get_sdft);
745 	ret |= libxmp_iff_register(handle, "SONG", get_song);
746 	ret |= libxmp_iff_register(handle, "DSMP", get_dsmp_cnt);
747 	ret |= libxmp_iff_register(handle, "PBOD", get_pbod_cnt);
748 
749 	if (ret != 0)
750 		goto err;
751 
752 	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
753 
754 	/* Load IFF chunks */
755 	if (libxmp_iff_load(handle, m, f, &data) < 0) {
756 		libxmp_iff_release(handle);
757 		goto err;
758 	}
759 
760 	libxmp_iff_release(handle);
761 
762 	mod->trk = mod->pat * mod->chn;
763 	data.pnam = malloc(mod->pat * 8);	/* pattern names */
764 	if (data.pnam == NULL)
765 		goto err;
766 
767 	data.pord = malloc(XMP_MAX_MOD_LENGTH * 8);	/* pattern orders */
768 	if (data.pord == NULL)
769 		goto err2;
770 
771 	libxmp_set_type(m, data.sinaria ?
772 		"Sinaria PSM" : "Epic MegaGames MASI PSM");
773 
774 	m->c4rate = C4_NTSC_RATE;
775 
776 	MODULE_INFO();
777 
778 	if (libxmp_init_instrument(m) < 0)
779 		goto err3;
780 
781 	if (libxmp_init_pattern(mod) < 0)
782 		goto err3;
783 
784 	D_(D_INFO "Stored patterns: %d", mod->pat);
785 	D_(D_INFO "Stored samples : %d", mod->smp);
786 
787 	hio_seek(f, start + offset, SEEK_SET);
788 
789 	mod->len = 0;
790 
791 	handle = libxmp_iff_new();
792 	if (handle == NULL)
793 		goto err3;
794 
795 	/* IFF chunk IDs */
796 	ret = libxmp_iff_register(handle, "SONG", get_song_2);
797 	ret |= libxmp_iff_register(handle, "DSMP", get_dsmp);
798 	ret |= libxmp_iff_register(handle, "PBOD", get_pbod);
799 
800 	if (ret != 0)
801 		goto err3;
802 
803 	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
804 
805 	/* Load IFF chunks */
806 	if (libxmp_iff_load(handle, m, f, &data) < 0) {
807 		libxmp_iff_release(handle);
808 		goto err3;
809 	}
810 
811 	libxmp_iff_release(handle);
812 
813 	for (i = 0; i < mod->len; i++) {
814 		for (j = 0; j < mod->pat; j++) {
815 			if (!memcmp(data.pord + i * 8, data.pnam + j * 8, data.sinaria ? 8 : 4)) {
816 				mod->xxo[i] = j;
817 				break;
818 			}
819 		}
820 
821 		if (j == mod->pat)
822 			break;
823 	}
824 
825 	free(data.pord);
826 	free(data.pnam);
827 
828 	return 0;
829 
830     err3:
831 	free(data.pord);
832     err2:
833 	free(data.pnam);
834     err:
835 	return -1;
836 }
837