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   UNIMOD (libmikmod's and APlayer's internal module format) loader
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 <stdio.h>
38 #ifdef HAVE_MEMORY_H
39 #include <memory.h>
40 #endif
41 #include <string.h>
42 
43 #include "mikmod_internals.h"
44 
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 #endif
48 
49 /*========== Module structure */
50 
51 typedef struct UNIHEADER {
52 	CHAR  id[4];
53 	UBYTE numchn;
54 	UWORD numpos;
55 	UWORD reppos;
56 	UWORD numpat;
57 	UWORD numtrk;
58 	UWORD numins;
59 	UWORD numsmp;
60 	UBYTE initspeed;
61 	UBYTE inittempo;
62 	UBYTE initvolume;
63 	UWORD flags;
64 	UBYTE numvoices;
65 	UWORD bpmlimit;
66 
67 	UBYTE positions[256];
68 	UBYTE panning[32];
69 } UNIHEADER;
70 
71 typedef struct UNISMP05 {
72 	UWORD c2spd;
73 	UWORD transpose;
74 	UBYTE volume;
75 	UBYTE panning;
76 	ULONG length;
77 	ULONG loopstart;
78 	ULONG loopend;
79 	UWORD flags;
80 	CHAR* samplename;
81 	UBYTE vibtype;
82 	UBYTE vibsweep;
83 	UBYTE vibdepth;
84 	UBYTE vibrate;
85 } UNISMP05;
86 
87 /*========== Loader variables */
88 
89 static UWORD universion;
90 static UNIHEADER mh;
91 
92 #define UNI_SMPINCR 64
93 static UNISMP05 *wh=NULL,*s=NULL;
94 
95 /*========== Loader code */
96 
readstring(void)97 static char * readstring(void)
98 {
99 	char *str=NULL;
100 	UWORD len;
101 
102 	len=_mm_read_I_UWORD(modreader);
103 	if(len) {
104 		str=(char *) MikMod_malloc(len+1);
105 		_mm_read_UBYTES(str,len,modreader);
106 		str[len]=0;
107 	}
108 	return str;
109 }
110 
UNI_Test(void)111 static BOOL UNI_Test(void)
112 {
113 	char id[6];
114 
115 	if(!_mm_read_UBYTES(id,6,modreader)) return 0;
116 
117 	/* UNIMod created by MikCvt */
118 	if(!(memcmp(id,"UN0",3))) {
119 		if((id[3]>='4')&&(id[3]<='6')) return 1;
120 	}
121 	/* UNIMod created by APlayer */
122 	if(!(memcmp(id,"APUN\01",5))) {
123 		if((id[5]>=1)&&(id[5]<=6)) return 1;
124 	}
125 	return 0;
126 }
127 
UNI_Init(void)128 static BOOL UNI_Init(void)
129 {
130 	return 1;
131 }
132 
UNI_Cleanup(void)133 static void UNI_Cleanup(void)
134 {
135 	MikMod_free(wh);
136 	wh = s = NULL;
137 }
138 
readtrack(void)139 static UBYTE* readtrack(void)
140 {
141 	UBYTE *t;
142 	UWORD len;
143 	int cur=0,chunk;
144 
145 	if(universion>=6)
146 		len=_mm_read_M_UWORD(modreader);
147 	else
148 		len=_mm_read_I_UWORD(modreader);
149 
150 	if(!len) return NULL;
151 	if(!(t=(UBYTE*)MikMod_malloc(len))) return NULL;
152 	_mm_read_UBYTES(t,len,modreader);
153 
154 	/* Check if the track is correct */
155 	while(1) {
156 		chunk=t[cur++];
157 		if(!chunk) break;
158 		chunk=(chunk&0x1f)-1;
159 		while(chunk>0) {
160 			int opcode,oplen;
161 
162 			if(cur>=len) {
163 				MikMod_free(t);
164 				return NULL;
165 			}
166 			opcode=t[cur];
167 
168 			/* Remap opcodes */
169 			if (universion <= 5) {
170 				if (opcode > 29) {
171 					MikMod_free(t);
172 					return NULL;
173 				}
174 				switch (opcode) {
175 					/* UNI_NOTE .. UNI_S3MEFFECTQ are the same */
176 					case 25:
177 						opcode = UNI_S3MEFFECTT;
178 						break;
179 					case 26:
180 						opcode = UNI_XMEFFECTA;
181 						break;
182 					case 27:
183 						opcode = UNI_XMEFFECTG;
184 						break;
185 					case 28:
186 						opcode = UNI_XMEFFECTH;
187 						break;
188 					case 29:
189 						opcode = UNI_XMEFFECTP;
190 						break;
191 				}
192 			} else {
193 				/* APlayer < 1.05 does not have XMEFFECT6 */
194 				if (opcode >= UNI_XMEFFECT6 && universion < 0x105)
195 					opcode++;
196 				/* APlayer < 1.03 does not have ITEFFECTT */
197 				if (opcode >= UNI_ITEFFECTT && universion < 0x103)
198 					opcode++;
199 				/* APlayer < 1.02 does not have ITEFFECTZ */
200 				if (opcode >= UNI_ITEFFECTZ && universion < 0x102)
201 					opcode++;
202 			}
203 
204 			if((!opcode)||(opcode>=UNI_LAST)) {
205 				MikMod_free(t);
206 				return NULL;
207 			}
208 			t[cur]=opcode;
209 			oplen=unioperands[opcode]+1;
210 			cur+=oplen;
211 			chunk-=oplen;
212 		}
213 		if((chunk<0)||(cur>=len)) {
214 			MikMod_free(t);
215 			return NULL;
216 		}
217 	}
218 	return t;
219 }
220 
loadsmp6(void)221 static BOOL loadsmp6(void)
222 {
223 	int t;
224 	SAMPLE *sptr;
225 
226 	sptr=of.samples;
227 	for(t=0;t<of.numsmp;t++,sptr++) {
228 		int flags;
229 
230 		flags         = _mm_read_M_UWORD(modreader);
231 		sptr->flags=0;
232 		if(flags&0x0004) sptr->flags|=SF_STEREO;
233 		if(flags&0x0002) sptr->flags|=SF_SIGNED;
234 		if(flags&0x0001) sptr->flags|=SF_16BITS;
235 		/* convert flags */
236 		if(universion>=0x104) {
237 			if(flags&0x2000) sptr->flags|=SF_UST_LOOP;
238 			if(flags&0x1000) sptr->flags|=SF_OWNPAN;
239 			if(flags&0x0800) sptr->flags|=SF_SUSTAIN;
240 			if(flags&0x0400) sptr->flags|=SF_REVERSE;
241 			if(flags&0x0200) sptr->flags|=SF_BIDI;
242 			if(flags&0x0100) sptr->flags|=SF_LOOP;
243 			if(flags&0x0020) sptr->flags|=SF_ITPACKED;
244 			if(flags&0x0010) sptr->flags|=SF_DELTA;
245 			if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN;
246 		} else if(universion>=0x102) {
247 			if(flags&0x0800) sptr->flags|=SF_UST_LOOP;
248 			if(flags&0x0400) sptr->flags|=SF_OWNPAN;
249 			if(flags&0x0200) sptr->flags|=SF_SUSTAIN;
250 			if(flags&0x0100) sptr->flags|=SF_REVERSE;
251 			if(flags&0x0080) sptr->flags|=SF_BIDI;
252 			if(flags&0x0040) sptr->flags|=SF_LOOP;
253 			if(flags&0x0020) sptr->flags|=SF_ITPACKED;
254 			if(flags&0x0010) sptr->flags|=SF_DELTA;
255 			if(flags&0x0008) sptr->flags|=SF_BIG_ENDIAN;
256 		} else {
257 			if(flags&0x400) sptr->flags|=SF_UST_LOOP;
258 			if(flags&0x200) sptr->flags|=SF_OWNPAN;
259 			if(flags&0x100) sptr->flags|=SF_REVERSE;
260 			if(flags&0x080) sptr->flags|=SF_SUSTAIN;
261 			if(flags&0x040) sptr->flags|=SF_BIDI;
262 			if(flags&0x020) sptr->flags|=SF_LOOP;
263 			if(flags&0x010) sptr->flags|=SF_BIG_ENDIAN;
264 			if(flags&0x008) sptr->flags|=SF_DELTA;
265 		}
266 
267 		sptr->speed      = _mm_read_M_ULONG(modreader);
268 		sptr->volume     = _mm_read_UBYTE(modreader);
269 		sptr->panning    = _mm_read_M_UWORD(modreader);
270 		sptr->length     = _mm_read_M_ULONG(modreader);
271 		sptr->loopstart  = _mm_read_M_ULONG(modreader);
272 		sptr->loopend    = _mm_read_M_ULONG(modreader);
273 		sptr->susbegin   = _mm_read_M_ULONG(modreader);
274 		sptr->susend     = _mm_read_M_ULONG(modreader);
275 		sptr->globvol    = _mm_read_UBYTE(modreader);
276 		sptr->vibflags   = _mm_read_UBYTE(modreader);
277 		sptr->vibtype    = _mm_read_UBYTE(modreader);
278 		sptr->vibsweep   = _mm_read_UBYTE(modreader);
279 		sptr->vibdepth   = _mm_read_UBYTE(modreader);
280 		sptr->vibrate    = _mm_read_UBYTE(modreader);
281 
282 		sptr->samplename=readstring();
283 
284 		if(_mm_eof(modreader)) {
285 			_mm_errno = MMERR_LOADING_SAMPLEINFO;
286 			return 0;
287 		}
288 	}
289 	return 1;
290 }
291 
loadinstr6(void)292 static BOOL loadinstr6(void)
293 {
294 	int t,w;
295 	INSTRUMENT *i;
296 
297 	i=of.instruments;
298 	for(t=0;t<of.numins;t++,i++) {
299 		i->flags        = _mm_read_UBYTE(modreader);
300 		i->nnatype      = _mm_read_UBYTE(modreader);
301 		i->dca          = _mm_read_UBYTE(modreader);
302 		i->dct          = _mm_read_UBYTE(modreader);
303 		i->globvol      = _mm_read_UBYTE(modreader);
304 		i->panning      = _mm_read_M_UWORD(modreader);
305 		i->pitpansep    = _mm_read_UBYTE(modreader);
306 		i->pitpancenter = _mm_read_UBYTE(modreader);
307 		i->rvolvar      = _mm_read_UBYTE(modreader);
308 		i->rpanvar      = _mm_read_UBYTE(modreader);
309 		i->volfade      = _mm_read_M_UWORD(modreader);
310 
311 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
312 #define UNI_LoadEnvelope6(name) 										\
313 		i-> name##flg=_mm_read_UBYTE(modreader);						\
314 		i-> name##pts=_mm_read_UBYTE(modreader);						\
315 		i-> name##susbeg=_mm_read_UBYTE(modreader);						\
316 		i-> name##susend=_mm_read_UBYTE(modreader);						\
317 		i-> name##beg=_mm_read_UBYTE(modreader);						\
318 		i-> name##end=_mm_read_UBYTE(modreader);						\
319 		for(w=0;w<(universion>=0x100?32:i-> name##pts);w++) {			\
320 			i-> name##env[w].pos=_mm_read_M_SWORD(modreader);			\
321 			i-> name##env[w].val=_mm_read_M_SWORD(modreader);			\
322 		}
323 #else
324 #define UNI_LoadEnvelope6(name) 										\
325 		i-> name/**/flg=_mm_read_UBYTE(modreader);						\
326 		i-> name/**/pts=_mm_read_UBYTE(modreader);						\
327 		i-> name/**/susbeg=_mm_read_UBYTE(modreader);					\
328 		i-> name/**/susend=_mm_read_UBYTE(modreader);					\
329 		i-> name/**/beg=_mm_read_UBYTE(modreader);						\
330 		i-> name/**/end=_mm_read_UBYTE(modreader);						\
331 		for (w=0;w<(universion>=0x100?32:i-> name/**/pts);w++) {		\
332 			i-> name/**/env[w].pos=_mm_read_M_SWORD(modreader);			\
333 			i-> name/**/env[w].val=_mm_read_M_SWORD(modreader);			\
334 		}
335 #endif
336 
337 		UNI_LoadEnvelope6(vol);
338 		UNI_LoadEnvelope6(pan);
339 		UNI_LoadEnvelope6(pit);
340 #undef UNI_LoadEnvelope6
341 
342 		if(universion>=0x103)
343 			_mm_read_M_UWORDS(i->samplenumber,120,modreader);
344 		else
345 			for(w=0;w<120;w++)
346 				i->samplenumber[w]=_mm_read_UBYTE(modreader);
347 		_mm_read_UBYTES(i->samplenote,120,modreader);
348 
349 		i->insname=readstring();
350 
351 		if(_mm_eof(modreader)) {
352 			_mm_errno = MMERR_LOADING_SAMPLEINFO;
353 			return 0;
354 		}
355 	}
356 	return 1;
357 }
358 
loadinstr5(void)359 static BOOL loadinstr5(void)
360 {
361 	INSTRUMENT *i;
362 	int t;
363 	UWORD wavcnt=0;
364 	UBYTE vibtype,vibsweep,vibdepth,vibrate;
365 
366 	i=of.instruments;
367 	for(of.numsmp=t=0;t<of.numins;t++,i++) {
368 		int u,numsmp;
369 
370 		numsmp=_mm_read_UBYTE(modreader);
371 
372 		memset(i->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
373 		for(u=0;u<96;u++)
374 			i->samplenumber[u]=of.numsmp+_mm_read_UBYTE(modreader);
375 
376 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
377 #define UNI_LoadEnvelope5(name) 									\
378 		i-> name##flg=_mm_read_UBYTE(modreader);					\
379 		i-> name##pts=_mm_read_UBYTE(modreader);					\
380 		i-> name##susbeg=_mm_read_UBYTE(modreader);					\
381 		i-> name##susend=i-> name##susbeg;							\
382 		i-> name##beg=_mm_read_UBYTE(modreader);					\
383 		i-> name##end=_mm_read_UBYTE(modreader);					\
384 		for(u=0;u<12;u++) {											\
385 			i-> name##env[u].pos=_mm_read_I_SWORD(modreader);		\
386 			i-> name##env[u].val=_mm_read_I_SWORD(modreader);		\
387 		}
388 #else
389 #define UNI_LoadEnvelope5(name) 									\
390 		i-> name/**/flg=_mm_read_UBYTE(modreader);					\
391 		i-> name/**/pts=_mm_read_UBYTE(modreader);					\
392 		i-> name/**/susbeg=_mm_read_UBYTE(modreader);				\
393 		i-> name/**/susend=i-> name/**/susbeg;						\
394 		i-> name/**/beg=_mm_read_UBYTE(modreader);					\
395 		i-> name/**/end=_mm_read_UBYTE(modreader);					\
396 		for(u=0;u<12;u++) {											\
397 			i-> name/**/env[u].pos=_mm_read_I_SWORD(modreader);		\
398 			i-> name/**/env[u].val=_mm_read_I_SWORD(modreader);		\
399 		}
400 #endif
401 
402 		UNI_LoadEnvelope5(vol);
403 		UNI_LoadEnvelope5(pan);
404 #undef UNI_LoadEnvelope5
405 
406 		vibtype      =_mm_read_UBYTE(modreader);
407 		vibsweep     =_mm_read_UBYTE(modreader);
408 		vibdepth     =_mm_read_UBYTE(modreader);
409 		vibrate      =_mm_read_UBYTE(modreader);
410 
411 		i->volfade=_mm_read_I_UWORD(modreader);
412 		i->insname=readstring();
413 
414 		for(u=0;u<numsmp;u++,s++,of.numsmp++) {
415 			/* Allocate more room for sample information if necessary */
416 			if(of.numsmp+u==wavcnt) {
417 				wavcnt+=UNI_SMPINCR;
418 				if(!(wh=(UNISMP05*)MikMod_realloc(wh,wavcnt*sizeof(UNISMP05)))) {
419 					_mm_errno=MMERR_OUT_OF_MEMORY;
420 					return 0;
421 				}
422 				s=wh+(wavcnt-UNI_SMPINCR);
423 			}
424 
425 			s->c2spd    =_mm_read_I_UWORD(modreader);
426 			s->transpose=_mm_read_SBYTE(modreader);
427 			s->volume   =_mm_read_UBYTE(modreader);
428 			s->panning  =_mm_read_UBYTE(modreader);
429 			s->length   =_mm_read_I_ULONG(modreader);
430 			s->loopstart=_mm_read_I_ULONG(modreader);
431 			s->loopend  =_mm_read_I_ULONG(modreader);
432 			s->flags    =_mm_read_I_UWORD(modreader);
433 			s->samplename=readstring();
434 
435 			s->vibtype =vibtype;
436 			s->vibsweep=vibsweep;
437 			s->vibdepth=vibdepth;
438 			s->vibrate =vibrate;
439 
440 			if(_mm_eof(modreader)) {
441 				MikMod_free(wh);wh=NULL;
442 				_mm_errno=MMERR_LOADING_SAMPLEINFO;
443 				return 0;
444 			}
445 		}
446 	}
447 
448 	/* sanity check */
449 	if(!of.numsmp) {
450 		MikMod_free(wh);wh=NULL;
451 		_mm_errno=MMERR_LOADING_SAMPLEINFO;
452 		return 0;
453 	}
454 	return 1;
455 }
456 
loadsmp5(void)457 static BOOL loadsmp5(void)
458 {
459 	int t,u;
460 	SAMPLE *q;
461 	INSTRUMENT *d;
462 
463 	q=of.samples;s=wh;
464 	for(u=0;u<of.numsmp;u++,q++,s++) {
465 		q->samplename=s->samplename;
466 
467 		q->length   =s->length;
468 		q->loopstart=s->loopstart;
469 		q->loopend  =s->loopend;
470 		q->volume   =s->volume;
471 		q->speed    =s->c2spd;
472 		q->panning  =s->panning;
473 		q->vibtype  =s->vibtype;
474 		q->vibsweep =s->vibsweep;
475 		q->vibdepth =s->vibdepth;
476 		q->vibrate  =s->vibrate;
477 
478 		/* convert flags */
479 		q->flags=0;
480 		if(s->flags&128) q->flags|=SF_REVERSE;
481 		if(s->flags& 64) q->flags|=SF_SUSTAIN;
482 		if(s->flags& 32) q->flags|=SF_BIDI;
483 		if(s->flags& 16) q->flags|=SF_LOOP;
484 		if(s->flags&  8) q->flags|=SF_BIG_ENDIAN;
485 		if(s->flags&  4) q->flags|=SF_DELTA;
486 		if(s->flags&  2) q->flags|=SF_SIGNED;
487 		if(s->flags&  1) q->flags|=SF_16BITS;
488 	}
489 
490 	d=of.instruments;s=wh;
491 	for(u=0;u<of.numins;u++,d++)
492 		for(t=0;t<INSTNOTES;t++)
493 			d->samplenote[t]=(d->samplenumber[t]>=of.numsmp)?
494 			  255:(t+s[d->samplenumber[t]].transpose);
495 
496 	MikMod_free(wh);wh=NULL;
497 
498 	return 1;
499 }
500 
UNI_Load(BOOL curious)501 static BOOL UNI_Load(BOOL curious)
502 {
503 	int t;
504 	char *modtype,*oldtype=NULL;
505 	INSTRUMENT *d;
506 	SAMPLE *q;
507 
508 	/* read module header */
509 	_mm_read_UBYTES(mh.id,4,modreader);
510 	if(mh.id[3]!='N')
511 		universion=mh.id[3]-'0';
512 	else
513 		universion=0x100;
514 
515 	if(universion>=6) {
516 		if (universion==6) {
517 			_mm_skip_BYTE(modreader);
518 		} else {
519 			universion=_mm_read_M_UWORD(modreader);
520 		}
521 		mh.flags     =_mm_read_M_UWORD(modreader);
522 		mh.numchn    =_mm_read_UBYTE(modreader);
523 		mh.numvoices =_mm_read_UBYTE(modreader);
524 		mh.numpos    =_mm_read_M_UWORD(modreader);
525 		mh.numpat    =_mm_read_M_UWORD(modreader);
526 		mh.numtrk    =_mm_read_M_UWORD(modreader);
527 		mh.numins    =_mm_read_M_UWORD(modreader);
528 		mh.numsmp    =_mm_read_M_UWORD(modreader);
529 		mh.reppos    =_mm_read_M_UWORD(modreader);
530 		mh.initspeed =_mm_read_UBYTE(modreader);
531 		mh.inittempo =_mm_read_UBYTE(modreader);
532 		mh.initvolume=_mm_read_UBYTE(modreader);
533 		/* I expect this to show up soon in APlayer 1.06 format */
534 		if (universion >= 0x106)
535 			mh.bpmlimit=_mm_read_M_UWORD(modreader);
536 		else
537 			mh.bpmlimit=32;
538 
539 		mh.flags &= UF_XMPERIODS | UF_LINEAR | UF_INST | UF_NNA;
540 		mh.flags |= UF_PANNING;
541 	} else {
542 		mh.numchn    =_mm_read_UBYTE(modreader);
543 		mh.numpos    =_mm_read_I_UWORD(modreader);
544 		mh.reppos    =(universion==5)?_mm_read_I_UWORD(modreader):0;
545 		mh.numpat    =_mm_read_I_UWORD(modreader);
546 		mh.numtrk    =_mm_read_I_UWORD(modreader);
547 		mh.numins    =_mm_read_I_UWORD(modreader);
548 		mh.initspeed =_mm_read_UBYTE(modreader);
549 		mh.inittempo =_mm_read_UBYTE(modreader);
550 		_mm_read_UBYTES(mh.positions,256,modreader);
551 		_mm_read_UBYTES(mh.panning,32,modreader);
552 		mh.flags     =_mm_read_UBYTE(modreader);
553 		mh.bpmlimit  =32;
554 
555 		mh.flags &= UF_XMPERIODS | UF_LINEAR;
556 		mh.flags |= UF_INST | UF_NOWRAP | UF_PANNING;
557 	}
558 
559 	/* set module parameters */
560 	of.flags     =mh.flags;
561 	of.numchn    =mh.numchn;
562 	of.numpos    =mh.numpos;
563 	of.numpat    =mh.numpat;
564 	of.numtrk    =mh.numtrk;
565 	of.numins    =mh.numins;
566 	of.reppos    =mh.reppos;
567 	of.initspeed =mh.initspeed;
568 	of.inittempo =mh.inittempo;
569 	if(mh.bpmlimit)
570 		of.bpmlimit=mh.bpmlimit;
571 	else
572 		/* be bug-compatible with older releases */
573 		of.bpmlimit=32;
574 
575 	of.songname=readstring();
576 	if(universion<0x102)
577 		oldtype=readstring();
578 	if(oldtype) {
579 		size_t len=strlen(oldtype)+20;
580 		if(!(modtype=(char*)MikMod_malloc(len))) return 0;
581 #ifdef HAVE_SNPRINTF
582 		snprintf(modtype,len,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
583 #else
584 		sprintf(modtype,"%s (was %s)",(universion>=0x100)?"APlayer":"MikCvt2",oldtype);
585 #endif
586 	} else {
587 		if(!(modtype=(char*)MikMod_malloc(10))) return 0;
588 #ifdef HAVE_SNPRINTF
589 		snprintf(modtype,10,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
590 #else
591 		sprintf(modtype,"%s",(universion>=0x100)?"APlayer":"MikCvt3");
592 #endif
593 	}
594 	of.modtype=MikMod_strdup(modtype);
595 	MikMod_free(modtype);MikMod_free(oldtype);
596 	of.comment=readstring();
597 
598 	if(universion>=6) {
599 		of.numvoices=mh.numvoices;
600 		of.initvolume=mh.initvolume;
601 	}
602 
603 	if(_mm_eof(modreader)) {
604 		_mm_errno=MMERR_LOADING_HEADER;
605 		return 0;
606 	}
607 
608 	/* positions */
609 	if(!AllocPositions(of.numpos)) return 0;
610 	if(universion>=6) {
611 		if(universion>=0x100)
612 			_mm_read_M_UWORDS(of.positions,of.numpos,modreader);
613 		else
614 			for(t=0;t<of.numpos;t++) of.positions[t]=_mm_read_UBYTE(modreader);
615 		_mm_read_M_UWORDS(of.panning,of.numchn,modreader);
616 		_mm_read_UBYTES(of.chanvol,of.numchn,modreader);
617 	} else {
618 		if((mh.numpos>256)||(mh.numchn>32)) {
619 			_mm_errno=MMERR_LOADING_HEADER;
620 			return 0;
621 		}
622 		for(t=0;t<of.numpos;t++) of.positions[t]=mh.positions[t];
623 		for(t=0;t<of.numchn;t++) of.panning[t]=mh.panning[t];
624 	}
625 	/* convert the ``end of song'' pattern code if necessary */
626 	if(universion<0x106)
627 		for(t=0;t<of.numpos;t++)
628 			if(of.positions[t]==255) of.positions[t]=LAST_PATTERN;
629 
630 	/* instruments and samples */
631 	if(universion>=6) {
632 		of.numsmp=mh.numsmp;
633 		if(!AllocSamples()) return 0;
634 		if(!loadsmp6()) return 0;
635 
636 		if(of.flags&UF_INST) {
637 			if(!AllocInstruments()) return 0;
638 			if(!loadinstr6()) return 0;
639 		}
640 	} else {
641 		if(!AllocInstruments()) return 0;
642 		if(!loadinstr5()) return 0;
643 		if(!AllocSamples()) {
644 			MikMod_free(wh);wh=NULL;
645 			return 0;
646 		}
647 		if(!loadsmp5()) return 0;
648 
649 		/* check if the original file had no instruments */
650 		if(of.numsmp==of.numins) {
651 			for(t=0,d=of.instruments;t<of.numins;t++,d++) {
652 				int u;
653 
654 				if((d->volpts)||(d->panpts)||(d->globvol!=64)) break;
655 				for(u=0;u<96;u++)
656 					if((d->samplenumber[u]!=t)||(d->samplenote[u]!=u)) break;
657 				if(u!=96) break;
658 			}
659 			if(t==of.numins) {
660 				of.flags&=~UF_INST;
661 				of.flags&=~UF_NOWRAP;
662 				for(t=0,d=of.instruments,q=of.samples;t<of.numins;t++,d++,q++) {
663 					q->samplename=d->insname;
664 					d->insname=NULL;
665 				}
666 			}
667 		}
668 	}
669 
670 	/* patterns */
671 	if(!AllocPatterns()) return 0;
672 	if(universion>=6) {
673 		_mm_read_M_UWORDS(of.pattrows,of.numpat,modreader);
674 		_mm_read_M_UWORDS(of.patterns,of.numpat*of.numchn,modreader);
675 	} else {
676 		_mm_read_I_UWORDS(of.pattrows,of.numpat,modreader);
677 		_mm_read_I_UWORDS(of.patterns,of.numpat*of.numchn,modreader);
678 	}
679 
680 	/* tracks */
681 	if(!AllocTracks()) return 0;
682 	for(t=0;t<of.numtrk;t++)
683 		if(!(of.tracks[t]=readtrack())) {
684 			_mm_errno=MMERR_LOADING_TRACK;
685 			return 0;
686 		}
687 
688 	return 1;
689 }
690 
UNI_LoadTitle(void)691 static CHAR *UNI_LoadTitle(void)
692 {
693 	UBYTE ver;
694 	int posit[3]={304,306,26};
695 
696 	_mm_fseek(modreader,3,SEEK_SET);
697 	ver=_mm_read_UBYTE(modreader);
698 	if(ver=='N') ver='6';
699 
700 	_mm_fseek(modreader,posit[ver-'4'],SEEK_SET);
701 	return readstring();
702 }
703 
704 /*========== Loader information */
705 
706 MIKMODAPI MLOADER load_uni={
707 	NULL,
708 	"UNI",
709 	"APUN (APlayer) and UNI (MikMod)",
710 	UNI_Init,
711 	UNI_Test,
712 	UNI_Load,
713 	UNI_Cleanup,
714 	UNI_LoadTitle
715 };
716 
717 /* ex:set ts=4: */
718