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$
24 
25   General DigiMusic (GDM) module loader
26 
27 ==============================================================================*/
28 
29 /*
30 
31 	Written by Kev Vance<kvance@zeux.org>
32 	based on the file format description written by 'MenTaLguY'
33 	                                                        <mental@kludge.org>
34 
35 */
36 
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 
45 #include <stdio.h>
46 #ifdef HAVE_MEMORY_H
47 #include <memory.h>
48 #endif
49 #include <string.h>
50 
51 #include "mikmod_internals.h"
52 
53 #ifdef SUNOS
54 extern int fprintf(FILE *, const char *, ...);
55 #endif
56 
57 typedef struct GDMNOTE {
58 	UBYTE note;
59 	UBYTE samp;
60 	struct {
61 		UBYTE effect;
62 		UBYTE param;
63 	} effect[4];
64 } GDMNOTE;
65 
66 typedef GDMNOTE GDMTRACK[64];
67 
68 typedef struct GDMHEADER {
69 	CHAR  id1[4];
70 	CHAR  songname[32];
71 	CHAR  author[32];
72 	CHAR  eofmarker[3];
73 	CHAR  id2[4];
74 
75 	UBYTE majorver;
76 	UBYTE minorver;
77 	UWORD trackerid;
78 	UBYTE t_majorver;
79 	UBYTE t_minorver;
80 	UBYTE pantable[32];
81 	UBYTE mastervol;
82 	UBYTE mastertempo;
83 	UBYTE masterbpm;
84 	UWORD flags;
85 
86 	ULONG orderloc;
87 	UBYTE ordernum;
88 	ULONG patternloc;
89 	UBYTE patternnum;
90 	ULONG samhead;
91 	ULONG samdata;
92 	UBYTE samnum;
93 	ULONG messageloc;
94 	ULONG messagelen;
95 	ULONG scrollyloc;
96 	UWORD scrollylen;
97 	ULONG graphicloc;
98 	UWORD graphiclen;
99 } GDMHEADER;
100 
101 typedef struct GDMSAMPLE {
102 	CHAR  sampname[32];
103 	CHAR  filename[13];
104 	UBYTE ems;
105 	ULONG length;
106 	ULONG loopbeg;
107 	ULONG loopend;
108 	UBYTE flags;
109 	UWORD c4spd;
110 	UBYTE vol;
111 	UBYTE pan;
112 } GDMSAMPLE;
113 
114 static GDMHEADER *mh=NULL;	/* pointer to GDM header */
115 static GDMNOTE *gdmbuf=NULL;	/* pointer to a complete GDM pattern */
116 
117 static CHAR GDM_Version[]="General DigiMusic 1.xx";
118 
GDM_Test(void)119 static BOOL GDM_Test(void)
120 {
121 	/* test for gdm magic numbers */
122 	UBYTE id[4];
123 
124 	_mm_fseek(modreader,0x00,SEEK_SET);
125 	if (!_mm_read_UBYTES(id,4,modreader))
126 		return 0;
127 	if (!memcmp(id,"GDM\xfe",4)) {
128 		_mm_fseek(modreader,71,SEEK_SET);
129 		if (!_mm_read_UBYTES(id,4,modreader))
130 			return 0;
131 		if (!memcmp(id,"GMFS",4))
132 			return 1;
133 	}
134 	return 0;
135 }
136 
GDM_Init(void)137 static BOOL GDM_Init(void)
138 {
139 	if (!(gdmbuf=(GDMNOTE*)MikMod_malloc(32*64*sizeof(GDMNOTE)))) return 0;
140 	if (!(mh=(GDMHEADER*)MikMod_malloc(sizeof(GDMHEADER)))) return 0;
141 
142 	return 1;
143 }
144 
GDM_Cleanup(void)145 static void GDM_Cleanup(void)
146 {
147 	MikMod_free(mh);
148 	MikMod_free(gdmbuf);
149 	mh=NULL;
150 	gdmbuf=NULL;
151 }
152 
GDM_ReadPattern(void)153 static BOOL GDM_ReadPattern(void)
154 {
155 	int pos,flag,ch,i;
156 	GDMNOTE n;
157 	SLONG length,x=0;
158 
159 	/* get pattern length */
160 	length=(SLONG)_mm_read_I_UWORD(modreader);
161 	length-=2;
162 
163 	/* clear pattern data */
164 	memset(gdmbuf,255,32*64*sizeof(GDMNOTE));
165 	pos=0;
166 
167 	while (x<length) {
168 		memset(&n,255,sizeof(GDMNOTE));
169 		flag=_mm_read_UBYTE(modreader);
170 		x++;
171 
172 		if (_mm_eof(modreader))
173 			return 0;
174 
175 		ch=flag&31;
176 		if (ch > of.numchn)
177 			return 0;
178 
179 		if (!flag) {
180 			pos++;
181 			if (x==length) {
182 				if (pos > 64)
183 				    return 0;
184 			} else {
185 				if (pos >= 64)
186 				    return 0;
187 			}
188 			continue;
189 		}
190 		if (flag&0x60) {
191 			if (flag&0x20) {
192 				/* new note */
193 				n.note=_mm_read_UBYTE(modreader)&127;
194 				n.samp=_mm_read_UBYTE(modreader);
195 				x +=2;
196 			}
197 			if (flag&0x40) {
198 				do {
199 					/* effect channel set */
200 					i=_mm_read_UBYTE(modreader);
201 					n.effect[i>>6].effect=i&31;
202 					n.effect[i>>6].param=_mm_read_UBYTE(modreader);
203 					x +=2;
204 				} while (i&32);
205 			}
206 			memcpy(gdmbuf+(64U*ch)+pos,&n,sizeof(GDMNOTE));
207 		}
208 	}
209 	return 1;
210 }
211 
GDM_ConvertTrack(GDMNOTE * tr)212 static UBYTE *GDM_ConvertTrack(GDMNOTE*tr)
213 {
214 	int t,i=0;
215 	UBYTE note,ins,inf;
216 
217 	UniReset();
218 	for (t=0;t<64;t++) {
219 		note=tr[t].note;
220 		ins=tr[t].samp;
221 
222 		if ((ins)&&(ins!=255))
223 			UniInstrument(ins-1);
224 		if (note!=255) {
225 			UniNote(((note>>4)*OCTAVE)+(note&0xf)-1);
226 		}
227 		for (i=0;i<4;i++) {
228 			inf = tr[t].effect[i].param;
229 			switch (tr[t].effect[i].effect) {
230 				case 1:	/* toneslide up */
231 					UniEffect(UNI_S3MEFFECTF,inf);
232 					break;
233 				case 2:	/* toneslide down */
234 					UniEffect(UNI_S3MEFFECTE,inf);
235 					break;
236 				case 3:	/* glissando to note */
237 					UniEffect(UNI_ITEFFECTG,inf);
238 					break;
239 				case 4:	/* vibrato */
240 					UniEffect(UNI_ITEFFECTH,inf);
241 					break;
242 				case 5:	/* portamento+volslide */
243 					UniEffect(UNI_ITEFFECTG,0);
244 					UniEffect(UNI_S3MEFFECTD,inf);
245 					break;
246 				case 6:	/* vibrato+volslide */
247 					UniEffect(UNI_ITEFFECTH,0);
248 					UniEffect(UNI_S3MEFFECTD,inf);
249 					break;
250 				case 7:	/* tremolo */
251 					UniEffect(UNI_S3MEFFECTR,inf);
252 					break;
253 				case 8:	/* tremor */
254 					UniEffect(UNI_S3MEFFECTI,inf);
255 					break;
256 				case 9:	/* offset */
257 					UniPTEffect(0x09,inf);
258 					break;
259 				case 0x0a:	/* volslide */
260 					UniEffect(UNI_S3MEFFECTD,inf);
261 					break;
262 				case 0x0b:	/* jump to order */
263 					UniPTEffect(0x0b,inf);
264 					break;
265 				case 0x0c:	/* volume set */
266 					UniPTEffect(0x0c,inf);
267 					break;
268 				case 0x0d:	/* pattern break */
269 					UniPTEffect(0x0d,inf);
270 					break;
271 				case 0x0e:	/* extended */
272 					switch (inf&0xf0) {
273 						case 0x10:	/* fine portamento up */
274 							UniEffect(UNI_S3MEFFECTF, 0x0f|((inf<<4)&0x0f));
275 							break;
276 						case 0x20:	/* fine portamento down */
277 							UniEffect(UNI_S3MEFFECTE, 0xf0|(inf&0x0f));
278 							break;
279 						case 0x30:	/* glissando control */
280 							UniEffect(SS_GLISSANDO, inf&0x0f);
281 							break;
282 						case 0x40:	/* vibrato waveform */
283 							UniEffect(SS_VIBWAVE, inf&0x0f);
284 							break;
285 						case 0x50:	/* set c4spd */
286 							UniEffect(SS_FINETUNE, inf&0x0f);
287 							break;
288 						case 0x60:	/* loop fun */
289 							UniEffect(UNI_ITEFFECTS0, (inf&0x0f)|0xb0);
290 							break;
291 						case 0x70:	/* tremolo waveform */
292 							UniEffect(SS_TREMWAVE, inf&0x0f);
293 							break;
294 						case 0x80:	/* extra fine porta up */
295 							UniEffect(UNI_S3MEFFECTF, 0x0e|((inf<<4)&0x0f));
296 							break;
297 						case 0x90:	/* extra fine porta down */
298 							UniEffect(UNI_S3MEFFECTE, 0xe0|(inf&0x0f));
299 							break;
300 						case 0xa0:	/* fine volslide up */
301 							UniEffect(UNI_S3MEFFECTD, 0x0f|((inf<<4)&0x0f));
302 							break;
303 						case 0xb0:	/* fine volslide down */
304 							UniEffect(UNI_S3MEFFECTE, 0xf0|(inf&0x0f));
305 							break;
306 						case 0xc0:	/* note cut */
307 						case 0xd0:	/* note delay */
308 						case 0xe0:	/* extend row */
309 							UniPTEffect(0xe,inf);
310 							break;
311 					}
312 					break;
313 				case 0x0f:	/* set tempo */
314 					UniEffect(UNI_S3MEFFECTA,inf);
315 					break;
316 				case 0x10:	/* arpeggio */
317 					UniPTEffect(0x0,inf);
318 					break;
319 				case 0x12:	/* retrigger */
320 					UniEffect(UNI_S3MEFFECTQ,inf);
321 					break;
322 				case 0x13:	/* set global volume */
323 					UniEffect(UNI_XMEFFECTG,inf<<1);
324 					break;
325 				case 0x14:	/* fine vibrato */
326 					UniEffect(UNI_ITEFFECTU,inf);
327 					break;
328 				case 0x1e:	/* special */
329 					switch (inf&0xf0) {
330 						case 8:	/* set pan position */
331 							if (inf >=128)
332 								UniPTEffect(0x08,255);
333 							else
334 								UniPTEffect(0x08,inf<<1);
335 							break;
336 					}
337 					break;
338 				case 0x1f:	/* set bpm */
339 					if (inf >=0x20)
340 						UniEffect(UNI_S3MEFFECTT,inf);
341 					break;
342 			}
343 		}
344 		UniNewline();
345 	}
346 	return UniDup();
347 }
348 
GDM_Load(BOOL curious)349 static BOOL GDM_Load(BOOL curious)
350 {
351 	int i,x,u,track;
352 	SAMPLE *q;
353 	GDMSAMPLE s;
354 	ULONG position;
355 
356 	/* read header */
357 	_mm_read_string(mh->id1,4,modreader);
358 	_mm_read_string(mh->songname,32,modreader);
359 	_mm_read_string(mh->author,32,modreader);
360 	_mm_read_string(mh->eofmarker,3,modreader);
361 	_mm_read_string(mh->id2,4,modreader);
362 
363 	mh->majorver=_mm_read_UBYTE(modreader);
364 	mh->minorver=_mm_read_UBYTE(modreader);
365 	mh->trackerid=_mm_read_I_UWORD(modreader);
366 	mh->t_majorver=_mm_read_UBYTE(modreader);
367 	mh->t_minorver=_mm_read_UBYTE(modreader);
368 	_mm_read_UBYTES(mh->pantable,32,modreader);
369 	mh->mastervol=_mm_read_UBYTE(modreader);
370 	mh->mastertempo=_mm_read_UBYTE(modreader);
371 	mh->masterbpm=_mm_read_UBYTE(modreader);
372 	mh->flags=_mm_read_I_UWORD(modreader);
373 
374 	mh->orderloc=_mm_read_I_ULONG(modreader);
375 	mh->ordernum=_mm_read_UBYTE(modreader);
376 	mh->patternloc=_mm_read_I_ULONG(modreader);
377 	mh->patternnum=_mm_read_UBYTE(modreader);
378 	mh->samhead=_mm_read_I_ULONG(modreader);
379 	mh->samdata=_mm_read_I_ULONG(modreader);
380 	mh->samnum=_mm_read_UBYTE(modreader);
381 	mh->messageloc=_mm_read_I_ULONG(modreader);
382 	mh->messagelen=_mm_read_I_ULONG(modreader);
383 	mh->scrollyloc=_mm_read_I_ULONG(modreader);
384 	mh->scrollylen=_mm_read_I_UWORD(modreader);
385 	mh->graphicloc=_mm_read_I_ULONG(modreader);
386 	mh->graphiclen=_mm_read_I_UWORD(modreader);
387 
388 	/* have we ended abruptly? */
389 	if (_mm_eof(modreader)) {
390 		_mm_errno=MMERR_LOADING_HEADER;
391 		return 0;
392 	}
393 
394 	/* any orders? */
395 	if(mh->ordernum==255) {
396 		_mm_errno=MMERR_LOADING_PATTERN;
397 		return 0;
398 	}
399 
400 	/* now we fill */
401 	of.modtype=MikMod_strdup(GDM_Version);
402 	of.modtype[18]=mh->majorver+'0';
403 	of.modtype[20]=mh->minorver/10+'0';
404 	of.modtype[21]=mh->minorver%10+'0';
405 	of.songname=DupStr(mh->songname,32,0);
406 	of.numpat=mh->patternnum+1;
407 	of.reppos=0;
408 	of.numins=of.numsmp=mh->samnum+1;
409 	of.initspeed=mh->mastertempo;
410 	of.inittempo=mh->masterbpm;
411 	of.initvolume=mh->mastervol<<1;
412 	of.flags|=UF_S3MSLIDES | UF_PANNING;
413 	/* XXX whenever possible, we should try to determine the original format.
414 	   Here we assume it was S3M-style wrt bpmlimit... */
415 	of.bpmlimit = 32;
416 
417 	/* read the order data */
418 	if (!AllocPositions(mh->ordernum+1)) {
419 		_mm_errno=MMERR_OUT_OF_MEMORY;
420 		return 0;
421 	}
422 
423 	_mm_fseek(modreader,mh->orderloc,SEEK_SET);
424 	for (i=0;i<mh->ordernum+1;i++)
425 		of.positions[i]=_mm_read_UBYTE(modreader);
426 
427 	of.numpos=0;
428 	for (i=0;i<mh->ordernum+1;i++) {
429 		int order=of.positions[i];
430 		if(order==255) order=LAST_PATTERN;
431 		of.positions[of.numpos]=order;
432 		if (of.positions[i]<254) of.numpos++;
433 	}
434 
435 	/* have we ended abruptly yet? */
436 	if (_mm_eof(modreader)) {
437 		_mm_errno=MMERR_LOADING_HEADER;
438 		return 0;
439 	}
440 
441 	/* time to load the samples */
442 	if (!AllocSamples()) {
443 		_mm_errno=MMERR_OUT_OF_MEMORY;
444 		return 0;
445 	}
446 
447 	q=of.samples;
448 	position=mh->samdata;
449 
450 	/* seek to instrument position */
451 	_mm_fseek(modreader,mh->samhead,SEEK_SET);
452 
453 	for (i=0;i<of.numins;i++) {
454 		/* load sample info */
455 		_mm_read_UBYTES(s.sampname,32,modreader);
456 		_mm_read_UBYTES(s.filename,12,modreader);
457 		s.ems=_mm_read_UBYTE(modreader);
458 		s.length=_mm_read_I_ULONG(modreader);
459 		s.loopbeg=_mm_read_I_ULONG(modreader);
460 		s.loopend=_mm_read_I_ULONG(modreader);
461 		s.flags=_mm_read_UBYTE(modreader);
462 		s.c4spd=_mm_read_I_UWORD(modreader);
463 		s.vol=_mm_read_UBYTE(modreader);
464 		s.pan=_mm_read_UBYTE(modreader);
465 
466 		if (_mm_eof(modreader)) {
467 			_mm_errno=MMERR_LOADING_SAMPLEINFO;
468 			return 0;
469 		}
470 		q->samplename=DupStr(s.sampname,32,0);
471 		q->speed=s.c4spd;
472 		q->length=s.length;
473 		q->loopstart=s.loopbeg;
474 		q->loopend=s.loopend;
475 		q->volume=s.vol;
476 		q->panning=s.pan;
477 		q->seekpos=position;
478 
479 		position +=s.length;
480 
481 		if (s.flags&1)
482 			q->flags |=SF_LOOP;
483 		if (s.flags&2)
484 			q->flags |=SF_16BITS;
485 		if (s.flags&16)
486 			q->flags |=SF_STEREO;
487 		q++;
488 	}
489 
490 	/* set the panning */
491 	for (i=x=0;i<32;i++) {
492 		of.panning[i]=mh->pantable[i];
493 		if (!of.panning[i])
494 			of.panning[i]=PAN_LEFT;
495 		else if (of.panning[i]==8)
496 			of.panning[i]=PAN_CENTER;
497 		else if (of.panning[i]==15)
498 			of.panning[i]=PAN_RIGHT;
499 		else if (of.panning[i]==16)
500 			of.panning[i]=PAN_SURROUND;
501 		else if (of.panning[i]==255)
502 			of.panning[i]=128;
503 		else
504 			of.panning[i]<<=3;
505 		if (mh->pantable[i]!=255)
506 			x=i;
507 	}
508 
509 	of.numchn=x+1;
510 	if (of.numchn<1)
511 		of.numchn=1;	/* for broken counts */
512 
513 	/* load the pattern info */
514 	of.numtrk=of.numpat*of.numchn;
515 
516 	/* jump to patterns */
517 	_mm_fseek(modreader,mh->patternloc,SEEK_SET);
518 
519 	if (!AllocTracks()) {
520 		_mm_errno=MMERR_OUT_OF_MEMORY;
521 		return 0;
522 	}
523 
524 	if (!AllocPatterns()) {
525 		_mm_errno=MMERR_OUT_OF_MEMORY;
526 		return 0;
527 	}
528 
529 	for (i=track=0;i<of.numpat;i++) {
530 		if (!GDM_ReadPattern()) {
531 			_mm_errno=MMERR_LOADING_PATTERN;
532 			return 0;
533 		}
534 		for (u=0;u<of.numchn;u++,track++) {
535 			of.tracks[track]=GDM_ConvertTrack(&gdmbuf[u<<6]);
536 			if (!of.tracks[track]) {
537 				_mm_errno=MMERR_LOADING_TRACK;
538 				return 0;
539 			}
540 		}
541 	}
542 	return 1;
543 }
544 
GDM_LoadTitle(void)545 static CHAR *GDM_LoadTitle(void)
546 {
547 	CHAR s[32];
548 
549 	_mm_fseek(modreader,4,SEEK_SET);
550 	if (!_mm_read_UBYTES(s,32,modreader)) return NULL;
551 
552 	return DupStr(s,28,0);
553 }
554 
555 MIKMODAPI MLOADER load_gdm=
556 {
557 	NULL,
558 	"GDM",
559 	"GDM (General DigiMusic)",
560 	GDM_Init,
561 	GDM_Test,
562 	GDM_Load,
563 	GDM_Cleanup,
564 	GDM_LoadTitle
565 };
566 
567 /* ex:set ts=4: */
568