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