ptformat: Update to upstream d5a73a0
[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 #if 0
28 #define verbose_printf(...) printf(__VA_ARGS__)
29 #else
30 #define verbose_printf(...)
31 #endif
32
33 using namespace std;
34
35 static bool wavidx_compare(PTFFormat::wav_t& w1, PTFFormat::wav_t& w2) {
36         return w1.index < w2.index;
37 }
38
39 static bool wavname_compare(PTFFormat::wav_t& w1, PTFFormat::wav_t& w2) {
40         return (strcasecmp(w1.filename.c_str(), w2.filename.c_str()) < 0);
41 }
42
43 static bool regidx_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) {
44         return r1.index < r2.index;
45 }
46
47 static bool regname_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) {
48         return (strcasecmp(r1.name.c_str(), r2.name.c_str()) < 0);
49 }
50
51 static void
52 hexdump(uint8_t *data, int len)
53 {
54         int i,j,end,step=16;
55
56         for (i = 0; i < len; i += step) {
57                 printf("0x%02X: ", i);
58                 end = i + step;
59                 if (end > len) end = len;
60                 for (j = i; j < end; j++) {
61                         printf("0x%02X ", data[j]);
62                 }
63                 for (j = i; j < end; j++) {
64                         if (data[j] < 128 && data[j] > 32)
65                                 printf("%c", data[j]);
66                         else
67                                 printf(".");
68                 }
69                 printf("\n");
70         }
71 }
72
73 PTFFormat::PTFFormat() : version(0), product(NULL) {
74 }
75
76 PTFFormat::~PTFFormat() {
77         if (ptfunxored) {
78                 free(ptfunxored);
79         }
80 }
81
82 int64_t
83 PTFFormat::foundat(unsigned char *haystack, uint64_t n, const char *needle) {
84         int64_t found = 0;
85         uint64_t i, j, needle_n;
86         needle_n = strlen(needle);
87
88         for (i = 0; i < n; i++) {
89                 found = i;
90                 for (j = 0; j < needle_n; j++) {
91                         if (haystack[i+j] != needle[j]) {
92                                 found = -1;
93                                 break;
94                         }
95                 }
96                 if (found > 0)
97                         return found;
98         }
99         return -1;
100 }
101
102 bool
103 PTFFormat::jumpto(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
104         uint64_t i;
105         uint64_t k = *currpos;
106         while (k + needlelen < maxoffset) {
107                 bool foundall = true;
108                 for (i = 0; i < needlelen; i++) {
109                         if (buf[k+i] != needle[i]) {
110                                 foundall = false;
111                                 break;
112                         }
113                 }
114                 if (foundall) {
115                         *currpos = k;
116                         return true;
117                 }
118                 k++;
119         }
120         return false;
121 }
122
123 bool
124 PTFFormat::jumpback(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
125         uint64_t i;
126         uint64_t k = *currpos;
127         while (k > 0 && k + needlelen < maxoffset) {
128                 bool foundall = true;
129                 for (i = 0; i < needlelen; i++) {
130                         if (buf[k+i] != needle[i]) {
131                                 foundall = false;
132                                 break;
133                         }
134                 }
135                 if (foundall) {
136                         *currpos = k;
137                         return true;
138                 }
139                 k--;
140         }
141         return false;
142 }
143
144 bool
145 PTFFormat::foundin(std::string haystack, std::string needle) {
146         size_t found = haystack.find(needle);
147         if (found != std::string::npos) {
148                 return true;
149         } else {
150                 return false;
151         }
152 }
153
154 /* Return values:       0            success
155                         -1           could not decrypt pt session
156 */
157 int
158 PTFFormat::unxor(std::string path) {
159         FILE *fp;
160         unsigned char xxor[256];
161         unsigned char ct;
162         uint64_t i;
163         uint8_t xor_type;
164         uint8_t xor_value;
165         uint8_t xor_delta;
166         uint16_t xor_len;
167
168         if (! (fp = g_fopen(path.c_str(), "rb"))) {
169                 return -1;
170         }
171
172         fseek(fp, 0, SEEK_END);
173         len = ftell(fp);
174         if (len < 0x14) {
175                 fclose(fp);
176                 return -1;
177         }
178
179         if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
180                 /* Silently fail -- out of memory*/
181                 fclose(fp);
182                 ptfunxored = 0;
183                 return -1;
184         }
185
186         /* The first 20 bytes are always unencrypted */
187         fseek(fp, 0x00, SEEK_SET);
188         i = fread(ptfunxored, 1, 0x14, fp);
189         if (i < 0x14) {
190                 fclose(fp);
191                 return -1;
192         }
193
194         xor_type = ptfunxored[0x12];
195         xor_value = ptfunxored[0x13];
196         xor_len = 256;
197
198         // xor_type 0x01 = ProTools 5, 6, 7, 8 and 9
199         // xor_type 0x05 = ProTools 10, 11, 12
200         switch(xor_type) {
201         case 0x01:
202                 xor_delta = gen_xor_delta(xor_value, 53, false);
203                 break;
204         case 0x05:
205                 xor_delta = gen_xor_delta(xor_value, 11, true);
206                 break;
207         default:
208                 fclose(fp);
209                 return -1;
210         }
211
212         /* Generate the xor_key */
213         for (i=0; i < xor_len; i++)
214                 xxor[i] = (i * xor_delta) & 0xff;
215
216         /* hexdump(xxor, xor_len); */
217
218         /* Read file and decrypt rest of file */
219         i = 0x14;
220         fseek(fp, i, SEEK_SET);
221         while (fread(&ct, 1, 1, fp) != 0) {
222                 uint8_t xor_index = (xor_type == 0x01) ? i & 0xff : (i >> 12) & 0xff;
223                 ptfunxored[i++] = ct ^ xxor[xor_index];
224         }
225         fclose(fp);
226         return 0;
227 }
228
229 /* Return values:       0            success
230                         -1           could not parse pt session
231 */
232 int
233 PTFFormat::load(std::string path, int64_t targetsr) {
234         if (unxor(path))
235                 return -1;
236
237         if (parse_version())
238                 return -1;
239
240         if (version < 5 || version > 12)
241                 return -1;
242
243         targetrate = targetsr;
244
245         if (parse())
246                 return -1;
247
248         return 0;
249 }
250
251 bool
252 PTFFormat::parse_version() {
253         uint32_t seg_len,str_len;
254         uint8_t *data = ptfunxored + 0x14;
255         uintptr_t data_end = ((uintptr_t)ptfunxored) + 0x100;
256         uint8_t seg_type;
257         bool success = false;
258
259         while( ((uintptr_t)data < data_end) && (success == false) ) {
260
261                 if (data[0] != 0x5a) {
262                         success = false;
263                         break;
264                 }
265
266                 seg_type = data[1];
267                 /* Skip segment header */
268                 data += 3;
269                 if (data[0] == 0 && data[1] == 0) {
270                         /* LE */
271                         seg_len = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
272                 } else {
273                         /* BE */
274                         seg_len = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
275                 }
276                 /* Skip seg_len */
277                 data += 4;
278                 if (!(seg_type == 0x04 || seg_type == 0x03) || data[0] != 0x03) {
279                         /* Go to next segment */
280                         data += seg_len;
281                         continue;
282                 }
283                 /* Skip 0x03 0x00 0x00 */
284                 data += 3;
285                 seg_len -= 3;
286                 str_len = (*(uint8_t *)data);
287                 if (! (product = (uint8_t *)malloc((str_len+1) * sizeof(uint8_t)))) {
288                         success = false;
289                         break;
290                 }
291
292                 /* Skip str_len */
293                 data += 4;
294                 seg_len -= 4;
295
296                 memcpy(product, data, str_len);
297                 product[str_len] = 0;
298                 data += str_len;
299                 seg_len -= str_len;
300
301                 /* Skip 0x03 0x00 0x00 0x00 */
302                 data += 4;
303                 seg_len -= 4;
304
305                 version = data[0];
306                 if (version == 0) {
307                         version = data[3];
308                 }
309                 data += seg_len;
310                 success = true;
311         }
312
313         /* If the above does not work, try other heuristics */
314         if ((uintptr_t)data >= data_end - seg_len) {
315                 version = ptfunxored[0x40];
316                 if (version == 0) {
317                         version = ptfunxored[0x3d];
318                 }
319                 if (version == 0) {
320                         version = ptfunxored[0x3a] + 2;
321                 }
322                 if (version != 0) {
323                         success = true;
324                 }
325         }
326         return (!success);
327 }
328
329 uint8_t
330 PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) {
331         uint16_t i;
332         for (i = 0; i < 256; i++) {
333                 if (((i * mul) & 0xff) == xor_value) {
334                                 return (negative) ? i * (-1) : i;
335                 }
336         }
337         // Should not occur
338         return 0;
339 }
340
341 int
342 PTFFormat::parse(void) {
343         if (version == 5) {
344                 parse5header();
345                 setrates();
346                 if (sessionrate < 44100 || sessionrate > 192000)
347                   return -1;
348                 parseaudio5();
349                 parserest5();
350                 parsemidi();
351         } else if (version == 7) {
352                 parse7header();
353                 setrates();
354                 if (sessionrate < 44100 || sessionrate > 192000)
355                   return -1;
356                 parseaudio();
357                 parserest89();
358                 parsemidi();
359         } else if (version == 8) {
360                 parse8header();
361                 setrates();
362                 if (sessionrate < 44100 || sessionrate > 192000)
363                   return -1;
364                 parseaudio();
365                 parserest89();
366                 parsemidi();
367         } else if (version == 9) {
368                 parse9header();
369                 setrates();
370                 if (sessionrate < 44100 || sessionrate > 192000)
371                   return -1;
372                 parseaudio();
373                 parserest89();
374                 parsemidi();
375         } else if (version == 10 || version == 11 || version == 12) {
376                 parse10header();
377                 setrates();
378                 if (sessionrate < 44100 || sessionrate > 192000)
379                   return -1;
380                 parseaudio();
381                 parserest12();
382                 parsemidi12();
383         } else {
384                 // Should not occur
385                 return -1;
386         }
387         return 0;
388 }
389
390 void
391 PTFFormat::setrates(void) {
392         ratefactor = 1.f;
393         if (sessionrate != 0) {
394                 ratefactor = (float)targetrate / sessionrate;
395         }
396 }
397
398 void
399 PTFFormat::parse5header(void) {
400         uint32_t k;
401
402         // Find session sample rate
403         k = 0x100;
404
405         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x02", 3);
406
407         sessionrate = 0;
408         sessionrate |= ptfunxored[k+12] << 16;
409         sessionrate |= ptfunxored[k+13] << 8;
410         sessionrate |= ptfunxored[k+14];
411 }
412
413 void
414 PTFFormat::parse7header(void) {
415         uint32_t k;
416
417         // Find session sample rate
418         k = 0x100;
419
420         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x05", 3);
421
422         sessionrate = 0;
423         sessionrate |= ptfunxored[k+12] << 16;
424         sessionrate |= ptfunxored[k+13] << 8;
425         sessionrate |= ptfunxored[k+14];
426 }
427
428 void
429 PTFFormat::parse8header(void) {
430         uint32_t k;
431
432         // Find session sample rate
433         k = 0;
434
435         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x05", 2);
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::parse9header(void) {
445         uint32_t k;
446
447         // Find session sample rate
448         k = 0x100;
449
450         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2);
451
452         sessionrate = 0;
453         sessionrate |= ptfunxored[k+11];
454         sessionrate |= ptfunxored[k+12] << 8;
455         sessionrate |= ptfunxored[k+13] << 16;
456 }
457
458 void
459 PTFFormat::parse10header(void) {
460         uint32_t k;
461
462         // Find session sample rate
463         k = 0x100;
464
465         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x09", 2);
466
467         sessionrate = 0;
468         sessionrate |= ptfunxored[k+11];
469         sessionrate |= ptfunxored[k+12] << 8;
470         sessionrate |= ptfunxored[k+13] << 16;
471 }
472
473 void
474 PTFFormat::parserest5(void) {
475         uint32_t i, j, k;
476         uint64_t regionspertrack, lengthofname;
477         uint64_t startbytes, lengthbytes, offsetbytes;
478         uint16_t tracknumber = 0;
479         uint16_t findex;
480         uint16_t rindex;
481
482         k = 0;
483         for (i = 0; i < 5; i++) {
484                 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x03", 3);
485                 k++;
486         }
487         k--;
488
489         for (i = 0; i < 2; i++) {
490                 jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
491                 if (k)
492                         k--;
493         }
494         k++;
495
496         rindex = 0;
497         while (k < len) {
498                 if (            (ptfunxored[k  ] == 0xff) &&
499                                 (ptfunxored[k+1] == 0xff)) {
500                         break;
501                 }
502                 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
503
504                 lengthofname = ptfunxored[k+12];
505                 if (ptfunxored[k+13] == 0x5a) {
506                         k++;
507                         break;
508                 }
509                 char name[256] = {0};
510                 for (j = 0; j < lengthofname; j++) {
511                         name[j] = ptfunxored[k+13+j];
512                 }
513                 name[j] = '\0';
514                 regionspertrack = ptfunxored[k+13+j+3];
515                 for (i = 0; i < regionspertrack; i++) {
516                         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x03", 3);
517                         j = k+16;
518                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
519                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
520                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
521                         //somethingbytes = (ptfunxored[j+1] & 0xf);
522                         findex = ptfunxored[k+14];
523                         j--;
524                         uint32_t start = 0;
525                         switch (startbytes) {
526                         case 4:
527                                 start |= (uint32_t)(ptfunxored[j+8] << 24);
528                         case 3:
529                                 start |= (uint32_t)(ptfunxored[j+7] << 16);
530                         case 2:
531                                 start |= (uint32_t)(ptfunxored[j+6] << 8);
532                         case 1:
533                                 start |= (uint32_t)(ptfunxored[j+5]);
534                         default:
535                                 break;
536                         }
537                         j+=startbytes;
538                         uint32_t length = 0;
539                         switch (lengthbytes) {
540                         case 4:
541                                 length |= (uint32_t)(ptfunxored[j+8] << 24);
542                         case 3:
543                                 length |= (uint32_t)(ptfunxored[j+7] << 16);
544                         case 2:
545                                 length |= (uint32_t)(ptfunxored[j+6] << 8);
546                         case 1:
547                                 length |= (uint32_t)(ptfunxored[j+5]);
548                         default:
549                                 break;
550                         }
551                         j+=lengthbytes;
552                         uint32_t sampleoffset = 0;
553                         switch (offsetbytes) {
554                         case 4:
555                                 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
556                         case 3:
557                                 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
558                         case 2:
559                                 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
560                         case 1:
561                                 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
562                         default:
563                                 break;
564                         }
565                         j+=offsetbytes;
566
567                         //printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex);
568
569                         std::string filename = string(name);
570                         wav_t f = {
571                                 filename,
572                                 findex,
573                                 (int64_t)(start*ratefactor),
574                                 (int64_t)(length*ratefactor),
575                         };
576
577                         vector<wav_t>::iterator begin = audiofiles.begin();
578                         vector<wav_t>::iterator finish = audiofiles.end();
579                         vector<wav_t>::iterator found;
580                         // Add file to lists
581                         if ((found = std::find(begin, finish, f)) != finish) {
582                                 f.filename = (*found).filename;
583                                 std::vector<midi_ev_t> m;
584                                 region_t r = {
585                                         name,
586                                         rindex,
587                                         (int64_t)(start*ratefactor),
588                                         (int64_t)(sampleoffset*ratefactor),
589                                         (int64_t)(length*ratefactor),
590                                         *found,
591                                         m
592                                 };
593                                 regions.push_back(r);
594                                 vector<track_t>::iterator ti;
595                                 vector<track_t>::iterator bt = tracks.begin();
596                                 vector<track_t>::iterator et = tracks.end();
597                                 track_t tr = { name, 0, 0, r };
598                                 if ((ti = std::find(bt, et, tr)) != et) {
599                                         tracknumber = (*ti).index;
600                                 } else {
601                                         tracknumber = tracks.size() + 1;
602                                 }
603                                 track_t t = {
604                                         name,
605                                         (uint16_t)tracknumber,
606                                         uint8_t(0),
607                                         r
608                                 };
609                                 tracks.push_back(t);
610                         } else {
611                                 std::vector<midi_ev_t> m;
612                                 region_t r = {
613                                         name,
614                                         rindex,
615                                         (int64_t)(start*ratefactor),
616                                         (int64_t)(sampleoffset*ratefactor),
617                                         (int64_t)(length*ratefactor),
618                                         f,
619                                         m,
620                                 };
621                                 regions.push_back(r);
622                                 vector<track_t>::iterator ti;
623                                 vector<track_t>::iterator bt = tracks.begin();
624                                 vector<track_t>::iterator et = tracks.end();
625                                 track_t tr = { name, 0, 0, r };
626                                 if ((ti = std::find(bt, et, tr)) != et) {
627                                         tracknumber = (*ti).index;
628                                 } else {
629                                         tracknumber = tracks.size() + 1;
630                                 }
631                                 track_t t = {
632                                         name,
633                                         (uint16_t)tracknumber,
634                                         uint8_t(0),
635                                         r
636                                 };
637                                 tracks.push_back(t);
638                         }
639                         rindex++;
640                         k++;
641                 }
642                 k++;
643         }
644 }
645
646 void
647 PTFFormat::resort(std::vector<wav_t>& ws) {
648         int j = 0;
649         std::sort(ws.begin(), ws.end());
650         for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) {
651                 (*i).index = j;
652                 j++;
653         }
654 }
655
656 void
657 PTFFormat::resort(std::vector<region_t>& rs) {
658         int j = 0;
659         //std::sort(rs.begin(), rs.end());
660         for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
661                 (*i).index = j;
662                 j++;
663         }
664 }
665
666 void
667 PTFFormat::filter(std::vector<region_t>& rs) {
668         for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
669                 if (i->length == 0)
670                         rs.erase(i);
671         }
672 }
673
674 void
675 PTFFormat::parseaudio5(void) {
676         uint32_t i,k,l;
677         uint64_t lengthofname, wavnumber;
678
679         // Find end of wav file list
680         k = 0;
681         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
682         k++;
683         jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
684
685         // Find actual wav names
686         uint16_t numberofwavs = ptfunxored[k-23];
687         char wavname[256];
688         i = k;
689         jumpto(&i, ptfunxored, len, (const unsigned char *)"Files", 5);
690
691         wavnumber = 0;
692         i+=16;
693         char ext[5];
694         while (i < len && numberofwavs > 0) {
695                 i++;
696                 if (            (ptfunxored[i  ] == 0x5a) &&
697                                 (ptfunxored[i+1] == 0x00) &&
698                                 (ptfunxored[i+2] == 0x05)) {
699                         break;
700                 }
701                 lengthofname = ptfunxored[i];
702                 i++;
703                 l = 0;
704                 while (l < lengthofname) {
705                         wavname[l] = ptfunxored[i+l];
706                         l++;
707                 }
708                 i+=lengthofname;
709                 ext[0] = ptfunxored[i++];
710                 ext[1] = ptfunxored[i++];
711                 ext[2] = ptfunxored[i++];
712                 ext[3] = ptfunxored[i++];
713                 ext[4] = '\0';
714
715                 wavname[l] = 0;
716                 if (foundin(wavname, ".L") || foundin(wavname, ".R")) {
717                         extension = string("");
718                 } else if (foundin(wavname, ".wav") || foundin(ext, "WAVE")) {
719                         extension = string(".wav");
720                 } else if (foundin(wavname, ".aif") || foundin(ext, "AIFF")) {
721                         extension = string(".aif");
722                 } else {
723                         extension = string("");
724                 }
725
726                 std::string wave = string(wavname);
727                 wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
728
729                 if (foundin(wave, string(".grp"))) {
730                         continue;
731                 }
732
733                 actualwavs.push_back(f);
734                 audiofiles.push_back(f);
735                 //printf("done\n");
736                 numberofwavs--;
737                 i += 7;
738         }
739         resort(actualwavs);
740         resort(audiofiles);
741 }
742
743 struct mchunk {
744         mchunk (uint64_t zt, uint64_t ml, std::vector<PTFFormat::midi_ev_t> const& c)
745         : zero (zt)
746         , maxlen (ml)
747         , chunk (c)
748         {}
749         uint64_t zero;
750         uint64_t maxlen;
751         std::vector<PTFFormat::midi_ev_t> chunk;
752 };
753
754 void
755 PTFFormat::parsemidi(void) {
756         uint32_t i, k;
757         uint64_t tr, n_midi_events, zero_ticks;
758         uint64_t midi_pos, midi_len, max_pos, region_pos;
759         uint8_t midi_velocity, midi_note;
760         uint16_t ridx;
761         uint16_t nmiditracks, regionnumber = 0;
762         uint32_t nregions, mr;
763
764         std::vector<mchunk> midichunks;
765         midi_ev_t m;
766
767         // Find MdNLB
768         k = 0;
769
770         // Parse all midi chunks, not 1:1 mapping to regions yet
771         while (k + 35 < len) {
772                 max_pos = 0;
773                 std::vector<midi_ev_t> midi;
774
775                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
776                         break;
777                 }
778                 k += 11;
779                 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
780                                 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
781
782                 k += 4;
783                 zero_ticks = (uint64_t)ptfunxored[k] |
784                         (uint64_t)ptfunxored[k+1] << 8 |
785                         (uint64_t)ptfunxored[k+2] << 16 |
786                         (uint64_t)ptfunxored[k+3] << 24 |
787                         (uint64_t)ptfunxored[k+4] << 32;
788                 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
789                         midi_pos = (uint64_t)ptfunxored[k] |
790                                 (uint64_t)ptfunxored[k+1] << 8 |
791                                 (uint64_t)ptfunxored[k+2] << 16 |
792                                 (uint64_t)ptfunxored[k+3] << 24 |
793                                 (uint64_t)ptfunxored[k+4] << 32;
794                         midi_pos -= zero_ticks;
795                         midi_note = ptfunxored[k+8];
796                         midi_len = (uint64_t)ptfunxored[k+9] |
797                                 (uint64_t)ptfunxored[k+10] << 8 |
798                                 (uint64_t)ptfunxored[k+11] << 16 |
799                                 (uint64_t)ptfunxored[k+12] << 24 |
800                                 (uint64_t)ptfunxored[k+13] << 32;
801                         midi_velocity = ptfunxored[k+17];
802
803                         if (midi_pos + midi_len > max_pos) {
804                                 max_pos = midi_pos + midi_len;
805                         }
806
807                         m.pos = midi_pos;
808                         m.length = midi_len;
809                         m.note = midi_note;
810                         m.velocity = midi_velocity;
811 #if 1
812 // stop gap measure to prevent crashes in ardour,
813 // remove when decryption is fully solved for .ptx
814                         if ((m.velocity & 0x80) || (m.note & 0x80) ||
815                                         (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
816                                 continue;
817                         }
818 #endif
819                         midi.push_back(m);
820                 }
821                 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
822         }
823
824         // Map midi chunks to regions
825         while (k < len) {
826                 char midiregionname[256];
827                 uint8_t namelen;
828
829                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
830                         break;
831                 }
832
833                 k += 41;
834
835                 nregions = 0;
836                 nregions |= ptfunxored[k];
837                 nregions |= ptfunxored[k+1] << 8;
838
839                 for (mr = 0; mr < nregions; mr++) {
840                         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x0c", 2)) {
841                                 break;
842                         }
843
844                         k += 9;
845
846                         namelen = ptfunxored[k];
847                         for (i = 0; i < namelen; i++) {
848                                 midiregionname[i] = ptfunxored[k+4+i];
849                         }
850                         midiregionname[namelen] = '\0';
851                         k += 4 + namelen;
852
853                         k += 5;
854                         /*
855                         region_pos = (uint64_t)ptfunxored[k] |
856                                         (uint64_t)ptfunxored[k+1] << 8 |
857                                         (uint64_t)ptfunxored[k+2] << 16 |
858                                         (uint64_t)ptfunxored[k+3] << 24 |
859                                         (uint64_t)ptfunxored[k+4] << 32;
860                         */
861                         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\xff\xff", 4)) {
862                                 break;
863                         }
864
865                         k += 40;
866
867                         ridx = ptfunxored[k];
868                         ridx |= ptfunxored[k+1] << 8;
869
870                         struct mchunk mc = *(midichunks.begin()+ridx);
871
872                         wav_t w = { std::string(""), 0, 0, 0 };
873                         region_t r = {
874                                 midiregionname,
875                                 regionnumber++,
876                                 //(int64_t)mc.zero,
877                                 (int64_t)0xe8d4a51000ull,
878                                 (int64_t)(0),
879                                 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
880                                 (int64_t)mc.maxlen,
881                                 w,
882                                 mc.chunk,
883                         };
884                         midiregions.push_back(r);
885                 }
886         }
887
888         // Put midi regions on midi tracks
889         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
890                 return;
891         }
892
893         k -= 4;
894
895         nmiditracks = 0;
896         nmiditracks |= ptfunxored[k];
897         nmiditracks |= ptfunxored[k+1] << 8;
898
899         k += 4;
900
901         for (tr = 0; tr < nmiditracks; tr++) {
902                 char miditrackname[256];
903                 uint8_t namelen;
904                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
905                         return;
906                 }
907
908                 namelen = ptfunxored[k+9];
909                 for (i = 0; i < namelen; i++) {
910                         miditrackname[i] = ptfunxored[k+13+i];
911                 }
912                 miditrackname[namelen] = '\0';
913                 k += 13 + namelen;
914                 nregions = 0;
915                 nregions |= ptfunxored[k];
916                 nregions |= ptfunxored[k+1] << 8;
917
918                 for (i = 0; (i < nregions) && (k < len); i++) {
919                         k += 24;
920
921                         ridx = 0;
922                         ridx |= ptfunxored[k];
923                         ridx |= ptfunxored[k+1] << 8;
924
925                         k += 5;
926
927                         region_pos = (uint64_t)ptfunxored[k] |
928                                         (uint64_t)ptfunxored[k+1] << 8 |
929                                         (uint64_t)ptfunxored[k+2] << 16 |
930                                         (uint64_t)ptfunxored[k+3] << 24 |
931                                         (uint64_t)ptfunxored[k+4] << 32;
932
933                         k += 20;
934
935                         track_t mtr;
936                         mtr.name = string(miditrackname);
937                         mtr.index = tr;
938                         mtr.playlist = 0;
939                         // Find the midi region with index 'ridx'
940                         std::vector<region_t>::iterator begin = midiregions.begin();
941                         std::vector<region_t>::iterator finish = midiregions.end();
942                         std::vector<region_t>::iterator mregion;
943                         wav_t w = { std::string(""), 0, 0, 0 };
944                         std::vector<midi_ev_t> m;
945                         region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
946                         if ((mregion = std::find(begin, finish, r)) != finish) {
947                                 mtr.reg = *mregion;
948                                 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
949                                 miditracks.push_back(mtr);
950                         }
951                 }
952         }
953 }
954
955 void
956 PTFFormat::parsemidi12(void) {
957         uint32_t i, k;
958         uint64_t tr, n_midi_events, zero_ticks;
959         uint64_t midi_pos, midi_len, max_pos, region_pos;
960         uint8_t midi_velocity, midi_note;
961         uint16_t ridx;
962         uint16_t nmiditracks, regionnumber = 0;
963         uint32_t nregions, mr;
964
965         std::vector<mchunk> midichunks;
966         midi_ev_t m;
967
968         k = 0;
969
970         // Parse all midi chunks, not 1:1 mapping to regions yet
971         while (k + 35 < len) {
972                 max_pos = 0;
973                 std::vector<midi_ev_t> midi;
974
975                 // Find MdNLB
976                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
977                         break;
978                 }
979
980                 k += 11;
981                 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
982                                 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
983
984                 k += 4;
985                 zero_ticks = (uint64_t)ptfunxored[k] |
986                         (uint64_t)ptfunxored[k+1] << 8 |
987                         (uint64_t)ptfunxored[k+2] << 16 |
988                         (uint64_t)ptfunxored[k+3] << 24 |
989                         (uint64_t)ptfunxored[k+4] << 32;
990                 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
991                         midi_pos = (uint64_t)ptfunxored[k] |
992                                 (uint64_t)ptfunxored[k+1] << 8 |
993                                 (uint64_t)ptfunxored[k+2] << 16 |
994                                 (uint64_t)ptfunxored[k+3] << 24 |
995                                 (uint64_t)ptfunxored[k+4] << 32;
996                         midi_pos -= zero_ticks;
997                         midi_note = ptfunxored[k+8];
998                         midi_len = (uint64_t)ptfunxored[k+9] |
999                                 (uint64_t)ptfunxored[k+10] << 8 |
1000                                 (uint64_t)ptfunxored[k+11] << 16 |
1001                                 (uint64_t)ptfunxored[k+12] << 24 |
1002                                 (uint64_t)ptfunxored[k+13] << 32;
1003                         midi_velocity = ptfunxored[k+17];
1004
1005                         if (midi_pos + midi_len > max_pos) {
1006                                 max_pos = midi_pos + midi_len;
1007                         }
1008
1009                         m.pos = midi_pos;
1010                         m.length = midi_len;
1011                         m.note = midi_note;
1012                         m.velocity = midi_velocity;
1013 #if 1
1014 // stop gap measure to prevent crashes in ardour,
1015 // remove when decryption is fully solved for .ptx
1016                         if ((m.velocity & 0x80) || (m.note & 0x80) ||
1017                                         (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
1018                                 continue;
1019                         }
1020 #endif
1021                         midi.push_back(m);
1022                 }
1023                 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
1024         }
1025
1026         // Map midi chunks to regions
1027         while (k < len) {
1028                 char midiregionname[256];
1029                 uint8_t namelen;
1030
1031                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
1032                         break;
1033                 }
1034
1035                 k += 41;
1036
1037                 nregions = 0;
1038                 nregions |= ptfunxored[k];
1039                 nregions |= ptfunxored[k+1] << 8;
1040
1041                 for (mr = 0; mr < nregions; mr++) {
1042                         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2)) {
1043                                 break;
1044                         }
1045                         k += 18;
1046
1047                         namelen = ptfunxored[k];
1048                         for (i = 0; i < namelen; i++) {
1049                                 midiregionname[i] = ptfunxored[k+4+i];
1050                         }
1051                         midiregionname[namelen] = '\0';
1052                         k += 4 + namelen;
1053
1054                         k += 5;
1055                         /*
1056                         region_pos = (uint64_t)ptfunxored[k] |
1057                                         (uint64_t)ptfunxored[k+1] << 8 |
1058                                         (uint64_t)ptfunxored[k+2] << 16 |
1059                                         (uint64_t)ptfunxored[k+3] << 24 |
1060                                         (uint64_t)ptfunxored[k+4] << 32;
1061                         */
1062                         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\x00\x00", 4)) {
1063                                 break;
1064                         }
1065
1066                         k += 37;
1067
1068                         ridx = ptfunxored[k];
1069                         ridx |= ptfunxored[k+1] << 8;
1070
1071                         k += 3;
1072                         struct mchunk mc = *(midichunks.begin()+ridx);
1073
1074                         wav_t w = { std::string(""), 0, 0, 0 };
1075                         region_t r = {
1076                                 midiregionname,
1077                                 regionnumber++,
1078                                 //(int64_t)mc.zero,
1079                                 (int64_t)0xe8d4a51000ull,
1080                                 (int64_t)(0),
1081                                 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
1082                                 (int64_t)mc.maxlen,
1083                                 w,
1084                                 mc.chunk,
1085                         };
1086                         midiregions.push_back(r);
1087                 }
1088         }
1089
1090         // Put midi regions on midi tracks
1091         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1092                 return;
1093         }
1094
1095         k -= 4;
1096
1097         nmiditracks = 0;
1098         nmiditracks |= ptfunxored[k];
1099         nmiditracks |= ptfunxored[k+1] << 8;
1100
1101         k += 4;
1102
1103         for (tr = 0; tr < nmiditracks; tr++) {
1104                 char miditrackname[256];
1105                 uint8_t namelen;
1106                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1107                         return;
1108                 }
1109
1110                 namelen = ptfunxored[k+9];
1111                 for (i = 0; i < namelen; i++) {
1112                         miditrackname[i] = ptfunxored[k+13+i];
1113                 }
1114                 miditrackname[namelen] = '\0';
1115                 k += 13 + namelen;
1116                 nregions = 0;
1117                 nregions |= ptfunxored[k];
1118                 nregions |= ptfunxored[k+1] << 8;
1119
1120                 k += 13;
1121
1122                 for (i = 0; (i < nregions) && (k < len); i++) {
1123                         while (k < len) {
1124                                 if (            (ptfunxored[k] == 0x5a) &&
1125                                                 (ptfunxored[k+1] & 0x08)) {
1126                                         break;
1127                                 }
1128                                 k++;
1129                         }
1130                         k += 11;
1131
1132                         ridx = 0;
1133                         ridx |= ptfunxored[k];
1134                         ridx |= ptfunxored[k+1] << 8;
1135
1136                         k += 5;
1137
1138                         region_pos = (uint64_t)ptfunxored[k] |
1139                                         (uint64_t)ptfunxored[k+1] << 8 |
1140                                         (uint64_t)ptfunxored[k+2] << 16 |
1141                                         (uint64_t)ptfunxored[k+3] << 24 |
1142                                         (uint64_t)ptfunxored[k+4] << 32;
1143
1144                         track_t mtr;
1145                         mtr.name = string(miditrackname);
1146                         mtr.index = tr;
1147                         mtr.playlist = 0;
1148                         // Find the midi region with index 'ridx'
1149                         std::vector<region_t>::iterator begin = midiregions.begin();
1150                         std::vector<region_t>::iterator finish = midiregions.end();
1151                         std::vector<region_t>::iterator mregion;
1152                         wav_t w = { std::string(""), 0, 0, 0 };
1153                         std::vector<midi_ev_t> m;
1154                         region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
1155                         if ((mregion = std::find(begin, finish, r)) != finish) {
1156                                 mtr.reg = *mregion;
1157                                 mtr.reg.startpos = std::labs(region_pos - mtr.reg.startpos);
1158                                 miditracks.push_back(mtr);
1159                         }
1160                         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8)) {
1161                                 return;
1162                         }
1163                 }
1164         }
1165 }
1166
1167 void
1168 PTFFormat::parseaudio(void) {
1169         uint32_t i,j,k,l;
1170         std::string wave;
1171
1172         k = 0;
1173         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Audio Files", 11))
1174                 return;
1175
1176         // Find end of wav file list
1177         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1178                 return;
1179
1180         // Find number of wave files
1181         uint16_t numberofwavs;
1182         j = k;
1183         if (!jumpback(&j, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
1184                 return;
1185
1186         numberofwavs = 0;
1187         numberofwavs |= (uint32_t)(ptfunxored[j-1] << 24);
1188         numberofwavs |= (uint32_t)(ptfunxored[j-2] << 16);
1189         numberofwavs |= (uint32_t)(ptfunxored[j-3] << 8);
1190         numberofwavs |= (uint32_t)(ptfunxored[j-4]);
1191         //printf("%d wavs\n", numberofwavs);
1192
1193         // Find actual wav names
1194         char wavname[256];
1195         j = k - 2;
1196         for (i = 0; i < numberofwavs; i++) {
1197                 while (j > 0) {
1198                         if (    ((ptfunxored[j  ] == 'W') || (ptfunxored[j  ] == 'A') || ptfunxored[j  ] == '\0') &&
1199                                 ((ptfunxored[j-1] == 'A') || (ptfunxored[j-1] == 'I') || ptfunxored[j-1] == '\0') &&
1200                                 ((ptfunxored[j-2] == 'V') || (ptfunxored[j-2] == 'F') || ptfunxored[j-2] == '\0')) {
1201                                 break;
1202                         }
1203                         j--;
1204                 }
1205                 j -= 4;
1206                 l = 0;
1207                 while (ptfunxored[j] != '\0') {
1208                         wavname[l] = ptfunxored[j];
1209                         l++;
1210                         j--;
1211                 }
1212                 wavname[l] = '\0';
1213
1214                 // Must be at least "vaw.z\0"
1215                 if (l < 6) {
1216                         i--;
1217                         continue;
1218                 }
1219
1220                 // and skip "zWAVE" or "zAIFF"
1221                 if (    (       (wavname[1] == 'W') &&
1222                                 (wavname[2] == 'A') &&
1223                                 (wavname[3] == 'V') &&
1224                                 (wavname[4] == 'E')) ||
1225                         (       (wavname[1] == 'A') &&
1226                                 (wavname[2] == 'I') &&
1227                                 (wavname[3] == 'F') &&
1228                                 (wavname[4] == 'F'))) {
1229                         wave = string(&wavname[5]);
1230                 } else {
1231                         wave = string(wavname);
1232                 }
1233                 //uint8_t playlist = ptfunxored[j-8];
1234
1235                 std::reverse(wave.begin(), wave.end());
1236                 wav_t f = { wave, (uint16_t)(numberofwavs - i - 1), 0, 0 };
1237
1238                 if (foundin(wave, string("Audio Files"))) {
1239                         i--;
1240                         continue;
1241                 }
1242
1243                 actualwavs.push_back(f);
1244                 audiofiles.push_back(f);
1245
1246                 //printf(" %d:%s \n", numberofwavs - i - 1, wave.c_str());
1247         }
1248         std::reverse(audiofiles.begin(), audiofiles.end());
1249         std::reverse(actualwavs.begin(), actualwavs.end());
1250         //resort(audiofiles);
1251         //resort(actualwavs);
1252 }
1253
1254 void
1255 PTFFormat::parserest89(void) {
1256         uint32_t i,j,k;
1257         uint8_t startbytes = 0;
1258         uint8_t lengthbytes = 0;
1259         uint8_t offsetbytes = 0;
1260         uint8_t somethingbytes = 0;
1261         uint8_t skipbytes = 0;
1262
1263         // Find Regions
1264         k = 0;
1265         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4)) {
1266                 return;
1267         }
1268
1269         uint16_t rindex = 0;
1270         uint32_t findex = 0;
1271         for (i = k; i < len-70; i++) {
1272                 if (            (ptfunxored[i  ] == 0x5a) &&
1273                                 (ptfunxored[i+1] == 0x0a)) {
1274                                 break;
1275                 }
1276                 if (            (ptfunxored[i  ] == 0x5a) &&
1277                                 (ptfunxored[i+1] == 0x0c)) {
1278
1279                         uint8_t lengthofname = ptfunxored[i+9];
1280
1281                         char name[256] = {0};
1282                         for (j = 0; j < lengthofname; j++) {
1283                                 name[j] = ptfunxored[i+13+j];
1284                         }
1285                         name[j] = '\0';
1286                         j += i+13;
1287                         //uint8_t disabled = ptfunxored[j];
1288
1289                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1290                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1291                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1292                         somethingbytes = (ptfunxored[j+3] & 0xf);
1293                         skipbytes = ptfunxored[j+4];
1294                         findex = ptfunxored[j+5
1295                                         +startbytes
1296                                         +lengthbytes
1297                                         +offsetbytes
1298                                         +somethingbytes
1299                                         +skipbytes
1300                                         +40];
1301                         /*rindex = ptfunxored[j+5
1302                                         +startbytes
1303                                         +lengthbytes
1304                                         +offsetbytes
1305                                         +somethingbytes
1306                                         +skipbytes
1307                                         +24];
1308                         */
1309                         uint32_t sampleoffset = 0;
1310                         switch (offsetbytes) {
1311                         case 4:
1312                                 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
1313                         case 3:
1314                                 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
1315                         case 2:
1316                                 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
1317                         case 1:
1318                                 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
1319                         default:
1320                                 break;
1321                         }
1322                         j+=offsetbytes;
1323                         uint32_t length = 0;
1324                         switch (lengthbytes) {
1325                         case 4:
1326                                 length |= (uint32_t)(ptfunxored[j+8] << 24);
1327                         case 3:
1328                                 length |= (uint32_t)(ptfunxored[j+7] << 16);
1329                         case 2:
1330                                 length |= (uint32_t)(ptfunxored[j+6] << 8);
1331                         case 1:
1332                                 length |= (uint32_t)(ptfunxored[j+5]);
1333                         default:
1334                                 break;
1335                         }
1336                         j+=lengthbytes;
1337                         uint32_t start = 0;
1338                         switch (startbytes) {
1339                         case 4:
1340                                 start |= (uint32_t)(ptfunxored[j+8] << 24);
1341                         case 3:
1342                                 start |= (uint32_t)(ptfunxored[j+7] << 16);
1343                         case 2:
1344                                 start |= (uint32_t)(ptfunxored[j+6] << 8);
1345                         case 1:
1346                                 start |= (uint32_t)(ptfunxored[j+5]);
1347                         default:
1348                                 break;
1349                         }
1350                         j+=startbytes;
1351                         /*
1352                         uint32_t something = 0;
1353                         switch (somethingbytes) {
1354                         case 4:
1355                                 something |= (uint32_t)(ptfunxored[j+8] << 24);
1356                         case 3:
1357                                 something |= (uint32_t)(ptfunxored[j+7] << 16);
1358                         case 2:
1359                                 something |= (uint32_t)(ptfunxored[j+6] << 8);
1360                         case 1:
1361                                 something |= (uint32_t)(ptfunxored[j+5]);
1362                         default:
1363                                 break;
1364                         }
1365                         j+=somethingbytes;
1366                         */
1367                         std::string filename = string(name);
1368                         wav_t f = {
1369                                 filename,
1370                                 (uint16_t)findex,
1371                                 (int64_t)(start*ratefactor),
1372                                 (int64_t)(length*ratefactor),
1373                         };
1374
1375                         //printf("something=%d\n", something);
1376
1377                         vector<wav_t>::iterator begin = actualwavs.begin();
1378                         vector<wav_t>::iterator finish = actualwavs.end();
1379                         vector<wav_t>::iterator found;
1380                         // Add file to list only if it is an actual wav
1381                         if ((found = std::find(begin, finish, f)) != finish) {
1382                                 f.filename = (*found).filename;
1383                                 audiofiles.push_back(f);
1384                                 // Also add plain wav as region
1385                                 std::vector<midi_ev_t> m;
1386                                 region_t r = {
1387                                         name,
1388                                         rindex,
1389                                         (int64_t)(start*ratefactor),
1390                                         (int64_t)(sampleoffset*ratefactor),
1391                                         (int64_t)(length*ratefactor),
1392                                         f,
1393                                         m
1394                                 };
1395                                 regions.push_back(r);
1396                         // Region only
1397                         } else {
1398                                 if (foundin(filename, string(".grp"))) {
1399                                         continue;
1400                                 }
1401                                 std::vector<midi_ev_t> m;
1402                                 region_t r = {
1403                                         name,
1404                                         rindex,
1405                                         (int64_t)(start*ratefactor),
1406                                         (int64_t)(sampleoffset*ratefactor),
1407                                         (int64_t)(length*ratefactor),
1408                                         f,
1409                                         m
1410                                 };
1411                                 regions.push_back(r);
1412                         }
1413                         rindex++;
1414                 }
1415         }
1416
1417         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1418                 return;
1419         }
1420         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
1421                 return;
1422         }
1423         k++;
1424
1425         //  Tracks
1426         uint32_t offset;
1427         uint32_t tracknumber = 0;
1428         uint32_t regionspertrack = 0;
1429         for (;k < len; k++) {
1430                 if (    (ptfunxored[k  ] == 0x5a) &&
1431                         (ptfunxored[k+1] == 0x04)) {
1432                         break;
1433                 }
1434                 if (    (ptfunxored[k  ] == 0x5a) &&
1435                         (ptfunxored[k+1] == 0x02)) {
1436
1437                         uint8_t lengthofname = 0;
1438                         lengthofname = ptfunxored[k+9];
1439                         if (lengthofname == 0x5a) {
1440                                 continue;
1441                         }
1442                         track_t tr;
1443
1444                         regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
1445
1446                         //printf("regions/track=%d\n", regionspertrack);
1447                         char name[256] = {0};
1448                         for (j = 0; j < lengthofname; j++) {
1449                                 name[j] = ptfunxored[j+k+13];
1450                         }
1451                         name[j] = '\0';
1452                         tr.name = string(name);
1453                         tr.index = tracknumber++;
1454
1455                         for (j = k; regionspertrack > 0 && j < len; j++) {
1456                                 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x07", 2);
1457                                 tr.reg.index = (uint16_t)(ptfunxored[j+11] & 0xff)
1458                                         | (uint16_t)((ptfunxored[j+12] << 8) & 0xff00);
1459                                 vector<region_t>::iterator begin = regions.begin();
1460                                 vector<region_t>::iterator finish = regions.end();
1461                                 vector<region_t>::iterator found;
1462                                 if ((found = std::find(begin, finish, tr.reg)) != finish) {
1463                                         tr.reg = (*found);
1464                                 }
1465                                 i = j+16;
1466                                 offset = 0;
1467                                 offset |= (uint32_t)(ptfunxored[i+3] << 24);
1468                                 offset |= (uint32_t)(ptfunxored[i+2] << 16);
1469                                 offset |= (uint32_t)(ptfunxored[i+1] << 8);
1470                                 offset |= (uint32_t)(ptfunxored[i]);
1471                                 tr.reg.startpos = (int64_t)(offset*ratefactor);
1472                                 if (tr.reg.length > 0) {
1473                                         tracks.push_back(tr);
1474                                 }
1475                                 regionspertrack--;
1476                         }
1477                 }
1478         }
1479 }
1480
1481 void
1482 PTFFormat::parserest12(void) {
1483         uint32_t i,j,k,l,m,n;
1484         uint8_t startbytes = 0;
1485         uint8_t lengthbytes = 0;
1486         uint8_t offsetbytes = 0;
1487         uint8_t somethingbytes = 0;
1488         uint8_t skipbytes = 0;
1489         uint32_t maxregions = 0;
1490         uint32_t findex = 0;
1491         uint32_t findex2 = 0;
1492         uint32_t findex3 = 0;
1493         uint16_t rindex = 0;
1494         vector<region_t> groups;
1495         uint16_t groupcount, compoundcount, groupmax;
1496         uint16_t gindex, gindex2;
1497
1498         m = 0;
1499         n = 0;
1500         vector<compound_t> groupmap;
1501         // Find region group total
1502         k = 0;
1503         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1504                 goto nocustom;
1505
1506         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1507                 return;
1508
1509         if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1510                 return;
1511
1512         jumpto(&k, ptfunxored, k+0x500, (const unsigned char *)"\x5a\x03", 2);
1513         k++;
1514
1515         groupcount = 0;
1516         for (i = k; i < len - 0x500; i++) {
1517                 if (!jumpto(&i, ptfunxored, i+0x500, (const unsigned char *)"\x5a\x03", 2))
1518                         break;
1519                 groupcount++;
1520         }
1521         verbose_printf("groupcount=%d\n", groupcount);
1522
1523         // Find start of group names -> group indexes
1524         k = 0;
1525         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1526                 return;
1527
1528         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1529                 return;
1530
1531         if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1532                 return;
1533         k++;
1534
1535         // Skip total number of groups
1536         for (i = 0; i < groupcount; i++) {
1537                 while (k < len) {
1538                         if (            (ptfunxored[k  ] == 0x5a) &&
1539                                         ((ptfunxored[k+1] == 0x03) || (ptfunxored[k+1] == 0x0a))) {
1540                                 break;
1541                         }
1542                         k++;
1543                 }
1544                 k++;
1545         }
1546
1547         while (k < len) {
1548                 if (            (ptfunxored[k  ] == 0x5a) &&
1549                                 (ptfunxored[k+1] & 0x02)) {
1550                         break;
1551                 }
1552                 k++;
1553         }
1554         k++;
1555
1556         while (k < len) {
1557                 if (            (ptfunxored[k  ] == 0x5a) &&
1558                                 (ptfunxored[k+1] & 0x02)) {
1559                         break;
1560                 }
1561                 k++;
1562         }
1563         k++;
1564
1565         verbose_printf("start of groups k=0x%x\n", k);
1566         // Loop over all groups and associate the compound index/name
1567         for (i = 0; i < groupcount; i++) {
1568                 while (k < len) {
1569                         if (            (ptfunxored[k  ] == 0x5a) &&
1570                                         (ptfunxored[k+1] & 0x02)) {
1571                                 break;
1572                         }
1573                         k++;
1574                 }
1575                 if (k > len)
1576                         break;
1577                 gindex = ptfunxored[k+9] | ptfunxored[k+10] << 8;
1578                 gindex2 = ptfunxored[k+3] | ptfunxored[k+4] << 8;
1579
1580                 uint8_t lengthofname = ptfunxored[k+13];
1581                 char name[256] = {0};
1582                 for (l = 0; l < lengthofname; l++) {
1583                         name[l] = ptfunxored[k+17+l];
1584                 }
1585                 name[l] = '\0';
1586
1587                 if (strlen(name) == 0) {
1588                         i--;
1589                         k++;
1590                         continue;
1591                 }
1592                 compound_t c = {
1593                         (uint16_t)i,    // curr_index
1594                         gindex,         // unknown1
1595                         0,              // level
1596                         0,              // ontopof_index
1597                         gindex2,        // next_index
1598                         string(name)
1599                 };
1600                 groupmap.push_back(c);
1601                 k++;
1602         }
1603
1604         // Sort lookup table by group index
1605         //std::sort(glookup.begin(), glookup.end(), regidx_compare);
1606
1607         // print compounds as flattened tree
1608         j = 0;
1609         for (std::vector<compound_t>::iterator i = groupmap.begin(); i != groupmap.end(); ++i) {
1610                 verbose_printf("g(%u) uk(%u) ni(%u) %s\n", i->curr_index, i->unknown1, i->next_index, i->name.c_str());
1611                 j++;
1612         }
1613
1614 nocustom:
1615         // Find region groups
1616         k = 0;
1617         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4))
1618                 return;
1619
1620         if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2))
1621                 return;
1622         for (l = 0; l < 11; l++) {
1623                 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1624                         return;
1625                 k++;
1626         }
1627
1628         /*
1629         // Hack to find actual start of region group information
1630         while (k < len) {
1631                 if ((ptfunxored[k+13] == 0x5a) && (ptfunxored[k+14] & 0xf)) {
1632                         k += 13;
1633                         continue;
1634                 } else {
1635                         if ((ptfunxored[k+9] == 0x5a) && (ptfunxored[k+10] & 0xf)) {
1636                                 k += 9;
1637                                 continue;
1638                         }
1639                 }
1640                 if ((ptfunxored[k] == 0x5a) && (ptfunxored[k+1] & 0xf))
1641                         break;
1642                 k++;
1643         }
1644         */
1645         verbose_printf("hack region groups k=0x%x\n", k);
1646
1647         groupcount = 0;
1648         compoundcount = 0;
1649         j = k;
1650         if (!jumpto(&j, ptfunxored, j+100, (const unsigned char *)"\x5a\x09", 2)) {
1651                 groupmax = 0;
1652         } else {
1653                 groupmax = ptfunxored[j+3] | ptfunxored[j+4] << 8;
1654         }
1655         i = k;
1656         for (; (groupcount < groupmax) && (i < len-70); i++) {
1657                 if (            (ptfunxored[i  ] == 0x5a) &&
1658                                 (ptfunxored[i+1] == 0x03)) {
1659                                 break;
1660                 }
1661                 if (            (ptfunxored[i  ] == 0x5a) &&
1662                                 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1663
1664                         //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1665                         //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1666
1667                         uint8_t lengthofname = ptfunxored[i+9];
1668                         if (ptfunxored[i+13] == 0x5a) {
1669                                 continue;
1670                         }
1671                         char name[256] = {0};
1672                         for (j = 0; j < lengthofname; j++) {
1673                                 name[j] = ptfunxored[i+13+j];
1674                         }
1675                         name[j] = '\0';
1676                         j += i+13;
1677
1678                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1679                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1680                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1681                         somethingbytes = (ptfunxored[j+3] & 0xf);
1682                         skipbytes = ptfunxored[j+4];
1683                         uint16_t regionsingroup = ptfunxored[j+5
1684                                         +startbytes
1685                                         +lengthbytes
1686                                         +offsetbytes
1687                                         +somethingbytes
1688                                         +skipbytes
1689                                         +12]
1690                                 | ptfunxored[j+5
1691                                         +startbytes
1692                                         +lengthbytes
1693                                         +offsetbytes
1694                                         +somethingbytes
1695                                         +skipbytes
1696                                         +13] << 8;
1697
1698                         findex = ptfunxored[j+5
1699                                         +startbytes
1700                                         +lengthbytes
1701                                         +offsetbytes
1702                                         +somethingbytes
1703                                         +skipbytes
1704                                         +37]
1705                                 | ptfunxored[j+5
1706                                         +startbytes
1707                                         +lengthbytes
1708                                         +offsetbytes
1709                                         +somethingbytes
1710                                         +skipbytes
1711                                         +38] << 8;
1712
1713                         uint64_t sampleoffset = 0;
1714                         switch (offsetbytes) {
1715                         case 5:
1716                                 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
1717                         case 4:
1718                                 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
1719                         case 3:
1720                                 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
1721                         case 2:
1722                                 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
1723                         case 1:
1724                                 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
1725                         default:
1726                                 break;
1727                         }
1728                         j+=offsetbytes;
1729                         uint64_t length = 0;
1730                         switch (lengthbytes) {
1731                         case 5:
1732                                 length |= (uint64_t)(ptfunxored[j+9]) << 32;
1733                         case 4:
1734                                 length |= (uint64_t)(ptfunxored[j+8]) << 24;
1735                         case 3:
1736                                 length |= (uint64_t)(ptfunxored[j+7]) << 16;
1737                         case 2:
1738                                 length |= (uint64_t)(ptfunxored[j+6]) << 8;
1739                         case 1:
1740                                 length |= (uint64_t)(ptfunxored[j+5]);
1741                         default:
1742                                 break;
1743                         }
1744                         j+=lengthbytes;
1745                         uint64_t start = 0;
1746                         switch (startbytes) {
1747                         case 5:
1748                                 start |= (uint64_t)(ptfunxored[j+9]) << 32;
1749                         case 4:
1750                                 start |= (uint64_t)(ptfunxored[j+8]) << 24;
1751                         case 3:
1752                                 start |= (uint64_t)(ptfunxored[j+7]) << 16;
1753                         case 2:
1754                                 start |= (uint64_t)(ptfunxored[j+6]) << 8;
1755                         case 1:
1756                                 start |= (uint64_t)(ptfunxored[j+5]);
1757                         default:
1758                                 break;
1759                         }
1760                         j+=startbytes;
1761
1762                         if (offsetbytes == 5)
1763                                 sampleoffset -= 1000000000000ul;
1764                         if (startbytes == 5)
1765                                 start -= 1000000000000ul;
1766
1767                         std::string filename = string(name);
1768                         wav_t f = {
1769                                 filename,
1770                                 (uint16_t)findex,
1771                                 (int64_t)(start*ratefactor),
1772                                 (int64_t)(length*ratefactor),
1773                         };
1774
1775                         if (strlen(name) == 0) {
1776                                 continue;
1777                         }
1778                         if (length == 0) {
1779                                 continue;
1780                         }
1781                         //if (foundin(filename, string(".grp")) && !regionsingroup && !findex) {
1782                         //      // Empty region group
1783                         //      verbose_printf("        EMPTY: %s\n", name);
1784                         //      continue;
1785                         if (regionsingroup) {
1786                                 // Active region grouping
1787                                 // Iterate parsing all the regions in the group
1788                                 verbose_printf("\nGROUP\t%d %s\n", groupcount, name);
1789                                 m = j;
1790                                 n = j+16;
1791
1792                                 for (l = 0; l < regionsingroup; l++) {
1793                                         if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
1794                                                 return;
1795                                         }
1796                                         n++;
1797                                 }
1798                                 n--;
1799                                 //printf("n=0x%x\n", n+112);
1800                                 //findex = ptfunxored[n+112] | (ptfunxored[n+113] << 8);
1801                                 findex = ptfunxored[i-11] | ptfunxored[i-10] << 8;
1802                                 findex2 = ptfunxored[n+108] | (ptfunxored[n+109] << 8);
1803                                 //findex2= rindex; //XXX
1804                                 // Find wav with correct findex
1805                                 vector<wav_t>::iterator wave = actualwavs.end();
1806                                 for (vector<wav_t>::iterator aw = actualwavs.begin();
1807                                                 aw != actualwavs.end(); ++aw) {
1808                                         if (aw->index == findex) {
1809                                                 wave = aw;
1810                                         }
1811                                 }
1812                                 if (wave == actualwavs.end())
1813                                         return;
1814
1815                                 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1816                                         return;
1817                                 n += 37;
1818                                 //rindex = ptfunxored[n] | (ptfunxored[n+1] << 8);
1819                                 for (l = 0; l < regionsingroup; l++) {
1820                                         if (!jumpto(&m, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1821                                                 return;
1822
1823                                         m += 37;
1824                                         rindex = ptfunxored[m] | (ptfunxored[m+1] << 8);
1825
1826                                         m += 12;
1827                                         sampleoffset = 0;
1828                                         switch (offsetbytes) {
1829                                         case 5:
1830                                                 sampleoffset |= (uint64_t)(ptfunxored[m+4]) << 32;
1831                                         case 4:
1832                                                 sampleoffset |= (uint64_t)(ptfunxored[m+3]) << 24;
1833                                         case 3:
1834                                                 sampleoffset |= (uint64_t)(ptfunxored[m+2]) << 16;
1835                                         case 2:
1836                                                 sampleoffset |= (uint64_t)(ptfunxored[m+1]) << 8;
1837                                         case 1:
1838                                                 sampleoffset |= (uint64_t)(ptfunxored[m]);
1839                                         default:
1840                                                 break;
1841                                         }
1842                                         m+=offsetbytes+3;
1843                                         start = 0;
1844                                         switch (offsetbytes) {
1845                                         case 5:
1846                                                 start |= (uint64_t)(ptfunxored[m+4]) << 32;
1847                                         case 4:
1848                                                 start |= (uint64_t)(ptfunxored[m+3]) << 24;
1849                                         case 3:
1850                                                 start |= (uint64_t)(ptfunxored[m+2]) << 16;
1851                                         case 2:
1852                                                 start |= (uint64_t)(ptfunxored[m+1]) << 8;
1853                                         case 1:
1854                                                 start |= (uint64_t)(ptfunxored[m]);
1855                                         default:
1856                                                 break;
1857                                         }
1858                                         m+=offsetbytes+3;
1859                                         length = 0;
1860                                         switch (lengthbytes) {
1861                                         case 5:
1862                                                 length |= (uint64_t)(ptfunxored[m+4]) << 32;
1863                                         case 4:
1864                                                 length |= (uint64_t)(ptfunxored[m+3]) << 24;
1865                                         case 3:
1866                                                 length |= (uint64_t)(ptfunxored[m+2]) << 16;
1867                                         case 2:
1868                                                 length |= (uint64_t)(ptfunxored[m+1]) << 8;
1869                                         case 1:
1870                                                 length |= (uint64_t)(ptfunxored[m]);
1871                                         default:
1872                                                 break;
1873                                         }
1874                                         m+=8;
1875                                         findex3 = ptfunxored[m] | (ptfunxored[m+1] << 8);
1876                                         sampleoffset -= 1000000000000ul;
1877                                         start -= 1000000000000ul;
1878
1879                                         /*
1880                                         // Find wav with correct findex
1881                                         vector<wav_t>::iterator wave = actualwavs.end();
1882                                         for (vector<wav_t>::iterator aw = actualwavs.begin();
1883                                                         aw != actualwavs.end(); ++aw) {
1884                                                 if (aw->index == (glookup.begin()+findex2)->startpos) {
1885                                                         wave = aw;
1886                                                 }
1887                                         }
1888                                         if (wave == actualwavs.end())
1889                                                 return;
1890                                         // findex is the true source
1891                                         std::vector<midi_ev_t> md;
1892                                         region_t r = {
1893                                                 name,
1894                                                 (uint16_t)rindex,
1895                                                 (int64_t)findex, //(start*ratefactor),
1896                                                 (int64_t)findex2, //(sampleoffset*ratefactor),
1897                                                 (int64_t)findex3, //(length*ratefactor),
1898                                                 *wave,
1899                                                 md
1900                                         };
1901                                         groups.push_back(r);
1902                                         */
1903                                         vector<compound_t>::iterator g = groupmap.begin()+findex2;
1904                                         if (g >= groupmap.end())
1905                                                 continue;
1906                                         compound_t c;
1907                                         c.name = string(g->name);
1908                                         c.curr_index = compoundcount;
1909                                         c.level = findex;
1910                                         c.ontopof_index = findex3;
1911                                         c.next_index = g->next_index;
1912                                         c.unknown1 = g->unknown1;
1913                                         compounds.push_back(c);
1914                                         verbose_printf("COMPOUND\tc(%d) %s (%d %d) -> c(%u) %s\n", c.curr_index, c.name.c_str(), c.level, c.ontopof_index, c.next_index, name);
1915                                         compoundcount++;
1916                                 }
1917                                 groupcount++;
1918                         }
1919                 }
1920         }
1921         j = 0;
1922
1923         // Start pure regions
1924         k = m != 0 ? m : k - 1;
1925         if (!jumpto(&k, ptfunxored, k+64, (const unsigned char *)"\x5a\x05", 2))
1926                 jumpto(&k, ptfunxored, k+128, (const unsigned char *)"\x5a\x02", 2);
1927
1928         verbose_printf("pure regions k=0x%x\n", k);
1929
1930         maxregions |= (uint32_t)(ptfunxored[k-4]);
1931         maxregions |= (uint32_t)(ptfunxored[k-3]) << 8;
1932         maxregions |= (uint32_t)(ptfunxored[k-2]) << 16;
1933         maxregions |= (uint32_t)(ptfunxored[k-1]) << 24;
1934
1935         verbose_printf("maxregions=%u\n", maxregions);
1936         rindex = 0;
1937         for (i = k; rindex < maxregions && i < len; i++) {
1938                 if (            (ptfunxored[i  ] == 0xff) &&
1939                                 (ptfunxored[i+1] == 0x5a) &&
1940                                 (ptfunxored[i+2] == 0x01)) {
1941                         break;
1942                 }
1943                 //if (          (ptfunxored[i  ] == 0x5a) &&
1944                 //              (ptfunxored[i+1] == 0x03)) {
1945                 //      break;
1946                 //}
1947                 if (            (ptfunxored[i  ] == 0x5a) &&
1948                                 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1949
1950                         //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1951                         //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1952
1953                         uint8_t lengthofname = ptfunxored[i+9];
1954                         if (ptfunxored[i+13] == 0x5a) {
1955                                 continue;
1956                         }
1957                         char name[256] = {0};
1958                         for (j = 0; j < lengthofname; j++) {
1959                                 name[j] = ptfunxored[i+13+j];
1960                         }
1961                         name[j] = '\0';
1962                         j += i+13;
1963
1964                         offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1965                         lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1966                         startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1967                         somethingbytes = (ptfunxored[j+3] & 0xf);
1968                         skipbytes = ptfunxored[j+4];
1969                         findex = ptfunxored[j+5
1970                                         +startbytes
1971                                         +lengthbytes
1972                                         +offsetbytes
1973                                         +somethingbytes
1974                                         +skipbytes
1975                                         +37]
1976                                 | ptfunxored[j+5
1977                                         +startbytes
1978                                         +lengthbytes
1979                                         +offsetbytes
1980                                         +somethingbytes
1981                                         +skipbytes
1982                                         +38] << 8;
1983
1984                         uint64_t sampleoffset = 0;
1985                         switch (offsetbytes) {
1986                         case 5:
1987                                 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
1988                         case 4:
1989                                 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
1990                         case 3:
1991                                 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
1992                         case 2:
1993                                 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
1994                         case 1:
1995                                 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
1996                         default:
1997                                 break;
1998                         }
1999                         j+=offsetbytes;
2000                         uint64_t length = 0;
2001                         switch (lengthbytes) {
2002                         case 5:
2003                                 length |= (uint64_t)(ptfunxored[j+9]) << 32;
2004                         case 4:
2005                                 length |= (uint64_t)(ptfunxored[j+8]) << 24;
2006                         case 3:
2007                                 length |= (uint64_t)(ptfunxored[j+7]) << 16;
2008                         case 2:
2009                                 length |= (uint64_t)(ptfunxored[j+6]) << 8;
2010                         case 1:
2011                                 length |= (uint64_t)(ptfunxored[j+5]);
2012                         default:
2013                                 break;
2014                         }
2015                         j+=lengthbytes;
2016                         uint64_t start = 0;
2017                         switch (startbytes) {
2018                         case 5:
2019                                 start |= (uint64_t)(ptfunxored[j+9]) << 32;
2020                         case 4:
2021                                 start |= (uint64_t)(ptfunxored[j+8]) << 24;
2022                         case 3:
2023                                 start |= (uint64_t)(ptfunxored[j+7]) << 16;
2024                         case 2:
2025                                 start |= (uint64_t)(ptfunxored[j+6]) << 8;
2026                         case 1:
2027                                 start |= (uint64_t)(ptfunxored[j+5]);
2028                         default:
2029                                 break;
2030                         }
2031                         j+=startbytes;
2032
2033                         if (offsetbytes == 5)
2034                                 sampleoffset -= 1000000000000ul;
2035                         if (startbytes == 5)
2036                                 start -= 1000000000000ul;
2037
2038                         std::string filename = string(name);
2039                         wav_t f = {
2040                                 filename,
2041                                 (uint16_t)findex,
2042                                 (int64_t)(start*ratefactor),
2043                                 (int64_t)(length*ratefactor),
2044                         };
2045
2046                         if (strlen(name) == 0) {
2047                                 continue;
2048                         }
2049                         if (length == 0) {
2050                                 continue;
2051                         }
2052                         // Regular region mapping to a source
2053                         uint32_t n = j;
2054                         if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2055                                 return;
2056                         //printf("XXX=%d\n", ptfunxored[n+12] | ptfunxored[n+13]<<8);
2057
2058                         // Find wav with correct findex
2059                         vector<wav_t>::iterator wave = actualwavs.end();
2060                         for (vector<wav_t>::iterator aw = actualwavs.begin();
2061                                         aw != actualwavs.end(); ++aw) {
2062                                 if (aw->index == findex) {
2063                                         wave = aw;
2064                                 }
2065                         }
2066                         if (wave == actualwavs.end()) {
2067                                 verbose_printf("missing source with findex\n");
2068                                 continue;
2069                         }
2070                         //verbose_printf("\n+r(%d) w(%d) REGION: %s st(%lx)x%u of(%lx)x%u ln(%lx)x%u\n", rindex, findex, name, start, startbytes, sampleoffset, offsetbytes, length, lengthbytes);
2071                         verbose_printf("REGION\tg(NA)\tr(%d)\tw(%d) %s(%s)\n", rindex, findex, name, wave->filename.c_str());
2072                         std::vector<midi_ev_t> md;
2073                         region_t r = {
2074                                 name,
2075                                 rindex,
2076                                 (int64_t)(start*ratefactor),
2077                                 (int64_t)(sampleoffset*ratefactor),
2078                                 (int64_t)(length*ratefactor),
2079                                 *wave,
2080                                 md
2081                         };
2082                         regions.push_back(r);
2083                         rindex++;
2084                 }
2085         }
2086
2087         // print compounds
2088         vector<uint16_t> rootnodes;
2089         bool found = false;
2090
2091         j = 0;
2092         for (vector<compound_t>::iterator cmp = compounds.begin();
2093                         cmp != compounds.end(); ++cmp) {
2094                 found = false;
2095                 for (vector<compound_t>::iterator tmp = compounds.begin();
2096                                 tmp != compounds.end(); ++tmp) {
2097                         if (tmp == cmp)
2098                                 continue;
2099                         if (tmp->ontopof_index == cmp->curr_index)
2100                                 found = true;
2101                 }
2102                 // Collect a vector of all the root nodes (no others point to)
2103                 if (!found)
2104                         rootnodes.push_back(cmp->curr_index);
2105         }
2106
2107         for (vector<uint16_t>::iterator rt = rootnodes.begin();
2108                         rt != rootnodes.end(); ++rt) {
2109                 vector<compound_t>::iterator cmp = compounds.begin()+(*rt);
2110                 // Now we are at a root node, follow to leaf
2111                 if (cmp >= compounds.end())
2112                         continue;
2113
2114                 verbose_printf("----\n");
2115
2116                 for (; cmp < compounds.end() && cmp->curr_index != cmp->next_index;
2117                                 cmp = compounds.begin()+cmp->next_index) {
2118
2119                         // Find region
2120                         vector<region_t>::iterator r = regions.end();
2121                         for (vector<region_t>::iterator rs = regions.begin();
2122                                         rs != regions.end(); rs++) {
2123                                 if (rs->index == cmp->unknown1 + cmp->level) {
2124                                         r = rs;
2125                                 }
2126                         }
2127                         if (r == regions.end())
2128                                 continue;
2129                         verbose_printf("\t->cidx(%u) pl(%u)+ridx(%u) cflags(0x%x) ?(%u) grp(%s) reg(%s)\n", cmp->curr_index, cmp->level, cmp->unknown1, cmp->ontopof_index, cmp->next_index, cmp->name.c_str(), r->name.c_str());
2130                 }
2131                 // Find region
2132                 vector<region_t>::iterator r = regions.end();
2133                 for (vector<region_t>::iterator rs = regions.begin();
2134                                 rs != regions.end(); rs++) {
2135                         if (rs->index == cmp->unknown1 + cmp->level) {
2136                                 r = rs;
2137                         }
2138                 }
2139                 if (r == regions.end())
2140                         continue;
2141                 verbose_printf("\tLEAF->cidx(%u) pl(%u)+ridx(%u) cflags(0x%x) ?(%u) grp(%s) reg(%s)\n", cmp->curr_index, cmp->level, cmp->unknown1, cmp->ontopof_index, cmp->next_index, cmp->name.c_str(), r->name.c_str());
2142         }
2143
2144         // Start grouped regions
2145
2146         // Print region groups mapped to sources
2147         for (vector<region_t>::iterator a = groups.begin(); a != groups.end(); ++a) {
2148                 // Find wav with findex
2149                 vector<wav_t>::iterator wav = audiofiles.end();
2150                 for (vector<wav_t>::iterator ws = audiofiles.begin();
2151                                 ws != audiofiles.end(); ws++) {
2152                         if (ws->index == a->startpos) {
2153                                 wav = ws;
2154                         }
2155                 }
2156                 if (wav == audiofiles.end())
2157                         continue;
2158
2159                 // Find wav with findex2
2160                 vector<wav_t>::iterator wav2 = audiofiles.end();
2161                 for (vector<wav_t>::iterator ws = audiofiles.begin();
2162                                 ws != audiofiles.end(); ws++) {
2163                         if (ws->index == a->sampleoffset) {
2164                                 wav2 = ws;
2165                         }
2166                 }
2167                 if (wav2 == audiofiles.end())
2168                         continue;
2169
2170                 verbose_printf("Group: %s -> %s OR %s\n", a->name.c_str(), wav->filename.c_str(), wav2->filename.c_str());
2171         }
2172
2173         //filter(regions);
2174         //resort(regions);
2175
2176         //  Tracks
2177         uint32_t offset;
2178         uint32_t tracknumber = 0;
2179         uint32_t regionspertrack = 0;
2180         uint32_t maxtracks = 0;
2181
2182         // Total tracks
2183         j = k;
2184         if (!jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x03\x00", 3))
2185                 return;
2186         maxtracks |= (uint32_t)(ptfunxored[j-4]);
2187         maxtracks |= (uint32_t)(ptfunxored[j-3]) << 8;
2188         maxtracks |= (uint32_t)(ptfunxored[j-2]) << 16;
2189         maxtracks |= (uint32_t)(ptfunxored[j-1]) << 24;
2190
2191         // Jump to start of region -> track mappings
2192         if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x08", 2)) {
2193                 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
2194                         return;
2195         } else if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x0a", 2)) {
2196                 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2197                         return;
2198         } else {
2199                 return;
2200         }
2201         verbose_printf("tracks k=0x%x\n", k);
2202
2203         for (;k < len; k++) {
2204                 if (    (ptfunxored[k  ] == 0x5a) &&
2205                         (ptfunxored[k+1] & 0x04)) {
2206                         break;
2207                 }
2208                 if (    (ptfunxored[k  ] == 0x5a) &&
2209                         (ptfunxored[k+1] & 0x02)) {
2210
2211                         uint8_t lengthofname = 0;
2212                         lengthofname = ptfunxored[k+9];
2213                         if (lengthofname == 0x5a) {
2214                                 continue;
2215                         }
2216                         track_t tr;
2217
2218                         regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
2219
2220                         //printf("regions/track=%d\n", regionspertrack);
2221                         char name[256] = {0};
2222                         for (j = 0; j < lengthofname; j++) {
2223                                 name[j] = ptfunxored[j+k+13];
2224                         }
2225                         name[j] = '\0';
2226                         tr.name = string(name);
2227                         tr.index = tracknumber++;
2228
2229                         for (j = k+18+lengthofname; regionspertrack > 0 && j < len; j++) {
2230                                 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a", 1);
2231                                 bool isgroup = ptfunxored[j+27] > 0;
2232                                 if (isgroup) {
2233                                         tr.reg.name = string("");
2234                                         tr.reg.length = 0;
2235                                         //tr.reg.index = 0xffff;
2236                                         verbose_printf("TRACK: t(%d) g(%d) G(%s) -> T(%s)\n",
2237                                                 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2238                                 } else {
2239                                         tr.reg.index = ((uint16_t)(ptfunxored[j+11]) & 0xff)
2240                                                 | (((uint16_t)(ptfunxored[j+12]) << 8) & 0xff00);
2241                                         vector<region_t>::iterator begin = regions.begin();
2242                                         vector<region_t>::iterator finish = regions.end();
2243                                         vector<region_t>::iterator found;
2244                                         if ((found = std::find(begin, finish, tr.reg)) != finish) {
2245                                                 tr.reg = *found;
2246                                         }
2247                                         verbose_printf("TRACK: t(%d) r(%d) R(%s) -> T(%s)\n",
2248                                                 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2249                                 }
2250                                 i = j+16;
2251                                 offset = 0;
2252                                 offset |= (uint32_t)(ptfunxored[i+3] << 24);
2253                                 offset |= (uint32_t)(ptfunxored[i+2] << 16);
2254                                 offset |= (uint32_t)(ptfunxored[i+1] << 8);
2255                                 offset |= (uint32_t)(ptfunxored[i]);
2256                                 tr.reg.startpos = (int64_t)(offset*ratefactor);
2257                                 if (tr.reg.length > 0) {
2258                                         tracks.push_back(tr);
2259                                 }
2260                                 regionspertrack--;
2261
2262                                 jumpto(&j, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);
2263                                 j += 12;
2264                         }
2265                 }
2266         }
2267 }