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