comparison win95kggui/dep/ft2play/pmplay.c @ 126:8e4ee43d3b81

remove submodules
author Paper <mrpapersonic@gmail.com>
date Sun, 01 Oct 2023 03:48:43 -0400
parents
children
comparison
equal deleted inserted replaced
125:5cc85ef3a675 126:8e4ee43d3b81
1 /*
2 ** - loaders and replayer handlers -
3 */
4
5 #define DEFAULT_AMP 4
6 #define DEFAULT_MASTER_VOL 256
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include <math.h>
14 #include <assert.h>
15 #include "pmplay.h"
16 #include "pmp_mix.h"
17 #include "snd_masm.h"
18 #include "tables.h"
19
20 #define INSTR_HEADER_SIZE 263
21
22 #define SWAP16(value) \
23 ( \
24 (((uint16_t)((value) & 0x00FF)) << 8) | \
25 (((uint16_t)((value) & 0xFF00)) >> 8) \
26 )
27
28 #ifdef _MSC_VER
29 #pragma pack(push)
30 #pragma pack(1)
31 #endif
32 typedef struct songHeaderTyp_t
33 {
34 char sig[17], name[21], progName[20];
35 uint16_t ver;
36 int32_t headerSize;
37 uint16_t len, repS, antChn, antPtn, antInstrs, flags, defTempo, defSpeed;
38 uint8_t songTab[256];
39 }
40 #ifdef __GNUC__
41 __attribute__ ((packed))
42 #endif
43 songHeaderTyp;
44
45 typedef struct modSampleTyp
46 {
47 char name[22];
48 uint16_t len;
49 uint8_t fine, vol;
50 uint16_t repS, repL;
51 }
52 #ifdef __GNUC__
53 __attribute__ ((packed))
54 #endif
55 modSampleTyp;
56
57 typedef struct songMOD31HeaderTyp
58 {
59 char name[20];
60 modSampleTyp sample[31];
61 uint8_t len, repS, songTab[128];
62 char Sig[4];
63 }
64 #ifdef __GNUC__
65 __attribute__ ((packed))
66 #endif
67 songMOD31HeaderTyp;
68
69 typedef struct songMOD15HeaderTyp
70 {
71 char name[20];
72 modSampleTyp sample[15];
73 uint8_t len, repS, songTab[128];
74 }
75 #ifdef __GNUC__
76 __attribute__ ((packed))
77 #endif
78 songMOD15HeaderTyp;
79
80 typedef struct sampleHeaderTyp_t
81 {
82 int32_t len, repS, repL;
83 uint8_t vol;
84 int8_t fine;
85 uint8_t typ, pan;
86 int8_t relTon;
87 uint8_t skrap;
88 char name[22];
89 }
90 #ifdef __GNUC__
91 __attribute__ ((packed))
92 #endif
93 sampleHeaderTyp;
94
95 typedef struct instrHeaderTyp_t
96 {
97 int32_t instrSize;
98 char name[22];
99 uint8_t typ;
100 uint16_t antSamp;
101 int32_t sampleSize;
102 uint8_t ta[96];
103 int16_t envVP[12][2], envPP[12][2];
104 uint8_t envVPAnt, envPPAnt, envVSust, envVRepS, envVRepE, envPSust, envPRepS;
105 uint8_t envPRepE, envVTyp, envPTyp, vibTyp, vibSweep, vibDepth, vibRate;
106 uint16_t fadeOut;
107 uint8_t midiOn, midiChannel;
108 int16_t midiProgram, midiBend;
109 int8_t mute;
110 uint8_t reserved[15];
111 sampleHeaderTyp samp[32];
112 }
113 #ifdef __GNUC__
114 __attribute__ ((packed))
115 #endif
116 instrHeaderTyp;
117
118 typedef struct patternHeaderTyp_t
119 {
120 int32_t patternHeaderSize;
121 uint8_t typ;
122 uint16_t pattLen, dataLen;
123 }
124 #ifdef __GNUC__
125 __attribute__ ((packed))
126 #endif
127 patternHeaderTyp;
128 #ifdef _MSC_VER
129 #pragma pack(pop)
130 #endif
131
132 static int32_t soundBufferSize;
133
134 // globalized
135 volatile bool interpolationFlag, volumeRampingFlag, moduleLoaded, musicPaused, WAVDump_Flag;
136 bool linearFrqTab;
137 volatile const uint16_t *note2Period;
138 uint16_t pattLens[256];
139 int16_t PMPTmpActiveChannel, boostLevel = DEFAULT_AMP;
140 int32_t masterVol = DEFAULT_MASTER_VOL, PMPLeft = 0;
141 int32_t realReplayRate, quickVolSizeVal, speedVal;
142 uint32_t frequenceDivFactor, frequenceMulFactor, CDA_Amp = 8*DEFAULT_AMP;
143 tonTyp *patt[256];
144 instrTyp *instr[1+128];
145 songTyp song;
146 stmTyp stm[32];
147 // ------------------
148
149 // 8bb: added these for loader
150 typedef struct
151 {
152 uint8_t *_ptr, *_base;
153 bool _eof;
154 size_t _cnt, _bufsiz;
155 } MEMFILE;
156
157 static MEMFILE *mopen(const uint8_t *src, uint32_t length);
158 static void mclose(MEMFILE **buf);
159 static size_t mread(void *buffer, size_t size, size_t count, MEMFILE *buf);
160 static bool meof(MEMFILE *buf);
161 static void mseek(MEMFILE *buf, int32_t offset, int32_t whence);
162 static void mrewind(MEMFILE *buf);
163 // --------------------------
164
165 static void resetMusic(void);
166 static void freeAllPatterns(void);
167 static void setFrqTab(bool linear);
168
169 static CIType *getVoice(int32_t ch) // 8bb: added this
170 {
171 if (ch < 0 || ch > 31)
172 return NULL;
173
174 return &CI[chnReloc[ch]];
175 }
176
177 /***************************************************************************
178 * ROUTINES FOR SAMPLE HANDLING ETC. *
179 ***************************************************************************/
180
181 // 8bb: modifies wrapped sample after loop/end (for branchless mixer interpolation)
182 static void fixSample(sampleTyp *s)
183 {
184 if (s->pek == NULL)
185 return; // empty sample
186
187 const bool sample16Bit = !!(s->typ & SAMPLE_16BIT);
188 uint8_t loopType = s->typ & 3;
189 int16_t *ptr16 = (int16_t *)s->pek;
190 int32_t len = s->len;
191 int32_t loopStart = s->repS;
192 int32_t loopEnd = s->repS + s->repL;
193
194 if (sample16Bit)
195 {
196 len >>= 1;
197 loopStart >>= 1;
198 loopEnd >>= 1;
199 }
200
201 if (len < 1)
202 return;
203
204 /* 8bb:
205 ** This is the exact bit test order of which FT2 handles
206 ** the sample tap fix.
207 **
208 ** This order is important for rare cases where both the
209 ** "forward" and "pingpong" loop bits are set at once.
210 **
211 ** This means that if both flags are set, the mixer will
212 ** play the sample with pingpong looping, but the sample fix
213 ** is handled as if it was a forward loop. This results in
214 ** the wrong interpolation tap sample being written after the
215 ** loop end point.
216 */
217
218 if (loopType & LOOP_FORWARD)
219 {
220 if (sample16Bit)
221 ptr16[loopEnd] = ptr16[loopStart];
222 else
223 s->pek[loopEnd] = s->pek[loopStart];
224
225 return;
226 }
227 else if (loopType & LOOP_PINGPONG)
228 {
229 if (sample16Bit)
230 ptr16[loopEnd] = ptr16[loopEnd-1];
231 else
232 s->pek[loopEnd] = s->pek[loopEnd-1];
233 }
234 else // no loop
235 {
236 if (sample16Bit)
237 ptr16[len] = 0;
238 else
239 s->pek[len] = 0;
240 }
241 }
242
243 static void checkSampleRepeat(int32_t nr, int32_t nr2)
244 {
245 instrTyp *i = instr[nr];
246 if (i == NULL)
247 return;
248
249 sampleTyp *s = &i->samp[nr2];
250
251 if (s->repS < 0) s->repS = 0;
252 if (s->repL < 0) s->repL = 0;
253 if (s->repS > s->len) s->repS = s->len;
254 if (s->repS+s->repL > s->len) s->repL = s->len - s->repS;
255 }
256
257 static void upDateInstrs(void)
258 {
259 for (int32_t i = 0; i <= 128; i++)
260 {
261 instrTyp *ins = instr[i];
262 if (ins == NULL)
263 continue;
264
265 sampleTyp *s = ins->samp;
266 for (int32_t j = 0; j < 16; j++, s++)
267 {
268 checkSampleRepeat(i, j);
269 fixSample(s);
270
271 if (s->pek == NULL)
272 {
273 s->len = 0;
274 s->repS = 0;
275 s->repL = 0;
276 }
277 }
278 }
279 }
280
281 static bool patternEmpty(uint16_t nr)
282 {
283 if (patt[nr] == NULL)
284 return true;
285
286 const uint8_t *scanPtr = (const uint8_t *)patt[nr];
287 const int32_t scanLen = pattLens[nr] * song.antChn * sizeof (tonTyp);
288
289 for (int32_t i = 0; i < scanLen; i++)
290 {
291 if (scanPtr[i] != 0)
292 return false;
293 }
294
295 return true;
296 }
297
298 static bool allocateInstr(uint16_t i)
299 {
300 if (instr[i] != NULL)
301 return true;
302
303 instrTyp *p = (instrTyp *)calloc(1, sizeof (instrTyp));
304 if (p == NULL)
305 return false;
306
307 sampleTyp *s = p->samp;
308 for (int32_t j = 0; j < 16; j++, s++)
309 {
310 s->pan = 128;
311 s->vol = 64;
312 }
313
314 instr[i] = p;
315 return true;
316 }
317
318 static void freeInstr(uint16_t nr)
319 {
320 if (nr > 128)
321 return;
322
323 instrTyp *ins = instr[nr];
324 if (ins == NULL)
325 return;
326
327 sampleTyp *s = ins->samp;
328 for (uint8_t i = 0; i < 16; i++, s++)
329 {
330 if (s->pek != NULL)
331 free(s->pek);
332 }
333
334 free(ins);
335 instr[nr] = NULL;
336 }
337
338 static void freeAllInstr(void)
339 {
340 for (uint16_t i = 0; i <= 128; i++)
341 freeInstr(i);
342 }
343
344 static void freeAllPatterns(void) // 8bb: added this one, since it's handy
345 {
346 for (int32_t i = 0; i < 256; i++)
347 {
348 if (patt[i] != NULL)
349 {
350 free(patt[i]);
351 patt[i] = NULL;
352 }
353
354 pattLens[i] = 64;
355 }
356 }
357
358 static void delta2Samp(int8_t *p, uint32_t len, bool sample16Bit)
359 {
360 if (sample16Bit)
361 {
362 len >>= 1;
363
364 int16_t *p16 = (int16_t *)p;
365
366 int16_t olds16 = 0;
367 for (uint32_t i = 0; i < len; i++)
368 {
369 const int16_t news16 = p16[i] + olds16;
370 p16[i] = news16;
371 olds16 = news16;
372 }
373 }
374 else
375 {
376 int8_t *p8 = (int8_t *)p;
377
378 int8_t olds8 = 0;
379 for (uint32_t i = 0; i < len; i++)
380 {
381 const int8_t news8 = p8[i] + olds8;
382 p8[i] = news8;
383 olds8 = news8;
384 }
385 }
386 }
387
388 static void unpackPatt(uint8_t *dst, uint16_t inn, uint16_t len, uint8_t antChn)
389 {
390 if (dst == NULL)
391 return;
392
393 const uint8_t *src = dst + inn;
394 const int32_t srcEnd = len * (sizeof (tonTyp) * antChn);
395
396 int32_t srcIdx = 0;
397 for (int32_t i = 0; i < len; i++)
398 {
399 for (int32_t j = 0; j < antChn; j++)
400 {
401 if (srcIdx >= srcEnd)
402 return; // error!
403
404 const uint8_t note = *src++;
405 if (note & 0x80)
406 {
407 *dst++ = (note & 0x01) ? *src++ : 0;
408 *dst++ = (note & 0x02) ? *src++ : 0;
409 *dst++ = (note & 0x04) ? *src++ : 0;
410 *dst++ = (note & 0x08) ? *src++ : 0;
411 *dst++ = (note & 0x10) ? *src++ : 0;
412 }
413 else
414 {
415 *dst++ = note;
416 *dst++ = *src++;
417 *dst++ = *src++;
418 *dst++ = *src++;
419 *dst++ = *src++;
420 }
421
422 // 8bb: added this. If note >97, remove it (prevents out-of-range read in note->sample LUT)
423 if (*(dst-5) > 97)
424 *(dst-5) = 0;
425
426 srcIdx += sizeof (tonTyp);
427 }
428 }
429 }
430
431 void freeMusic(void)
432 {
433 stopMusic();
434 freeAllInstr();
435 freeAllPatterns();
436
437 song.tempo = 6;
438 song.speed = 125;
439 song.timer = 1;
440
441 setFrqTab(true);
442 resetMusic();
443 }
444
445 void stopVoices(void)
446 {
447 lockMixer();
448
449 stmTyp *ch = stm;
450 for (uint8_t i = 0; i < 32; i++, ch++)
451 {
452 ch->tonTyp = 0;
453 ch->relTonNr = 0;
454 ch->instrNr = 0;
455 ch->instrSeg = instr[0]; // 8bb: placeholder instrument
456 ch->status = IS_Vol;
457
458 ch->realVol = 0;
459 ch->outVol = 0;
460 ch->oldVol = 0;
461 ch->finalVol = 0;
462 ch->oldPan = 128;
463 ch->outPan = 128;
464 ch->finalPan = 128;
465 ch->vibDepth = 0;
466 }
467
468 unlockMixer();
469 }
470
471 static void resetMusic(void)
472 {
473 song.timer = 1;
474 stopVoices();
475 setPos(0, 0);
476 }
477
478 void setPos(int32_t pos, int32_t row) // -1 = don't change
479 {
480 if (pos != -1)
481 {
482 song.songPos = (int16_t)pos;
483 if (song.len > 0 && song.songPos >= song.len)
484 song.songPos = song.len - 1;
485
486 song.pattNr = song.songTab[song.songPos];
487 song.pattLen = pattLens[song.pattNr];
488 }
489
490 if (row != -1)
491 {
492 song.pattPos = (int16_t)row;
493 if (song.pattPos >= song.pattLen)
494 song.pattPos = song.pattLen - 1;
495 }
496
497 song.timer = 1;
498 }
499
500 /***************************************************************************
501 * MODULE LOADING ROUTINES *
502 ***************************************************************************/
503
504 static bool loadInstrHeader(MEMFILE *f, uint16_t i)
505 {
506 instrHeaderTyp ih;
507
508 memset(&ih, 0, INSTR_HEADER_SIZE);
509 mread(&ih.instrSize, 4, 1, f);
510 if (ih.instrSize > INSTR_HEADER_SIZE) ih.instrSize = INSTR_HEADER_SIZE;
511
512 if (ih.instrSize < 4) // 8bb: added protection
513 return false;
514
515 mread(ih.name, ih.instrSize-4, 1, f);
516
517 if (ih.antSamp > 16)
518 return false;
519
520 if (ih.antSamp > 0)
521 {
522 if (!allocateInstr(i))
523 return false;
524
525 instrTyp *ins = instr[i];
526
527 memcpy(ins->name, ih.name, 22);
528 ins->name[22] = '\0';
529
530 // 8bb: copy instrument header elements to our instrument struct
531 memcpy(ins->ta, ih.ta, 96);
532 memcpy(ins->envVP, ih.envVP, 12*2*sizeof(int16_t));
533 memcpy(ins->envPP, ih.envPP, 12*2*sizeof(int16_t));
534 ins->envVPAnt = ih.envVPAnt;
535 ins->envPPAnt = ih.envPPAnt;
536 ins->envVSust = ih.envVSust;
537 ins->envVRepS = ih.envVRepS;
538 ins->envVRepE = ih.envVRepE;
539 ins->envPSust = ih.envPSust;
540 ins->envPRepS = ih.envPRepS;
541 ins->envPRepE = ih.envPRepE;
542 ins->envVTyp = ih.envVTyp;
543 ins->envPTyp = ih.envPTyp;
544 ins->vibTyp = ih.vibTyp;
545 ins->vibSweep = ih.vibSweep;
546 ins->vibDepth = ih.vibDepth;
547 ins->vibRate = ih.vibRate;
548 ins->fadeOut = ih.fadeOut;
549 ins->mute = (ih.mute == 1) ? true : false; // 8bb: correct logic!
550 ins->antSamp = ih.antSamp;
551
552 if (mread(ih.samp, ih.antSamp * sizeof (sampleHeaderTyp), 1, f) != 1)
553 return false;
554
555 sampleTyp *s = instr[i]->samp;
556 sampleHeaderTyp *src = ih.samp;
557 for (int32_t j = 0; j < ih.antSamp; j++, s++, src++)
558 {
559 memcpy(s->name, src->name, 22);
560 s->name[22] = '\0';
561
562 s->len = src->len;
563 s->repS = src->repS;
564 s->repL = src->repL;
565 s->vol = src->vol;
566 s->fine = src->fine;
567 s->typ = src->typ;
568 s->pan = src->pan;
569 s->relTon = src->relTon;
570 }
571 }
572
573 return true;
574 }
575
576 static bool loadInstrSample(MEMFILE *f, uint16_t i)
577 {
578 if (instr[i] == NULL)
579 return true; // empty instrument
580
581 sampleTyp *s = instr[i]->samp;
582 for (uint16_t j = 0; j < instr[i]->antSamp; j++, s++)
583 {
584 if (s->len > 0)
585 {
586 bool sample16Bit = !!(s->typ & SAMPLE_16BIT);
587
588 s->pek = (int8_t *)malloc(s->len+2); // 8bb: +2 for fixed interpolation tap sample
589 if (s->pek == NULL)
590 return false;
591
592 mread(s->pek, 1, s->len, f);
593 delta2Samp(s->pek, s->len, sample16Bit);
594 }
595
596 checkSampleRepeat(i, j);
597 }
598
599 return true;
600 }
601
602 static bool loadPatterns(MEMFILE *f, uint16_t antPtn)
603 {
604 uint8_t tmpLen;
605 patternHeaderTyp ph;
606
607 for (uint16_t i = 0; i < antPtn; i++)
608 {
609 mread(&ph.patternHeaderSize, 4, 1, f);
610 mread(&ph.typ, 1, 1, f);
611
612 ph.pattLen = 0;
613 if (song.ver == 0x0102)
614 {
615 mread(&tmpLen, 1, 1, f);
616 mread(&ph.dataLen, 2, 1, f);
617 ph.pattLen = (uint16_t)tmpLen + 1; // 8bb: +1 in v1.02
618
619 if (ph.patternHeaderSize > 8)
620 mseek(f, ph.patternHeaderSize - 8, SEEK_CUR);
621 }
622 else
623 {
624 mread(&ph.pattLen, 2, 1, f);
625 mread(&ph.dataLen, 2, 1, f);
626
627 if (ph.patternHeaderSize > 9)
628 mseek(f, ph.patternHeaderSize - 9, SEEK_CUR);
629 }
630
631 if (meof(f))
632 {
633 mclose(&f);
634 return false;
635 }
636
637 pattLens[i] = ph.pattLen;
638 if (ph.dataLen)
639 {
640 const uint16_t a = ph.pattLen * song.antChn * sizeof (tonTyp);
641
642 patt[i] = (tonTyp *)malloc(a);
643 if (patt[i] == NULL)
644 return false;
645
646 uint8_t *pattPtr = (uint8_t *)patt[i];
647
648 memset(pattPtr, 0, a);
649 mread(&pattPtr[a - ph.dataLen], 1, ph.dataLen, f);
650 unpackPatt(pattPtr, a - ph.dataLen, ph.pattLen, song.antChn);
651 }
652
653 if (patternEmpty(i))
654 {
655 if (patt[i] != NULL)
656 {
657 free(patt[i]);
658 patt[i] = NULL;
659 }
660
661 pattLens[i] = 64;
662 }
663 }
664
665 return true;
666 }
667
668 static bool loadMusicMOD(MEMFILE *f)
669 {
670 uint8_t ha[sizeof (songMOD31HeaderTyp)];
671 songMOD31HeaderTyp *h_MOD31 = (songMOD31HeaderTyp *)ha;
672 songMOD15HeaderTyp *h_MOD15 = (songMOD15HeaderTyp *)ha;
673
674 mread(ha, sizeof (ha), 1, f);
675 if (meof(f))
676 goto loadError2;
677
678 memcpy(song.name, h_MOD31->name, 20);
679 song.name[20] = '\0';
680
681 uint8_t j = 0;
682 for (uint8_t i = 1; i <= 16; i++)
683 {
684 if (memcmp(h_MOD31->Sig, MODSig[i-1], 4) == 0)
685 j = i + i;
686 }
687
688 if (memcmp(h_MOD31->Sig, "M!K!", 4) == 0 || memcmp(h_MOD31->Sig, "FLT4", 4) == 0)
689 j = 4;
690
691 if (memcmp(h_MOD31->Sig, "OCTA", 4) == 0)
692 j = 8;
693
694 uint8_t typ;
695 if (j > 0)
696 {
697 typ = 1;
698 song.antChn = j;
699 }
700 else
701 {
702 typ = 2;
703 song.antChn = 4;
704 }
705
706 int16_t ai;
707 if (typ == 1)
708 {
709 mseek(f, sizeof (songMOD31HeaderTyp), SEEK_SET);
710 song.len = h_MOD31->len;
711 song.repS = h_MOD31->repS;
712 memcpy(song.songTab, h_MOD31->songTab, 128);
713 ai = 31;
714 }
715 else
716 {
717 mseek(f, sizeof (songMOD15HeaderTyp), SEEK_SET);
718 song.len = h_MOD15->len;
719 song.repS = h_MOD15->repS;
720 memcpy(song.songTab, h_MOD15->songTab, 128);
721 ai = 15;
722 }
723
724 song.antInstrs = ai; // 8bb: added this
725
726 if (meof(f))
727 goto loadError2;
728
729 int32_t b = 0;
730 for (int32_t a = 0; a < 128; a++)
731 {
732 if (song.songTab[a] > b)
733 b = song.songTab[a];
734 }
735
736 uint8_t pattBuf[32 * 4 * 64]; // 8bb: max pattern size (32 channels, 64 rows)
737 for (uint16_t a = 0; a <= b; a++)
738 {
739 patt[a] = (tonTyp *)calloc(song.antChn * 64, sizeof (tonTyp));
740 if (patt[a] == NULL)
741 goto loadError;
742
743 pattLens[a] = 64;
744
745 mread(pattBuf, 1, song.antChn * 4 * 64, f);
746 if (meof(f))
747 goto loadError;
748
749 // convert pattern
750 uint8_t *bytes = pattBuf;
751 tonTyp *ton = patt[a];
752 for (int32_t i = 0; i < 64 * song.antChn; i++, bytes += 4, ton++)
753 {
754 const uint16_t period = ((bytes[0] & 0x0F) << 8) | bytes[1];
755 for (uint8_t k = 0; k < 96; k++)
756 {
757 if (period >= amigaPeriod[k])
758 {
759 ton->ton = k+1;
760 break;
761 }
762 }
763
764 ton->instr = (bytes[0] & 0xF0) | (bytes[2] >> 4);
765 ton->effTyp = bytes[2] & 0x0F;
766 ton->eff = bytes[3];
767
768 switch (ton->effTyp)
769 {
770 case 0xC:
771 {
772 if (ton->eff > 64)
773 ton->eff = 64;
774 }
775 break;
776
777 case 0x1:
778 case 0x2:
779 {
780 if (ton->eff == 0)
781 ton->effTyp = 0;
782 }
783 break;
784
785 case 0x5:
786 {
787 if (ton->eff == 0)
788 ton->effTyp = 3;
789 }
790 break;
791
792 case 0x6:
793 {
794 if (ton->eff == 0)
795 ton->effTyp = 4;
796 }
797 break;
798
799 case 0xA:
800 {
801 if (ton->eff == 0)
802 ton->effTyp = 0;
803 }
804 break;
805
806 case 0xE:
807 {
808 const uint8_t effTyp = ton->effTyp >> 4;
809 const uint8_t eff = ton->effTyp & 15;
810
811 if (eff == 0 && (effTyp == 0x1 || effTyp == 0x2 || effTyp == 0xA || effTyp == 0xB))
812 {
813 ton->eff = 0;
814 ton->effTyp = 0;
815 }
816 }
817 break;
818
819 default: break;
820 }
821 }
822
823 if (patternEmpty(a))
824 {
825 free(patt[a]);
826 patt[a] = NULL;
827 pattLens[a] = 64;
828 }
829 }
830
831 for (uint16_t a = 1; a <= ai; a++)
832 {
833 modSampleTyp *modSmp = &h_MOD31->sample[a-1];
834
835 uint32_t len = 2 * SWAP16(modSmp->len);
836 if (len == 0)
837 continue;
838
839 if (!allocateInstr(a))
840 goto loadError;
841
842 sampleTyp *xmSmp = &instr[a]->samp[0];
843
844 memcpy(xmSmp->name, modSmp->name, 22);
845 xmSmp->name[22] = '\0';
846
847 uint32_t repS = 2 * SWAP16(modSmp->repS);
848 uint32_t repL = 2 * SWAP16(modSmp->repL);
849
850 if (repL <= 2)
851 {
852 repS = 0;
853 repL = 0;
854 }
855
856 if (repS+repL > len)
857 {
858 if (repS >= len)
859 {
860 repS = 0;
861 repL = 0;
862 }
863 else
864 {
865 repL = len-repS;
866 }
867 }
868
869 xmSmp->typ = (repL > 2) ? 1 : 0;
870 xmSmp->len = len;
871 xmSmp->vol = (modSmp->vol <= 64) ? modSmp->vol : 64;
872 xmSmp->fine = 8 * ((2 * ((modSmp->fine & 15) ^ 8)) - 16);
873 xmSmp->repL = repL;
874 xmSmp->repS = repS;
875
876 xmSmp->pek = (int8_t *)malloc(len + 2);
877 if (xmSmp->pek == NULL)
878 goto loadError;
879
880 mread(xmSmp->pek, 1, len, f);
881 }
882
883 mclose(&f);
884
885 if (song.repS > song.len)
886 song.repS = 0;
887
888 resetMusic();
889 upDateInstrs();
890
891 moduleLoaded = true;
892 return true;
893 loadError:
894 freeAllInstr();
895 freeAllPatterns();
896 loadError2:
897 mclose(&f);
898 return false;
899 }
900
901 bool loadMusicFromData(const uint8_t *data, uint32_t dataLength) // .XM/.MOD/.FT
902 {
903 uint16_t i;
904 songHeaderTyp h;
905
906 freeMusic();
907 setFrqTab(false);
908
909 moduleLoaded = false;
910
911 MEMFILE *f = mopen(data, dataLength);
912 if (f == NULL)
913 return false;
914
915 // 8bb: instr 0 is a placeholder for empty instruments
916 allocateInstr(0);
917 instr[0]->samp[0].vol = 0;
918
919 mread(&h, sizeof (h), 1, f);
920 if (meof(f))
921 goto loadError2;
922
923 if (memcmp(h.sig, "Extended Module: ", 17) != 0)
924 {
925 mrewind(f);
926 return loadMusicMOD(f);
927 }
928
929 if (h.ver < 0x0102 || h.ver > 0x104 || h.antChn < 2 || h.antChn > 32 || (h.antChn & 1) != 0 ||
930 h.antPtn > 256 || h.antInstrs > 128)
931 {
932 goto loadError2;
933 }
934
935 mseek(f, 60+h.headerSize, SEEK_SET);
936 if (meof(f))
937 goto loadError2;
938
939 memcpy(song.name, h.name, 20);
940 song.name[20] = '\0';
941
942 song.len = h.len;
943 song.repS = h.repS;
944 song.antChn = (uint8_t)h.antChn;
945 bool linearFrequencies = !!(h.flags & LINEAR_FREQUENCIES);
946 setFrqTab(linearFrequencies);
947 memcpy(song.songTab, h.songTab, 256);
948
949 song.antInstrs = h.antInstrs; // 8bb: added this
950 if (h.defSpeed == 0) h.defSpeed = 125; // 8bb: (BPM) FT2 doesn't do this, but we do it for safety
951 song.speed = h.defSpeed;
952 song.tempo = h.defTempo;
953 song.ver = h.ver;
954
955 // 8bb: bugfixes...
956 if (song.speed < 1) song.speed = 1;
957 if (song.tempo < 1) song.tempo = 1;
958 // ----------------
959
960 if (song.ver < 0x0104) // old FT2 XM format
961 {
962 for (i = 1; i <= h.antInstrs; i++)
963 {
964 if (!loadInstrHeader(f, i))
965 goto loadError;
966 }
967
968 if (!loadPatterns(f, h.antPtn))
969 goto loadError;
970
971 for (i = 1; i <= h.antInstrs; i++)
972 {
973 if (!loadInstrSample(f, i))
974 goto loadError;
975 }
976 }
977 else // latest FT2 XM format
978 {
979 if (!loadPatterns(f, h.antPtn))
980 goto loadError;
981
982 for (i = 1; i <= h.antInstrs; i++)
983 {
984 if (!loadInstrHeader(f, i))
985 goto loadError;
986
987 if (!loadInstrSample(f, i))
988 goto loadError;
989 }
990 }
991
992 mclose(&f);
993
994 if (song.repS > song.len)
995 song.repS = 0;
996
997 resetMusic();
998 upDateInstrs();
999
1000 moduleLoaded = true;
1001 return true;
1002
1003 loadError:
1004 freeAllInstr();
1005 freeAllPatterns();
1006 loadError2:
1007 mclose(&f);
1008 return false;
1009 }
1010
1011 bool loadMusic(const char *fileName) // .XM/.MOD/.FT
1012 {
1013 FILE *f = fopen(fileName, "rb");
1014 if (f == NULL)
1015 return false;
1016
1017 fseek(f, 0, SEEK_END);
1018 const uint32_t fileSize = (uint32_t)ftell(f);
1019 rewind(f);
1020
1021 uint8_t *fileBuffer = (uint8_t *)malloc(fileSize);
1022 if (fileBuffer == NULL)
1023 {
1024 fclose(f);
1025 return false;
1026 }
1027
1028 if (fread(fileBuffer, 1, fileSize, f) != fileSize)
1029 {
1030 free(fileBuffer);
1031 fclose(f);
1032 return false;
1033 }
1034
1035 fclose(f);
1036
1037 if (!loadMusicFromData((const uint8_t *)fileBuffer, fileSize))
1038 {
1039 free(fileBuffer);
1040 return false;
1041 }
1042
1043 free(fileBuffer);
1044 return true;
1045 }
1046
1047 /***************************************************************************
1048 * PROCESS HANDLING *
1049 ***************************************************************************/
1050
1051 bool startMusic(void)
1052 {
1053 if (!moduleLoaded || song.speed == 0)
1054 return false;
1055
1056 mix_ClearChannels();
1057 stopVoices();
1058 song.globVol = 64;
1059
1060 speedVal = ((realReplayRate * 5) / 2) / song.speed;
1061 quickVolSizeVal = realReplayRate / 200;
1062
1063 if (!mix_Init(soundBufferSize))
1064 return false;
1065
1066 if (openMixer(realReplayRate, soundBufferSize))
1067 {
1068 musicPaused = false;
1069 return true;
1070 }
1071
1072 return false;
1073 }
1074
1075 void stopMusic(void)
1076 {
1077 pauseMusic();
1078
1079 closeMixer();
1080 mix_Free();
1081 song.globVol = 64;
1082
1083 resumeMusic();
1084 }
1085
1086 void startPlaying(void)
1087 {
1088 stopMusic();
1089 song.pattDelTime = song.pattDelTime2 = 0; // 8bb: added these
1090 setPos(0, 0);
1091 startMusic();
1092 }
1093
1094 void stopPlaying(void)
1095 {
1096 stopMusic();
1097 stopVoices();
1098 }
1099
1100 void pauseMusic(void)
1101 {
1102 musicPaused = true;
1103 }
1104
1105 void resumeMusic(void)
1106 {
1107 musicPaused = false;
1108 }
1109
1110 // 8bb: added these three, handy
1111 void toggleMusic(void)
1112 {
1113 musicPaused ^= 1;
1114 }
1115
1116 void setInterpolation(bool on)
1117 {
1118 interpolationFlag = on;
1119 mix_ClearChannels();
1120 }
1121
1122 void setVolumeRamping(bool on)
1123 {
1124 volumeRampingFlag = on;
1125 mix_ClearChannels();
1126 }
1127
1128 /***************************************************************************
1129 * CONFIGURATION ROUTINES *
1130 ***************************************************************************/
1131
1132 void setMasterVol(int32_t v) // 0..256
1133 {
1134 masterVol = CLAMP(v, 0, 256);
1135
1136 stmTyp *ch = stm;
1137 for (int32_t i = 0; i < 32; i++, ch++)
1138 ch->status |= IS_Vol;
1139 }
1140
1141 void setAmp(int32_t level) // 1..32
1142 {
1143 boostLevel = (int16_t)CLAMP(level, 1, 32);
1144 CDA_Amp = boostLevel * 8;
1145 }
1146
1147 int32_t getMasterVol(void) // 8bb: added this
1148 {
1149 return masterVol;
1150 }
1151
1152 int32_t getAmp(void) // 8bb: added this
1153 {
1154 return boostLevel;
1155 }
1156
1157 uint8_t getNumActiveVoices(void) // 8bb: added this
1158 {
1159 uint8_t activeVoices = 0;
1160 for (int32_t i = 0; i < song.antChn; i++)
1161 {
1162 CIType *v = getVoice(i);
1163 if (!(v->SType & SType_Off) && v->SVol > 0)
1164 activeVoices++;
1165 }
1166
1167 return activeVoices;
1168 }
1169
1170 static void setFrqTab(bool linear)
1171 {
1172 linearFrqTab = linear;
1173 note2Period = linear ? linearPeriods : amigaPeriods;
1174 }
1175
1176 void updateReplayRate(void)
1177 {
1178 lockMixer();
1179
1180 // 8bb: bit-exact to FT2
1181 frequenceDivFactor = (uint32_t)round(65536.0*1712.0/realReplayRate*8363.0);
1182 frequenceMulFactor = (uint32_t)round(256.0*65536.0/realReplayRate*8363.0);
1183
1184 unlockMixer();
1185 }
1186
1187 /***************************************************************************
1188 * INITIALIZATION ROUTINES *
1189 ***************************************************************************/
1190
1191 bool initMusic(int32_t audioFrequency, int32_t audioBufferSize, bool interpolation, bool volumeRamping)
1192 {
1193 closeMixer();
1194 freeMusic();
1195 memset(stm, 0, sizeof (stm));
1196
1197 realReplayRate = CLAMP(audioFrequency, 8000, 96000);
1198 updateReplayRate();
1199
1200 soundBufferSize = audioBufferSize;
1201 interpolationFlag = interpolation;
1202 volumeRampingFlag = volumeRamping;
1203
1204 song.tempo = 6;
1205 song.speed = 125;
1206 setFrqTab(true);
1207 resetMusic();
1208
1209 return true;
1210 }
1211
1212 /***************************************************************************
1213 * WAV DUMPING ROUTINES *
1214 ***************************************************************************/
1215
1216 static void WAV_WriteHeader(FILE *f, int32_t frq)
1217 {
1218 uint16_t w;
1219 uint32_t l;
1220
1221 // 12 bytes
1222
1223 const uint32_t RIFF = 0x46464952;
1224 fwrite(&RIFF, 4, 1, f);
1225 fseek(f, 4, SEEK_CUR);
1226 const uint32_t WAVE = 0x45564157;
1227 fwrite(&WAVE, 4, 1, f);
1228
1229 // 24 bytes
1230
1231 const uint32_t fmt = 0x20746D66;
1232 fwrite(&fmt, 4, 1, f);
1233 l = 16; fwrite(&l, 4, 1, f);
1234 w = 1; fwrite(&w, 2, 1, f);
1235 w = 2; fwrite(&w, 2, 1, f);
1236 l = frq; fwrite(&l, 4, 1, f);
1237 l = frq*2*2; fwrite(&l, 4, 1, f);
1238 w = 2*2; fwrite(&w, 2, 1, f);
1239 w = 8*2; fwrite(&w, 2, 1, f);
1240
1241 // 8 bytes
1242
1243 const uint32_t DATA = 0x61746164;
1244 fwrite(&DATA, 4, 1, f);
1245 fseek(f, 4, SEEK_CUR);
1246 }
1247
1248 static void WAV_WriteEnd(FILE *f, uint32_t size)
1249 {
1250 fseek(f, 4, SEEK_SET);
1251 uint32_t l = size+4+24+8;
1252 fwrite(&l, 4, 1, f);
1253 fseek(f, 12+24+4, SEEK_SET);
1254 fwrite(&size, 4, 1, f);
1255 }
1256
1257 void WAVDump_Abort(void) // 8bb: added this
1258 {
1259 WAVDump_Flag = false;
1260 }
1261
1262 bool WAVDump_Record(const char *filenameOut)
1263 {
1264 FILE *fil = fopen(filenameOut, "wb");
1265 if (fil == NULL)
1266 {
1267 WAVDump_Flag = false;
1268 return false;
1269 }
1270
1271 const int32_t WDFrequency = realReplayRate;
1272 const int32_t WDAmp = boostLevel;
1273
1274 const uint32_t maxSamplesPerTick = (WDFrequency*5 / 2) / 1; // 8bb: added this (min. BPM = 1, through hex editing)
1275 int16_t *pBlock = (int16_t *)malloc(maxSamplesPerTick * (2 * sizeof (int16_t)));
1276 if (pBlock == NULL)
1277 {
1278 fclose(fil);
1279 WAVDump_Flag = false;
1280 return false;
1281 }
1282
1283 WAV_WriteHeader(fil, WDFrequency);
1284
1285 stopMusic();
1286 mix_Init(maxSamplesPerTick);
1287
1288 uint16_t WDStartPos = 0;
1289 uint16_t WDStopPos = song.len-1;
1290
1291 dump_Init(WDFrequency, WDAmp, WDStartPos);
1292
1293 uint32_t totSize = 0;
1294
1295 WAVDump_Flag = true;
1296 while (!dump_EndOfTune(WDStopPos))
1297 {
1298 if (!WAVDump_Flag) // extra check so that external threads can force-abort render
1299 break;
1300
1301 const uint32_t size = dump_GetFrame(pBlock);
1302 fwrite(pBlock, 1, size, fil);
1303 totSize += size;
1304 }
1305 WAVDump_Flag = false;
1306
1307 mix_Free();
1308
1309 WAV_WriteEnd(fil, totSize);
1310 dump_Close();
1311
1312 stopMusic();
1313 fclose(fil);
1314
1315 free(pBlock);
1316
1317 WAVDump_Flag = false;
1318 return true;
1319 }
1320
1321 /***************************************************************************
1322 * MEMORY READ ROUTINES (8bb: added these) *
1323 ***************************************************************************/
1324
1325 static MEMFILE *mopen(const uint8_t *src, uint32_t length)
1326 {
1327 if (src == NULL || length == 0)
1328 return NULL;
1329
1330 MEMFILE *b = (MEMFILE *)malloc(sizeof (MEMFILE));
1331 if (b == NULL)
1332 return NULL;
1333
1334 b->_base = (uint8_t *)src;
1335 b->_ptr = (uint8_t *)src;
1336 b->_cnt = length;
1337 b->_bufsiz = length;
1338 b->_eof = false;
1339
1340 return b;
1341 }
1342
1343 static void mclose(MEMFILE **buf)
1344 {
1345 if (*buf != NULL)
1346 {
1347 free(*buf);
1348 *buf = NULL;
1349 }
1350 }
1351
1352 static size_t mread(void *buffer, size_t size, size_t count, MEMFILE *buf)
1353 {
1354 if (buf == NULL || buf->_ptr == NULL)
1355 return 0;
1356
1357 size_t wrcnt = size * count;
1358 if (size == 0 || buf->_eof)
1359 return 0;
1360
1361 int32_t pcnt = (buf->_cnt > wrcnt) ? (int32_t)wrcnt : (int32_t)buf->_cnt;
1362 memcpy(buffer, buf->_ptr, pcnt);
1363
1364 buf->_cnt -= pcnt;
1365 buf->_ptr += pcnt;
1366
1367 if (buf->_cnt <= 0)
1368 {
1369 buf->_ptr = buf->_base + buf->_bufsiz;
1370 buf->_cnt = 0;
1371 buf->_eof = true;
1372 }
1373
1374 return pcnt / size;
1375 }
1376
1377 static bool meof(MEMFILE *buf)
1378 {
1379 if (buf == NULL)
1380 return true;
1381
1382 return buf->_eof;
1383 }
1384
1385 static void mseek(MEMFILE *buf, int32_t offset, int32_t whence)
1386 {
1387 if (buf == NULL)
1388 return;
1389
1390 if (buf->_base)
1391 {
1392 switch (whence)
1393 {
1394 case SEEK_SET: buf->_ptr = buf->_base + offset; break;
1395 case SEEK_CUR: buf->_ptr += offset; break;
1396 case SEEK_END: buf->_ptr = buf->_base + buf->_bufsiz + offset; break;
1397 default: break;
1398 }
1399
1400 buf->_eof = false;
1401 if (buf->_ptr >= buf->_base+buf->_bufsiz)
1402 {
1403 buf->_ptr = buf->_base + buf->_bufsiz;
1404 buf->_eof = true;
1405 }
1406
1407 buf->_cnt = (buf->_base + buf->_bufsiz) - buf->_ptr;
1408 }
1409 }
1410
1411 static void mrewind(MEMFILE *buf)
1412 {
1413 mseek(buf, 0, SEEK_SET);
1414 }