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 5.0 module file loader
28 *
29 * Based on the format description by Dr.Eggman
30 * (http://www.jazz2online.com/J2Ov2/articles/view.php?articleID=288)
31 * and Jazz Jackrabbit modules by Alexander Brandon from Lori Central
32 * (http://www.loricentral.com/jj2music.html)
33 */
34
35 static int gal5_test(HIO_HANDLE *, char *, const int);
36 static int gal5_load(struct module_data *, HIO_HANDLE *, const int);
37
38 const struct format_loader libxmp_loader_gal5 = {
39 "Galaxy Music System 5.0 (J2B)",
40 gal5_test,
41 gal5_load
42 };
43
44
45 struct local_data {
46 uint8 chn_pan[64];
47 };
48
gal5_test(HIO_HANDLE * f,char * t,const int start)49 static int gal5_test(HIO_HANDLE *f, char *t, const int start)
50 {
51 if (hio_read32b(f) != MAGIC4('R', 'I', 'F', 'F'))
52 return -1;
53
54 hio_read32b(f);
55
56 if (hio_read32b(f) != MAGIC4('A', 'M', ' ', ' '))
57 return -1;
58
59 if (hio_read32b(f) != MAGIC4('I', 'N', 'I', 'T'))
60 return -1;
61
62 hio_read32b(f); /* skip size */
63 libxmp_read_title(f, t, 64);
64
65 return 0;
66 }
67
get_init(struct module_data * m,int size,HIO_HANDLE * f,void * parm)68 static int get_init(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
69 {
70 struct xmp_module *mod = &m->mod;
71 struct local_data *data = (struct local_data *)parm;
72 char buf[64];
73 int flags;
74
75 hio_read(buf, 1, 64, f);
76 strncpy(mod->name, buf, 63); /* ensure string terminator */
77 mod->name[63] = '\0';
78 libxmp_set_type(m, "Galaxy Music System 5.0");
79 flags = hio_read8(f); /* bit 0: Amiga period */
80 if (~flags & 0x01)
81 m->period_type = PERIOD_LINEAR;
82 mod->chn = hio_read8(f);
83 mod->spd = hio_read8(f);
84 mod->bpm = hio_read8(f);
85 hio_read16l(f); /* unknown - 0x01c5 */
86 hio_read16l(f); /* unknown - 0xff00 */
87 hio_read8(f); /* unknown - 0x80 */
88 hio_read(data->chn_pan, 1, 64, f);
89
90 /* Sanity check */
91 if (mod->chn > XMP_MAX_CHANNELS)
92 return -1;
93
94 return 0;
95 }
96
get_ordr(struct module_data * m,int size,HIO_HANDLE * f,void * parm)97 static int get_ordr(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
98 {
99 struct xmp_module *mod = &m->mod;
100 int i;
101
102 mod->len = hio_read8(f) + 1;
103 /* Don't follow Dr.Eggman's specs here */
104
105 for (i = 0; i < mod->len; i++)
106 mod->xxo[i] = hio_read8(f);
107
108 return 0;
109 }
110
get_patt_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)111 static int get_patt_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
112 {
113 struct xmp_module *mod = &m->mod;
114 int i;
115
116 i = hio_read8(f) + 1; /* pattern number */
117
118 if (i > mod->pat)
119 mod->pat = i;
120
121 return 0;
122 }
123
get_inst_cnt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)124 static int get_inst_cnt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
125 {
126 struct xmp_module *mod = &m->mod;
127 int i;
128
129 hio_read32b(f); /* 42 01 00 00 */
130 hio_read8(f); /* 00 */
131 i = hio_read8(f) + 1; /* instrument number */
132
133 /* Sanity check */
134 if (i > MAX_INSTRUMENTS)
135 return -1;
136
137 if (i > mod->ins)
138 mod->ins = i;
139
140 return 0;
141 }
142
get_patt(struct module_data * m,int size,HIO_HANDLE * f,void * parm)143 static int get_patt(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
144 {
145 struct xmp_module *mod = &m->mod;
146 struct xmp_event *event, dummy;
147 int i, len, chan;
148 int rows, r;
149 uint8 flag;
150
151 i = hio_read8(f); /* pattern number */
152 len = hio_read32l(f);
153
154 rows = hio_read8(f) + 1;
155
156 /* Sanity check - don't allow duplicate patterns. */
157 if (len < 0 || mod->xxp[i] != NULL)
158 return -1;
159
160 if (libxmp_alloc_pattern_tracks(mod, i, rows) < 0)
161 return -1;
162
163 for (r = 0; r < rows; ) {
164 if ((flag = hio_read8(f)) == 0) {
165 r++;
166 continue;
167 }
168 if (hio_error(f)) {
169 return -1;
170 }
171
172 chan = flag & 0x1f;
173
174 event = chan < mod->chn ? &EVENT(i, chan, r) : &dummy;
175
176 if (flag & 0x80) {
177 uint8 fxp = hio_read8(f);
178 uint8 fxt = hio_read8(f);
179
180 switch (fxt) {
181 case 0x14: /* speed */
182 fxt = FX_S3M_SPEED;
183 break;
184 default:
185 if (fxt > 0x0f) {
186 D_(D_CRIT "p%d r%d c%d unknown effect %02x %02x", i, r, chan, fxt, fxp);
187 fxt = fxp = 0;
188 }
189 }
190
191 event->fxt = fxt;
192 event->fxp = fxp;
193 }
194
195 if (flag & 0x40) {
196 event->ins = hio_read8(f);
197 event->note = hio_read8(f);
198
199 if (event->note == 128) {
200 event->note = XMP_KEY_OFF;
201 }
202 }
203
204 if (flag & 0x20) {
205 event->vol = 1 + hio_read8(f) / 2;
206 }
207 }
208
209 return 0;
210 }
211
get_inst(struct module_data * m,int size,HIO_HANDLE * f,void * parm)212 static int get_inst(struct module_data *m, int size, HIO_HANDLE *f, void *parm)
213 {
214 struct xmp_module *mod = &m->mod;
215 int i, srate, finetune, flags;
216 int has_unsigned_sample;
217
218 hio_read32b(f); /* 42 01 00 00 */
219 hio_read8(f); /* 00 */
220 i = hio_read8(f); /* instrument number */
221
222 /* Sanity check - don't allow duplicate instruments. */
223 if (mod->xxi[i].nsm != 0)
224 return -1;
225
226 hio_read(mod->xxi[i].name, 1, 28, f);
227 hio_seek(f, 290, SEEK_CUR); /* Sample/note map, envelopes */
228 mod->xxi[i].nsm = hio_read16l(f);
229
230 D_(D_INFO "[%2X] %-28.28s %2d ", i, mod->xxi[i].name, mod->xxi[i].nsm);
231
232 if (mod->xxi[i].nsm == 0)
233 return 0;
234
235 if (libxmp_alloc_subinstrument(mod, i, mod->xxi[i].nsm) < 0)
236 return -1;
237
238 /* FIXME: Currently reading only the first sample */
239
240 hio_read32b(f); /* RIFF */
241 hio_read32b(f); /* size */
242 hio_read32b(f); /* AS */
243 hio_read32b(f); /* SAMP */
244 hio_read32b(f); /* size */
245 hio_read32b(f); /* unknown - usually 0x40000000 */
246
247 hio_read(mod->xxs[i].name, 1, 28, f);
248
249 hio_read32b(f); /* unknown - 0x0000 */
250 hio_read8(f); /* unknown - 0x00 */
251
252 mod->xxi[i].sub[0].sid = i;
253 mod->xxi[i].vol = hio_read8(f);
254 mod->xxi[i].sub[0].pan = 0x80;
255 mod->xxi[i].sub[0].vol = (hio_read16l(f) + 1) / 512;
256 flags = hio_read16l(f);
257 hio_read16l(f); /* unknown - 0x0080 */
258 mod->xxs[i].len = hio_read32l(f);
259 mod->xxs[i].lps = hio_read32l(f);
260 mod->xxs[i].lpe = hio_read32l(f);
261
262 mod->xxs[i].flg = 0;
263 has_unsigned_sample = 0;
264 if (flags & 0x04)
265 mod->xxs[i].flg |= XMP_SAMPLE_16BIT;
266 if (flags & 0x08)
267 mod->xxs[i].flg |= XMP_SAMPLE_LOOP;
268 if (flags & 0x10)
269 mod->xxs[i].flg |= XMP_SAMPLE_LOOP | XMP_SAMPLE_LOOP_BIDIR;
270 if (~flags & 0x80)
271 has_unsigned_sample = 1;
272
273 srate = hio_read32l(f);
274 finetune = 0;
275 libxmp_c2spd_to_note(srate, &mod->xxi[i].sub[0].xpo, &mod->xxi[i].sub[0].fin);
276 mod->xxi[i].sub[0].fin += finetune;
277
278 hio_read32l(f); /* 0x00000000 */
279 hio_read32l(f); /* unknown */
280
281 D_(D_INFO " %x: %05x%c%05x %05x %c V%02x %04x %5d",
282 0, mod->xxs[i].len,
283 mod->xxs[i].flg & XMP_SAMPLE_16BIT ? '+' : ' ',
284 mod->xxs[i].lps,
285 mod->xxs[i].lpe,
286 mod->xxs[i].flg & XMP_SAMPLE_LOOP_BIDIR ? 'B' :
287 mod->xxs[i].flg & XMP_SAMPLE_LOOP ? 'L' : ' ',
288 mod->xxi[i].sub[0].vol, flags, srate);
289
290 if (mod->xxs[i].len > 1) {
291 if (libxmp_load_sample(m, f, has_unsigned_sample ?
292 SAMPLE_FLAG_UNS : 0, &mod->xxs[i], NULL) < 0)
293 return -1;
294 }
295
296 return 0;
297 }
298
gal5_load(struct module_data * m,HIO_HANDLE * f,const int start)299 static int gal5_load(struct module_data *m, HIO_HANDLE *f, const int start)
300 {
301 struct xmp_module *mod = &m->mod;
302 iff_handle handle;
303 int i, ret, offset;
304 struct local_data data;
305
306 LOAD_INIT();
307
308 hio_read32b(f); /* Skip RIFF */
309 hio_read32b(f); /* Skip size */
310 hio_read32b(f); /* Skip AM */
311
312 offset = hio_tell(f);
313
314 mod->smp = mod->ins = 0;
315
316 handle = libxmp_iff_new();
317 if (handle == NULL)
318 return -1;
319
320 m->c4rate = C4_NTSC_RATE;
321
322 /* IFF chunk IDs */
323 ret = libxmp_iff_register(handle, "INIT", get_init); /* Galaxy 5.0 */
324 ret |= libxmp_iff_register(handle, "ORDR", get_ordr);
325 ret |= libxmp_iff_register(handle, "PATT", get_patt_cnt);
326 ret |= libxmp_iff_register(handle, "INST", get_inst_cnt);
327
328 if (ret != 0)
329 return -1;
330
331 libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
332 libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED);
333 libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2);
334
335 /* Load IFF chunks */
336 if (libxmp_iff_load(handle, m, f, &data) < 0) {
337 libxmp_iff_release(handle);
338 return -1;
339 }
340
341 libxmp_iff_release(handle);
342
343 mod->trk = mod->pat * mod->chn;
344 mod->smp = mod->ins;
345
346 MODULE_INFO();
347
348 if (libxmp_init_instrument(m) < 0)
349 return -1;
350
351 if (libxmp_init_pattern(mod) < 0)
352 return -1;
353
354 D_(D_INFO "Stored patterns: %d", mod->pat);
355 D_(D_INFO "Stored samples: %d ", mod->smp);
356
357 hio_seek(f, start + offset, SEEK_SET);
358
359 handle = libxmp_iff_new();
360 if (handle == NULL)
361 return -1;
362
363 /* IFF chunk IDs */
364 ret = libxmp_iff_register(handle, "PATT", get_patt);
365 ret |= libxmp_iff_register(handle, "INST", get_inst);
366
367 if (ret != 0)
368 return -1;
369
370 libxmp_iff_set_quirk(handle, IFF_LITTLE_ENDIAN);
371 libxmp_iff_set_quirk(handle, IFF_SKIP_EMBEDDED);
372 libxmp_iff_set_quirk(handle, IFF_CHUNK_ALIGN2);
373
374 /* Load IFF chunks */
375 if (libxmp_iff_load(handle, m, f, &data) < 0) {
376 libxmp_iff_release(handle);
377 return -1;
378 }
379
380 libxmp_iff_release(handle);
381
382 /* Alloc missing patterns */
383 for (i = 0; i < mod->pat; i++) {
384 if (mod->xxp[i] == NULL) {
385 if (libxmp_alloc_pattern_tracks(mod, i, 64) < 0) {
386 return -1;
387 }
388 }
389 }
390
391 for (i = 0; i < mod->chn; i++) {
392 mod->xxc[i].pan = data.chn_pan[i] * 2;
393 }
394
395 m->quirk |= QUIRKS_FT2;
396 m->read_event_type = READ_EVENT_FT2;
397
398 return 0;
399 }
400