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