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 #include "loader.h"
24 #include "iff.h"
25 #include "period.h"
26 
27 /* Galaxy Music System 4.0 module file loader
28  *
29  * Based on modules converted using mod2j2b.exe
30  */
31 
32 static int gal4_test(HIO_HANDLE *, char *, const int);
33 static int gal4_load(struct module_data *, HIO_HANDLE *, const int);
34 
35 const struct format_loader libxmp_loader_gal4 = {
36 	"Galaxy Music System 4.0",
37 	gal4_test,
38 	gal4_load
39 };
40 
gal4_test(HIO_HANDLE * f,char * t,const int start)41 static int gal4_test(HIO_HANDLE *f, char *t, const int start)
42 {
43         if (hio_read32b(f) != MAGIC4('R', 'I', 'F', 'F'))
44 		return -1;
45 
46 	hio_read32b(f);
47 
48 	if (hio_read32b(f) != MAGIC4('A', 'M', 'F', 'F'))
49 		return -1;
50 
51 	if (hio_read32b(f) != MAGIC4('M', 'A', 'I', 'N'))
52 		return -1;
53 
54 	hio_read32b(f);		/* skip size */
55 	libxmp_read_title(f, t, 64);
56 
57 	return 0;
58 }
59 
60 struct local_data {
61     int snum;
62 };
63 
get_main(struct module_data * m,int size,HIO_HANDLE * f,void * parm)64 static int get_main(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
65 {
66 	struct xmp_module *mod = &m->mod;
67 	char buf[64];
68 	int flags;
69 
70 	hio_read(buf, 1, 64, f);
71 	strncpy(mod->name, buf, 63);	/* ensure string terminator */
72 	mod->name[63] = '\0';
73 	libxmp_set_type(m, "Galaxy Music System 4.0");
74 
75 	flags = hio_read8(f);
76 	if (~flags & 0x01)
77 		m->period_type = PERIOD_LINEAR;
78 	mod->chn = hio_read8(f);
79 	mod->spd = hio_read8(f);
80 	mod->bpm = hio_read8(f);
81 	hio_read16l(f);		/* unknown - 0x01c5 */
82 	hio_read16l(f);		/* unknown - 0xff00 */
83 	hio_read8(f);		/* unknown - 0x80 */
84 
85 	/* Sanity check */
86 	if (mod->chn > 32) {
87 		return -1;
88 	}
89 
90 	return 0;
91 }
92 
get_ordr(struct module_data * m,int size,HIO_HANDLE * f,void * parm)93 static int get_ordr(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
94 {
95 	struct xmp_module *mod = &m->mod;
96 	int i;
97 
98 	mod->len = hio_read8(f) + 1;
99 	if (hio_error(f)) {
100 		return -1;
101 	}
102 
103 	for (i = 0; i < mod->len; i++) {
104 		mod->xxo[i] = hio_read8(f);
105 	}
106 
107 	return 0;
108 }
109 
get_patt_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)110 static int get_patt_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
111 {
112 	struct xmp_module *mod = &m->mod;
113 	int i;
114 
115 	i = hio_read8(f) + 1;		/* pattern number */
116 
117 	if (i > mod->pat)
118 		mod->pat = i;
119 
120 	return 0;
121 }
122 
get_inst_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)123 static int get_inst_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
124 {
125 	struct xmp_module *mod = &m->mod;
126 	int i;
127 
128 	hio_read8(f);			/* 00 */
129 	i = hio_read8(f) + 1;		/* instrument number */
130 
131 	/* Sanity check */
132 	if (i > MAX_INSTRUMENTS)
133 		return -1;
134 
135 	if (i > mod->ins)
136 		mod->ins = i;
137 
138 	hio_seek(f, 28, SEEK_CUR);		/* skip name */
139 
140 	mod->smp += hio_read8(f);
141 
142 	return 0;
143 }
144 
get_patt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)145 static int get_patt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
146 {
147 	struct xmp_module *mod = &m->mod;
148 	struct xmp_event *event, dummy;
149 	int i, len, chan;
150 	int rows, r;
151 	uint8 flag;
152 
153 	i = hio_read8(f);	/* pattern number */
154 	len = hio_read32l(f);
155 
156 	/* Sanity check */
157 	if (i >= mod->pat || len <= 0 || mod->xxp[i]) {
158 		return -1;
159 	}
160 
161 	rows = hio_read8(f) + 1;
162 
163 	if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0)
164 		return -1;
165 
166 	for (r = 0; r < rows; ) {
167 		if ((flag = hio_read8(f)) == 0) {
168 			r++;
169 			continue;
170 		}
171 		if (hio_error(f)) {
172 			return -1;
173 		}
174 
175 		chan = flag & 0x1f;
176 
177 		event = chan < mod->chn ? &EVENT(i, chan, r) : &dummy;
178 
179 		if (flag & 0x80) {
180 			uint8 fxp = hio_read8(f);
181 			uint8 fxt = hio_read8(f);
182 
183 			switch (fxt) {
184 			case 0x14:		/* speed */
185 				fxt = FX_S3M_SPEED;
186 				break;
187 			default:
188 				if (fxt > 0x0f) {
189 					D_(D_CRIT "p%d r%d c%d unknown effect %02x %02x", i, r, chan, fxt, fxp);
190 					fxt = fxp = 0;
191 				}
192 			}
193 
194 			event->fxt = fxt;
195 			event->fxp = fxp;
196 		}
197 
198 		if (flag & 0x40) {
199 			event->ins = hio_read8(f);
200 			event->note = hio_read8(f);
201 
202 			if (event->note == 128) {
203 				event->note = XMP_KEY_OFF;
204 			}
205 		}
206 
207 		if (flag & 0x20) {
208 			event->vol = 1 + hio_read8(f) / 2;
209 		}
210 	}
211 
212 	return 9;
213 }
214 
get_inst(struct module_data * m,int size,HIO_HANDLE * f,void * parm)215 static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
216 {
217 	struct xmp_module *mod = &m->mod;
218 	struct local_data *data = (struct local_data *)parm;
219 	int i, j;
220 	int srate, finetune, flags;
221 	int val, vwf, vra, vde, vsw, fade;
222 	uint8 buf[30];
223 
224 	hio_read8(f);		/* 00 */
225 	i = hio_read8(f);		/* instrument number */
226 
227 	/* Sanity check */
228 	if (i >= mod->ins || mod->xxi[i].nsm) {
229 		return -1;
230 	}
231 
232 	hio_read(mod->xxi[i].name, 1, 28, f);
233 	mod->xxi[i].nsm = hio_read8(f);
234 
235 	for (j = 0; j < 108; j++) {
236 		mod->xxi[i].map[j].ins = hio_read8(f);
237 	}
238 
239 	hio_seek(f, 11, SEEK_CUR);		/* unknown */
240 	vwf = hio_read8(f);			/* vibrato waveform */
241 	vsw = hio_read8(f);			/* vibrato sweep */
242 	hio_read8(f);			/* unknown */
243 	hio_read8(f);			/* unknown */
244 	vde = hio_read8(f);		/* vibrato depth */
245 	vra = hio_read16l(f) / 16;		/* vibrato speed */
246 	hio_read8(f);			/* unknown */
247 
248 	val = hio_read8(f);			/* PV envelopes flags */
249 	if (LSN(val) & 0x01)
250 		mod->xxi[i].aei.flg |= XMP_ENVELOPE_ON;
251 	if (LSN(val) & 0x02)
252 		mod->xxi[i].aei.flg |= XMP_ENVELOPE_SUS;
253 	if (LSN(val) & 0x04)
254 		mod->xxi[i].aei.flg |= XMP_ENVELOPE_LOOP;
255 	if (MSN(val) & 0x01)
256 		mod->xxi[i].pei.flg |= XMP_ENVELOPE_ON;
257 	if (MSN(val) & 0x02)
258 		mod->xxi[i].pei.flg |= XMP_ENVELOPE_SUS;
259 	if (MSN(val) & 0x04)
260 		mod->xxi[i].pei.flg |= XMP_ENVELOPE_LOOP;
261 
262 	val = hio_read8(f);			/* PV envelopes points */
263 	mod->xxi[i].aei.npt = LSN(val) + 1;
264 	mod->xxi[i].pei.npt = MSN(val) + 1;
265 
266 	val = hio_read8(f);			/* PV envelopes sustain point */
267 	mod->xxi[i].aei.sus = LSN(val);
268 	mod->xxi[i].pei.sus = MSN(val);
269 
270 	val = hio_read8(f);			/* PV envelopes loop start */
271 	mod->xxi[i].aei.lps = LSN(val);
272 	mod->xxi[i].pei.lps = MSN(val);
273 
274 	hio_read8(f);			/* PV envelopes loop end */
275 	mod->xxi[i].aei.lpe = LSN(val);
276 	mod->xxi[i].pei.lpe = MSN(val);
277 
278 	if (mod->xxi[i].aei.npt <= 0 || mod->xxi[i].aei.npt > MIN(10, XMP_MAX_ENV_POINTS))
279 		mod->xxi[i].aei.flg &= ~XMP_ENVELOPE_ON;
280 
281 	if (mod->xxi[i].pei.npt <= 0 || mod->xxi[i].pei.npt > MIN(10, XMP_MAX_ENV_POINTS))
282 		mod->xxi[i].pei.flg &= ~XMP_ENVELOPE_ON;
283 
284 	hio_read(buf, 1, 30, f);		/* volume envelope points */;
285 	for (j = 0; j < mod->xxi[i].aei.npt; j++) {
286 		if (j >= 10) {
287 			break;
288 		}
289 		mod->xxi[i].aei.data[j * 2] = readmem16l(buf + j * 3) / 16;
290 		mod->xxi[i].aei.data[j * 2 + 1] = buf[j * 3 + 2];
291 	}
292 
293 	hio_read(buf, 1, 30, f);		/* pan envelope points */;
294 	for (j = 0; j < mod->xxi[i].pei.npt; j++) {
295 		if (j >= 10) {
296 			break;
297 		}
298 		mod->xxi[i].pei.data[j * 2] = readmem16l(buf + j * 3) / 16;
299 		mod->xxi[i].pei.data[j * 2 + 1] = buf[j * 3 + 2];
300 	}
301 
302 	fade = hio_read8(f);		/* fadeout - 0x80->0x02 0x310->0x0c */
303 	hio_read8(f);			/* unknown */
304 
305 	D_(D_INFO "[%2X] %-28.28s  %2d ", i, mod->xxi[i].name, mod->xxi[i].nsm);
306 
307 	if (mod->xxi[i].nsm == 0)
308 		return 0;
309 
310 	if (libxmp_alloc_subinstrument(mod, i, mod->xxi[i].nsm) < 0)
311 		return -1;
312 
313 	for (j = 0; j < mod->xxi[i].nsm; j++, data->snum++) {
314 		hio_read32b(f);	/* SAMP */
315 		hio_read32b(f);	/* size */
316 
317 		hio_read(mod->xxs[data->snum].name, 1, 28, f);
318 
319 		mod->xxi[i].sub[j].pan = hio_read8(f) * 4;
320 		if (mod->xxi[i].sub[j].pan == 0)	/* not sure about this */
321 			mod->xxi[i].sub[j].pan = 0x80;
322 
323 		mod->xxi[i].sub[j].vol = hio_read8(f);
324 		flags = hio_read8(f);
325 		hio_read8(f);	/* unknown - 0x80 */
326 
327 		mod->xxi[i].sub[j].vwf = vwf;
328 		mod->xxi[i].sub[j].vde = vde;
329 		mod->xxi[i].sub[j].vra = vra;
330 		mod->xxi[i].sub[j].vsw = vsw;
331 		mod->xxi[i].sub[j].sid = data->snum;
332 
333 		mod->xxs[data->snum].len = hio_read32l(f);
334 		mod->xxs[data->snum].lps = hio_read32l(f);
335 		mod->xxs[data->snum].lpe = hio_read32l(f);
336 
337 		mod->xxs[data->snum].flg = 0;
338 		if (flags & 0x04)
339 			mod->xxs[data->snum].flg |= XMP_SAMPLE_16BIT;
340 		if (flags & 0x08)
341 			mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP;
342 		if (flags & 0x10)
343 			mod->xxs[data->snum].flg |= XMP_SAMPLE_LOOP_BIDIR;
344 		/* if (flags & 0x80)
345 			mod->xxs[data->snum].flg |= ? */
346 
347 		srate = hio_read32l(f);
348 		finetune = 0;
349 		libxmp_c2spd_to_note(srate, &mod->xxi[i].sub[j].xpo, &mod->xxi[i].sub[j].fin);
350 		mod->xxi[i].sub[j].fin += finetune;
351 
352 		hio_read32l(f);			/* 0x00000000 */
353 		hio_read32l(f);			/* unknown */
354 
355 		D_(D_INFO "  %X: %05x%c%05x %05x %c V%02x P%02x %5d",
356 			j, mod->xxs[data->snum].len,
357 			mod->xxs[data->snum].flg & XMP_SAMPLE_16BIT ? '+' : ' ',
358 			mod->xxs[data->snum].lps,
359 			mod->xxs[data->snum].lpe,
360 			mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' :
361 			mod->xxs[data->snum].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
362 			mod->xxi[i].sub[j].vol,
363 			mod->xxi[i].sub[j].pan,
364 			srate);
365 
366 		if (mod->xxs[data->snum].len > 1) {
367 			int snum = data->snum;
368 			if (libxmp_load_sample(m, f, 0, &mod->xxs[snum], NULL) < 0)
369 				return -1;
370 		}
371 	}
372 
373 	return 0;
374 }
375 
gal4_load(struct module_data * m,HIO_HANDLE * f,const int start)376 static int gal4_load(struct module_data *m, HIO_HANDLE *f, const int start)
377 {
378 	struct xmp_module *mod = &m->mod;
379 	iff_handle handle;
380 	int i, ret, offset;
381 	struct local_data data;
382 
383 	LOAD_INIT();
384 
385 	hio_read32b(f);	/* Skip RIFF */
386 	hio_read32b(f);	/* Skip size */
387 	hio_read32b(f);	/* Skip AM   */
388 
389 	offset = hio_tell(f);
390 
391 	mod->smp = mod->ins = 0;
392 
393 	handle = libxmp_iff_new();
394 	if (handle == NULL)
395 		return -1;
396 
397 	m->c4rate = C4_NTSC_RATE;
398 
399 	/* IFF chunk IDs */
400 	ret = libxmp_iff_register(handle, "MAIN", get_main);
401 	ret |= libxmp_iff_register(handle, "ORDR", get_ordr);
402 	ret |= libxmp_iff_register(handle, "PATT", get_patt_cnt);
403 	ret |= libxmp_iff_register(handle, "INST", get_inst_cnt);
404 
405 	if (ret != 0)
406 		return -1;
407 
408 	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
409 	libxmp_iff_set_quirk(handle, IFF_CHUNK_TRUNC4);
410 
411 	/* Load IFF chunks */
412 	if (libxmp_iff_load(handle, m, f, &data) < 0) {
413 		libxmp_iff_release(handle);
414 		return -1;
415 	}
416 
417 	libxmp_iff_release(handle);
418 
419 	mod->trk = mod->pat * mod->chn;
420 
421 	MODULE_INFO();
422 
423 	if (libxmp_init_instrument(m) < 0)
424 		return -1;
425 
426 	if (libxmp_init_pattern(mod) < 0)
427 		return -1;
428 
429 	D_(D_INFO "Stored patterns: %d\n", mod->pat);
430 	D_(D_INFO "Stored samples : %d ", mod->smp);
431 
432 	hio_seek(f, start + offset, SEEK_SET);
433 	data.snum = 0;
434 
435 	handle = libxmp_iff_new();
436 	if (handle == NULL)
437 		return -1;
438 
439 	/* IFF chunk IDs */
440 	ret = libxmp_iff_register(handle, "PATT", get_patt);
441 	ret |= libxmp_iff_register(handle, "INST", get_inst);
442 
443 	if (ret != 0)
444 		return -1;
445 
446 	libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
447 	libxmp_iff_set_quirk(handle, IFF_CHUNK_TRUNC4);
448 
449 	/* Load IFF chunks */
450 	if (libxmp_iff_load(handle, m, f, &data) < 0) {
451 		libxmp_iff_release(handle);
452 		return -1;
453 	}
454 
455 	libxmp_iff_release(handle);
456 
457 	/* Alloc missing patterns */
458 	for (i = 0; i < mod->pat; i++) {
459 		if (mod->xxp[i] == NULL) {
460 			if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) {
461 				return -1;
462 			}
463 		}
464 	}
465 
466 	for (i = 0; i < mod->chn; i++) {
467 		mod->xxc[i].pan = 0x80;
468 	}
469 
470 	m->quirk |= QUIRKS_FT2;
471 	m->read_event_type = READ_EVENT_FT2;
472 
473 	return 0;
474 }
475