NOOP, remove trailing tabs/whitespace.
[ardour.git] / libs / ptformat / ptfformat.cc
1 /*
2     Copyright (C) 2015  Damien Zammit
3     Copyright (C) 2015  Robin Gareus
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15 */
16
17 #include "ptfformat.h"
18
19 #include <stdio.h>
20 #include <string>
21 #include <string.h>
22 #include <assert.h>
23
24 using namespace std;
25
26 static const uint32_t baselut[16] = {
27         0xaaaaaaaa, 0xaa955555, 0xa9554aaa, 0xa552a955,
28         0xb56ad5aa, 0x95a95a95, 0x94a5294a, 0x9696b4b5,
29         0xd2d25a5a, 0xd24b6d25, 0xdb6db6da, 0xd9249b6d,
30         0xc9b64d92, 0xcd93264d, 0xccd99b32, 0xcccccccd
31 };
32
33 static const uint32_t xorlut[16] = {
34         0x00000000, 0x00000b00, 0x000100b0, 0x00b0b010,
35         0x010b0b01, 0x0b10b10b, 0x01bb101b, 0x0111bbbb,
36         0x1111bbbb, 0x1bbb10bb, 0x1bb0bb0b, 0xbb0b0bab,
37         0xbab0b0ba, 0xb0abaaba, 0xba0aabaa, 0xbaaaaaaa
38 };
39
40 static uint32_t swapbytes32 (const uint32_t v) {
41         uint32_t rv = 0;
42         rv |= ((v >>  0) & 0xf) << 28;
43         rv |= ((v >>  4) & 0xf) << 24;
44         rv |= ((v >>  8) & 0xf) << 20;
45         rv |= ((v >> 12) & 0xf) << 16;
46         rv |= ((v >> 16) & 0xf) << 12;
47         rv |= ((v >> 20) & 0xf) <<  8;
48         rv |= ((v >> 24) & 0xf) <<  4;
49         rv |= ((v >> 28) & 0xf) <<  0;
50         return rv;
51 }
52
53 static uint64_t gen_secret (int i) {
54         assert (i > 0 && i < 256);
55         int iwrap = i & 0x7f; // wrap at 0x80;
56         uint32_t xor_lo = 0;  // 0x40 flag
57         int idx;              // mirror at 0x40;
58
59         if (iwrap & 0x40) {
60                 xor_lo = 0x1;
61                 idx    = 0x80 - iwrap;
62         } else {
63                 idx    = iwrap;
64         }
65
66         int i16 = (idx >> 1) & 0xf;
67         if (idx & 0x20) {
68                 i16 = 15 - i16;
69         }
70
71         uint32_t lo = baselut [i16];
72         uint32_t xk = xorlut  [i16];
73
74         if (idx & 0x20) {
75                 lo ^= 0xaaaaaaab;
76                 xk ^= 0x10000000;
77         }
78         uint32_t hi = swapbytes32 (lo) ^ xk;
79         return  ((uint64_t)hi << 32) | (lo ^ xor_lo);
80 }
81
82 PTFFormat::PTFFormat() {
83 }
84
85 PTFFormat::~PTFFormat() {
86         if (ptfunxored) {
87                 free(ptfunxored);
88         }
89 }
90
91 bool
92 PTFFormat::foundin(std::string haystack, std::string needle) {
93         size_t found = haystack.find(needle);
94         if (found != std::string::npos) {
95                 return true;
96         } else {
97                 return false;
98         }
99 }
100
101 /* Return values:       0            success
102                         0x01 to 0xff value of missing lut
103                         -1           could not open file as ptf
104 */
105 int
106 PTFFormat::load(std::string path, int64_t targetsr) {
107         FILE *fp;
108         unsigned char xxor[256];
109         unsigned char ct;
110         unsigned char px;
111         uint64_t key;
112         uint16_t i;
113         int j;
114         int inv;
115         unsigned char message;
116
117         if (! (fp = fopen(path.c_str(), "rb"))) {
118                 return -1;
119         }
120
121         fseek(fp, 0, SEEK_END);
122         len = ftell(fp);
123         if (len < 0x40) {
124                 fclose(fp);
125                 return -1;
126         }
127         fseek(fp, 0x40, SEEK_SET);
128         fread(&c0, 1, 1, fp);
129         fread(&c1, 1, 1, fp);
130
131         // For version <= 7 support:
132         version = c0 & 0x0f;
133         c0 = c0 & 0xc0;
134
135         if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
136                 /* Silently fail -- out of memory*/
137                 fclose(fp);
138                 ptfunxored = 0;
139                 return -1;
140         }
141
142         fseek(fp, 0x0, SEEK_SET);
143
144         switch (c0) {
145         case 0x00:
146                 // Success! easy one
147                 xxor[0] = c0;
148                 xxor[1] = c1;
149                 //fprintf(stderr, "%02x %02x", c0, c1);
150
151                 for (i = 2; i < 64; i++) {
152                         xxor[i] = (xxor[i-1] + c1 - c0) & 0xff;
153                         //fprintf(stderr, "%02x ", xxor[i]);
154                 }
155                 px = xxor[0];
156                 fread(&ct, 1, 1, fp);
157                 message = px ^ ct;
158                 ptfunxored[0] = message;
159                 px  = xxor[1];
160                 fread(&ct, 1, 1, fp);
161                 message = px ^ ct;
162                 ptfunxored[1] = message;
163                 i = 2;
164                 j = 2;
165                 while (fread(&ct, 1, 1, fp) != 0) {
166                         if (i%64 == 0) {
167                                 i = 0;
168                         }
169                         message = xxor[i] ^ ct;
170                         ptfunxored[j] = message;
171                         i++;
172                         j++;
173                 }
174                 break;
175         case 0x80:
176                 //Success! easy two
177                 xxor[0] = c0;
178                 xxor[1] = c1;
179                 for (i = 2; i < 256; i++) {
180                         if (i%64 == 0) {
181                                 xxor[i] = c0;
182                         } else {
183                                 xxor[i] = ((xxor[i-1] + c1 - c0) & 0xff);
184                         }
185                 }
186                 for (i = 0; i < 64; i++) {
187                         xxor[i] ^= 0x80;
188                 }
189                 for (i = 128; i < 192; i++) {
190                         xxor[i] ^= 0x80;
191                 }
192                 px = xxor[0];
193                 fread(&ct, 1, 1, fp);
194                 message = px ^ ct;
195                 ptfunxored[0] = message;
196                 px  = xxor[1];
197                 fread(&ct, 1, 1, fp);
198                 message = px ^ ct;
199                 ptfunxored[1] = message;
200                 i = 2;
201                 j = 2;
202                 while (fread(&ct, 1, 1, fp) != 0) {
203                         if (i%256 == 0) {
204                                 i = 0;
205                         }
206                         message = xxor[i] ^ ct;
207                         ptfunxored[j] = message;
208                         i++;
209                         j++;
210                 }
211                 break;
212         case 0x40:
213         case 0xc0:
214                 xxor[0] = c0;
215                 xxor[1] = c1;
216                 for (i = 2; i < 256; i++) {
217                         if (i%64 == 0) {
218                                 xxor[i] = c0;
219                         } else {
220                                 xxor[i] = ((xxor[i-1] + c1 - c0) & 0xff);
221                         }
222                 }
223
224                 key = gen_secret(c1);
225                 for (i = 0; i < 64; i++) {
226                         xxor[i] ^= (((key >> i) & 1) * 2 * 0x40) + 0x40;
227                 }
228                 for (i = 128; i < 192; i++) {
229                         inv = (((key >> (i-128)) & 1) == 1) ? 1 : 3;
230                         xxor[i] ^= (inv * 0x40);
231                 }
232
233                 for (i = 192; i < 256; i++) {
234                         xxor[i] ^= 0x80;
235                 }
236                 px = xxor[0];
237                 fread(&ct, 1, 1, fp);
238                 message = px ^ ct;
239                 ptfunxored[0] = message;
240                 px  = xxor[1];
241                 fread(&ct, 1, 1, fp);
242                 message = px ^ ct;
243                 ptfunxored[1] = message;
244                 i = 2;
245                 j = 2;
246                 while (fread(&ct, 1, 1, fp) != 0) {
247                         if (i%256 == 0) {
248                                 i = 0;
249                         }
250                         message = xxor[i] ^ ct;
251                         ptfunxored[j] = message;
252                         i++;
253                         j++;
254                 }
255                 break;
256                 break;
257         default:
258                 //Should not happen, failed c[0] c[1]
259                 return -1;
260                 break;
261         }
262         fclose(fp);
263         targetrate = targetsr;
264         parse();
265         return 0;
266 }
267
268 void
269 PTFFormat::unxor10(void)
270 {
271         key10a = ptfunxored[0x9f];
272         key10b = ptfunxored[0x9e] - ptfunxored[0x9b];
273         int j, k, currkey;
274
275         k = 0x1000;
276         for (j = k; j < k + 0x1000 && j < len; j++) {
277                 ptfunxored[j] ^= key10a;
278         }
279         k = 0x2000;
280         for (j = k; j < k + 0x1000 && j < len; j++) {
281                 ptfunxored[j] ^= key10b;
282         }
283         currkey = key10b;
284         while (k < len) {
285                 k += 0x1000;
286                 currkey = (key10a + currkey) & 0xff;
287                 for (j = k; j < k + 0x1000 && j < len; j++) {
288                         ptfunxored[j] ^= currkey;
289                 }
290         }
291 }
292
293 void
294 PTFFormat::parse(void) {
295         version = (version == 0) ? ptfunxored[61] : version;
296
297         if (version == 5) {
298                 parse5header();
299                 setrates();
300                 parseaudio5();
301                 parserest5();
302         } else if (version == 7) {
303                 parse7header();
304                 setrates();
305                 parseaudio();
306                 parserest89();
307         } else if (version == 8) {
308                 parse8header();
309                 setrates();
310                 parseaudio();
311                 parserest89();
312         } else if (version == 9) {
313                 parse9header();
314                 setrates();
315                 parseaudio();
316                 parserest89();
317         } else if (version == 10) {
318                 unxor10();
319                 parse10header();
320                 setrates();
321                 parseaudio();
322                 parserest10();
323         } else {
324                 // Should not occur
325         }
326 }
327
328 void
329 PTFFormat::setrates(void) {
330         ratefactor = 1.f;
331         if (sessionrate != 0) {
332                 ratefactor = (float)targetrate / sessionrate;
333         }
334 }
335
336 void
337 PTFFormat::parse5header(void) {
338         int k;
339
340         // Find session sample rate
341         k = 0x100;
342         while (k < len) {
343                 if (            (ptfunxored[k  ] == 0x5a) &&
344                                 (ptfunxored[k+1] == 0x00) &&
345                                 (ptfunxored[k+2] == 0x02)) {
346                         break;
347                 }
348                 k++;
349         }
350
351         sessionrate = 0;
352         sessionrate |= ptfunxored[k+12] << 16;
353         sessionrate |= ptfunxored[k+13] << 8;
354         sessionrate |= ptfunxored[k+14];
355 }
356
357 void
358 PTFFormat::parse7header(void) {
359         int k;
360
361         // Find session sample rate
362         k = 0x100;
363         while (k < len) {
364                 if (            (ptfunxored[k  ] == 0x5a) &&
365                                 (ptfunxored[k+1] == 0x00) &&
366                                 (ptfunxored[k+2] == 0x05)) {
367                         break;
368                 }
369                 k++;
370         }
371
372         sessionrate = 0;
373         sessionrate |= ptfunxored[k+12] << 16;
374         sessionrate |= ptfunxored[k+13] << 8;
375         sessionrate |= ptfunxored[k+14];
376 }
377
378 void
379 PTFFormat::parse8header(void) {
380         int k;
381
382         // Find session sample rate
383         k = 0;
384         while (k < len) {
385                 if (            (ptfunxored[k  ] == 0x5a) &&
386                                 (ptfunxored[k+1] == 0x05)) {
387                         break;
388                 }
389                 k++;
390         }
391
392         sessionrate = 0;
393         sessionrate |= ptfunxored[k+11];
394         sessionrate |= ptfunxored[k+12] << 8;
395         sessionrate |= ptfunxored[k+13] << 16;
396 }
397
398 void
399 PTFFormat::parse9header(void) {
400         int k;
401
402         // Find session sample rate
403         k = 0x100;
404         while (k < len) {
405                 if (            (ptfunxored[k  ] == 0x5a) &&
406                                 (ptfunxored[k+1] == 0x06)) {
407                         break;
408                 }
409                 k++;
410         }
411
412         sessionrate = 0;
413         sessionrate |= ptfunxored[k+11];
414         sessionrate |= ptfunxored[k+12] << 8;
415         sessionrate |= ptfunxored[k+13] << 16;
416 }
417
418 void
419 PTFFormat::parse10header(void) {
420         int k;
421
422         // Find session sample rate
423         k = 0;
424         while (k < len) {
425                 if (            (ptfunxored[k  ] == 0x5a) &&
426                                 (ptfunxored[k+1] == 0x09)) {
427                         break;
428                 }
429                 k++;
430         }
431
432         sessionrate = 0;
433         sessionrate |= ptfunxored[k+11];
434         sessionrate |= ptfunxored[k+12] << 8;
435         sessionrate |= ptfunxored[k+13] << 16;
436 }
437
438 void
439 PTFFormat::parserest5(void) {
440         int i, j, k;
441         int regionspertrack, lengthofname;
442         int startbytes, lengthbytes, offsetbytes;
443         uint16_t tracknumber = 0;
444         uint16_t findex;
445         uint16_t rindex;
446
447         k = 0;
448         for (i = 0; i < 5; i++) {
449                 while (k < len) {
450                         if (            (ptfunxored[k  ] == 0x5a) &&
451                                         (ptfunxored[k+1] == 0x00) &&
452                                         (ptfunxored[k+2] == 0x03)) {
453                                 break;
454                         }
455                         k++;
456                 }
457                 k++;
458         }
459         k--;
460
461         for (i = 0; i < 2; i++) {
462                 while (k > 0) {
463                         if (            (ptfunxored[k  ] == 0x5a) &&
464                                         (ptfunxored[k+1] == 0x00) &&
465                                         (ptfunxored[k+2] == 0x01)) {
466                                 break;
467                         }
468                         k--;
469                 }
470                 k--;
471         }
472         k++;
473
474         rindex = 0;
475         while (k < len) {
476                 if (            (ptfunxored[k  ] == 0xff) &&
477                                 (ptfunxored[k+1] == 0xff)) {
478                         break;
479                 }
480                 while (k < len) {
481                         if (            (ptfunxored[k  ] == 0x5a) &&
482                                         (ptfunxored[k+1] == 0x00) &&
483                                         (ptfunxored[k+2] == 0x01)) {
484                                 break;
485                         }
486                         k++;
487                 }
488
489                 lengthofname = ptfunxored[k+12];
490                 if (ptfunxored[k+13] == 0x5a) {
491                         k++;
492                         break;
493                 }
494                 char name[256] = {0};
495                 for (j = 0; j < lengthofname; j++) {
496                         name[j] = ptfunxored[k+13+j];
497                 }
498                 name[j] = '\0';
499                 regionspertrack = ptfunxored[k+13+j+3];
500                 for (i = 0; i < regionspertrack; i++) {
501                         while (k < len) {
502                                 if (            (ptfunxored[k  ] == 0x5a) &&
503                                                 (ptfunxored[k+1] == 0x00) &&
504                                                 (ptfunxored[k+2] == 0x03)) {
505                                         break;
506                                 }
507                                 k++;
508                         }
509                         j = k+16;
510                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
511                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
512                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
513                         //somethingbytes = (ptfunxored[j+1] & 0xf);
514                         findex = ptfunxored[k+14];
515                         j--;
516                         uint32_t start = 0;
517                         switch (startbytes) {
518                         case 4:
519                                 start |= (uint32_t)(ptfunxored[j+8] << 24);
520                         case 3:
521                                 start |= (uint32_t)(ptfunxored[j+7] << 16);
522                         case 2:
523                                 start |= (uint32_t)(ptfunxored[j+6] << 8);
524                         case 1:
525                                 start |= (uint32_t)(ptfunxored[j+5]);
526                         default:
527                                 break;
528                         }
529                         j+=startbytes;
530                         uint32_t length = 0;
531                         switch (lengthbytes) {
532                         case 4:
533                                 length |= (uint32_t)(ptfunxored[j+8] << 24);
534                         case 3:
535                                 length |= (uint32_t)(ptfunxored[j+7] << 16);
536                         case 2:
537                                 length |= (uint32_t)(ptfunxored[j+6] << 8);
538                         case 1:
539                                 length |= (uint32_t)(ptfunxored[j+5]);
540                         default:
541                                 break;
542                         }
543                         j+=lengthbytes;
544                         uint32_t sampleoffset = 0;
545                         switch (offsetbytes) {
546                         case 4:
547                                 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
548                         case 3:
549                                 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
550                         case 2:
551                                 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
552                         case 1:
553                                 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
554                         default:
555                                 break;
556                         }
557                         j+=offsetbytes;
558
559                         //printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex);
560
561                         std::string filename = string(name) + extension;
562                         wav_t f = {
563                                 filename,
564                                 findex,
565                                 (int64_t)(start*ratefactor),
566                                 (int64_t)(length*ratefactor),
567                         };
568
569                         vector<wav_t>::iterator begin = audiofiles.begin();
570                         vector<wav_t>::iterator finish = audiofiles.end();
571                         vector<wav_t>::iterator found;
572                         // Add file to lists
573                         if ((found = std::find(begin, finish, f)) != finish) {
574                                 region_t r = {
575                                         name,
576                                         rindex,
577                                         (int64_t)(start*ratefactor),
578                                         (int64_t)(sampleoffset*ratefactor),
579                                         (int64_t)(length*ratefactor),
580                                         *found,
581                                 };
582                                 regions.push_back(r);
583                                 vector<track_t>::iterator ti;
584                                 vector<track_t>::iterator bt = tracks.begin();
585                                 vector<track_t>::iterator et = tracks.end();
586                                 track_t tr = { name, 0, 0, r };
587                                 if ((ti = std::find(bt, et, tr)) != et) {
588                                         tracknumber = (*ti).index;
589                                 } else {
590                                         tracknumber = tracks.size() + 1;
591                                 }
592                                 track_t t = {
593                                         name,
594                                         (uint16_t)tracknumber,
595                                         uint8_t(0),
596                                         r
597                                 };
598                                 tracks.push_back(t);
599                         } else {
600                                 region_t r = {
601                                         name,
602                                         rindex,
603                                         (int64_t)(start*ratefactor),
604                                         (int64_t)(sampleoffset*ratefactor),
605                                         (int64_t)(length*ratefactor),
606                                         f,
607                                 };
608                                 regions.push_back(r);
609                                 vector<track_t>::iterator ti;
610                                 vector<track_t>::iterator bt = tracks.begin();
611                                 vector<track_t>::iterator et = tracks.end();
612                                 track_t tr = { name, 0, 0, r };
613                                 if ((ti = std::find(bt, et, tr)) != et) {
614                                         tracknumber = (*ti).index;
615                                 } else {
616                                         tracknumber = tracks.size() + 1;
617                                 }
618                                 track_t t = {
619                                         name,
620                                         (uint16_t)tracknumber,
621                                         uint8_t(0),
622                                         r
623                                 };
624                                 tracks.push_back(t);
625                         }
626                         rindex++;
627                         k++;
628                 }
629                 k++;
630         }
631 }
632
633 void
634 PTFFormat::parseaudio5(void) {
635         int i,k,l;
636         int lengthofname, wavnumber;
637
638         // Find end of wav file list
639         k = 0;
640         while (k < len) {
641                 if (            (ptfunxored[k  ] == 0x5f) &&
642                                 (ptfunxored[k+1] == 0x50) &&
643                                 (ptfunxored[k+2] == 0x35)) {
644                         break;
645                 }
646                 k++;
647         }
648         k++;
649         while (k < len) {
650                 if (            (ptfunxored[k  ] == 0x5f) &&
651                                 (ptfunxored[k+1] == 0x50) &&
652                                 (ptfunxored[k+2] == 0x35)) {
653                         break;
654                 }
655                 k++;
656         }
657
658         // Find actual wav names
659         uint16_t numberofwavs = ptfunxored[k-23];
660         char wavname[256];
661         for (i = k; i < len; i++) {
662                 if (            (ptfunxored[i  ] == 'F') &&
663                                 (ptfunxored[i+1] == 'i') &&
664                                 (ptfunxored[i+2] == 'l') &&
665                                 (ptfunxored[i+3] == 'e') &&
666                                 (ptfunxored[i+4] == 's')) {
667                         break;
668                 }
669         }
670
671         wavnumber = 0;
672         i+=16;
673         while (i < len && numberofwavs > 0) {
674                 i++;
675                 if (            (ptfunxored[i  ] == 0x5a) &&
676                                 (ptfunxored[i+1] == 0x00) &&
677                                 (ptfunxored[i+2] == 0x05)) {
678                         break;
679                 }
680                 lengthofname = ptfunxored[i];
681                 i++;
682                 l = 0;
683                 while (l < lengthofname) {
684                         wavname[l] = ptfunxored[i+l];
685                         l++;
686                 }
687                 i+=lengthofname + 4;
688                 wavname[l] = 0;
689                 if (foundin(wavname, ".wav")) {
690                         extension = string(".wav");
691                 } else if (foundin(wavname, ".aif")) {
692                         extension = string(".aif");
693                 } else {
694                         extension = string("");
695                 }
696
697                 std::string wave = string(wavname);
698                 wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
699
700                 if (foundin(wave, string(".grp"))) {
701                         continue;
702                 }
703
704                 actualwavs.push_back(f);
705                 audiofiles.push_back(f);
706                 //printf("done\n");
707                 numberofwavs--;
708                 i += 7;
709         }
710 }
711
712 void
713 PTFFormat::parseaudio(void) {
714         int i,j,k,l;
715
716         // Find end of wav file list
717         k = 0;
718         while (k < len) {
719                 if (            (ptfunxored[k  ] == 0xff) &&
720                                 (ptfunxored[k+1] == 0xff) &&
721                                 (ptfunxored[k+2] == 0xff) &&
722                                 (ptfunxored[k+3] == 0xff)) {
723                         break;
724                 }
725                 k++;
726         }
727
728         // Find actual wav names
729         bool first = true;
730         uint16_t numberofwavs;
731         char wavname[256];
732         for (i = k; i > 4; i--) {
733                 if (            ((ptfunxored[i  ] == 'W') || (ptfunxored[i  ] == 'A')) &&
734                                 ((ptfunxored[i-1] == 'A') || (ptfunxored[i-1] == 'I')) &&
735                                 ((ptfunxored[i-2] == 'V') || (ptfunxored[i-2] == 'F')) &&
736                                 ((ptfunxored[i-3] == 'E') || (ptfunxored[i-3] == 'F'))) {
737                         j = i-4;
738                         l = 0;
739                         while (ptfunxored[j] != '\0') {
740                                 wavname[l] = ptfunxored[j];
741                                 l++;
742                                 j--;
743                         }
744                         wavname[l] = 0;
745                         if (ptfunxored[i] == 'W') {
746                                 extension = string(".wav");
747                         } else {
748                                 extension = string(".aif");
749                         }
750                         //uint8_t playlist = ptfunxored[j-8];
751
752                         if (first) {
753                                 first = false;
754                                 for (j = k; j > 4; j--) {
755                                         if (    (ptfunxored[j  ] == 0x01) &&
756                                                 (ptfunxored[j-1] == 0x5a)) {
757
758                                                 numberofwavs = 0;
759                                                 numberofwavs |= (uint32_t)(ptfunxored[j-2] << 24);
760                                                 numberofwavs |= (uint32_t)(ptfunxored[j-3] << 16);
761                                                 numberofwavs |= (uint32_t)(ptfunxored[j-4] << 8);
762                                                 numberofwavs |= (uint32_t)(ptfunxored[j-5]);
763                                                 //printf("%d wavs\n", numberofwavs);
764                                                 break;
765                                         }
766                                 k--;
767                                 }
768                         }
769
770                         std::string wave = string(wavname);
771                         std::reverse(wave.begin(), wave.end());
772                         wav_t f = { wave, (uint16_t)(numberofwavs - 1), 0, 0 };
773
774                         if (foundin(wave, string(".grp"))) {
775                                 continue;
776                         }
777
778                         actualwavs.push_back(f);
779
780                         numberofwavs--;
781                         if (numberofwavs <= 0)
782                                 break;
783                 }
784         }
785 }
786
787 void
788 PTFFormat::parserest89(void) {
789         int i,j,k,l;
790         // Find Regions
791         uint8_t startbytes = 0;
792         uint8_t lengthbytes = 0;
793         uint8_t offsetbytes = 0;
794         uint8_t somethingbytes = 0;
795         uint8_t skipbytes = 0;
796
797         k = 0;
798         while (k < len) {
799                 if (            (ptfunxored[k  ] == 'S') &&
800                                 (ptfunxored[k+1] == 'n') &&
801                                 (ptfunxored[k+2] == 'a') &&
802                                 (ptfunxored[k+3] == 'p')) {
803                         break;
804                 }
805                 k++;
806         }
807         uint16_t rindex = 0;
808         uint32_t findex = 0;
809         for (i = k; i < len-70; i++) {
810                 if (            (ptfunxored[i  ] == 0x5a) &&
811                                 (ptfunxored[i+1] == 0x0a)) {
812                                 break;
813                 }
814                 if (            (ptfunxored[i  ] == 0x5a) &&
815                                 (ptfunxored[i+1] == 0x0c)) {
816
817                         uint8_t lengthofname = ptfunxored[i+9];
818
819                         char name[256] = {0};
820                         for (j = 0; j < lengthofname; j++) {
821                                 name[j] = ptfunxored[i+13+j];
822                         }
823                         name[j] = '\0';
824                         j += i+13;
825                         //uint8_t disabled = ptfunxored[j];
826
827                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
828                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
829                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
830                         somethingbytes = (ptfunxored[j+3] & 0xf);
831                         skipbytes = ptfunxored[j+4];
832                         findex = ptfunxored[j+5
833                                         +startbytes
834                                         +lengthbytes
835                                         +offsetbytes
836                                         +somethingbytes
837                                         +skipbytes
838                                         +40];
839                         /*rindex = ptfunxored[j+5
840                                         +startbytes
841                                         +lengthbytes
842                                         +offsetbytes
843                                         +somethingbytes
844                                         +skipbytes
845                                         +24];
846                         */
847                         uint32_t sampleoffset = 0;
848                         switch (offsetbytes) {
849                         case 4:
850                                 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
851                         case 3:
852                                 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
853                         case 2:
854                                 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
855                         case 1:
856                                 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
857                         default:
858                                 break;
859                         }
860                         j+=offsetbytes;
861                         uint32_t length = 0;
862                         switch (lengthbytes) {
863                         case 4:
864                                 length |= (uint32_t)(ptfunxored[j+8] << 24);
865                         case 3:
866                                 length |= (uint32_t)(ptfunxored[j+7] << 16);
867                         case 2:
868                                 length |= (uint32_t)(ptfunxored[j+6] << 8);
869                         case 1:
870                                 length |= (uint32_t)(ptfunxored[j+5]);
871                         default:
872                                 break;
873                         }
874                         j+=lengthbytes;
875                         uint32_t start = 0;
876                         switch (startbytes) {
877                         case 4:
878                                 start |= (uint32_t)(ptfunxored[j+8] << 24);
879                         case 3:
880                                 start |= (uint32_t)(ptfunxored[j+7] << 16);
881                         case 2:
882                                 start |= (uint32_t)(ptfunxored[j+6] << 8);
883                         case 1:
884                                 start |= (uint32_t)(ptfunxored[j+5]);
885                         default:
886                                 break;
887                         }
888                         j+=startbytes;
889                         /*
890                         uint32_t something = 0;
891                         switch (somethingbytes) {
892                         case 4:
893                                 something |= (uint32_t)(ptfunxored[j+8] << 24);
894                         case 3:
895                                 something |= (uint32_t)(ptfunxored[j+7] << 16);
896                         case 2:
897                                 something |= (uint32_t)(ptfunxored[j+6] << 8);
898                         case 1:
899                                 something |= (uint32_t)(ptfunxored[j+5]);
900                         default:
901                                 break;
902                         }
903                         j+=somethingbytes;
904                         */
905                         std::string filename = string(name) + extension;
906                         wav_t f = {
907                                 filename,
908                                 0,
909                                 (int64_t)(start*ratefactor),
910                                 (int64_t)(length*ratefactor),
911                         };
912
913                         f.index = findex;
914                         //printf("something=%d\n", something);
915
916                         vector<wav_t>::iterator begin = actualwavs.begin();
917                         vector<wav_t>::iterator finish = actualwavs.end();
918                         vector<wav_t>::iterator found;
919                         // Add file to list only if it is an actual wav
920                         if ((found = std::find(begin, finish, f)) != finish) {
921                                 audiofiles.push_back(f);
922                                 // Also add plain wav as region
923                                 region_t r = {
924                                         name,
925                                         rindex,
926                                         (int64_t)(start*ratefactor),
927                                         (int64_t)(sampleoffset*ratefactor),
928                                         (int64_t)(length*ratefactor),
929                                         f
930                                 };
931                                 regions.push_back(r);
932                         // Region only
933                         } else {
934                                 if (foundin(filename, string(".grp"))) {
935                                         continue;
936                                 }
937                                 region_t r = {
938                                         name,
939                                         rindex,
940                                         (int64_t)(start*ratefactor),
941                                         (int64_t)(sampleoffset*ratefactor),
942                                         (int64_t)(length*ratefactor),
943                                         f
944                                 };
945                                 regions.push_back(r);
946                         }
947                         rindex++;
948                 }
949         }
950
951         while (k < len) {
952                 if (            (ptfunxored[k  ] == 0x5a) &&
953                                 (ptfunxored[k+1] == 0x03)) {
954                                 break;
955                 }
956                 k++;
957         }
958         while (k < len) {
959                 if (            (ptfunxored[k  ] == 0x5a) &&
960                                 (ptfunxored[k+1] == 0x02)) {
961                                 break;
962                 }
963                 k++;
964         }
965         k++;
966
967         //  Tracks
968         uint32_t offset;
969         uint32_t tracknumber = 0;
970         uint32_t regionspertrack = 0;
971         for (;k < len; k++) {
972                 if (    (ptfunxored[k  ] == 0x5a) &&
973                         (ptfunxored[k+1] == 0x04)) {
974                         break;
975                 }
976                 if (    (ptfunxored[k  ] == 0x5a) &&
977                         (ptfunxored[k+1] == 0x02)) {
978
979                         uint8_t lengthofname = 0;
980                         lengthofname = ptfunxored[k+9];
981                         if (lengthofname == 0x5a) {
982                                 continue;
983                         }
984                         track_t tr;
985
986                         regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
987
988                         //printf("regions/track=%d\n", regionspertrack);
989                         char name[256] = {0};
990                         for (j = 0; j < lengthofname; j++) {
991                                 name[j] = ptfunxored[j+k+13];
992                         }
993                         name[j] = '\0';
994                         tr.name = string(name);
995                         tr.index = tracknumber++;
996
997                         for (j = k; regionspertrack > 0 && j < len; j++) {
998                                 for (l = j; l < len; l++) {
999                                         if (    (ptfunxored[l  ] == 0x5a) &&
1000                                                 (ptfunxored[l+1] == 0x07)) {
1001                                                 j = l;
1002                                                 break;
1003                                         }
1004                                 }
1005
1006
1007                                 if (regionspertrack == 0) {
1008                                 //      tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5];
1009                                         break;
1010                                 } else {
1011
1012                                         tr.reg.index = (uint8_t)(ptfunxored[l+11]);
1013                                         vector<region_t>::iterator begin = regions.begin();
1014                                         vector<region_t>::iterator finish = regions.end();
1015                                         vector<region_t>::iterator found;
1016                                         if ((found = std::find(begin, finish, tr.reg)) != finish) {
1017                                                 tr.reg = (*found);
1018                                         }
1019                                         i = l+16;
1020                                         offset = 0;
1021                                         offset |= (uint32_t)(ptfunxored[i+3] << 24);
1022                                         offset |= (uint32_t)(ptfunxored[i+2] << 16);
1023                                         offset |= (uint32_t)(ptfunxored[i+1] << 8);
1024                                         offset |= (uint32_t)(ptfunxored[i]);
1025                                         tr.reg.startpos = (int64_t)(offset*ratefactor);
1026                                         if (tr.reg.length > 0) {
1027                                                 tracks.push_back(tr);
1028                                         }
1029                                         regionspertrack--;
1030                                 }
1031                         }
1032                 }
1033         }
1034 }
1035
1036 void
1037 PTFFormat::parserest10(void) {
1038         int i,j,k,l;
1039         // Find Regions
1040         uint8_t startbytes = 0;
1041         uint8_t lengthbytes = 0;
1042         uint8_t offsetbytes = 0;
1043         uint8_t somethingbytes = 0;
1044         uint8_t skipbytes = 0;
1045
1046         k = 0;
1047         while (k < len) {
1048                 if (            (ptfunxored[k  ] == 'S') &&
1049                                 (ptfunxored[k+1] == 'n') &&
1050                                 (ptfunxored[k+2] == 'a') &&
1051                                 (ptfunxored[k+3] == 'p')) {
1052                         break;
1053                 }
1054                 k++;
1055         }
1056         for (i = k; i < len-70; i++) {
1057                 if (            (ptfunxored[i  ] == 0x5a) &&
1058                                 (ptfunxored[i+1] == 0x02)) {
1059                                 k = i;
1060                                 break;
1061                 }
1062         }
1063         k++;
1064         for (i = k; i < len-70; i++) {
1065                 if (            (ptfunxored[i  ] == 0x5a) &&
1066                                 (ptfunxored[i+1] == 0x02)) {
1067                                 k = i;
1068                                 break;
1069                 }
1070         }
1071         k++;
1072         uint16_t rindex = 0;
1073         uint32_t findex = 0;
1074         for (i = k; i < len-70; i++) {
1075                 if (            (ptfunxored[i  ] == 0x5a) &&
1076                                 (ptfunxored[i+1] == 0x08)) {
1077                                 break;
1078                 }
1079                 if (            (ptfunxored[i  ] == 0x5a) &&
1080                                 (ptfunxored[i+1] == 0x01)) {
1081
1082                         uint8_t lengthofname = ptfunxored[i+9];
1083                         if (ptfunxored[i+13] == 0x5a) {
1084                                 continue;
1085                         }
1086                         char name[256] = {0};
1087                         for (j = 0; j < lengthofname; j++) {
1088                                 name[j] = ptfunxored[i+13+j];
1089                         }
1090                         name[j] = '\0';
1091                         j += i+13;
1092                         //uint8_t disabled = ptfunxored[j];
1093                         //printf("%s\n", name);
1094
1095                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1096                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1097                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1098                         somethingbytes = (ptfunxored[j+3] & 0xf);
1099                         skipbytes = ptfunxored[j+4];
1100                         findex = ptfunxored[j+5
1101                                         +startbytes
1102                                         +lengthbytes
1103                                         +offsetbytes
1104                                         +somethingbytes
1105                                         +skipbytes
1106                                         +37];
1107                         /*rindex = ptfunxored[j+5
1108                                         +startbytes
1109                                         +lengthbytes
1110                                         +offsetbytes
1111                                         +somethingbytes
1112                                         +skipbytes
1113                                         +24];
1114                         */
1115                         uint32_t sampleoffset = 0;
1116                         switch (offsetbytes) {
1117                         case 4:
1118                                 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
1119                         case 3:
1120                                 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
1121                         case 2:
1122                                 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
1123                         case 1:
1124                                 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
1125                         default:
1126                                 break;
1127                         }
1128                         j+=offsetbytes;
1129                         uint32_t length = 0;
1130                         switch (lengthbytes) {
1131                         case 4:
1132                                 length |= (uint32_t)(ptfunxored[j+8] << 24);
1133                         case 3:
1134                                 length |= (uint32_t)(ptfunxored[j+7] << 16);
1135                         case 2:
1136                                 length |= (uint32_t)(ptfunxored[j+6] << 8);
1137                         case 1:
1138                                 length |= (uint32_t)(ptfunxored[j+5]);
1139                         default:
1140                                 break;
1141                         }
1142                         j+=lengthbytes;
1143                         uint32_t start = 0;
1144                         switch (startbytes) {
1145                         case 4:
1146                                 start |= (uint32_t)(ptfunxored[j+8] << 24);
1147                         case 3:
1148                                 start |= (uint32_t)(ptfunxored[j+7] << 16);
1149                         case 2:
1150                                 start |= (uint32_t)(ptfunxored[j+6] << 8);
1151                         case 1:
1152                                 start |= (uint32_t)(ptfunxored[j+5]);
1153                         default:
1154                                 break;
1155                         }
1156                         j+=startbytes;
1157                         /*
1158                         uint32_t something = 0;
1159                         switch (somethingbytes) {
1160                         case 4:
1161                                 something |= (uint32_t)(ptfunxored[j+8] << 24);
1162                         case 3:
1163                                 something |= (uint32_t)(ptfunxored[j+7] << 16);
1164                         case 2:
1165                                 something |= (uint32_t)(ptfunxored[j+6] << 8);
1166                         case 1:
1167                                 something |= (uint32_t)(ptfunxored[j+5]);
1168                         default:
1169                                 break;
1170                         }
1171                         j+=somethingbytes;
1172                         */
1173                         std::string filename = string(name) + extension;
1174                         wav_t f = {
1175                                 filename,
1176                                 0,
1177                                 (int64_t)(start*ratefactor),
1178                                 (int64_t)(length*ratefactor),
1179                         };
1180
1181                         if (strlen(name) == 0) {
1182                                 continue;
1183                         }
1184                         if (length == 0) {
1185                                 continue;
1186                         }
1187                         f.index = findex;
1188                         //printf("something=%d\n", something);
1189
1190                         vector<wav_t>::iterator begin = actualwavs.begin();
1191                         vector<wav_t>::iterator finish = actualwavs.end();
1192                         vector<wav_t>::iterator found;
1193                         // Add file to list only if it is an actual wav
1194                         if ((found = std::find(begin, finish, f)) != finish) {
1195                                 audiofiles.push_back(f);
1196                                 // Also add plain wav as region
1197                                 region_t r = {
1198                                         name,
1199                                         rindex,
1200                                         (int64_t)(start*ratefactor),
1201                                         (int64_t)(sampleoffset*ratefactor),
1202                                         (int64_t)(length*ratefactor),
1203                                         f
1204                                 };
1205                                 regions.push_back(r);
1206                         // Region only
1207                         } else {
1208                                 if (foundin(filename, string(".grp"))) {
1209                                         continue;
1210                                 }
1211                                 region_t r = {
1212                                         name,
1213                                         rindex,
1214                                         (int64_t)(start*ratefactor),
1215                                         (int64_t)(sampleoffset*ratefactor),
1216                                         (int64_t)(length*ratefactor),
1217                                         f
1218                                 };
1219                                 regions.push_back(r);
1220                         }
1221                         rindex++;
1222                         //printf("%s\n", name);
1223                 }
1224         }
1225         //  Tracks
1226         uint32_t offset;
1227         uint32_t tracknumber = 0;
1228         uint32_t regionspertrack = 0;
1229         for (;k < len; k++) {
1230                 if (    (ptfunxored[k  ] == 0x5a) &&
1231                         (ptfunxored[k+1] == 0x08)) {
1232                         break;
1233                 }
1234         }
1235         k++;
1236         for (;k < len; k++) {
1237                 if (    (ptfunxored[k  ] == 0x5a) &&
1238                         (ptfunxored[k+1] == 0x04)) {
1239                         break;
1240                 }
1241                 if (    (ptfunxored[k  ] == 0x5a) &&
1242                         (ptfunxored[k+1] == 0x02)) {
1243
1244                         uint8_t lengthofname = 0;
1245                         lengthofname = ptfunxored[k+9];
1246                         if (lengthofname == 0x5a) {
1247                                 continue;
1248                         }
1249                         track_t tr;
1250
1251                         regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
1252
1253                         //printf("regions/track=%d\n", regionspertrack);
1254                         char name[256] = {0};
1255                         for (j = 0; j < lengthofname; j++) {
1256                                 name[j] = ptfunxored[j+k+13];
1257                         }
1258                         name[j] = '\0';
1259                         tr.name = string(name);
1260                         tr.index = tracknumber++;
1261
1262                         for (j = k; regionspertrack > 0 && j < len; j++) {
1263                                 for (l = j; l < len; l++) {
1264                                         if (    (ptfunxored[l  ] == 0x5a) &&
1265                                                 (ptfunxored[l+1] == 0x08)) {
1266                                                 j = l+1;
1267                                                 break;
1268                                         }
1269                                 }
1270
1271
1272                                 if (regionspertrack == 0) {
1273                                 //      tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5];
1274                                         break;
1275                                 } else {
1276
1277                                         tr.reg.index = (uint8_t)(ptfunxored[l+11]);
1278                                         vector<region_t>::iterator begin = regions.begin();
1279                                         vector<region_t>::iterator finish = regions.end();
1280                                         vector<region_t>::iterator found;
1281                                         if ((found = std::find(begin, finish, tr.reg)) != finish) {
1282                                                 tr.reg = (*found);
1283                                         }
1284                                         i = l+16;
1285                                         offset = 0;
1286                                         offset |= (uint32_t)(ptfunxored[i+3] << 24);
1287                                         offset |= (uint32_t)(ptfunxored[i+2] << 16);
1288                                         offset |= (uint32_t)(ptfunxored[i+1] << 8);
1289                                         offset |= (uint32_t)(ptfunxored[i]);
1290                                         tr.reg.startpos = (int64_t)(offset*ratefactor);
1291                                         if (tr.reg.length > 0) {
1292                                                 tracks.push_back(tr);
1293                                         }
1294                                         regionspertrack--;
1295                                 }
1296                         }
1297                 }
1298         }
1299 }