1 //
2 // GOATTRACKER v2 table editor
3 //
4 
5 #define GTABLE_C
6 
7 #include "goattrk2.h"
8 
9 unsigned char ltablecopybuffer[MAX_TABLELEN];
10 unsigned char rtablecopybuffer[MAX_TABLELEN];
11 int tablecopyrows = 0;
12 
13 int etview[MAX_TABLES];
14 int etnum;
15 int etpos;
16 int etcolumn;
17 int etlock = 1;
18 int etmarknum = -1;
19 int etmarkstart;
20 int etmarkend;
21 
tablecommands(void)22 void tablecommands(void)
23 {
24   int c;
25 
26   switch(rawkey)
27   {
28     case KEY_Q:
29     if ((shiftpressed) && (etnum == STBL))
30     {
31       int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos];
32       speed *= 34716;
33       speed /= 32768;
34       if (speed > 65535) speed = 65535;
35 
36       ltable[etnum][etpos] = speed >> 8;
37       rtable[etnum][etpos] = speed & 0xff;
38     }
39     break;
40 
41     case KEY_A:
42     if ((shiftpressed) && (etnum == STBL))
43     {
44       int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos];
45       speed *= 30929;
46       speed /= 32768;
47 
48       ltable[etnum][etpos] = speed >> 8;
49       rtable[etnum][etpos] = speed & 0xff;
50     }
51     break;
52 
53     case KEY_W:
54     if ((shiftpressed) && (etnum == STBL))
55     {
56       int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos];
57       speed *= 2;
58       if (speed > 65535) speed = 65535;
59 
60       ltable[etnum][etpos] = speed >> 8;
61       rtable[etnum][etpos] = speed & 0xff;
62     }
63     if ((shiftpressed) && ((etnum == PTBL) || (etnum == FTBL)) && (ltable[etnum][etpos] < 0x80))
64     {
65       int speed = (signed char)(rtable[etnum][etpos]);
66       speed *= 2;
67 
68       if (speed > 127) speed = 127;
69       if (speed < -128) speed = -128;
70       rtable[etnum][etpos] = speed;
71     }
72     break;
73 
74     case KEY_S:
75     if ((shiftpressed) && (etnum == STBL))
76     {
77       int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos];
78       speed /= 2;
79 
80       ltable[etnum][etpos] = speed >> 8;
81       rtable[etnum][etpos] = speed & 0xff;
82     }
83     if ((shiftpressed) && ((etnum == PTBL) || (etnum == FTBL)) && (ltable[etnum][etpos] < 0x80))
84     {
85       int speed = (signed char)(rtable[etnum][etpos]);
86       speed /= 2;
87 
88       rtable[etnum][etpos] = speed;
89     }
90     break;
91 
92     case KEY_SPACE:
93     if (!shiftpressed)
94       playtestnote(FIRSTNOTE + epoctave * 12, einum, epchn);
95     else
96       releasenote(epchn);
97     break;
98 
99     case KEY_RIGHT:
100     etcolumn++;
101     if (etcolumn > 3)
102     {
103       etpos -= etview[etnum];
104       etcolumn = 0;
105       etnum++;
106       if (etnum >= MAX_TABLES) etnum = 0;
107       etpos += etview[etnum];
108     }
109     if (shiftpressed) etmarknum = -1;
110     break;
111 
112     case KEY_LEFT:
113     etcolumn--;
114     if (etcolumn < 0)
115     {
116       etpos -= etview[etnum];
117       etcolumn = 3;
118       etnum--;
119       if (etnum < 0) etnum = MAX_TABLES - 1;
120       etpos += etview[etnum];
121     }
122     if (shiftpressed) etmarknum = -1;
123     break;
124 
125     case KEY_HOME:
126     while (etpos != 0) tableup();
127     break;
128 
129     case KEY_END:
130     while (etpos != MAX_TABLELEN-1) tabledown();
131     break;
132 
133     case KEY_PGUP:
134     for (c = 0; c < PGUPDNREPEAT; c++) tableup();
135     break;
136 
137     case KEY_PGDN:
138     for (c = 0; c < PGUPDNREPEAT; c++) tabledown();
139     break;
140 
141     case KEY_UP:
142     tableup();
143     break;
144 
145     case KEY_DOWN:
146     tabledown();
147     break;
148 
149     case KEY_X:
150     case KEY_C:
151     if (shiftpressed)
152     {
153       if (etmarknum != -1)
154       {
155         int d = 0;
156         if (etmarkstart <= etmarkend)
157         {
158           for (c = etmarkstart; c <= etmarkend; c++)
159           {
160             ltablecopybuffer[d] = ltable[etmarknum][c];
161             rtablecopybuffer[d] = rtable[etmarknum][c];
162             if (rawkey == KEY_X)
163             {
164               ltable[etmarknum][c] = 0;
165               rtable[etmarknum][c] = 0;
166             }
167             d++;
168           }
169         }
170         else
171         {
172           for (c = etmarkend; c <= etmarkstart; c++)
173           {
174             ltablecopybuffer[d] = ltable[etmarknum][c];
175             rtablecopybuffer[d] = rtable[etmarknum][c];
176             if (rawkey == KEY_X)
177             {
178               ltable[etmarknum][c] = 0;
179               rtable[etmarknum][c] = 0;
180             }
181             d++;
182           }
183         }
184         tablecopyrows = d;
185       }
186       etmarknum = -1;
187     }
188     break;
189 
190     case KEY_V:
191     if (shiftpressed)
192     {
193       if (tablecopyrows)
194       {
195         for (c = 0; c < tablecopyrows; c++)
196         {
197           ltable[etnum][etpos] = ltablecopybuffer[c];
198           rtable[etnum][etpos] = rtablecopybuffer[c];
199           etpos++;
200           if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1;
201         }
202       }
203     }
204     break;
205 
206     case KEY_O:
207     if (shiftpressed) optimizetable(etnum);
208     break;
209 
210     case KEY_U:
211     if (shiftpressed)
212     {
213       etlock ^= 1;
214       validatetableview();
215     }
216     break;
217 
218     case KEY_R:
219     if (etnum == WTBL)
220     {
221       if (ltable[etnum][etpos] != 0xff)
222       {
223         // Convert absolute pitch to relative pitch or vice versa
224         int basenote = epoctave * 12;
225         int note = rtable[etnum][etpos];
226 
227         if (note >= 0x80)
228         {
229           note -= basenote;
230           note &= 0x7f;
231         }
232         else
233         {
234           note += basenote;
235           note |= 0x80;
236         }
237 
238         rtable[etnum][etpos] = note;
239       }
240     }
241 
242     case KEY_L:
243     if (etnum == PTBL)
244     {
245       int c;
246       int currentpulse = -1;
247       int targetpulse = ltable[etnum][etpos] << 4;
248       int speed = rtable[etnum][etpos];
249       int time;
250       int steps;
251 
252       if (!speed) break;
253 
254       // Follow the chain of pulse commands backwards to the nearest set command so we know what current pulse is
255       for (c = etpos-1; c >= 0; c--)
256       {
257         if (ltable[etnum][c] == 0xff) break;
258         if (ltable[etnum][c] >= 0x80)
259         {
260           currentpulse = (ltable[etnum][c] << 8) | rtable[etnum][c];
261           currentpulse &= 0xfff;
262           break;
263         }
264       }
265       if (currentpulse == -1) break;
266 
267       // Then follow the chain of modulation steps
268       for (; c < etpos; c++)
269       {
270         if (ltable[etnum][c] < 0x80)
271         {
272           currentpulse += ltable[etnum][c] * (rtable[etnum][c] & 0xff);
273           if (rtable[etnum][c] >= 0x80) currentpulse -= 256 * ltable[etnum][c];
274           currentpulse &= 0xfff;
275         }
276       }
277 
278       time = abs(targetpulse - currentpulse) / speed;
279       if (speed < 128)
280         steps = (time + 126) / 127;
281       else
282         steps = time;
283 
284       if (!steps) break;
285       if (etpos + steps > MAX_TABLELEN) break;
286       if (targetpulse < currentpulse) speed = -speed;
287 
288       // Make room in the table
289       for (c = steps; c > 1; c--) inserttable(etnum, etpos, 1);
290 
291       while (time)
292       {
293         if (abs(speed) < 128)
294         {
295           if (time < 127) ltable[etnum][etpos] = time;
296             else ltable[etnum][etpos] = 127;
297           rtable[etnum][etpos] = speed;
298           time -= ltable[etnum][etpos];
299           etpos++;
300         }
301         else
302         {
303           currentpulse += speed;
304           ltable[etnum][etpos] = 0x80 | ((currentpulse >> 8) & 0xf);
305           rtable[etnum][etpos] = currentpulse & 0xff;
306           time--;
307           etpos++;
308         }
309       }
310     }
311     if (etnum == FTBL)
312     {
313       int c;
314       int currentfilter = -1;
315       int targetfilter = ltable[etnum][etpos];
316       int speed = rtable[etnum][etpos] & 0x7f;
317       int time;
318       int steps;
319 
320       if (!speed) break;
321 
322       // Follow the chain of filter commands backwards to the nearest set command so we know what current pulse is
323       for (c = etpos-1; c >= 0; c--)
324       {
325         if (ltable[etnum][c] == 0xff) break;
326         if (ltable[etnum][c] == 0x00)
327         {
328           currentfilter = rtable[etnum][c];
329           break;
330         }
331       }
332       if (currentfilter == -1) break;
333 
334       // Then follow the chain of modulation steps
335       for (; c < etpos; c++)
336       {
337         if (ltable[etnum][c] < 0x80)
338         {
339           currentfilter += ltable[etnum][c] * rtable[etnum][c];
340           currentfilter &= 0xff;
341         }
342       }
343 
344       time = abs(targetfilter - currentfilter) / speed;
345       steps = (time + 126) / 127;
346       if (!steps) break;
347       if (etpos + steps > MAX_TABLELEN) break;
348       if (targetfilter < currentfilter) speed = -speed;
349 
350       // Make room in the table
351       for (c = steps; c > 1; c--) inserttable(etnum, etpos, 1);
352 
353       while (time)
354       {
355         if (time < 127) ltable[etnum][etpos] = time;
356           else ltable[etnum][etpos] = 127;
357         rtable[etnum][etpos] = speed;
358         time -= ltable[etnum][etpos];
359         etpos++;
360       }
361     }
362     break;
363 
364     case KEY_N:
365     if (shiftpressed)
366     {
367       switch (etnum)
368       {
369         // Negate pulse or filter speed
370         case FTBL:
371         if (!ltable[etnum][etpos]) break;
372         case PTBL:
373         if (ltable[etnum][etpos] < 0x80)
374           rtable[etnum][etpos] = (rtable[etnum][etpos] ^ 0xff) + 1;
375         break;
376 
377         // Negate relative note
378         case WTBL:
379         if ((ltable[etnum][etpos] != 0xff) && (rtable[etnum][etpos] < 0x80))
380           rtable[etnum][etpos] = (0x80 - rtable[etnum][etpos]) & 0x7f;
381         break;
382       }
383     }
384     break;
385 
386     case KEY_DEL:
387     deletetable(etnum, etpos);
388     break;
389 
390     case KEY_INS:
391     inserttable(etnum, etpos, shiftpressed);
392     break;
393 
394     case KEY_ENTER:
395     if (etnum == WTBL)
396     {
397       int table = -1;
398       int mstmode = MST_PORTAMENTO;
399 
400       switch (ltable[etnum][etpos])
401       {
402         case WAVECMD + CMD_PORTAUP:
403         case WAVECMD + CMD_PORTADOWN:
404         case WAVECMD + CMD_TONEPORTA:
405         table = STBL;
406         break;
407 
408         case WAVECMD + CMD_VIBRATO:
409         table = STBL;
410         mstmode = finevibrato;
411         break;
412 
413         case WAVECMD + CMD_FUNKTEMPO:
414         table = STBL;
415         mstmode = MST_FUNKTEMPO;
416         break;
417 
418         case WAVECMD + CMD_SETPULSEPTR:
419         table = PTBL;
420         break;
421 
422         case WAVECMD + CMD_SETFILTERPTR:
423         table = FTBL;
424         break;
425       }
426       switch (table)
427       {
428         default:
429         editmode = EDIT_INSTRUMENT;
430         eipos = etnum + 2;
431         return;
432 
433         case STBL:
434         if (rtable[etnum][etpos])
435         {
436           if (!shiftpressed)
437           {
438             gototable(STBL, rtable[etnum][etpos] - 1);
439             return;
440           }
441           else
442           {
443             int oldeditpos = etpos;
444             int oldeditcolumn = etcolumn;
445             int pos = makespeedtable(rtable[etnum][etpos], mstmode, 1);
446             gototable(WTBL, oldeditpos);
447             etcolumn = oldeditcolumn;
448 
449             rtable[etnum][etpos] = pos + 1;
450             return;
451           }
452         }
453         else
454         {
455           int pos = findfreespeedtable();
456           if (pos >= 0)
457           {
458             rtable[etnum][etpos] = pos + 1;
459             gototable(STBL, pos);
460             return;
461           }
462         }
463         break;
464 
465         case PTBL:
466         case FTBL:
467         if (rtable[etnum][etpos])
468         {
469           gototable(table, rtable[etnum][etpos] - 1);
470           return;
471         }
472         else
473         {
474           if (shiftpressed)
475           {
476             int pos = gettablelen(table);
477             if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1;
478             rtable[etnum][etpos] = pos + 1;
479             gototable(table, pos);
480             return;
481           }
482         }
483       }
484     }
485     else
486     {
487       editmode = EDIT_INSTRUMENT;
488       eipos = etnum + 2;
489       return;
490     }
491     break;
492 
493     case KEY_APOST2:
494     if (shiftpressed)
495     {
496       etpos -= etview[etnum];
497       etnum--;
498       if (etnum < 0) etnum = MAX_TABLES-1;
499       etpos += etview[etnum];
500     }
501     else
502     {
503       etpos -= etview[etnum];
504       etnum++;
505       if (etnum >= MAX_TABLES) etnum = 0;
506       etpos += etview[etnum];
507     }
508   }
509 
510   if (hexnybble >= 0)
511   {
512     switch(etcolumn)
513     {
514       case 0:
515       ltable[etnum][etpos] &= 0x0f;
516       ltable[etnum][etpos] |= hexnybble << 4;
517       break;
518       case 1:
519       ltable[etnum][etpos] &= 0xf0;
520       ltable[etnum][etpos] |= hexnybble;
521       break;
522       case 2:
523       rtable[etnum][etpos] &= 0x0f;
524       rtable[etnum][etpos] |= hexnybble << 4;
525       break;
526       case 3:
527       rtable[etnum][etpos] &= 0xf0;
528       rtable[etnum][etpos] |= hexnybble;
529       break;
530     }
531     etcolumn++;
532     if (etcolumn > 3)
533     {
534       etcolumn = 0;
535       etpos++;
536       if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1;
537     }
538   }
539 
540   validatetableview();
541 }
542 
deletetable(int num,int pos)543 void deletetable(int num, int pos)
544 {
545   int c, d;
546 
547   // Shift tablepointers in instruments
548   for (c = 1; c < MAX_INSTR; c++)
549   {
550     if ((instr[c].ptr[num]-1) > pos) instr[c].ptr[num]--;
551   }
552 
553   // Shift tablepointers in wavetable commands
554   for (c = 0; c < MAX_TABLELEN; c++)
555   {
556     if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD))
557     {
558       int cmd = ltable[WTBL][c] & 0xf;
559 
560       if (num < STBL)
561       {
562         if (cmd == CMD_SETWAVEPTR+num)
563         {
564           if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]--;
565         }
566       }
567       else
568       {
569         if ((cmd == CMD_FUNKTEMPO) || ((cmd >= CMD_PORTAUP) && (cmd <= CMD_VIBRATO)))
570         {
571           if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]--;
572         }
573       }
574     }
575   }
576 
577   // Shift tablepointers in patterns
578   for (c = 0; c < MAX_PATT; c++)
579   {
580     for (d = 0; d <= MAX_PATTROWS; d++)
581     {
582       if (num < STBL)
583       {
584         if (pattern[c][d*4+2] == CMD_SETWAVEPTR+num)
585         {
586           if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]--;
587         }
588       }
589       else
590       {
591         if ((pattern[c][d*4+2] == CMD_FUNKTEMPO) ||
592            ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO)))
593         {
594           if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]--;
595         }
596       }
597     }
598   }
599 
600   // Shift jumppointers in the table itself
601   for (c = 0; c < MAX_TABLELEN; c++)
602   {
603     if (num != STBL)
604     {
605       if (ltable[num][c] == 0xff)
606         if ((rtable[num][c]-1) > pos) rtable[num][c]--;
607     }
608   }
609 
610   for (c = pos; c < MAX_TABLELEN; c++)
611   {
612     if (c+1 < MAX_TABLELEN)
613     {
614       ltable[num][c] = ltable[num][c+1];
615       rtable[num][c] = rtable[num][c+1];
616     }
617     else
618     {
619       ltable[num][c] = 0;
620       rtable[num][c] = 0;
621     }
622   }
623 }
624 
inserttable(int num,int pos,int mode)625 void inserttable(int num, int pos, int mode)
626 {
627   int c, d;
628 
629   // Shift tablepointers in instruments
630   for (c = 1; c < MAX_INSTR; c++)
631   {
632     if (!mode)
633     {
634       if ((instr[c].ptr[num]-1) >= pos) instr[c].ptr[num]++;
635     }
636     else
637     {
638       if ((instr[c].ptr[num]-1) > pos) instr[c].ptr[num]++;
639     }
640   }
641 
642   // Shift tablepointers in wavetable commands
643   for (c = 0; c < MAX_TABLELEN; c++)
644   {
645     if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD))
646     {
647       int cmd = ltable[WTBL][c] & 0xf;
648 
649       if (num < STBL)
650       {
651         if (cmd == CMD_SETWAVEPTR+num)
652         {
653           if (!mode)
654           {
655             if ((rtable[WTBL][c]-1) >= pos) rtable[WTBL][c]++;
656           }
657           else
658           {
659             if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]++;
660           }
661         }
662       }
663       else
664       {
665         if ((cmd == CMD_FUNKTEMPO) || ((cmd >= CMD_PORTAUP) && (cmd <= CMD_VIBRATO)))
666         {
667           if (!mode)
668           {
669             if ((rtable[WTBL][c]-1) >= pos) rtable[WTBL][c]++;
670           }
671           else
672           {
673             if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]++;
674           }
675         }
676       }
677     }
678   }
679 
680 
681   // Shift tablepointers in patterns
682   for (c = 0; c < MAX_PATT; c++)
683   {
684     for (d = 0; d <= MAX_PATTROWS; d++)
685     {
686       if (num < STBL)
687       {
688         if (pattern[c][d*4+2] == CMD_SETWAVEPTR+num)
689         {
690           if (!mode)
691           {
692             if ((pattern[c][d*4+3]-1) >= pos) pattern[c][d*4+3]++;
693           }
694           else
695           {
696             if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]++;
697           }
698         }
699       }
700       else
701       {
702         if ((pattern[c][d*4+2] == CMD_FUNKTEMPO) ||
703            ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO)))
704         {
705           if (!mode)
706           {
707             if ((pattern[c][d*4+3]-1) >= pos) pattern[c][d*4+3]++;
708           }
709           else
710           {
711             if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]++;
712           }
713         }
714       }
715     }
716   }
717 
718   // Shift jumppointers in the table itself
719   if (num != STBL)
720   {
721     for (c = 0; c < MAX_TABLELEN; c++)
722     {
723       if (ltable[num][c] == 0xff)
724       {
725         if (!mode)
726         {
727           if ((rtable[num][c]-1) >= pos) rtable[num][c]++;
728         }
729         else
730         {
731           if ((rtable[num][c]-1) > pos) rtable[num][c]++;
732         }
733       }
734     }
735   }
736 
737   for (c = MAX_TABLELEN-1; c >= pos; c--)
738   {
739     if (c > pos)
740     {
741       ltable[num][c] = ltable[num][c-1];
742       rtable[num][c] = rtable[num][c-1];
743     }
744     else
745     {
746       if ((num == WTBL) && (mode == 1))
747       {
748         ltable[num][c] = 0xe9;
749         rtable[num][c] = 0;
750       }
751       else
752       {
753         ltable[num][c] = 0;
754         rtable[num][c] = 0;
755       }
756     }
757   }
758 }
759 
gettablelen(int num)760 int gettablelen(int num)
761 {
762   int c;
763 
764   for (c = MAX_TABLELEN-1; c >= 0; c--)
765   {
766     if (ltable[num][c] | rtable[num][c]) break;
767   }
768   return c+1;
769 }
770 
gettablepartlen(int num,int pos)771 int gettablepartlen(int num, int pos)
772 {
773   int c;
774 
775   if (pos < 0) return 0;
776   if (num == STBL) return 1;
777 
778   for (c = pos; c < MAX_TABLELEN; c++)
779   {
780     if (ltable[num][c] == 0xff)
781     {
782       c++;
783       break;
784     }
785   }
786   return c-pos;
787 }
788 
optimizetable(int num)789 void optimizetable(int num)
790 {
791   int c,d;
792 
793   memset(tableused, 0, sizeof tableused);
794 
795   for (c = 0; c < MAX_PATT; c++)
796   {
797     for (d = 0; d < pattlen[c]; d++)
798     {
799       if ((pattern[c][d*4+2] >= CMD_SETWAVEPTR) && (pattern[c][d*4+2] <= CMD_SETFILTERPTR))
800         exectable(pattern[c][d*4+2] - CMD_SETWAVEPTR, pattern[c][d*4+3]);
801       if ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO))
802         exectable(STBL, pattern[c][d*4+3]);
803       if (pattern[c][d*4+2] == CMD_FUNKTEMPO)
804         exectable(STBL, pattern[c][d*4+3]);
805     }
806   }
807 
808   for (c = 0; c < MAX_INSTR; c++)
809   {
810     for (d = 0; d < MAX_TABLES; d++)
811     {
812       exectable(d, instr[c].ptr[d]);
813     }
814   }
815 
816   for (c = 0; c < MAX_TABLELEN; c++)
817   {
818     if (tableused[WTBL][c+1])
819     {
820       if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD))
821       {
822         d = -1;
823 
824         switch(ltable[WTBL][c] - WAVECMD)
825         {
826           case CMD_PORTAUP:
827           case CMD_PORTADOWN:
828           case CMD_TONEPORTA:
829           case CMD_VIBRATO:
830           d = STBL;
831           break;
832 
833           case CMD_SETPULSEPTR:
834           d = PTBL;
835            break;
836 
837            case CMD_SETFILTERPTR:
838            d = FTBL;
839           break;
840         }
841 
842         if (d != -1) exectable(d, rtable[WTBL][c]);
843       }
844     }
845   }
846 
847   for (c = MAX_TABLELEN-1; c >= 0; c--)
848   {
849     if ((ltable[num][c]) || (rtable[num][c])) break;
850   }
851   for (; c >= 0; c--)
852   {
853     if (!tableused[num][c+1]) deletetable(num, c);
854   }
855 }
856 
makespeedtable(unsigned data,int mode,int makenew)857 int makespeedtable(unsigned data, int mode, int makenew)
858 {
859   int c;
860   unsigned char l = 0, r = 0;
861 
862   if (!data) return -1;
863 
864   switch (mode)
865   {
866     case MST_NOFINEVIB:
867     l = (data & 0xf0) >> 4;
868     r = (data & 0x0f) << 4;
869     break;
870 
871     case MST_FINEVIB:
872     l = (data & 0x70) >> 4;
873     r = ((data & 0x0f) << 4) | ((data & 0x80) >> 4);
874     break;
875 
876     case MST_FUNKTEMPO:
877     l = (data & 0xf0) >> 4;
878     r = data & 0x0f;
879     break;
880 
881     case MST_PORTAMENTO:
882     l = (data << 2) >> 8;
883     r = (data << 2) & 0xff;
884     break;
885 
886     case MST_RAW:
887     r = data & 0xff;
888     l = data >> 8;
889     break;
890   }
891 
892   if (makenew == 0)
893   {
894     for (c = 0; c < MAX_TABLELEN; c++)
895     {
896       if ((ltable[STBL][c] == l) && (rtable[STBL][c] == r))
897         return c;
898     }
899   }
900 
901   for (c = 0; c < MAX_TABLELEN; c++)
902   {
903     if ((!ltable[STBL][c]) && (!rtable[STBL][c]))
904     {
905       ltable[STBL][c] = l;
906       rtable[STBL][c] = r;
907 
908       settableview(STBL, c);
909       return c;
910     }
911   }
912   return -1;
913 }
914 
deleteinstrtable(int i)915 void deleteinstrtable(int i)
916 {
917   int c,d;
918   int eraseok = 1;
919 
920   for (c = 0; c < MAX_TABLES; c++)
921   {
922     if (instr[i].ptr[c])
923     {
924       int pos = instr[i].ptr[c]-1;
925       int len = gettablepartlen(c, pos);
926 
927       // Check that this table area isn't used by another instrument
928       for (d = 1; d < MAX_INSTR; d++)
929       {
930         if ((d != i) && (instr[d].ptr[c]))
931         {
932           int cmppos = instr[d].ptr[c]-1;
933           if ((cmppos >= pos) && (cmppos < pos+len)) eraseok = 0;
934         }
935       }
936       if (eraseok)
937         while (len--) deletetable(c, pos);
938     }
939   }
940 }
941 
gototable(int num,int pos)942 void gototable(int num, int pos)
943 {
944   editmode = EDIT_TABLES;
945   settableview(num, pos);
946 }
947 
settableview(int num,int pos)948 void settableview(int num, int pos)
949 {
950   etnum = num;
951   etcolumn = 0;
952   etpos = pos;
953 
954   validatetableview();
955 }
956 
settableviewfirst(int num,int pos)957 void settableviewfirst(int num, int pos)
958 {
959   etview[num] = pos;
960   settableview(num, pos);
961 }
validatetableview(void)962 void validatetableview(void)
963 {
964   if (etpos - etview[etnum] < 0)
965     etview[etnum] = etpos;
966   if (etpos - etview[etnum] >= VISIBLETABLEROWS)
967     etview[etnum] = etpos - VISIBLETABLEROWS + 1;
968 
969   // Table view lock?
970   if (etlock)
971   {
972     int c;
973 
974     for (c = 0; c < MAX_TABLES; c++) etview[c] = etview[etnum];
975   }
976 }
977 
tableup(void)978 void tableup(void)
979 {
980   if (shiftpressed)
981   {
982     if ((etmarknum != etnum) || (etpos != etmarkend))
983     {
984       etmarknum = etnum;
985       etmarkstart = etmarkend = etpos;
986     }
987   }
988   etpos--;
989   if (etpos < 0) etpos = 0;
990   if (shiftpressed) etmarkend = etpos;
991 }
992 
tabledown(void)993 void tabledown(void)
994 {
995   if (shiftpressed)
996   {
997     if ((etmarknum != etnum) || (etpos != etmarkend))
998     {
999       etmarknum = etnum;
1000       etmarkstart = etmarkend = etpos;
1001     }
1002   }
1003   etpos++;
1004   if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1;
1005   if (shiftpressed) etmarkend = etpos;
1006 }
1007 
exectable(int num,int ptr)1008 void exectable(int num, int ptr)
1009 {
1010   // Jump error check
1011   if ((num != STBL) && (ptr) && (ptr <= MAX_TABLELEN))
1012   {
1013     if (ltable[num][ptr-1] == 0xff)
1014     {
1015       tableerror = TYPE_JUMP;
1016       return;
1017     }
1018   }
1019 
1020   for (;;)
1021   {
1022     // Exit when table stopped
1023     if (!ptr) break;
1024     // Overflow check
1025     if ((num != STBL) && (ptr > MAX_TABLELEN))
1026     {
1027       tableerror = TYPE_OVERFLOW;
1028       break;
1029     }
1030     // If were already here, exit
1031     if (tableused[num][ptr]) break;
1032     // Mark current position used
1033     tableused[num][ptr] = 1;
1034     // Go to next ptr.
1035     if (num != STBL)
1036     {
1037       if (ltable[num][ptr-1] == 0xff)
1038       {
1039         ptr = rtable[num][ptr-1];
1040       }
1041       else ptr++;
1042     }
1043     else break;
1044   }
1045 }
1046 
findfreespeedtable(void)1047 int findfreespeedtable(void)
1048 {
1049   int c;
1050   for (c = 0; c < MAX_TABLELEN; c++)
1051   {
1052     if ((!ltable[STBL][c]) && (!rtable[STBL][c]))
1053     {
1054       return c;
1055     }
1056   }
1057   return -1;
1058 }
1059 
1060