1 //
2 // GOATTRACKER v2 playroutine
3 //
4
5 #define GPLAY_C
6
7 #include "goattrk2.h"
8
9 unsigned char freqtbllo[] = {
10 0x17,0x27,0x39,0x4b,0x5f,0x74,0x8a,0xa1,0xba,0xd4,0xf0,0x0e,
11 0x2d,0x4e,0x71,0x96,0xbe,0xe8,0x14,0x43,0x74,0xa9,0xe1,0x1c,
12 0x5a,0x9c,0xe2,0x2d,0x7c,0xcf,0x28,0x85,0xe8,0x52,0xc1,0x37,
13 0xb4,0x39,0xc5,0x5a,0xf7,0x9e,0x4f,0x0a,0xd1,0xa3,0x82,0x6e,
14 0x68,0x71,0x8a,0xb3,0xee,0x3c,0x9e,0x15,0xa2,0x46,0x04,0xdc,
15 0xd0,0xe2,0x14,0x67,0xdd,0x79,0x3c,0x29,0x44,0x8d,0x08,0xb8,
16 0xa1,0xc5,0x28,0xcd,0xba,0xf1,0x78,0x53,0x87,0x1a,0x10,0x71,
17 0x42,0x89,0x4f,0x9b,0x74,0xe2,0xf0,0xa6,0x0e,0x33,0x20,0xff,
18 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
19 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
20 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
21 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
22
23 unsigned char freqtblhi[] = {
24 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,
25 0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x04,
26 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x08,
27 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x10,
28 0x11,0x12,0x13,0x14,0x15,0x17,0x18,0x1a,0x1b,0x1d,0x1f,0x20,
29 0x22,0x24,0x27,0x29,0x2b,0x2e,0x31,0x34,0x37,0x3a,0x3e,0x41,
30 0x45,0x49,0x4e,0x52,0x57,0x5c,0x62,0x68,0x6e,0x75,0x7c,0x83,
31 0x8b,0x93,0x9c,0xa5,0xaf,0xb9,0xc4,0xd0,0xdd,0xea,0xf8,0xff,
32 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
33 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
34 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
35 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
36
37 CHN chn[MAX_CHN];
38 unsigned char filterctrl = 0;
39 unsigned char filtertype = 0;
40 unsigned char filtercutoff = 0;
41 unsigned char filtertime = 0;
42 unsigned char filterptr = 0;
43 unsigned char funktable[2];
44 unsigned char masterfader = 0x0f;
45 int psnum = 0;
46 int songinit = 0;
47 int lastsonginit = 0;
48 int startpattpos = 0;
49
50 void sequencer(int c, CHN *cptr);
51
initchannels(void)52 void initchannels(void)
53 {
54 int c;
55 CHN *cptr = &chn[0];
56
57 memset(chn, 0, sizeof chn);
58
59 for (c = 0; c < MAX_CHN; c++)
60 {
61 chn[c].trans = 0;
62 chn[c].instr = 1;
63 if (multiplier)
64 cptr->tempo = 6*multiplier-1;
65 else
66 cptr->tempo = 6-1;
67 cptr++;
68 }
69
70 if (multiplier)
71 {
72 funktable[0] = 9*multiplier-1;
73 funktable[1] = 6*multiplier-1;
74 }
75 else
76 {
77 funktable[0] = 9-1;
78 funktable[1] = 6-1;
79 }
80 }
81
initsong(int num,int mode)82 void initsong(int num, int mode)
83 {
84 sound_suspend();
85 songinit = PLAY_STOPPED;
86 psnum = num;
87 songinit = mode;
88 startpattpos = 0;
89 sound_flush();
90 }
91
initsongpos(int num,int mode,int pattpos)92 void initsongpos(int num, int mode, int pattpos)
93 {
94 sound_suspend();
95 songinit = PLAY_STOPPED;
96 psnum = num;
97 songinit = mode;
98 startpattpos = pattpos;
99 sound_flush();
100 }
101
stopsong(void)102 void stopsong(void)
103 {
104 if (songinit != PLAY_STOPPED)
105 {
106 sound_suspend();
107 songinit = PLAY_STOP;
108 sound_flush();
109 }
110 }
111
rewindsong(void)112 void rewindsong(void)
113 {
114 if (lastsonginit == PLAY_BEGINNING) lastsonginit = PLAY_POS;
115 initsong(psnum, lastsonginit);
116 }
117
playtestnote(int note,int ins,int chnnum)118 void playtestnote(int note, int ins, int chnnum)
119 {
120 if (note == KEYON) return;
121 if ((note == REST) || (note == KEYOFF))
122 {
123 releasenote(chnnum);
124 return;
125 }
126
127 if (!(instr[ins].gatetimer & 0x40))
128 {
129 chn[chnnum].gate = 0xfe; // Keyoff
130 if (!(instr[ins].gatetimer & 0x80))
131 {
132 sidreg[0x5+chnnum*7] = adparam>>8; // Hardrestart
133 sidreg[0x6+chnnum*7] = adparam&0xff;
134 }
135 }
136
137 chn[chnnum].instr = ins;
138 chn[chnnum].newnote = note;
139 if (songinit == PLAY_STOPPED)
140 {
141 chn[chnnum].tick = (instr[ins].gatetimer & 0x3f)+1;
142 chn[chnnum].gatetimer = instr[ins].gatetimer & 0x3f;
143 }
144 }
145
releasenote(int chnnum)146 void releasenote(int chnnum)
147 {
148 chn[chnnum].gate = 0xfe;
149 }
150
mutechannel(int chnnum)151 void mutechannel(int chnnum)
152 {
153 chn[chnnum].mute ^= 1;
154 }
155
isplaying(void)156 int isplaying(void)
157 {
158 return (songinit != PLAY_STOPPED);
159 }
160
playroutine(void)161 void playroutine(void)
162 {
163 INSTR *iptr;
164 CHN *cptr = &chn[0];
165 int c;
166
167 if (songinit == PLAY_STOP)
168 followplay = 0;
169
170 if ((songinit > 0) && (songinit < PLAY_STOPPED))
171 {
172 lastsonginit = songinit;
173
174 filterctrl = 0;
175 filterptr = 0;
176
177 resettime();
178
179 if ((songinit == 0x02) || (songinit == 0x03))
180 {
181 if ((espos[0] >= songlen[psnum][0]) || (espos[1] >= songlen[psnum][1]) || (espos[2] >= songlen[psnum][2]))
182 songinit = 0x01;
183 }
184
185 for (c = 0; c < MAX_CHN; c++)
186 {
187 cptr->songptr = 0;
188 cptr->command = 0;
189 cptr->cmddata = 0;
190 cptr->newcommand = 0;
191 cptr->newcmddata = 0;
192 cptr->advance = 1;
193 cptr->wave = 0;
194 cptr->ptr[WTBL] = 0;
195 cptr->newnote = 0;
196 cptr->repeat = 0;
197 if (multiplier)
198 cptr->tick = 6*multiplier-1;
199 else
200 cptr->tick = 6-1;
201 cptr->gatetimer = instr[1].gatetimer & 0x3f;
202 cptr->pattptr = 0x7fffffff;
203 if (cptr->tempo < 2) cptr->tempo = 0;
204
205 switch (songinit)
206 {
207 case PLAY_BEGINNING:
208 if (multiplier)
209 {
210 funktable[0] = 9*multiplier-1;
211 funktable[1] = 6*multiplier-1;
212 cptr->tempo = 6*multiplier-1;
213 }
214 else
215 {
216 funktable[0] = 9-1;
217 funktable[1] = 6-1;
218 cptr->tempo = 6-1;
219 }
220 if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL])))
221 cptr->tempo = instr[MAX_INSTR-1].ad - 1;
222 cptr->trans = 0;
223 cptr->instr = 1;
224 sequencer(c, cptr);
225 break;
226
227 case PLAY_PATTERN:
228 cptr->advance = 0;
229 cptr->pattptr = startpattpos * 4;
230 cptr->pattnum = epnum[c];
231 if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4))
232 cptr->pattptr = 0;
233 break;
234
235 case PLAY_POS:
236 cptr->songptr = espos[c];
237 sequencer(c, cptr);
238 break;
239 }
240 cptr++;
241 }
242 if (songinit != PLAY_STOP)
243 songinit = 0;
244 else
245 songinit = PLAY_STOPPED;
246 if ((!songlen[psnum][0]) || (!songlen[psnum][1]) || (!songlen[psnum][2]))
247 songinit = PLAY_STOPPED; // Zero length song
248
249 startpattpos = 0;
250 }
251 else
252 {
253 if (filterptr)
254 {
255 // Filter jump
256 if (ltable[FTBL][filterptr-1] == 0xff)
257 {
258 filterptr = rtable[FTBL][filterptr-1];
259 if (!filterptr) goto FILTERSTOP;
260 }
261
262 if (!filtertime)
263 {
264 // Filter set
265 if (ltable[FTBL][filterptr-1] >= 0x80)
266 {
267 filtertype = ltable[FTBL][filterptr-1] & 0x70;
268 filterctrl = rtable[FTBL][filterptr-1];
269 filterptr++;
270 // Can be combined with cutoff set
271 if (ltable[FTBL][filterptr-1] == 0x00)
272 {
273 filtercutoff = rtable[FTBL][filterptr-1];
274 filterptr++;
275 }
276 }
277 else
278 {
279 // New modulation step
280 if (ltable[FTBL][filterptr-1])
281 filtertime = ltable[FTBL][filterptr-1];
282 else
283 {
284 // Cutoff set
285 filtercutoff = rtable[FTBL][filterptr-1];
286 filterptr++;
287 }
288 }
289 }
290 // Filter modulation
291 if (filtertime)
292 {
293 filtercutoff += rtable[FTBL][filterptr-1];
294 filtertime--;
295 if (!filtertime) filterptr++;
296 }
297 }
298 FILTERSTOP:
299 sidreg[0x15] = 0x00;
300 sidreg[0x16] = filtercutoff;
301 sidreg[0x17] = filterctrl;
302 sidreg[0x18] = filtertype | masterfader;
303
304 for (c = 0; c < MAX_CHN; c++)
305 {
306 iptr = &instr[cptr->instr];
307
308 // Reset tempo in jammode
309 if ((songinit == PLAY_STOPPED) && (cptr->tempo < 2))
310 {
311 if (multiplier)
312 cptr->tempo = 6*multiplier-1;
313 else
314 cptr->tempo = 6-1;
315 }
316
317 // Decrease tick
318 cptr->tick--;
319 if (!cptr->tick) goto TICK0;
320
321 // Tick N
322 // Reload counter
323 if (cptr->tick >= 0x80)
324 {
325 if (cptr->tempo >= 2)
326 cptr->tick = cptr->tempo;
327 else
328 {
329 // Set funktempo, switch between 2 values
330 cptr->tick = funktable[cptr->tempo];
331 cptr->tempo ^= 1;
332 }
333 // Check for illegally high gatetimer and stop the song in this case
334 if (chn->gatetimer > cptr->tick)
335 stopsong();
336 }
337 goto WAVEEXEC;
338
339 // Tick 0
340 TICK0:
341 // Advance in sequencer
342 sequencer(c, cptr);
343
344 // Get gatetimer compare-value
345 cptr->gatetimer = iptr->gatetimer & 0x3f;
346
347 // New note init
348 if (cptr->newnote)
349 {
350 cptr->note = cptr->newnote-FIRSTNOTE;
351 cptr->command = 0;
352 cptr->vibdelay = iptr->vibdelay;
353 cptr->cmddata = iptr->ptr[STBL];
354 if (cptr->newcommand != CMD_TONEPORTA)
355 {
356 if (iptr->firstwave)
357 {
358 if (iptr->firstwave >= 0xfe) cptr->gate = iptr->firstwave;
359 else
360 {
361 cptr->wave = iptr->firstwave;
362 cptr->gate = 0xff;
363 }
364 }
365
366
367 cptr->ptr[WTBL] = iptr->ptr[WTBL];
368
369 if (cptr->ptr[WTBL])
370 {
371 // Stop the song in case of jumping into a jump
372 if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
373 stopsong();
374 }
375 if (iptr->ptr[PTBL])
376 {
377 cptr->ptr[PTBL] = iptr->ptr[PTBL];
378 cptr->pulsetime = 0;
379 if (cptr->ptr[PTBL])
380 {
381 // Stop the song in case of jumping into a jump
382 if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
383 stopsong();
384 }
385 }
386 if (iptr->ptr[FTBL])
387 {
388 filterptr = iptr->ptr[FTBL];
389 filtertime = 0;
390 if (filterptr)
391 {
392 // Stop the song in case of jumping into a jump
393 if (ltable[FTBL][filterptr-1] == 0xff)
394 stopsong();
395 }
396 }
397 sidreg[0x5+7*c] = iptr->ad;
398 sidreg[0x6+7*c] = iptr->sr;
399 }
400 }
401
402 // Tick 0 effects
403
404 switch (cptr->newcommand)
405 {
406 case CMD_DONOTHING:
407 cptr->command = 0;
408 cptr->cmddata = iptr->ptr[STBL];
409 break;
410
411 case CMD_PORTAUP:
412 case CMD_PORTADOWN:
413 cptr->vibtime = 0;
414 cptr->command = cptr->newcommand;
415 cptr->cmddata = cptr->newcmddata;
416 break;
417
418 case CMD_TONEPORTA:
419 case CMD_VIBRATO:
420 cptr->command = cptr->newcommand;
421 cptr->cmddata = cptr->newcmddata;
422 break;
423
424 case CMD_SETAD:
425 sidreg[0x5+7*c] = cptr->newcmddata;
426 break;
427
428 case CMD_SETSR:
429 sidreg[0x6+7*c] = cptr->newcmddata;
430 break;
431
432 case CMD_SETWAVE:
433 cptr->wave = cptr->newcmddata;
434 break;
435
436 case CMD_SETWAVEPTR:
437 cptr->ptr[WTBL] = cptr->newcmddata;
438 cptr->wavetime = 0;
439 if (cptr->ptr[WTBL])
440 {
441 // Stop the song in case of jumping into a jump
442 if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
443 stopsong();
444 }
445 break;
446
447 case CMD_SETPULSEPTR:
448 cptr->ptr[PTBL] = cptr->newcmddata;
449 cptr->pulsetime = 0;
450 if (cptr->ptr[PTBL])
451 {
452 // Stop the song in case of jumping into a jump
453 if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
454 stopsong();
455 }
456 break;
457
458 case CMD_SETFILTERPTR:
459 filterptr = cptr->newcmddata;
460 filtertime = 0;
461 if (filterptr)
462 {
463 // Stop the song in case of jumping into a jump
464 if (ltable[FTBL][filterptr-1] == 0xff)
465 stopsong();
466 }
467 break;
468
469 case CMD_SETFILTERCTRL:
470 filterctrl = cptr->newcmddata;
471 if (!filterctrl) filterptr = 0;
472 break;
473
474 case CMD_SETFILTERCUTOFF:
475 filtercutoff = cptr->newcmddata;
476 break;
477
478 case CMD_SETMASTERVOL:
479 if (cptr->newcmddata < 0x10)
480 masterfader = cptr->newcmddata;
481 break;
482
483 case CMD_FUNKTEMPO:
484 if (cptr->newcmddata)
485 {
486 funktable[0] = ltable[STBL][cptr->newcmddata-1]-1;
487 funktable[1] = rtable[STBL][cptr->newcmddata-1]-1;
488 }
489 chn[0].tempo = 0;
490 chn[1].tempo = 0;
491 chn[2].tempo = 0;
492 break;
493
494 case CMD_SETTEMPO:
495 {
496 unsigned char newtempo = cptr->newcmddata & 0x7f;
497
498 if (newtempo >= 3) newtempo--;
499 if (cptr->newcmddata >= 0x80)
500 cptr->tempo = newtempo;
501 else
502 {
503 chn[0].tempo = newtempo;
504 chn[1].tempo = newtempo;
505 chn[2].tempo = newtempo;
506 }
507 }
508 break;
509 }
510 if (cptr->newnote)
511 {
512 cptr->newnote = 0;
513 if (cptr->newcommand != CMD_TONEPORTA) goto NEXTCHN;
514 }
515
516 WAVEEXEC:
517 if (cptr->ptr[WTBL])
518 {
519 unsigned char wave = ltable[WTBL][cptr->ptr[WTBL]-1];
520 unsigned char note = rtable[WTBL][cptr->ptr[WTBL]-1];
521
522 if (wave > WAVELASTDELAY)
523 {
524 // Normal waveform values
525 if (wave < WAVESILENT) cptr->wave = wave;
526 // Values without waveform selected
527 if ((wave >= WAVESILENT) && (wave <= WAVELASTSILENT)) cptr->wave = wave & 0xf;
528 // Command execution from wavetable
529 if ((wave >= WAVECMD) && (wave <= WAVELASTCMD))
530 {
531 unsigned char param = rtable[WTBL][cptr->ptr[WTBL]-1];
532 switch (wave & 0xf)
533 {
534 case CMD_DONOTHING:
535 case CMD_SETWAVEPTR:
536 case CMD_FUNKTEMPO:
537 stopsong();
538 break;
539
540 case CMD_PORTAUP:
541 {
542 unsigned short speed = 0;
543 if (param)
544 {
545 speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
546 }
547 if (speed >= 0x8000)
548 {
549 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
550 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
551 speed >>= rtable[STBL][param-1];
552 }
553 cptr->freq += speed;
554 }
555 break;
556
557 case CMD_PORTADOWN:
558 {
559 unsigned short speed = 0;
560 if (param)
561 {
562 speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
563 }
564 if (speed >= 0x8000)
565 {
566 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
567 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
568 speed >>= rtable[STBL][param-1];
569 }
570 cptr->freq -= speed;
571 }
572 break;
573
574 case CMD_TONEPORTA:
575 {
576 unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8);
577 unsigned short speed = 0;
578
579 if (!param)
580 {
581 cptr->freq = targetfreq;
582 cptr->vibtime = 0;
583 }
584 else
585 {
586 speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
587 if (speed >= 0x8000)
588 {
589 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
590 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
591 speed >>= rtable[STBL][param-1];
592 }
593 if (cptr->freq < targetfreq)
594 {
595 cptr->freq += speed;
596 if (cptr->freq > targetfreq)
597 {
598 cptr->freq = targetfreq;
599 cptr->vibtime = 0;
600 }
601 }
602 if (cptr->freq > targetfreq)
603 {
604 cptr->freq -= speed;
605 if (cptr->freq < targetfreq)
606 {
607 cptr->freq = targetfreq;
608 cptr->vibtime = 0;
609 }
610 }
611 }
612 }
613 break;
614
615 case CMD_VIBRATO:
616 {
617 unsigned short speed = 0;
618 unsigned char cmpvalue = 0;
619
620 if (param)
621 {
622 cmpvalue = ltable[STBL][param-1];
623 speed = rtable[STBL][param-1];
624 }
625 if (cmpvalue >= 0x80)
626 {
627 cmpvalue &= 0x7f;
628 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
629 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
630 speed >>= rtable[STBL][param-1];
631 }
632
633 if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue))
634 cptr->vibtime ^= 0xff;
635 cptr->vibtime += 0x02;
636 if (cptr->vibtime & 0x01)
637 cptr->freq -= speed;
638 else
639 cptr->freq += speed;
640 }
641 break;
642
643 case CMD_SETAD:
644 sidreg[0x5+7*c] = param;
645 break;
646
647 case CMD_SETSR:
648 sidreg[0x6+7*c] = param;;
649 break;
650
651 case CMD_SETWAVE:
652 cptr->wave = param;
653 break;
654
655 case CMD_SETPULSEPTR:
656 cptr->ptr[PTBL] = param;
657 cptr->pulsetime = 0;
658 if (cptr->ptr[PTBL])
659 {
660 // Stop the song in case of jumping into a jump
661 if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
662 stopsong();
663 }
664 break;
665
666 case CMD_SETFILTERPTR:
667 filterptr = param;
668 filtertime = 0;
669 if (filterptr)
670 {
671 // Stop the song in case of jumping into a jump
672 if (ltable[FTBL][filterptr-1] == 0xff)
673 stopsong();
674 }
675 break;
676
677 case CMD_SETFILTERCTRL:
678 filterctrl = param;
679 if (!filterctrl) filterptr = 0;
680 break;
681
682 case CMD_SETFILTERCUTOFF:
683 filtercutoff = param;
684 break;
685
686 case CMD_SETMASTERVOL:
687 if (param < 0x10)
688 masterfader = param;
689 break;
690 }
691 }
692 }
693 else
694 {
695 // Wavetable delay
696 if (cptr->wavetime != wave)
697 {
698 cptr->wavetime++;
699 goto TICKNEFFECTS;
700 }
701 }
702
703 cptr->wavetime = 0;
704 cptr->ptr[WTBL]++;
705 // Wavetable jump
706 if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
707 {
708 cptr->ptr[WTBL] = rtable[WTBL][cptr->ptr[WTBL]-1];
709 }
710
711 if ((wave >= WAVECMD) && (wave <= WAVELASTCMD))
712 goto PULSEEXEC;
713
714 if (note != 0x80)
715 {
716 if (note < 0x80)
717 note += cptr->note;
718 note &= 0x7f;
719 cptr->freq = freqtbllo[note] | (freqtblhi[note]<<8);
720 cptr->vibtime = 0;
721 cptr->lastnote = note;
722 goto PULSEEXEC;
723 }
724 }
725
726 // Tick N command
727 TICKNEFFECTS:
728 if ((!optimizerealtime) || (cptr->tick))
729 {
730 switch(cptr->command)
731 {
732 case CMD_PORTAUP:
733 {
734 unsigned short speed = 0;
735 if (cptr->cmddata)
736 {
737 speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
738 }
739 if (speed >= 0x8000)
740 {
741 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
742 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
743 speed >>= rtable[STBL][cptr->cmddata-1];
744 }
745 cptr->freq += speed;
746 }
747 break;
748
749 case CMD_PORTADOWN:
750 {
751 unsigned short speed = 0;
752 if (cptr->cmddata)
753 {
754 speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
755 }
756 if (speed >= 0x8000)
757 {
758 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
759 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
760 speed >>= rtable[STBL][cptr->cmddata-1];
761 }
762 cptr->freq -= speed;
763 }
764 break;
765
766 case CMD_DONOTHING:
767 if ((!cptr->cmddata) || (!cptr->vibdelay))
768 break;
769 if (cptr->vibdelay > 1)
770 {
771 cptr->vibdelay--;
772 break;
773 }
774 case CMD_VIBRATO:
775 {
776 unsigned short speed = 0;
777 unsigned char cmpvalue = 0;
778
779 if (cptr->cmddata)
780 {
781 cmpvalue = ltable[STBL][cptr->cmddata-1];
782 speed = rtable[STBL][cptr->cmddata-1];
783 }
784 if (cmpvalue >= 0x80)
785 {
786 cmpvalue &= 0x7f;
787 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
788 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
789 speed >>= rtable[STBL][cptr->cmddata-1];
790 }
791
792 if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue))
793 cptr->vibtime ^= 0xff;
794 cptr->vibtime += 0x02;
795 if (cptr->vibtime & 0x01)
796 cptr->freq -= speed;
797 else
798 cptr->freq += speed;
799 }
800 break;
801
802 case CMD_TONEPORTA:
803 {
804 unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8);
805 unsigned short speed = 0;
806
807 if (!cptr->cmddata)
808 {
809 cptr->freq = targetfreq;
810 cptr->vibtime = 0;
811 }
812 else
813 {
814 speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
815 if (speed >= 0x8000)
816 {
817 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
818 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
819 speed >>= rtable[STBL][cptr->cmddata-1];
820 }
821 if (cptr->freq < targetfreq)
822 {
823 cptr->freq += speed;
824 if (cptr->freq > targetfreq)
825 {
826 cptr->freq = targetfreq;
827 cptr->vibtime = 0;
828 }
829 }
830 if (cptr->freq > targetfreq)
831 {
832 cptr->freq -= speed;
833 if (cptr->freq < targetfreq)
834 {
835 cptr->freq = targetfreq;
836 cptr->vibtime = 0;
837 }
838 }
839 }
840 }
841 break;
842 }
843 }
844
845 PULSEEXEC:
846 if (optimizepulse)
847 {
848 if ((songinit != PLAY_STOPPED) && (cptr->tick == cptr->gatetimer)) goto GETNEWNOTES;
849 }
850
851 if (cptr->ptr[PTBL])
852 {
853 // Skip pulse when sequencer has been executed
854 if (optimizepulse)
855 {
856 if ((!cptr->tick) && (!cptr->pattptr)) goto NEXTCHN;
857 }
858
859 // Pulsetable jump
860 if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
861 {
862 cptr->ptr[PTBL] = rtable[PTBL][cptr->ptr[PTBL]-1];
863 if (!cptr->ptr[PTBL]) goto PULSEEXEC;
864 }
865
866 if (!cptr->pulsetime)
867 {
868 // Set pulse
869 if (ltable[PTBL][cptr->ptr[PTBL]-1] >= 0x80)
870 {
871 cptr->pulse = (ltable[PTBL][cptr->ptr[PTBL]-1] & 0xf) << 8;
872 cptr->pulse |= rtable[PTBL][cptr->ptr[PTBL]-1];
873 cptr->ptr[PTBL]++;
874 }
875 else
876 {
877 cptr->pulsetime = ltable[PTBL][cptr->ptr[PTBL]-1];
878 }
879 }
880 // Pulse modulation
881 if (cptr->pulsetime)
882 {
883 unsigned char speed = rtable[PTBL][cptr->ptr[PTBL]-1];
884 if (speed < 0x80)
885 {
886 cptr->pulse += speed;
887 cptr->pulse &= 0xfff;
888 }
889 else
890 {
891 cptr->pulse += speed;
892 cptr->pulse -= 0x100;
893 cptr->pulse &= 0xfff;
894 }
895 cptr->pulsetime--;
896 if (!cptr->pulsetime) cptr->ptr[PTBL]++;
897 }
898 }
899 if ((songinit == PLAY_STOPPED) || (cptr->tick != cptr->gatetimer)) goto NEXTCHN;
900
901 // New notes processing
902 GETNEWNOTES:
903 {
904 unsigned char newnote;
905
906 newnote = pattern[cptr->pattnum][cptr->pattptr];
907 if (pattern[cptr->pattnum][cptr->pattptr+1])
908 cptr->instr = pattern[cptr->pattnum][cptr->pattptr+1];
909 cptr->newcommand = pattern[cptr->pattnum][cptr->pattptr+2];
910 cptr->newcmddata = pattern[cptr->pattnum][cptr->pattptr+3];
911 cptr->pattptr += 4;
912 if (pattern[cptr->pattnum][cptr->pattptr] == ENDPATT)
913 cptr->pattptr = 0x7fffffff;
914
915 if (newnote == KEYOFF)
916 cptr->gate = 0xfe;
917 if (newnote == KEYON)
918 cptr->gate = 0xff;
919 if (newnote <= LASTNOTE)
920 {
921 cptr->newnote = newnote+cptr->trans;
922 if ((cptr->newcommand) != CMD_TONEPORTA)
923 {
924 if (!(instr[cptr->instr].gatetimer & 0x40))
925 {
926 cptr->gate = 0xfe;
927 if (!(instr[cptr->instr].gatetimer & 0x80))
928 {
929 sidreg[0x5+7*c] = adparam>>8;
930 sidreg[0x6+7*c] = adparam&0xff;
931 }
932 }
933 }
934 }
935 }
936 NEXTCHN:
937 if (cptr->mute)
938 sidreg[0x4+7*c] = cptr->wave = 0x08;
939 else
940 {
941 sidreg[0x0+7*c] = cptr->freq & 0xff;
942 sidreg[0x1+7*c] = cptr->freq >> 8;
943 sidreg[0x2+7*c] = cptr->pulse & 0xfe;
944 sidreg[0x3+7*c] = cptr->pulse >> 8;
945 sidreg[0x4+7*c] = cptr->wave & cptr->gate;
946 }
947 cptr++;
948 }
949 }
950 if (songinit != PLAY_STOPPED) incrementtime();
951 }
952
sequencer(int c,CHN * cptr)953 void sequencer(int c, CHN *cptr)
954 {
955 if ((songinit != PLAY_STOPPED) && (cptr->pattptr == 0x7fffffff))
956 {
957 cptr->pattptr = startpattpos * 4;
958 if (!cptr->advance) goto SEQDONE;
959 // Song loop
960 if (songorder[psnum][c][cptr->songptr] == LOOPSONG)
961 {
962 cptr->songptr = songorder[psnum][c][cptr->songptr+1];
963 if (cptr->songptr >= songlen[psnum][c])
964 {
965 stopsong();
966 cptr->songptr = 0;
967 goto SEQDONE;
968 }
969 }
970 // Transpose
971 if ((songorder[psnum][c][cptr->songptr] >= TRANSDOWN) && (songorder[psnum][c][cptr->songptr] < LOOPSONG))
972 {
973 cptr->trans = songorder[psnum][c][cptr->songptr]-TRANSUP;
974 cptr->songptr++;
975 }
976 // Repeat
977 if ((songorder[psnum][c][cptr->songptr] >= REPEAT) && (songorder[psnum][c][cptr->songptr] < TRANSDOWN))
978 {
979 cptr->repeat = songorder[psnum][c][cptr->songptr]-REPEAT;
980 cptr->songptr++;
981 }
982 // Pattern number
983 cptr->pattnum = songorder[psnum][c][cptr->songptr];
984 if (cptr->repeat)
985 cptr->repeat--;
986 else
987 cptr->songptr++;
988
989 // Check for illegal pattern now
990 if (cptr->pattnum >= MAX_PATT)
991 {
992 stopsong();
993 cptr->pattnum = 0;
994 }
995 if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4))
996 cptr->pattptr = 0;
997
998 // Check for playback endpos
999 if ((lastsonginit != PLAY_BEGINNING) && (esend[c] > 0) && (esend[c] > espos[c]) && (cptr->songptr > esend[c]) && (espos[c] < songlen[psnum][c]))
1000 cptr->songptr = espos[c];
1001 }
1002 SEQDONE: {}
1003 }
1004