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