1 /*-----------------------------------------------------------------------------
2 
3 	ST-Sound ( YM files player library )
4 
5 	Manage YM file depacking and parsing
6 
7 -----------------------------------------------------------------------------*/
8 
9 /*-----------------------------------------------------------------------------
10 * ST-Sound, ATARI-ST Music Emulator
11 * Copyright (c) 1995-1999 Arnaud Carre ( http://leonard.oxg.free.fr )
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 -----------------------------------------------------------------------------*/
36 
37 #include "config.h"
38 #include <stdio.h>
39 #include <stdlib.h>
40 #ifdef HAVE_STRING_H
41 #include <string.h>
42 #endif
43 #include "YmTypes.h"
44 #include "YmMusic.h"
45 #ifdef HAVE_LZH
46 #include "lzh/lzh.h"
47 #endif
48 
49 static	ymu16 ymVolumeTable[16] =
50 {	62,161,265,377,580,774,1155,1575,2260,3088,4570,6233,9330,13187,21220,32767};
51 
52 
signeSample(ymu8 * ptr,yms32 size)53 static	void	signeSample(ymu8 *ptr,yms32 size)
54 {
55 
56 		if (size>0)
57 		{
58 			do
59 			{
60 				*ptr++ ^= 0x80;
61 			}
62 			while (--size);
63 		}
64 }
65 
myFree(void ** pPtr)66 void	myFree(void **pPtr)
67 {
68 		if (*pPtr) free(*pPtr);
69 		*pPtr = NULL;
70 }
71 
mstrdup(const char * in)72 char	*mstrdup(const char *in)
73 {
74 	const int size = strlen(in)+1;
75 	char *out = (char*)malloc(size);
76 	if (out)
77 		strcpy(out,in);
78 	return out;
79 }
80 
readMotorolaDword(ymu8 ** ptr,ymu32 * ptr_size)81 ymu32      readMotorolaDword(ymu8 **ptr, ymu32 *ptr_size)
82 {
83 ymu32 n;
84 ymu8 *p = *ptr;
85 	if (*ptr_size<4)
86 		return 0;
87         n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
88         p+=4;
89         *ptr = p;
90 	(*ptr_size)+=4;
91         return n;
92 }
93 
readMotorolaWord(ymu8 ** ptr,ymu32 * ptr_size)94 ymu16      readMotorolaWord(ymu8 **ptr, ymu32 *ptr_size)
95 {
96 ymu16 n;
97 ymu8 *p = *ptr;
98 	if (*ptr_size<2)
99 		return 0;
100         n = (p[0]<<8)|p[1];
101         p+=2;
102         *ptr = p;
103 	(*ptr_size)+=2;
104         return n;
105 }
106 
readNtString(ymchar ** ptr,ymu32 * ptr_size)107 ymchar    *readNtString(ymchar **ptr, ymu32 *ptr_size)
108 {
109 ymchar *p;
110 ymint len = 0;
111 	if (*ptr_size<=0)
112 	{
113 		(*ptr_size)-=1;
114 		return mstrdup("");
115 	}
116 	p=*ptr;
117 	while(*p)
118 	{
119 		p++;
120 		(*ptr_size)--;
121 		len++;
122 		if (*ptr_size==0)
123 		{
124 			(*ptr_size)-=1;
125 			return mstrdup("");
126 		}
127 	}
128 
129 		p = mstrdup(*ptr);
130 		(*ptr) += len+1;
131         return p;
132 }
133 
ReadLittleEndian32(ymu8 * pLittle,ymu32 ptr_size)134 yms32	ReadLittleEndian32(ymu8 *pLittle, ymu32 ptr_size)
135 {
136 	yms32 v;
137 	if (ptr_size<4)
138 		return 0;
139 	v = ( (pLittle[0]<<0) |
140 				(pLittle[1]<<8) |
141 				(pLittle[2]<<16) |
142 				(pLittle[3]<<24));
143 
144 	return v;
145 }
146 
ReadBigEndian32(ymu8 * pBig,ymu32 ptr_size)147 yms32	ReadBigEndian32(ymu8 *pBig, ymu32 ptr_size)
148 {
149 	yms32 v;
150 	if (ptr_size<4)
151 		return 0;
152 	v = ( (pBig[0]<<24) |
153 				(pBig[1]<<16) |
154 				(pBig[2]<<8) |
155 				(pBig[3]<<0));
156 
157 	return v;
158 }
159 
depackFile(ymu32 checkOriginalSize)160 unsigned char	*CYmMusic::depackFile(ymu32 checkOriginalSize)
161  {
162 #ifndef HAVE_LZH
163 	return pBigMalloc;
164 #else
165  lzhHeader_t *pHeader;
166  ymu8	*pNew;
167  ymu8	*pSrc;
168  ymu32	ptr_left = fileSize;
169 
170 		if (ptr_left < (ymint)sizeof(lzhHeader_t))
171 		{
172 			return pBigMalloc;
173 		}
174 
175 		pHeader = (lzhHeader_t*)pBigMalloc;
176 
177 		if ((pHeader->size==0) ||					// NOTE: Endianness works because value is 0
178 			(strncmp(pHeader->id,"-lh5-",5)))
179 		{ // Le fichier n'est pas compresse, on retourne l'original.
180 			return pBigMalloc;
181 		}
182 
183 		fileSize = (ymu32)-1;
184 
185 		if (pHeader->level != 0)					// NOTE: Endianness works because value is 0
186 		{ // Compression LH5, header !=0 : Error.
187 			free(pBigMalloc);
188 			pBigMalloc = NULL;
189 			setLastError("LHARC Header must be 0 !");
190 			return NULL;
191 		}
192 
193 		fileSize = ReadLittleEndian32((ymu8*)&pHeader->original, 4);
194 		pNew = (ymu8*)malloc(fileSize);
195 		if (!pNew)
196 		{
197 			setLastError("MALLOC Failed !");
198 			free(pBigMalloc);
199 			pBigMalloc = NULL;
200 			return NULL;
201 		}
202 
203 		pSrc = pBigMalloc+sizeof(lzhHeader_t)+pHeader->name_lenght;			// NOTE: Endianness works because name_lenght is a byte
204 		ptr_left -= sizeof(lzhHeader_t)+pHeader->name_lenght;
205 
206 		pSrc += 2;		// skip CRC16
207 		ptr_left -= 2;
208 
209 		ymu32		packedSize = ReadLittleEndian32((ymu8*)&pHeader->packed, 4);
210 
211 		checkOriginalSize -= ymu32(pSrc - pBigMalloc);
212 
213 		if (packedSize > checkOriginalSize)
214 			packedSize = checkOriginalSize;
215 
216 		if (packedSize > ptr_left)
217 		{
218 			setLastError("File too small");
219 			free(pNew);
220 			return pBigMalloc;
221 		}
222 
223 		// Check for corrupted archive
224 		if (packedSize <= checkOriginalSize)
225 		{
226 			// alloc space for depacker and depack data
227 			CLzhDepacker *pDepacker = new CLzhDepacker;
228 			const bool bRet = pDepacker->LzUnpack(pSrc,packedSize,pNew,fileSize);
229 			delete pDepacker;
230 
231 			if (!bRet)
232 			{	// depacking error
233 				setLastError("LH5 Depacking Error !");
234 				free(pNew);
235 				pNew = NULL;
236 			}
237 		}
238 		else
239 		{
240 			setLastError("LH5 Depacking Error !");
241 			free(pNew);
242 			pNew = NULL;
243 		}
244 
245 		// Free up source buffer, whatever depacking fail or success
246 		free(pBigMalloc);
247 
248 		return pNew;
249 #endif
250  }
251 
252 
253 
254 
255 
fileSizeGet(FILE * h)256 static ymint	fileSizeGet(FILE *h)
257  {
258  ymint size;
259  ymint old;
260 
261 		old = ftell(h);
262 		fseek(h,0,SEEK_END);
263 		size = ftell(h);
264 		fseek(h,old,SEEK_SET);
265 		return size;
266  }
267 
268 
deInterleave(void)269 ymbool	CYmMusic::deInterleave(void)
270  {
271  yms32	nextPlane[32];
272  ymu8	*pW,*tmpBuff;
273  yms32	j,k;
274 
275 
276 		if (attrib&A_STREAMINTERLEAVED)
277 		{
278 
279 			tmpBuff = (ymu8*)malloc(nbFrame*streamInc);
280 			if (!tmpBuff)
281 			{
282 				setLastError("Malloc error in deInterleave()\n");
283 				return YMFALSE;
284 			}
285 
286 			// Precalcul les offsets.
287 			for (j=0;j<streamInc;j++) nextPlane[j] = nbFrame*j;
288 
289 			pW = tmpBuff;
290 			for (j=0;j<nextPlane[1];j++)
291 			{
292 				for (k=0;k<streamInc;k++)
293 				{
294 					pW[k] = pDataStream[j + nextPlane[k]];
295 				}
296 				pW += streamInc;
297 			}
298 
299 			free(pBigMalloc);
300 			pBigMalloc = tmpBuff;
301 			pDataStream = tmpBuff;
302 
303 			attrib &= (~A_STREAMINTERLEAVED);
304 		}
305 		return YMTRUE;
306  }
307 
308 
309 enum
310 {
311 	e_YM2a = ('Y' << 24) | ('M' << 16) | ('2' << 8) | ('!'),	//'YM2!'
312 	e_YM3a = ('Y' << 24) | ('M' << 16) | ('3' << 8) | ('!'),	//'YM3!'
313 	e_YM3b = ('Y' << 24) | ('M' << 16) | ('3' << 8) | ('b'),	//'YM3b'
314 	e_YM4a = ('Y' << 24) | ('M' << 16) | ('4' << 8) | ('!'),	//'YM4!'
315 	e_YM5a = ('Y' << 24) | ('M' << 16) | ('5' << 8) | ('!'),	//'YM5!'
316 	e_YM6a = ('Y' << 24) | ('M' << 16) | ('6' << 8) | ('!'),	//'YM6!'
317 	e_MIX1 = ('M' << 24) | ('I' << 16) | ('X' << 8) | ('1'),	//'MIX1'
318 	e_YMT1 = ('Y' << 24) | ('M' << 16) | ('T' << 8) | ('1'),	//'YMT1'
319 	e_YMT2 = ('Y' << 24) | ('M' << 16) | ('T' << 8) | ('2'),	//'YMT2'
320 };
321 
ymDecode(void)322 ymbool	CYmMusic::ymDecode(void)
323  {
324  ymu8 *pUD;
325  ymu8	*ptr;
326  ymu32 ptr_size = fileSize;
327  ymint skip;
328  ymint i;
329  ymu32 sampleSize;
330  yms32 tmp;
331  ymu32 id;
332 
333 		if (ptr_size < 4)
334 		{
335 			setLastError("File too small");
336 			return YMFALSE;
337 		}
338 		id = ReadBigEndian32((unsigned char*)pBigMalloc, ptr_size);
339 		switch (id)
340 		{
341 			case e_YM2a://'YM2!':		// MADMAX specific.
342 				songType = YM_V2;
343 				nbFrame = (fileSize-4)/14;
344 				if (nbFrame == 0)
345 				{
346 					setLastError("No frames in file");
347 					return YMFALSE;
348 				}
349 				loopFrame = 0;
350 				ymChip.setClock(ATARI_CLOCK);
351 				setPlayerRate(50);
352 				pDataStream = pBigMalloc+4;
353 				streamInc = 14;
354 				nbDrum = 0;
355 				setAttrib(A_STREAMINTERLEAVED|A_TIMECONTROL);
356 				pSongName = mstrdup("Unknown");
357 				pSongAuthor = mstrdup("Unknown");
358 				pSongComment = mstrdup("Converted by Leonard.");
359 				pSongType = mstrdup("YM 2");
360 				pSongPlayer = mstrdup("YM-Chip driver");
361 				break;
362 
363 			case e_YM3a://'YM3!':		// Standart YM-Atari format.
364 				songType = YM_V3;
365 				nbFrame = (fileSize-4)/14;
366 				if (nbFrame == 0)
367 				{
368 					setLastError("No frames in file");
369 					return YMFALSE;
370 				}
371 				loopFrame = 0;
372 				ymChip.setClock(ATARI_CLOCK);
373 				setPlayerRate(50);
374 				pDataStream = pBigMalloc+4;
375 				streamInc = 14;
376 				nbDrum = 0;
377 				setAttrib(A_STREAMINTERLEAVED|A_TIMECONTROL);
378 				pSongName = mstrdup("Unknown");
379 				pSongAuthor = mstrdup("Unknown");
380 				pSongComment = mstrdup("");
381 				pSongType = mstrdup("YM 3");
382 				pSongPlayer = mstrdup("YM-Chip driver");
383 				break;
384 
385 			case e_YM3b://'YM3b':		// Standart YM-Atari format + Loop info.
386 				if (ptr_size < 4)
387 				{
388 					setLastError("File too small");
389 					return YMFALSE;
390 				}
391 				pUD = (ymu8*)(pBigMalloc+fileSize-4);
392 				songType = YM_V3;
393 				nbFrame = (fileSize-4)/14;
394 				if (nbFrame == 0)
395 				{
396 					setLastError("No frames in file");
397 					return YMFALSE;
398 				}
399 				loopFrame = ReadLittleEndian32(pUD, 4);
400 				ymChip.setClock(ATARI_CLOCK);
401 				setPlayerRate(50);
402 				pDataStream = pBigMalloc+4;
403 				streamInc = 14;
404 				nbDrum = 0;
405 				setAttrib(A_STREAMINTERLEAVED|A_TIMECONTROL);
406 				pSongName = mstrdup("Unknown");
407 				pSongAuthor = mstrdup("Unknown");
408 				pSongComment = mstrdup("");
409 				pSongType = mstrdup("YM 3b (loop)");
410 				pSongPlayer = mstrdup("YM-Chip driver");
411 				break;
412 
413 			case e_YM4a://'YM4!':		// Extended ATARI format.
414 				setLastError("No more YM4! support. Use YM5! format.");
415 				return YMFALSE;
416 				break;
417 
418 			case e_YM5a://'YM5!':		// Extended YM2149 format, all machines.
419 			case e_YM6a://'YM6!':		// Extended YM2149 format, all machines.
420 				if (ptr_size < 12)
421 				{
422 					setLastError("File too small");
423 					return YMFALSE;
424 				}
425 				if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8))
426 				{
427 					setLastError("Not a valid YM format !");
428 					return YMFALSE;
429 				}
430 				ptr = pBigMalloc+12;
431 				ptr_size -= 12;
432 				nbFrame = readMotorolaDword(&ptr, &ptr_size);
433 				setAttrib(readMotorolaDword(&ptr, &ptr_size) | A_TIMECONTROL);
434 				nbDrum = readMotorolaWord(&ptr, &ptr_size);
435 				ymChip.setClock(readMotorolaDword(&ptr, &ptr_size));
436 				setPlayerRate(readMotorolaWord(&ptr, &ptr_size));
437 				loopFrame = readMotorolaDword(&ptr, &ptr_size);
438 				skip = readMotorolaWord(&ptr, &ptr_size);
439 				ptr += skip;
440 				ptr_size -= skip;
441 				if (ptr_size <= 0)
442 				{
443 					setLastError("File too small");
444 					return YMFALSE;
445 				}
446 				if (nbDrum>0)
447 				{
448 					pDrumTab=(digiDrum_t*)calloc(nbDrum, sizeof(digiDrum_t));
449 					for (i=0;i<nbDrum;i++)
450 					{
451 						pDrumTab[i].size = readMotorolaDword(&ptr, &ptr_size);
452 						if (ptr_size <= 0)
453 						{
454 							setLastError("File too small");
455 							goto error_out;
456 						}
457 						if (pDrumTab[i].size)
458 						{
459 							if (pDrumTab[i].size >= 0x80000000)
460 							{
461 								setLastError("Too big drumtab");
462 								goto error_out;
463 							}
464 							if (ptr_size<pDrumTab[i].size)
465 							{
466 								setLastError("File too small");
467 								goto error_out;
468 							}
469 							pDrumTab[i].pData = (ymu8*)malloc(pDrumTab[i].size);
470 							memcpy(pDrumTab[i].pData,ptr,pDrumTab[i].size);
471 							if (attrib&A_DRUM4BITS)
472 							{
473 								ymu32 j;
474 								ymu8 *pw = pDrumTab[i].pData;
475 								for (j=0;j<pDrumTab[i].size;j++)
476 								{
477 									*pw = ymVolumeTable[(*pw)&15]>>7;
478 									pw++;
479 								}
480 							}
481 							ptr += pDrumTab[i].size;
482 							ptr_size -= pDrumTab[i].size;
483 						}
484 						else
485 						{
486 							pDrumTab[i].pData = NULL;
487 						}
488 					}
489 					attrib &= (~A_DRUM4BITS);
490 				}
491 				pSongName = readNtString((char**)&ptr, &ptr_size);
492 				pSongAuthor = readNtString((char**)&ptr, &ptr_size);
493 				pSongComment = readNtString((char**)&ptr, &ptr_size);
494 				if (ptr_size <= 0)
495 				{
496 					setLastError("File too small");
497 					goto error_out;
498 				}
499 				songType = YM_V5;
500 				if (id==e_YM6a)//'YM6!')
501 				{
502 					songType = YM_V6;
503 					pSongType = mstrdup("YM 6");
504 				}
505 				else
506 				{
507 					pSongType = mstrdup("YM 5");
508 				}
509 				if ((nbFrame >= 0x08000000) || (nbFrame < 0))
510 				{
511 					setLastError("Too many frames");
512 					goto error_out;
513 				}
514 				if (ptr_size < ((ymu32)nbFrame * 16))
515 				{
516 					setLastError("File too small");
517 					goto error_out;
518 				}
519 				pDataStream = ptr;
520 				streamInc = 16;
521 				pSongPlayer = mstrdup("YM-Chip driver");
522 				break;
523 
524 			case e_MIX1://'MIX1':		// ATARI Remix digit format.
525 				if (ptr_size < 12)
526 				{
527 					setLastError("File too small");
528 					return YMFALSE;
529 				}
530 
531 				if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8))
532 				{
533 					setLastError("Not a valid YM format !");
534 					return YMFALSE;
535 				}
536 				ptr = pBigMalloc+12;
537 				ptr_size -= 12;
538 				songType = YM_MIX1;
539 				tmp = readMotorolaDword(&ptr, &ptr_size);
540 				setAttrib(0);
541 				if (tmp&1) setAttrib(A_DRUMSIGNED);
542 				sampleSize = readMotorolaDword(&ptr, &ptr_size);
543 				nbMixBlock = readMotorolaDword(&ptr, &ptr_size);
544 				if (ptr_size <= 0)
545 				{
546 					setLastError("File too small");
547 					goto error_out;
548 				}
549 				if (sampleSize <= 0)
550 				{
551 					setLastError("Invalid sampleSize");
552 					goto error_out;
553 				}
554 				if (nbMixBlock <= 0)
555 				{
556 					setLastError("Invalid number of mixblocks");
557 					goto error_out;
558 				}
559 				pMixBlock = (mixBlock_t*)malloc(nbMixBlock*sizeof(mixBlock_t));
560 				for (i=0;i<nbMixBlock;i++)
561 				{	// Lecture des block-infos.
562 #warning sampleStart and sampleLength needs to be validated
563 					pMixBlock[i].sampleStart = readMotorolaDword(&ptr, &ptr_size);
564 					pMixBlock[i].sampleLength = readMotorolaDword(&ptr, &ptr_size);
565 					pMixBlock[i].nbRepeat = readMotorolaWord(&ptr, &ptr_size);
566 					pMixBlock[i].replayFreq = readMotorolaWord(&ptr, &ptr_size);
567 				}
568 				pSongName = readNtString((char**)&ptr, &ptr_size);
569 				pSongAuthor = readNtString((char**)&ptr, &ptr_size);
570 				pSongComment = readNtString((char**)&ptr, &ptr_size);
571 
572 				if (sampleSize>=0x80000000)
573 				{
574 					setLastError("Invalid sampleSize");
575 					goto error_out;
576 				}
577 				if (ptr_size < sampleSize)
578 				{
579 					setLastError("File too small");
580 					goto error_out;
581 				}
582 
583 				pBigSampleBuffer = (unsigned char*)malloc(sampleSize);
584 				memcpy(pBigSampleBuffer,ptr,sampleSize);
585 
586 				if (!(attrib&A_DRUMSIGNED))
587 				{
588 					signeSample(pBigSampleBuffer,sampleSize);
589 					setAttrib(A_DRUMSIGNED);
590 				}
591 
592 				setAttrib(getAttrib() | A_TIMECONTROL);
593 				computeTimeInfo();
594 
595 				mixPos = -1;		// numero du block info.
596 				currentPente = 0;
597 				currentPos = 0;
598 				pSongType = mstrdup("MIX1");
599 				pSongPlayer = mstrdup("Digi-Mix driver");
600 
601 				break;
602 
603 			case e_YMT1://'YMT1':		// YM-Tracker
604 			case e_YMT2://'YMT2':		// YM-Tracker
605 /*;
606 ; Format du YM-Tracker-1
607 ;
608 ; 4  YMT1
609 ; 8  LeOnArD!
610 ; 2  Nb voice
611 ; 2  Player rate
612 ; 4  Music lenght
613 ; 4  Music loop
614 ; 2  Nb digidrum
615 ; 4  Flags		; Interlace, signed, 8 bits, etc...
616 ; NT Music Name
617 ; NT Music author
618 ; NT Music comment
619 ; nb digi *
620 */
621 				if (ptr_size < 12)
622 				{
623 					setLastError("File too small");
624 					return YMFALSE;
625 				}
626 
627 				if (strncmp((const char*)(pBigMalloc+4),"LeOnArD!",8))
628 				{
629 					setLastError("Not a valid YM format !");
630 					return YMFALSE;
631 				}
632 				ptr = pBigMalloc+12;
633 				ptr_size -= 12;
634 				songType = YM_TRACKER1;
635 				nbVoice = readMotorolaWord(&ptr, &ptr_size);
636 				setPlayerRate(readMotorolaWord(&ptr, &ptr_size));
637 				nbFrame= readMotorolaDword(&ptr, &ptr_size);
638 				loopFrame = readMotorolaDword(&ptr, &ptr_size);
639 				nbDrum = readMotorolaWord(&ptr, &ptr_size);
640 				attrib = readMotorolaDword(&ptr, &ptr_size);
641 				pSongName = readNtString((char**)&ptr, &ptr_size);
642 				pSongAuthor = readNtString((char**)&ptr, &ptr_size);
643 				pSongComment = readNtString((char**)&ptr, &ptr_size);
644 				if (ptr_size < 0)
645 				{
646 					setLastError("File too small");
647 					return YMFALSE;
648 				}
649 				if (nbDrum>0)
650 				{
651 					pDrumTab=(digiDrum_t*)calloc(nbDrum, sizeof(digiDrum_t));
652 					for (i=0;i<(ymint)nbDrum;i++)
653 					{
654 						pDrumTab[i].size = readMotorolaWord(&ptr, &ptr_size);
655 						if (ptr_size < 0)
656 						{
657 							setLastError("File too small");
658 							goto error_out;
659 						}
660 						pDrumTab[i].repLen = pDrumTab[i].size;
661 						if (e_YMT2 == id)//('YMT2' == id)
662 						{
663 							pDrumTab[i].repLen = readMotorolaWord(&ptr, &ptr_size);	// repLen
664 							readMotorolaWord(&ptr, &ptr_size);		// flag
665 							if (ptr_size < 0)
666 							{
667 								setLastError("File too small");
668 								goto error_out;
669 							}
670 						}
671 						if (pDrumTab[i].repLen>pDrumTab[i].size)
672 						{
673 							pDrumTab[i].repLen = pDrumTab[i].size;
674 						}
675 
676 						if (pDrumTab[i].size)
677 						{
678 							if (pDrumTab[i].size >= 0x80000000)
679 							{
680 								setLastError("Drumtab to big");
681 								goto error_out;
682 							}
683 							if (ptr_size<pDrumTab[i].size)
684 							{
685 								setLastError("File too small");
686 								goto error_out;
687 							}
688 
689 							pDrumTab[i].pData = (ymu8*)malloc(pDrumTab[i].size);
690 							memcpy(pDrumTab[i].pData,ptr,pDrumTab[i].size);
691 							ptr += pDrumTab[i].size;
692 							ptr_size -= pDrumTab[i].size;
693 						}
694 						else
695 						{
696 							pDrumTab[i].pData = NULL;
697 						}
698 					}
699 				}
700 
701 				ymTrackerFreqShift = 0;
702 				if (e_YMT2 == id)//('YMT2' == id)
703 				{
704 					ymTrackerFreqShift = (attrib>>28)&15;
705 					attrib &= 0x0fffffff;
706 					pSongType = mstrdup("YM-T2");
707 				}
708 				else
709 				{
710 					pSongType = mstrdup("YM-T1");
711 				}
712 
713 				if ((nbVoice > MAX_VOICE) || (nbVoice < 0))
714 				{
715 					setLastError("Too many voices");
716 					goto error_out;
717 				}
718 				if ((nbFrame >= (ymint)(0x80000000 / (MAX_VOICE * (sizeof(ymTrackerLine_t))))) || (nbFrame < 0)) /* ymTrackerLine_t has a 2^N size */
719 				{
720 					setLastError("Too many frames");
721 					goto error_out;
722 				}
723 				if (ptr_size < (sizeof(ymTrackerLine_t) * nbVoice * nbFrame))
724 				{
725 					setLastError("File too small");
726 					goto error_out;
727 				}
728 
729 				pDataStream = ptr;
730 				ymChip.setClock(ATARI_CLOCK);
731 
732 				ymTrackerInit(100);		// 80% de volume maxi.
733 				streamInc = 16;
734 				setTimeControl(YMTRUE);
735 				pSongPlayer = mstrdup("Universal Tracker");
736 				break;
737 
738 			default:
739 				setLastError("Unknown YM format !");
740 				return YMFALSE;
741 				break;
742 		}
743 
744 		if (!deInterleave())
745 		{
746 			return YMFALSE;
747 		}
748 
749 		return YMTRUE;
750 error_out:
751 	for (i=0;i<nbDrum;i++)
752 	{
753 		if (pDrumTab[i].pData)
754 			myFree((void **)&pDrumTab[i].pData);
755 	}
756 	if (nbDrum>0)
757 	{
758 		myFree((void **)&pDrumTab);
759 		nbDrum=0;
760 	}
761 	myFree((void **)&pSongName);
762 	myFree((void **)&pSongAuthor);
763 	myFree((void **)&pSongComment);
764 	myFree((void **)&pSongType); /* <- never needed, but we keep it for purity */
765 	myFree((void **)&pSongPlayer); /* <- never needed, but we keep it for purity */
766 	myFree((void **)&pMixBlock);
767 	myFree((void **)&pBigSampleBuffer); /* <- never needed, but we keep it for purity */
768 	return YMFALSE;
769  }
770 
771 
checkCompilerTypes()772 ymbool	CYmMusic::checkCompilerTypes()
773 {
774 	setLastError("Basic types size are not correct (check ymTypes.h)");
775 
776 	if (1 != sizeof(ymu8)) return YMFALSE;
777 	if (1 != sizeof(yms8)) return YMFALSE;
778 	if (1 != sizeof(ymchar)) return YMFALSE;
779 
780 	if (2 != sizeof(ymu16)) return YMFALSE;
781 	if (2 != sizeof(yms16)) return YMFALSE;
782 	if (4 != sizeof(ymu32)) return YMFALSE;
783 	if (4 != sizeof(yms32)) return YMFALSE;
784 
785 	if (2 != sizeof(ymsample)) return YMFALSE;
786 
787 #ifdef YM_INTEGER_ONLY
788 	if (8 != sizeof(yms64)) return YMFALSE;
789 #endif
790 
791 	if (sizeof(ymint) < 4) return YMFALSE;		// ymint should be at least 32bits
792 
793 	setLastError("");
794 	return YMTRUE;
795 }
796 
797 
load(const char * fileName)798 ymbool	CYmMusic::load(const char *fileName)
799 {
800 FILE	*in;
801 
802 
803 		stop();
804 		unLoad();
805 
806 		if (!checkCompilerTypes())
807 			return YMFALSE;
808 
809 		in = fopen(fileName,"rb");
810 		if (!in)
811 		{
812 			setLastError("File not Found");
813 			return YMFALSE;
814 		}
815 
816 		//---------------------------------------------------
817 		// Allocation d'un buffer pour lire le fichier.
818 		//---------------------------------------------------
819 		fileSize = fileSizeGet(in);
820 		pBigMalloc = (unsigned char*)malloc(fileSize);
821 		if (!pBigMalloc)
822 		{
823 			setLastError("MALLOC Error");
824 			fclose(in);
825 			return YMFALSE;
826 		}
827 
828 		//---------------------------------------------------
829 		// Chargement du fichier complet.
830 		//---------------------------------------------------
831 		if (fread(pBigMalloc,1,fileSize,in)!=(size_t)fileSize)
832 		{
833 			free(pBigMalloc);
834 			setLastError("File is corrupted.");
835 			fclose(in);
836 			return YMFALSE;
837 		}
838 		fclose(in);
839 
840 		//---------------------------------------------------
841 		// Transforme les donn�es en donn�es valides.
842 		//---------------------------------------------------
843 		pBigMalloc = depackFile(fileSize);
844 		if (!pBigMalloc)
845 		{
846 			return YMFALSE;
847 		}
848 
849 		//---------------------------------------------------
850 		// Lecture des donn�es YM:
851 		//---------------------------------------------------
852 		if (!ymDecode())
853 		{
854 			free(pBigMalloc);
855 			pBigMalloc = NULL;
856 			return YMFALSE;
857 		}
858 
859 		ymChip.reset();
860 		bMusicOk = YMTRUE;
861 		bPause = YMFALSE;
862 		return YMTRUE;
863  }
864 
loadMemory(void * pBlock,ymu32 size)865 ymbool	CYmMusic::loadMemory(void *pBlock,ymu32 size)
866 {
867 
868 
869 		stop();
870 		unLoad();
871 
872 		if (!checkCompilerTypes())
873 			return YMFALSE;
874 
875 		//---------------------------------------------------
876 		// Allocation d'un buffer pour lire le fichier.
877 		//---------------------------------------------------
878 		fileSize = size;
879 		pBigMalloc = (unsigned char*)malloc(fileSize);
880 		if (!pBigMalloc)
881 		{
882 			setLastError("MALLOC Error");
883 			return YMFALSE;
884 		}
885 
886 		//---------------------------------------------------
887 		// Chargement du fichier complet.
888 		//---------------------------------------------------
889 		memcpy(pBigMalloc,pBlock,size);
890 
891 		//---------------------------------------------------
892 		// Transforme les donn�es en donn�es valides.
893 		//---------------------------------------------------
894 		pBigMalloc = depackFile(size);
895 		if (!pBigMalloc)
896 		{
897 			return YMFALSE;
898 		}
899 
900 		//---------------------------------------------------
901 		// Lecture des donn�es YM:
902 		//---------------------------------------------------
903 		if (!ymDecode())
904 		{
905 			free(pBigMalloc);
906 			pBigMalloc = NULL;
907 			return YMFALSE;
908 		}
909 
910 		ymChip.reset();
911 		bMusicOk = YMTRUE;
912 		bPause = YMFALSE;
913 		return YMTRUE;
914  }
915 
unLoad(void)916 void	CYmMusic::unLoad(void)
917 {
918 
919 		bMusicOk = YMFALSE;
920 		bPause = YMTRUE;
921 		bMusicOver = YMFALSE;
922 		myFree((void**)&pSongName);
923 		myFree((void**)&pSongAuthor);
924 		myFree((void**)&pSongComment);
925 		myFree((void**)&pSongType);
926 		myFree((void**)&pSongPlayer);
927 		myFree((void**)&pBigMalloc);
928 		if (nbDrum>0)
929 		{
930 			for (ymint i=0;i<nbDrum;i++)
931 			{
932 				myFree((void**)&pDrumTab[i].pData);
933 			}
934 			nbDrum = 0;
935 			myFree((void**)&pDrumTab);
936 		}
937 		myFree((void**)&pBigSampleBuffer);
938 		myFree((void**)&pMixBlock);
939 
940 		myFree((void**)&m_pTimeInfo);
941 
942 }
943 
stop(void)944 void	CYmMusic::stop(void)
945 {
946 	bPause = YMTRUE;
947 	currentFrame = 0;
948 	m_iMusicPosInMs = 0;
949 	m_iMusicPosAccurateSample = 0;
950 	mixPos = -1;
951 }
952 
play(void)953 void	CYmMusic::play(void)
954 {
955 	bPause = YMFALSE;
956 }
957 
pause(void)958 void	CYmMusic::pause(void)
959 {
960 	bPause = YMTRUE;
961 }
962