summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/load_mod.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/load_mod.c')
-rw-r--r--apps/plugins/mikmod/load_mod.c512
1 files changed, 512 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_mod.c b/apps/plugins/mikmod/load_mod.c
new file mode 100644
index 0000000000..92b9787c50
--- /dev/null
+++ b/apps/plugins/mikmod/load_mod.c
@@ -0,0 +1,512 @@
1/* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id: load_mod.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
24
25 Generic MOD loader (Protracker, StarTracker, FastTracker, etc)
26
27==============================================================================*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#ifdef HAVE_UNISTD_H
34#include <unistd.h>
35#endif
36
37#include <ctype.h>
38#include <stdio.h>
39#ifdef HAVE_MEMORY_H
40#include <memory.h>
41#endif
42#include <string.h>
43
44#include "mikmod_internals.h"
45
46#ifdef SUNOS
47extern int fprintf(FILE *, const char *, ...);
48#endif
49
50/*========== Module structure */
51
52typedef struct MSAMPINFO {
53 CHAR samplename[23]; /* 22 in module, 23 in memory */
54 UWORD length;
55 UBYTE finetune;
56 UBYTE volume;
57 UWORD reppos;
58 UWORD replen;
59} MSAMPINFO;
60
61typedef struct MODULEHEADER {
62 CHAR songname[21]; /* the songname.. 20 in module, 21 in memory */
63 MSAMPINFO samples[31]; /* all sampleinfo */
64 UBYTE songlength; /* number of patterns used */
65 UBYTE magic1; /* should be 127 */
66 UBYTE positions[128]; /* which pattern to play at pos */
67 UBYTE magic2[4]; /* string "M.K." or "FLT4" or "FLT8" */
68} MODULEHEADER;
69
70typedef struct MODTYPE {
71 CHAR id[5];
72 UBYTE channels;
73 CHAR *name;
74} MODTYPE;
75
76typedef struct MODNOTE {
77 UBYTE a, b, c, d;
78} MODNOTE;
79
80/*========== Loader variables */
81
82#define MODULEHEADERSIZE 0x438
83
84static CHAR protracker[] = "Protracker";
85static CHAR startrekker[] = "Startrekker";
86static CHAR fasttracker[] = "Fasttracker";
87static CHAR oktalyser[] = "Oktalyser";
88static CHAR oktalyzer[] = "Oktalyzer";
89static CHAR taketracker[] = "TakeTracker";
90static CHAR orpheus[] = "Imago Orpheus (MOD format)";
91
92static MODULEHEADER *mh = NULL;
93static MODNOTE *patbuf = NULL;
94static int modtype, trekker;
95
96/*========== Loader code */
97
98/* given the module ID, determine the number of channels and the tracker
99 description ; also alters modtype */
100static int MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr)
101{
102 modtype = trekker = 0;
103
104 /* Protracker and variants */
105 if ((!memcmp(id, "M.K.", 4)) || (!memcmp(id, "M!K!", 4))) {
106 *descr = protracker;
107 modtype = 0;
108 *numchn = 4;
109 return 1;
110 }
111
112 /* Star Tracker */
113 if (((!memcmp(id, "FLT", 3)) || (!memcmp(id, "EXO", 3))) &&
114 (isdigit(id[3]))) {
115 *descr = startrekker;
116 modtype = trekker = 1;
117 *numchn = id[3] - '0';
118 if (*numchn == 4 || *numchn == 8)
119 return 1;
120#ifdef MIKMOD_DEBUG
121 else
122 fprintf(stderr, "\rUnknown FLT%d module type\n", *numchn);
123#endif
124 return 0;
125 }
126
127 /* Oktalyzer (Amiga) */
128 if (!memcmp(id, "OKTA", 4)) {
129 *descr = oktalyzer;
130 modtype = 1;
131 *numchn = 8;
132 return 1;
133 }
134
135 /* Oktalyser (Atari) */
136 if (!memcmp(id, "CD81", 4)) {
137 *descr = oktalyser;
138 modtype = 1;
139 *numchn = 8;
140 return 1;
141 }
142
143 /* Fasttracker */
144 if ((!memcmp(id + 1, "CHN", 3)) && (isdigit(id[0]))) {
145 *descr = fasttracker;
146 modtype = 1;
147 *numchn = id[0] - '0';
148 return 1;
149 }
150 /* Fasttracker or Taketracker */
151 if (((!memcmp(id + 2, "CH", 2)) || (!memcmp(id + 2, "CN", 2)))
152 && (isdigit(id[0])) && (isdigit(id[1]))) {
153 if (id[3] == 'H') {
154 *descr = fasttracker;
155 modtype = 2; /* this can also be Imago Orpheus */
156 } else {
157 *descr = taketracker;
158 modtype = 1;
159 }
160 *numchn = (id[0] - '0') * 10 + (id[1] - '0');
161 return 1;
162 }
163
164 return 0;
165}
166
167static int MOD_Test(void)
168{
169 UBYTE id[4], numchn;
170 CHAR *descr;
171
172 _mm_fseek(modreader, MODULEHEADERSIZE, SEEK_SET);
173 if (!_mm_read_UBYTES(id, 4, modreader))
174 return 0;
175
176 if (MOD_CheckType(id, &numchn, &descr))
177 return 1;
178
179 return 0;
180}
181
182static int MOD_Init(void)
183{
184 if (!(mh = (MODULEHEADER *)MikMod_malloc(sizeof(MODULEHEADER))))
185 return 0;
186 return 1;
187}
188
189static void MOD_Cleanup(void)
190{
191 MikMod_free(mh);
192 MikMod_free(patbuf);
193}
194
195/*
196Old (amiga) noteinfo:
197
198_____byte 1_____ byte2_ _____byte 3_____ byte4_
199/ \ / \ / \ / \
2000000 0000-00000000 0000 0000-00000000
201
202Upper four 12 bits for Lower four Effect command.
203bits of sam- note period. bits of sam-
204ple number. ple number.
205
206*/
207
208static UBYTE ConvertNote(MODNOTE *n, UBYTE lasteffect)
209{
210 UBYTE instrument, effect, effdat, note;
211 UWORD period;
212 UBYTE lastnote = 0;
213
214 /* extract the various information from the 4 bytes that make up a note */
215 instrument = (n->a & 0x10) | (n->c >> 4);
216 period = (((UWORD)n->a & 0xf) << 8) + n->b;
217 effect = n->c & 0xf;
218 effdat = n->d;
219
220 /* Convert the period to a note number */
221 note = 0;
222 if (period) {
223 for (note = 0; note < 7 * OCTAVE; note++)
224 if (period >= npertab[note])
225 break;
226 if (note == 7 * OCTAVE)
227 note = 0;
228 else
229 note++;
230 }
231
232 if (instrument) {
233 /* if instrument does not exist, note cut */
234 if ((instrument > 31) || (!mh->samples[instrument - 1].length)) {
235 UniPTEffect(0xc, 0);
236 if (effect == 0xc)
237 effect = effdat = 0;
238 } else {
239 /* Protracker handling */
240 if (!modtype) {
241 /* if we had a note, then change instrument... */
242 if (note)
243 UniInstrument(instrument - 1);
244 /* ...otherwise, only adjust volume... */
245 else {
246 /* ...unless an effect was specified, which forces a new
247 note to be played */
248 if (effect || effdat) {
249 UniInstrument(instrument - 1);
250 note = lastnote;
251 } else
252 UniPTEffect(0xc,
253 mh->samples[instrument -
254 1].volume & 0x7f);
255 }
256 } else {
257 /* Fasttracker handling */
258 UniInstrument(instrument - 1);
259 if (!note)
260 note = lastnote;
261 }
262 }
263 }
264 if (note) {
265 UniNote(note + 2 * OCTAVE - 1);
266 lastnote = note;
267 }
268
269 /* Convert pattern jump from Dec to Hex */
270 if (effect == 0xd)
271 effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf);
272
273 /* Volume slide, up has priority */
274 if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
275 effdat &= 0xf0;
276
277 /* Handle ``heavy'' volumes correctly */
278 if ((effect == 0xc) && (effdat > 0x40))
279 effdat = 0x40;
280
281 /* An isolated 100, 200 or 300 effect should be ignored (no
282 "standalone" porta memory in mod files). However, a sequence such
283 as 1XX, 100, 100, 100 is fine. */
284 if ((!effdat) && ((effect == 1)||(effect == 2)||(effect ==3)) &&
285 (lasteffect < 0x10) && (effect != lasteffect))
286 effect = 0;
287
288 UniPTEffect(effect, effdat);
289 if (effect == 8)
290 of.flags |= UF_PANNING;
291
292 return effect;
293}
294
295static UBYTE *ConvertTrack(MODNOTE *n, int numchn)
296{
297 int t;
298 UBYTE lasteffect = 0x10; /* non existant effect */
299
300 UniReset();
301 for (t = 0; t < 64; t++) {
302 lasteffect = ConvertNote(n,lasteffect);
303 UniNewline();
304 n += numchn;
305 }
306 return UniDup();
307}
308
309/* Loads all patterns of a modfile and converts them into the 3 byte format. */
310static int ML_LoadPatterns(void)
311{
312 int t, s, tracks = 0;
313
314 if (!AllocPatterns())
315 return 0;
316 if (!AllocTracks())
317 return 0;
318
319 /* Allocate temporary buffer for loading and converting the patterns */
320 if (!(patbuf = (MODNOTE *)MikMod_calloc(64U * of.numchn, sizeof(MODNOTE))))
321 return 0;
322
323 if (trekker && of.numchn == 8) {
324 /* Startrekker module dual pattern */
325 for (t = 0; t < of.numpat; t++) {
326 for (s = 0; s < (64U * 4); s++) {
327 patbuf[s].a = _mm_read_UBYTE(modreader);
328 patbuf[s].b = _mm_read_UBYTE(modreader);
329 patbuf[s].c = _mm_read_UBYTE(modreader);
330 patbuf[s].d = _mm_read_UBYTE(modreader);
331 }
332 for (s = 0; s < 4; s++)
333 if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4)))
334 return 0;
335 for (s = 0; s < (64U * 4); s++) {
336 patbuf[s].a = _mm_read_UBYTE(modreader);
337 patbuf[s].b = _mm_read_UBYTE(modreader);
338 patbuf[s].c = _mm_read_UBYTE(modreader);
339 patbuf[s].d = _mm_read_UBYTE(modreader);
340 }
341 for (s = 0; s < 4; s++)
342 if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4)))
343 return 0;
344 }
345 } else {
346 /* Generic module pattern */
347 for (t = 0; t < of.numpat; t++) {
348 /* Load the pattern into the temp buffer and convert it */
349 for (s = 0; s < (64U * of.numchn); s++) {
350 patbuf[s].a = _mm_read_UBYTE(modreader);
351 patbuf[s].b = _mm_read_UBYTE(modreader);
352 patbuf[s].c = _mm_read_UBYTE(modreader);
353 patbuf[s].d = _mm_read_UBYTE(modreader);
354 }
355 for (s = 0; s < of.numchn; s++)
356 if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, of.numchn)))
357 return 0;
358 }
359 }
360 return 1;
361}
362
363static int MOD_Load(int curious)
364{
365 int t, scan;
366 SAMPLE *q;
367 MSAMPINFO *s;
368 CHAR *descr;
369
370 /* try to read module header */
371 _mm_read_string((CHAR *)mh->songname, 20, modreader);
372 mh->songname[20] = 0; /* just in case */
373
374 for (t = 0; t < 31; t++) {
375 s = &mh->samples[t];
376 _mm_read_string(s->samplename, 22, modreader);
377 s->samplename[22] = 0; /* just in case */
378 s->length = _mm_read_M_UWORD(modreader);
379 s->finetune = _mm_read_UBYTE(modreader);
380 s->volume = _mm_read_UBYTE(modreader);
381 s->reppos = _mm_read_M_UWORD(modreader);
382 s->replen = _mm_read_M_UWORD(modreader);
383 }
384
385 mh->songlength = _mm_read_UBYTE(modreader);
386
387 /* this fixes mods which declare more than 128 positions.
388 * eg: beatwave.mod */
389 if (mh->songlength > 128) { mh->songlength = 128; }
390
391 mh->magic1 = _mm_read_UBYTE(modreader);
392 _mm_read_UBYTES(mh->positions, 128, modreader);
393 _mm_read_UBYTES(mh->magic2, 4, modreader);
394
395 if (_mm_eof(modreader)) {
396 _mm_errno = MMERR_LOADING_HEADER;
397 return 0;
398 }
399
400 /* set module variables */
401 of.initspeed = 6;
402 of.inittempo = 125;
403 if (!(MOD_CheckType(mh->magic2, &of.numchn, &descr))) {
404 _mm_errno = MMERR_NOT_A_MODULE;
405 return 0;
406 }
407 if (trekker && of.numchn == 8)
408 for (t = 0; t < 128; t++)
409 /* if module pretends to be FLT8, yet the order table
410 contains odd numbers, chances are it's a lying FLT4... */
411 if (mh->positions[t] & 1) {
412 of.numchn = 4;
413 break;
414 }
415 if (trekker && of.numchn == 8)
416 for (t = 0; t < 128; t++)
417 mh->positions[t] >>= 1;
418
419 of.songname = DupStr(mh->songname, 21, 1);
420 of.numpos = mh->songlength;
421 of.reppos = 0;
422
423 /* Count the number of patterns */
424 of.numpat = 0;
425 for (t = 0; t < of.numpos; t++)
426 if (mh->positions[t] > of.numpat)
427 of.numpat = mh->positions[t];
428
429 /* since some old modules embed extra patterns, we have to check the
430 whole list to get the samples' file offsets right - however we can find
431 garbage here, so check carefully */
432 scan = 1;
433 for (t = of.numpos; t < 128; t++)
434 if (mh->positions[t] >= 0x80)
435 scan = 0;
436 if (scan)
437 for (t = of.numpos; t < 128; t++) {
438 if (mh->positions[t] > of.numpat)
439 of.numpat = mh->positions[t];
440 if ((curious) && (mh->positions[t]))
441 of.numpos = t + 1;
442 }
443 of.numpat++;
444 of.numtrk = of.numpat * of.numchn;
445
446 if (!AllocPositions(of.numpos))
447 return 0;
448 for (t = 0; t < of.numpos; t++)
449 of.positions[t] = mh->positions[t];
450
451 /* Finally, init the sampleinfo structures */
452 of.numins = of.numsmp = 31;
453 if (!AllocSamples())
454 return 0;
455 s = mh->samples;
456 q = of.samples;
457 for (t = 0; t < of.numins; t++) {
458 /* convert the samplename */
459 q->samplename = DupStr(s->samplename, 23, 1);
460 /* init the sampleinfo variables and convert the size pointers */
461 q->speed = finetune[s->finetune & 0xf];
462 q->volume = s->volume & 0x7f;
463 q->loopstart = (ULONG)s->reppos << 1;
464 q->loopend = q->loopstart + ((ULONG)s->replen << 1);
465 q->length = (ULONG)s->length << 1;
466 q->flags = SF_SIGNED;
467 /* Imago Orpheus creates MODs with 16 bit samples, check */
468 if ((modtype == 2) && (s->volume & 0x80)) {
469 q->flags |= SF_16BITS;
470 descr = orpheus;
471 }
472 if (s->replen > 2)
473 q->flags |= SF_LOOP;
474
475 s++;
476 q++;
477 }
478
479 of.modtype = StrDup(descr);
480
481 if (!ML_LoadPatterns())
482 return 0;
483
484 return 1;
485}
486
487static CHAR *MOD_LoadTitle(void)
488{
489 CHAR s[21];
490
491 _mm_fseek(modreader, 0, SEEK_SET);
492 if (!_mm_read_UBYTES(s, 20, modreader))
493 return NULL;
494 s[20] = 0; /* just in case */
495
496 return (DupStr(s, 21, 1));
497}
498
499/*========== Loader information */
500
501MIKMODAPI MLOADER load_mod = {
502 NULL,
503 "Standard module",
504 "MOD (31 instruments)",
505 MOD_Init,
506 MOD_Test,
507 MOD_Load,
508 MOD_Cleanup,
509 MOD_LoadTitle
510};
511
512/* ex:set ts=4: */