2 * libptformat - a library to read ProTools sessions
4 * Copyright (C) 2015 Damien Zammit
5 * Copyright (C) 2015 Robin Gareus
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.
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.
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
29 #include <glib/gstdio.h>
31 #include "ptformat/ptfformat.h"
34 #define verbose_printf(...) printf(__VA_ARGS__)
36 #define verbose_printf(...)
41 static bool wavidx_compare(PTFFormat::wav_t& w1, PTFFormat::wav_t& w2) {
42 return w1.index < w2.index;
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);
49 static bool regidx_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) {
50 return r1.index < r2.index;
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);
58 hexdump(uint8_t *data, int len)
62 for (i = 0; i < len; i += step) {
63 printf("0x%02X: ", i);
65 if (end > len) end = len;
66 for (j = i; j < end; j++) {
67 printf("0x%02X ", data[j]);
69 for (j = i; j < end; j++) {
70 if (data[j] < 128 && data[j] > 32)
71 printf("%c", data[j]);
79 PTFFormat::PTFFormat() : version(0), product(NULL), ptfunxored(NULL) {
82 PTFFormat::~PTFFormat() {
87 PTFFormat::u_endian_read2(unsigned char *buf, bool bigendian)
90 return ((uint16_t)(buf[0]) << 8) | (uint16_t)(buf[1]);
92 return ((uint16_t)(buf[1]) << 8) | (uint16_t)(buf[0]);
97 PTFFormat::u_endian_read3(unsigned char *buf, bool bigendian)
100 return ((uint32_t)(buf[0]) << 16) |
101 ((uint32_t)(buf[1]) << 8) |
104 return ((uint32_t)(buf[2]) << 16) |
105 ((uint32_t)(buf[1]) << 8) |
111 PTFFormat::u_endian_read4(unsigned char *buf, bool bigendian)
114 return ((uint32_t)(buf[0]) << 24) |
115 ((uint32_t)(buf[1]) << 16) |
116 ((uint32_t)(buf[2]) << 8) |
119 return ((uint32_t)(buf[3]) << 24) |
120 ((uint32_t)(buf[2]) << 16) |
121 ((uint32_t)(buf[1]) << 8) |
127 PTFFormat::u_endian_read5(unsigned char *buf, bool bigendian)
130 return ((uint64_t)(buf[0]) << 32) |
131 ((uint64_t)(buf[1]) << 24) |
132 ((uint64_t)(buf[2]) << 16) |
133 ((uint64_t)(buf[3]) << 8) |
136 return ((uint64_t)(buf[4]) << 32) |
137 ((uint64_t)(buf[3]) << 24) |
138 ((uint64_t)(buf[2]) << 16) |
139 ((uint64_t)(buf[1]) << 8) |
145 PTFFormat::cleanup(void) {
161 PTFFormat::foundat(unsigned char *haystack, uint64_t n, const char *needle) {
163 uint64_t i, j, needle_n;
164 needle_n = strlen(needle);
166 for (i = 0; i < n; i++) {
168 for (j = 0; j < needle_n; j++) {
169 if (haystack[i+j] != needle[j]) {
181 PTFFormat::jumpto(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
183 uint64_t k = *currpos;
184 while (k + needlelen < maxoffset) {
185 bool foundall = true;
186 for (i = 0; i < needlelen; i++) {
187 if (buf[k+i] != needle[i]) {
202 PTFFormat::jumpback(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
204 uint64_t k = *currpos;
205 while (k > 0 && k + needlelen < maxoffset) {
206 bool foundall = true;
207 for (i = 0; i < needlelen; i++) {
208 if (buf[k+i] != needle[i]) {
223 PTFFormat::foundin(std::string haystack, std::string needle) {
224 size_t found = haystack.find(needle);
225 if (found != std::string::npos) {
232 /* Return values: 0 success
233 -1 could not decrypt pt session
236 PTFFormat::unxor(std::string path) {
238 unsigned char xxor[256];
246 if (! (fp = g_fopen(path.c_str(), "rb"))) {
250 fseek(fp, 0, SEEK_END);
257 if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
258 /* Silently fail -- out of memory*/
264 /* The first 20 bytes are always unencrypted */
265 fseek(fp, 0x00, SEEK_SET);
266 i = fread(ptfunxored, 1, 0x14, fp);
272 xor_type = ptfunxored[0x12];
273 xor_value = ptfunxored[0x13];
276 // xor_type 0x01 = ProTools 5, 6, 7, 8 and 9
277 // xor_type 0x05 = ProTools 10, 11, 12
280 xor_delta = gen_xor_delta(xor_value, 53, false);
283 xor_delta = gen_xor_delta(xor_value, 11, true);
290 /* Generate the xor_key */
291 for (i=0; i < xor_len; i++)
292 xxor[i] = (i * xor_delta) & 0xff;
294 /* hexdump(xxor, xor_len); */
296 /* Read file and decrypt rest of file */
298 fseek(fp, i, SEEK_SET);
299 while (fread(&ct, 1, 1, fp) != 0) {
300 uint8_t xor_index = (xor_type == 0x01) ? i & 0xff : (i >> 12) & 0xff;
301 ptfunxored[i++] = ct ^ xxor[xor_index];
307 /* Return values: 0 success
308 -1 could not parse pt session
311 PTFFormat::load(std::string ptf, int64_t targetsr) {
321 if (version < 5 || version > 12)
324 targetrate = targetsr;
333 PTFFormat::parse_version() {
334 uint32_t seg_len,str_len;
335 uint8_t *data = ptfunxored + 0x14;
336 uintptr_t data_end = ((uintptr_t)ptfunxored) + 0x100;
338 bool success = false;
340 while( ((uintptr_t)data < data_end) && (success == false) ) {
342 if (data[0] != 0x5a) {
348 /* Skip segment header */
350 if (data[0] == 0 && data[1] == 0) {
355 is_bigendian = false;
357 seg_len = u_endian_read4(&data[0], is_bigendian);
361 if (!(seg_type == 0x04 || seg_type == 0x03) || data[0] != 0x03) {
362 /* Go to next segment */
366 /* Skip 0x03 0x00 0x00 */
369 str_len = (*(uint8_t *)data);
370 if (! (product = (uint8_t *)malloc((str_len+1) * sizeof(uint8_t)))) {
379 memcpy(product, data, str_len);
380 product[str_len] = 0;
384 /* Skip 0x03 0x00 0x00 0x00 */
396 /* If the above does not work, try other heuristics */
397 if ((uintptr_t)data >= data_end - seg_len) {
398 version = ptfunxored[0x40];
400 version = ptfunxored[0x3d];
403 version = ptfunxored[0x3a] + 2;
413 PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) {
415 for (i = 0; i < 256; i++) {
416 if (((i * mul) & 0xff) == xor_value) {
417 return (negative) ? i * (-1) : i;
425 PTFFormat::parse(void) {
429 if (sessionrate < 44100 || sessionrate > 192000)
434 } else if (version == 7) {
437 if (sessionrate < 44100 || sessionrate > 192000)
442 } else if (version == 8) {
445 if (sessionrate < 44100 || sessionrate > 192000)
450 } else if (version == 9) {
453 if (sessionrate < 44100 || sessionrate > 192000)
458 } else if (version == 10 || version == 11 || version == 12) {
461 if (sessionrate < 44100 || sessionrate > 192000)
474 PTFFormat::setrates(void) {
476 if (sessionrate != 0) {
477 ratefactor = (float)targetrate / sessionrate;
482 PTFFormat::parse5header(void) {
485 // Find session sample rate
488 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x02", 3)) {
489 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2);
493 sessionrate = u_endian_read3(&ptfunxored[k+12], is_bigendian);
497 PTFFormat::parse7header(void) {
500 // Find session sample rate
503 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x05", 3);
505 sessionrate = u_endian_read3(&ptfunxored[k+12], is_bigendian);
509 PTFFormat::parse8header(void) {
512 // Find session sample rate
515 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x05", 2);
517 sessionrate = u_endian_read3(&ptfunxored[k+11], is_bigendian);
521 PTFFormat::parse9header(void) {
524 // Find session sample rate
527 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2);
529 sessionrate = u_endian_read3(&ptfunxored[k+11], is_bigendian);
533 PTFFormat::parse10header(void) {
536 // Find session sample rate
539 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x09", 2);
541 sessionrate = u_endian_read3(&ptfunxored[k+11], is_bigendian);
545 PTFFormat::parserest5(void) {
547 uint64_t regionspertrack, lengthofname, numberofregions;
548 uint64_t startbytes, lengthbytes, offsetbytes, somethingbytes, skipbytes;
549 uint16_t tracknumber = 0;
552 unsigned char tag1[3];
553 unsigned char tag2[3];
554 unsigned char tag3[3];
557 tag1[0] = tag2[0] = tag3[0] = '\x5a';
558 tag1[1] = tag2[1] = tag3[1] = '\x00';
563 tag1[0] = tag2[0] = tag3[0] = '\x5a';
567 tag1[2] = tag2[2] = tag3[2] = '\x00';
570 // Find Source->Region info
572 for (i = 0; i < 2; i++) {
573 jumpto(&k, ptfunxored, len, tag3, 3);
576 jumpto(&k, ptfunxored, len, tag2, 3);
578 numberofregions = u_endian_read4(&ptfunxored[k-13], is_bigendian);
581 while (numberofregions > 0 && i < len) {
582 jumpto(&i, ptfunxored, len, tag2, 3);
584 uint32_t lengthofname = u_endian_read4(&ptfunxored[i+9], is_bigendian);
586 char name[256] = {0};
587 for (j = 0; j < lengthofname; j++) {
588 name[j] = ptfunxored[i+13+j];
592 //uint8_t disabled = ptfunxored[j];
595 offsetbytes = (ptfunxored[j+4] & 0xf0) >> 4;
596 lengthbytes = (ptfunxored[j+3] & 0xf0) >> 4;
597 startbytes = (ptfunxored[j+2] & 0xf0) >> 4;
598 somethingbytes = (ptfunxored[j+2] & 0xf);
599 skipbytes = ptfunxored[j+1];
601 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4; //3
602 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
603 startbytes = (ptfunxored[j+3] & 0xf0) >> 4; //1
604 somethingbytes = (ptfunxored[j+3] & 0xf);
605 skipbytes = ptfunxored[j+4];
607 findex = u_endian_read4(&ptfunxored[j+5
612 +skipbytes], is_bigendian);
614 uint32_t sampleoffset = 0;
615 switch (offsetbytes) {
617 sampleoffset = u_endian_read4(&ptfunxored[j+5], false);
620 sampleoffset = u_endian_read3(&ptfunxored[j+5], false);
623 sampleoffset = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
626 sampleoffset = (uint32_t)(ptfunxored[j+5]);
633 switch (lengthbytes) {
635 length = u_endian_read4(&ptfunxored[j+5], false);
638 length = u_endian_read3(&ptfunxored[j+5], false);
641 length = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
644 length = (uint32_t)(ptfunxored[j+5]);
651 switch (startbytes) {
653 start = u_endian_read4(&ptfunxored[j+5], false);
656 start = u_endian_read3(&ptfunxored[j+5], false);
659 start = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
662 start = (uint32_t)(ptfunxored[j+5]);
669 std::string filename = string(name);
673 (int64_t)(start*ratefactor),
674 (int64_t)(length*ratefactor),
677 vector<wav_t>::iterator begin = actualwavs.begin();
678 vector<wav_t>::iterator finish = actualwavs.end();
679 vector<wav_t>::iterator found;
680 if ((found = std::find(begin, finish, f)) != finish) {
681 f.filename = (*found).filename;
683 std::vector<midi_ev_t> m;
687 (int64_t)(start*ratefactor),
688 (int64_t)(sampleoffset*ratefactor),
689 (int64_t)(length*ratefactor),
693 regions.push_back(r);
699 // Find Region->Track info
702 for (i = 0; i < 4; i++) {
703 jumpto(&k, ptfunxored, len, tag3, 3);
709 if (jumpto(&j, ptfunxored, j+13+3, tag1, 3)) {
711 if (jumpto(&j, ptfunxored, j+13+3, tag1, 3)) {
713 if (jumpto(&j, ptfunxored, j+13+3, tag1, 3)) {
714 if ((j == k+26) && (ptfunxored[j-13] == '\x5a') && (ptfunxored[j-26] == '\x5a')) {
725 if (ptfunxored[k+13] == '\x5a') {
729 // Start parsing track info
732 if ( (ptfunxored[k ] == 0xff) &&
733 (ptfunxored[k+1] == 0xff)) {
736 jumpto(&k, ptfunxored, len, tag1, 3);
738 lengthofname = u_endian_read4(&ptfunxored[k+9], is_bigendian);
739 if (ptfunxored[k+13] == 0x5a) {
743 char name[256] = {0};
744 for (j = 0; j < lengthofname; j++) {
745 name[j] = ptfunxored[k+13+j];
748 regionspertrack = u_endian_read4(&ptfunxored[k+13+j], is_bigendian);
749 for (i = 0; i < regionspertrack; i++) {
750 jumpto(&k, ptfunxored, len, tag3, 3);
753 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
754 //somethingbytes = (ptfunxored[j+2] & 0xf);
755 lengthbytes = (ptfunxored[j+3] & 0xf0) >> 4;
756 startbytes = (ptfunxored[j+4] & 0xf0) >> 4;
758 offsetbytes = (ptfunxored[j+4] & 0xf0) >> 4;
759 //somethingbytes = (ptfunxored[j+3] & 0xf);
760 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
761 startbytes = (ptfunxored[j+1] & 0xf0) >> 4;
763 rindex = u_endian_read4(&ptfunxored[k+11], is_bigendian);
765 switch (startbytes) {
767 start = u_endian_read4(&ptfunxored[j+5], false);
770 start = u_endian_read3(&ptfunxored[j+5], false);
773 start = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
776 start = (uint32_t)(ptfunxored[j+5]);
783 switch (lengthbytes) {
785 length = u_endian_read4(&ptfunxored[j+5], false);
788 length = u_endian_read3(&ptfunxored[j+5], false);
791 length = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
794 length = (uint32_t)(ptfunxored[j+5]);
800 uint32_t sampleoffset = 0;
801 switch (offsetbytes) {
803 sampleoffset = u_endian_read4(&ptfunxored[j+5], false);
806 sampleoffset = u_endian_read3(&ptfunxored[j+5], false);
809 sampleoffset = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
812 sampleoffset = (uint32_t)(ptfunxored[j+5]);
825 vector<region_t>::iterator begin = regions.begin();
826 vector<region_t>::iterator finish = regions.end();
827 vector<region_t>::iterator found;
828 if ((found = std::find(begin, finish, r)) != finish) {
832 tr.reg.startpos = (int64_t)(start*ratefactor);
833 tr.reg.sampleoffset = (int64_t)(sampleoffset*ratefactor);
834 tr.reg.length = (int64_t)(length*ratefactor);
835 vector<track_t>::iterator ti;
836 vector<track_t>::iterator bt = tracks.begin();
837 vector<track_t>::iterator et = tracks.end();
838 if ((ti = std::find(bt, et, tr)) != et) {
839 tracknumber = (*ti).index;
845 (uint16_t)tracknumber,
849 //if (tr.reg.length > 0) {
859 PTFFormat::resort(std::vector<wav_t>& ws) {
861 std::sort(ws.begin(), ws.end());
862 for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) {
869 PTFFormat::resort(std::vector<region_t>& rs) {
871 //std::sort(rs.begin(), rs.end());
872 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
879 PTFFormat::filter(std::vector<region_t>& rs) {
880 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
887 PTFFormat::parseaudio5(void) {
889 uint64_t lengthofname, wavnumber;
890 uint32_t numberofwavs;
891 unsigned char tag6_LE[3], tag5_BE[3];
892 unsigned char tag2_LE[3], tag2_BE[3];
894 // Find start of wav file list
896 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
898 numberofwavs = u_endian_read4(&ptfunxored[k-18], is_bigendian);
900 // Find actual wav names
903 jumpto(&i, ptfunxored, len, (const unsigned char *)"Files", 5);
908 while (i < len && numberofwavs > 0) {
910 if ( ((ptfunxored[i ] == 0x5a) &&
911 (ptfunxored[i+1] == 0x00) &&
912 (ptfunxored[i+2] == 0x05)) ||
913 ((ptfunxored[i ] == 0x5a) &&
914 (ptfunxored[i+1] == 0x06))) {
917 lengthofname = u_endian_read4(&ptfunxored[i-3], is_bigendian);
920 while (l < lengthofname) {
921 wavname[l] = ptfunxored[i+l];
925 ext[0] = ptfunxored[i++];
926 ext[1] = ptfunxored[i++];
927 ext[2] = ptfunxored[i++];
928 ext[3] = ptfunxored[i++];
932 if (foundin(wavname, ".L") || foundin(wavname, ".R")) {
933 extension = string("");
934 } else if (foundin(wavname, ".wav") || foundin(ext, "WAVE")) {
935 extension = string(".wav");
936 } else if (foundin(wavname, ".aif") || foundin(ext, "AIFF")) {
937 extension = string(".aif");
939 extension = string("");
942 std::string wave = string(wavname);
944 if (foundin(wave, string(".grp"))) {
947 if (foundin(wave, string("Fade Files"))) {
952 wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
954 actualwavs.push_back(f);
955 audiofiles.push_back(f);
963 tag5_BE[0] = tag6_LE[0] = tag2_BE[0] = tag2_LE[0] = '\x5a';
973 // Loop through all the sources
974 for (vector<wav_t>::iterator w = audiofiles.begin(); w != audiofiles.end(); ++w) {
975 // Jump to start of source metadata for this source
977 if (!jumpto(&i, ptfunxored, len, tag5_BE, 3))
979 if (!jumpto(&i, ptfunxored, len, tag2_BE, 3))
981 w->length = u_endian_read4(&ptfunxored[i+19], true);
983 if (!jumpto(&i, ptfunxored, len, tag6_LE, 3))
985 if (!jumpto(&i, ptfunxored, len, tag2_LE, 3))
987 w->length = u_endian_read4(&ptfunxored[i+15], false);
994 mchunk (uint64_t zt, uint64_t ml, std::vector<PTFFormat::midi_ev_t> const& c)
1001 std::vector<PTFFormat::midi_ev_t> chunk;
1005 PTFFormat::parsemidi(void) {
1007 uint64_t tr, n_midi_events, zero_ticks;
1008 uint64_t midi_pos, midi_len, max_pos, region_pos;
1009 uint8_t midi_velocity, midi_note;
1011 uint16_t nmiditracks, regionnumber = 0;
1012 uint32_t nregions, mr;
1014 std::vector<mchunk> midichunks;
1020 // Parse all midi chunks, not 1:1 mapping to regions yet
1021 while (k + 35 < len) {
1023 std::vector<midi_ev_t> midi;
1025 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
1029 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
1030 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
1033 zero_ticks = u_endian_read5(&ptfunxored[k], is_bigendian);
1034 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
1035 midi_pos = u_endian_read5(&ptfunxored[k], is_bigendian);
1036 midi_pos -= zero_ticks;
1037 midi_note = ptfunxored[k+8];
1038 midi_len = u_endian_read5(&ptfunxored[k+9], is_bigendian);
1039 midi_velocity = ptfunxored[k+17];
1041 if (midi_pos + midi_len > max_pos) {
1042 max_pos = midi_pos + midi_len;
1046 m.length = midi_len;
1048 m.velocity = midi_velocity;
1050 // stop gap measure to prevent crashes in ardour,
1051 // remove when decryption is fully solved for .ptx
1052 if ((m.velocity & 0x80) || (m.note & 0x80) ||
1053 (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
1059 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
1062 // Map midi chunks to regions
1064 char midiregionname[256];
1067 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
1073 nregions = u_endian_read2(&ptfunxored[k], is_bigendian);
1075 for (mr = 0; mr < nregions; mr++) {
1076 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x0c", 2)) {
1082 namelen = ptfunxored[k];
1083 for (i = 0; i < namelen; i++) {
1084 midiregionname[i] = ptfunxored[k+4+i];
1086 midiregionname[namelen] = '\0';
1091 region_pos = (uint64_t)ptfunxored[k] |
1092 (uint64_t)ptfunxored[k+1] << 8 |
1093 (uint64_t)ptfunxored[k+2] << 16 |
1094 (uint64_t)ptfunxored[k+3] << 24 |
1095 (uint64_t)ptfunxored[k+4] << 32;
1097 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\xff\xff", 4)) {
1103 ridx = ptfunxored[k];
1104 ridx |= ptfunxored[k+1] << 8;
1106 struct mchunk mc = *(midichunks.begin()+ridx);
1108 wav_t w = { std::string(""), 0, 0, 0 };
1113 (int64_t)0xe8d4a51000ULL,
1115 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
1120 midiregions.push_back(r);
1124 // Put midi regions on midi tracks
1125 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1129 nmiditracks = u_endian_read2(&ptfunxored[k-4], is_bigendian);
1131 for (tr = 0; tr < nmiditracks; tr++) {
1132 char miditrackname[256];
1134 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1138 namelen = ptfunxored[k+9];
1139 for (i = 0; i < namelen; i++) {
1140 miditrackname[i] = ptfunxored[k+13+i];
1142 miditrackname[namelen] = '\0';
1144 nregions = u_endian_read2(&ptfunxored[k], is_bigendian);
1146 for (i = 0; (i < nregions) && (k < len); i++) {
1149 ridx = u_endian_read2(&ptfunxored[k], is_bigendian);
1153 region_pos = u_endian_read5(&ptfunxored[k], is_bigendian);
1158 mtr.name = string(miditrackname);
1161 // Find the midi region with index 'ridx'
1162 std::vector<region_t>::iterator begin = midiregions.begin();
1163 std::vector<region_t>::iterator finish = midiregions.end();
1164 std::vector<region_t>::iterator mregion;
1165 wav_t w = { std::string(""), 0, 0, 0 };
1166 std::vector<midi_ev_t> m;
1167 region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
1168 if ((mregion = std::find(begin, finish, r)) != finish) {
1170 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
1171 miditracks.push_back(mtr);
1178 PTFFormat::parsemidi12(void) {
1180 uint64_t tr, n_midi_events, zero_ticks;
1181 uint64_t midi_pos, midi_len, max_pos, region_pos;
1182 uint8_t midi_velocity, midi_note;
1184 uint16_t nmiditracks, regionnumber = 0;
1185 uint32_t nregions, mr;
1187 std::vector<mchunk> midichunks;
1192 // Parse all midi chunks, not 1:1 mapping to regions yet
1193 while (k + 35 < len) {
1195 std::vector<midi_ev_t> midi;
1198 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
1203 n_midi_events = u_endian_read4(&ptfunxored[k], is_bigendian);
1206 zero_ticks = u_endian_read5(&ptfunxored[k], is_bigendian);
1207 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
1208 midi_pos = u_endian_read5(&ptfunxored[k], is_bigendian);
1209 midi_pos -= zero_ticks;
1210 midi_note = ptfunxored[k+8];
1211 midi_len = u_endian_read5(&ptfunxored[k+9], is_bigendian);
1212 midi_velocity = ptfunxored[k+17];
1214 if (midi_pos + midi_len > max_pos) {
1215 max_pos = midi_pos + midi_len;
1219 m.length = midi_len;
1221 m.velocity = midi_velocity;
1223 // stop gap measure to prevent crashes in ardour,
1224 // remove when decryption is fully solved for .ptx
1225 if ((m.velocity & 0x80) || (m.note & 0x80) ||
1226 (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
1232 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
1235 // Map midi chunks to regions
1237 char midiregionname[256];
1240 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
1246 nregions = u_endian_read2(&ptfunxored[k], is_bigendian);
1248 for (mr = 0; mr < nregions; mr++) {
1249 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2)) {
1254 namelen = ptfunxored[k];
1255 for (i = 0; i < namelen; i++) {
1256 midiregionname[i] = ptfunxored[k+4+i];
1258 midiregionname[namelen] = '\0';
1263 region_pos = (uint64_t)ptfunxored[k] |
1264 (uint64_t)ptfunxored[k+1] << 8 |
1265 (uint64_t)ptfunxored[k+2] << 16 |
1266 (uint64_t)ptfunxored[k+3] << 24 |
1267 (uint64_t)ptfunxored[k+4] << 32;
1269 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\x00\x00", 4)) {
1275 ridx = u_endian_read2(&ptfunxored[k], is_bigendian);
1278 struct mchunk mc = *(midichunks.begin()+ridx);
1280 wav_t w = { std::string(""), 0, 0, 0 };
1285 (int64_t)0xe8d4a51000ULL,
1287 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
1292 midiregions.push_back(r);
1296 // Put midi regions on midi tracks
1297 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1301 nmiditracks = u_endian_read2(&ptfunxored[k-4], is_bigendian);
1303 for (tr = 0; tr < nmiditracks; tr++) {
1304 char miditrackname[256];
1306 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1310 namelen = ptfunxored[k+9];
1311 for (i = 0; i < namelen; i++) {
1312 miditrackname[i] = ptfunxored[k+13+i];
1314 miditrackname[namelen] = '\0';
1316 nregions = u_endian_read2(&ptfunxored[k], is_bigendian);
1320 for (i = 0; (i < nregions) && (k < len); i++) {
1322 if ( (ptfunxored[k] == 0x5a) &&
1323 (ptfunxored[k+1] & 0x08)) {
1330 ridx = u_endian_read2(&ptfunxored[k], is_bigendian);
1334 region_pos = u_endian_read5(&ptfunxored[k], is_bigendian);
1337 mtr.name = string(miditrackname);
1340 // Find the midi region with index 'ridx'
1341 std::vector<region_t>::iterator begin = midiregions.begin();
1342 std::vector<region_t>::iterator finish = midiregions.end();
1343 std::vector<region_t>::iterator mregion;
1344 wav_t w = { std::string(""), 0, 0, 0 };
1345 std::vector<midi_ev_t> m;
1346 region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
1347 if ((mregion = std::find(begin, finish, r)) != finish) {
1349 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
1350 miditracks.push_back(mtr);
1352 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8)) {
1360 PTFFormat::parseaudio(void) {
1365 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Audio Files", 11))
1368 // Find end of wav file list
1369 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1372 // Find number of wave files
1373 uint16_t numberofwavs;
1375 if (!jumpback(&j, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
1378 numberofwavs = u_endian_read4(&ptfunxored[j-4], is_bigendian);
1379 //printf("%d wavs\n", numberofwavs);
1381 // Find actual wav names
1384 for (i = 0; i < numberofwavs; i++) {
1386 if ( ((ptfunxored[j ] == 'W') || (ptfunxored[j ] == 'A') || ptfunxored[j ] == '\0') &&
1387 ((ptfunxored[j-1] == 'A') || (ptfunxored[j-1] == 'I') || ptfunxored[j-1] == '\0') &&
1388 ((ptfunxored[j-2] == 'V') || (ptfunxored[j-2] == 'F') || ptfunxored[j-2] == '\0')) {
1395 while (ptfunxored[j] != '\0') {
1396 wavname[l] = ptfunxored[j];
1402 // Must be at least "vaw.z\0"
1408 // and skip "zWAVE" or "zAIFF"
1409 if ( ( (wavname[1] == 'W') &&
1410 (wavname[2] == 'A') &&
1411 (wavname[3] == 'V') &&
1412 (wavname[4] == 'E')) ||
1413 ( (wavname[1] == 'A') &&
1414 (wavname[2] == 'I') &&
1415 (wavname[3] == 'F') &&
1416 (wavname[4] == 'F'))) {
1417 wave = string(&wavname[5]);
1419 wave = string(wavname);
1421 //uint8_t playlist = ptfunxored[j-8];
1423 std::reverse(wave.begin(), wave.end());
1424 wav_t f = { wave, (uint16_t)(numberofwavs - i - 1), 0, 0 };
1426 if (foundin(wave, string("Audio Files")) ||
1427 foundin(wave, string("Fade Files"))) {
1432 actualwavs.push_back(f);
1433 audiofiles.push_back(f);
1435 //printf(" %d:%s \n", numberofwavs - i - 1, wave.c_str());
1437 std::reverse(audiofiles.begin(), audiofiles.end());
1438 std::reverse(actualwavs.begin(), actualwavs.end());
1439 //resort(audiofiles);
1440 //resort(actualwavs);
1442 // Jump to end of wav file list
1443 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1446 // Loop through all the sources
1447 for (vector<wav_t>::iterator w = audiofiles.begin(); w != audiofiles.end(); ++w) {
1448 // Jump to start of source metadata for this source
1449 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x07", 2))
1451 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1454 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1457 w->length = u_endian_read4(&ptfunxored[k-25], false);
1462 PTFFormat::parserest89(void) {
1464 uint8_t startbytes = 0;
1465 uint8_t lengthbytes = 0;
1466 uint8_t offsetbytes = 0;
1467 uint8_t somethingbytes = 0;
1468 uint8_t skipbytes = 0;
1472 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4)) {
1476 uint16_t rindex = 0;
1477 uint32_t findex = 0;
1478 for (i = k; i < len-70; i++) {
1479 if ( (ptfunxored[i ] == 0x5a) &&
1480 (ptfunxored[i+1] == 0x0a)) {
1483 if ( (ptfunxored[i ] == 0x5a) &&
1484 (ptfunxored[i+1] == 0x0c)) {
1486 uint8_t lengthofname = ptfunxored[i+9];
1488 char name[256] = {0};
1489 for (j = 0; j < lengthofname; j++) {
1490 name[j] = ptfunxored[i+13+j];
1494 //uint8_t disabled = ptfunxored[j];
1496 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1497 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1498 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1499 somethingbytes = (ptfunxored[j+3] & 0xf);
1500 skipbytes = ptfunxored[j+4];
1501 findex = ptfunxored[j+5
1508 /*rindex = ptfunxored[j+5
1516 uint32_t sampleoffset = 0;
1517 switch (offsetbytes) {
1519 sampleoffset = u_endian_read4(&ptfunxored[j+5], false);
1522 sampleoffset = u_endian_read3(&ptfunxored[j+5], false);
1525 sampleoffset = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
1528 sampleoffset = (uint32_t)(ptfunxored[j+5]);
1534 uint32_t length = 0;
1535 switch (lengthbytes) {
1537 length = u_endian_read4(&ptfunxored[j+5], false);
1540 length = u_endian_read3(&ptfunxored[j+5], false);
1543 length = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
1546 length = (uint32_t)(ptfunxored[j+5]);
1553 switch (startbytes) {
1555 start = u_endian_read4(&ptfunxored[j+5], false);
1558 start = u_endian_read3(&ptfunxored[j+5], false);
1561 start = (uint32_t)u_endian_read2(&ptfunxored[j+5], false);
1564 start = (uint32_t)(ptfunxored[j+5]);
1571 uint32_t something = 0;
1572 switch (somethingbytes) {
1574 something |= (uint32_t)(ptfunxored[j+8] << 24);
1576 something |= (uint32_t)(ptfunxored[j+7] << 16);
1578 something |= (uint32_t)(ptfunxored[j+6] << 8);
1580 something |= (uint32_t)(ptfunxored[j+5]);
1586 std::string filename = string(name);
1590 (int64_t)(start*ratefactor),
1591 (int64_t)(length*ratefactor),
1594 //printf("something=%d\n", something);
1596 vector<wav_t>::iterator begin = actualwavs.begin();
1597 vector<wav_t>::iterator finish = actualwavs.end();
1598 vector<wav_t>::iterator found;
1599 // Add file to list only if it is an actual wav
1600 if ((found = std::find(begin, finish, f)) != finish) {
1601 f.filename = (*found).filename;
1602 // Also add plain wav as region
1603 std::vector<midi_ev_t> m;
1607 (int64_t)(start*ratefactor),
1608 (int64_t)(sampleoffset*ratefactor),
1609 (int64_t)(length*ratefactor),
1613 regions.push_back(r);
1616 if (foundin(filename, string(".grp"))) {
1619 std::vector<midi_ev_t> m;
1623 (int64_t)(start*ratefactor),
1624 (int64_t)(sampleoffset*ratefactor),
1625 (int64_t)(length*ratefactor),
1629 regions.push_back(r);
1635 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1638 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
1645 uint32_t tracknumber = 0;
1646 uint32_t regionspertrack = 0;
1647 for (;k < len; k++) {
1648 if ( (ptfunxored[k ] == 0x5a) &&
1649 (ptfunxored[k+1] == 0x04)) {
1652 if ( (ptfunxored[k ] == 0x5a) &&
1653 (ptfunxored[k+1] == 0x02)) {
1655 uint8_t lengthofname = 0;
1656 lengthofname = ptfunxored[k+9];
1657 if (lengthofname == 0x5a) {
1662 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
1664 //printf("regions/track=%d\n", regionspertrack);
1665 char name[256] = {0};
1666 for (j = 0; j < lengthofname; j++) {
1667 name[j] = ptfunxored[j+k+13];
1670 tr.name = string(name);
1671 tr.index = tracknumber++;
1673 for (j = k; regionspertrack > 0 && j < len; j++) {
1674 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x07", 2);
1675 tr.reg.index = (uint16_t)(ptfunxored[j+11] & 0xff)
1676 | (uint16_t)((ptfunxored[j+12] << 8) & 0xff00);
1677 vector<region_t>::iterator begin = regions.begin();
1678 vector<region_t>::iterator finish = regions.end();
1679 vector<region_t>::iterator found;
1680 if ((found = std::find(begin, finish, tr.reg)) != finish) {
1684 offset = u_endian_read4(&ptfunxored[i], is_bigendian);
1685 tr.reg.startpos = (int64_t)(offset*ratefactor);
1686 if (tr.reg.length > 0) {
1687 tracks.push_back(tr);
1696 PTFFormat::parserest12(void) {
1697 uint32_t i,j,k,l,m,n;
1698 uint8_t startbytes = 0;
1699 uint8_t lengthbytes = 0;
1700 uint8_t offsetbytes = 0;
1701 uint8_t somethingbytes = 0;
1702 uint8_t skipbytes = 0;
1703 uint32_t maxregions = 0;
1704 uint32_t findex = 0;
1705 uint32_t findex2 = 0;
1706 uint32_t findex3 = 0;
1707 uint16_t rindex = 0;
1708 vector<region_t> groups;
1709 uint16_t groupcount, compoundcount, groupmax;
1710 uint16_t gindex, gindex2;
1714 vector<compound_t> groupmap;
1715 // Find region group total
1717 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1720 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1723 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1726 jumpto(&k, ptfunxored, k+0x2000, (const unsigned char *)"\x5a\x03", 2);
1730 for (i = k; i < len; i++) {
1731 if (!jumpto(&i, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2))
1735 verbose_printf("groupcount=%d\n", groupcount);
1737 // Find start of group names -> group indexes
1739 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1742 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1745 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1749 // Skip total number of groups
1750 for (i = 0; i < groupcount; i++) {
1752 if ( (ptfunxored[k ] == 0x5a) &&
1753 ((ptfunxored[k+1] == 0x03) || (ptfunxored[k+1] == 0x0a))) {
1762 if ( (ptfunxored[k ] == 0x5a) &&
1763 (ptfunxored[k+1] & 0x02)) {
1771 if ( (ptfunxored[k ] == 0x5a) &&
1772 (ptfunxored[k+1] & 0x02)) {
1779 verbose_printf("start of groups k=0x%x\n", k);
1780 // Loop over all groups and associate the compound index/name
1781 for (i = 0; i < groupcount; i++) {
1783 if ( (ptfunxored[k ] == 0x5a) &&
1784 (ptfunxored[k+1] & 0x02)) {
1791 gindex = u_endian_read2(&ptfunxored[k+9], is_bigendian);
1792 gindex2 = u_endian_read2(&ptfunxored[k+3], is_bigendian);
1794 uint8_t lengthofname = ptfunxored[k+13];
1795 char name[256] = {0};
1796 for (l = 0; l < lengthofname; l++) {
1797 name[l] = ptfunxored[k+17+l];
1801 if (strlen(name) == 0) {
1807 (uint16_t)i, // curr_index
1811 gindex2, // next_index
1814 groupmap.push_back(c);
1818 // Sort lookup table by group index
1819 //std::sort(glookup.begin(), glookup.end(), regidx_compare);
1821 // print compounds as flattened tree
1823 for (std::vector<compound_t>::iterator i = groupmap.begin(); i != groupmap.end(); ++i) {
1824 verbose_printf("g(%u) uk(%u) ni(%u) %s\n", i->curr_index, i->unknown1, i->next_index, i->name.c_str());
1829 // Find region groups
1831 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4))
1834 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2))
1838 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))
1842 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))
1846 // Hack to find actual start of region group information
1848 if ((ptfunxored[k+13] == 0x5a) && (ptfunxored[k+14] & 0xf)) {
1852 if ((ptfunxored[k+9] == 0x5a) && (ptfunxored[k+10] & 0xf)) {
1857 if ((ptfunxored[k] == 0x5a) && (ptfunxored[k+1] & 0xf))
1861 verbose_printf("hack region groups k=0x%x\n", k);
1865 groupmax = groupcount == 0 ? 0 : u_endian_read2(&ptfunxored[j+3], is_bigendian);
1867 for (i = k; (groupcount < groupmax) && (i < len-70); i++) {
1868 if ( (ptfunxored[i ] == 0x5a) &&
1869 (ptfunxored[i+1] == 0x03)) {
1872 if ( (ptfunxored[i ] == 0x5a) &&
1873 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1875 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1876 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1878 uint8_t lengthofname = ptfunxored[i+9];
1879 if (ptfunxored[i+13] == 0x5a) {
1882 char name[256] = {0};
1883 for (j = 0; j < lengthofname; j++) {
1884 name[j] = ptfunxored[i+13+j];
1889 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1890 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1891 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1892 somethingbytes = (ptfunxored[j+3] & 0xf);
1893 skipbytes = ptfunxored[j+4];
1894 uint16_t regionsingroup = ptfunxored[j+5
1909 findex = ptfunxored[j+5
1924 uint64_t sampleoffset = 0;
1925 switch (offsetbytes) {
1927 sampleoffset = u_endian_read5(&ptfunxored[j+5], false);
1930 sampleoffset = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
1933 sampleoffset = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
1936 sampleoffset = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
1939 sampleoffset = (uint64_t)(ptfunxored[j+5]);
1945 uint64_t length = 0;
1946 switch (lengthbytes) {
1948 length = u_endian_read5(&ptfunxored[j+5], false);
1951 length = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
1954 length = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
1957 length = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
1960 length = (uint64_t)(ptfunxored[j+5]);
1967 switch (startbytes) {
1969 start = u_endian_read5(&ptfunxored[j+5], false);
1972 start = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
1975 start = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
1978 start = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
1981 start = (uint64_t)(ptfunxored[j+5]);
1988 if (offsetbytes == 5)
1989 sampleoffset -= 1000000000000ULL;
1990 if (startbytes == 5)
1991 start -= 1000000000000ULL;
1993 std::string filename = string(name);
1997 (int64_t)(start*ratefactor),
1998 (int64_t)(length*ratefactor),
2001 if (strlen(name) == 0) {
2007 //if (foundin(filename, string(".grp")) && !regionsingroup && !findex) {
2008 // // Empty region group
2009 // verbose_printf(" EMPTY: %s\n", name);
2011 if (regionsingroup) {
2012 // Active region grouping
2013 // Iterate parsing all the regions in the group
2014 verbose_printf("\nGROUP\t%d %s\n", groupcount, name);
2018 for (l = 0; l < regionsingroup; l++) {
2019 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
2025 //printf("n=0x%x\n", n+112);
2026 //findex = ptfunxored[n+112] | (ptfunxored[n+113] << 8);
2027 findex = u_endian_read2(&ptfunxored[i-11], is_bigendian);
2028 findex2 = u_endian_read2(&ptfunxored[n+108], is_bigendian);
2029 //findex2= rindex; //XXX
2030 // Find wav with correct findex
2031 vector<wav_t>::iterator wave = actualwavs.end();
2032 for (vector<wav_t>::iterator aw = actualwavs.begin();
2033 aw != actualwavs.end(); ++aw) {
2034 if (aw->index == findex) {
2038 if (wave == actualwavs.end())
2041 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
2044 //rindex = ptfunxored[n] | (ptfunxored[n+1] << 8);
2045 for (l = 0; l < regionsingroup; l++) {
2046 if (!jumpto(&m, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
2050 rindex = u_endian_read2(&ptfunxored[m], is_bigendian);
2054 switch (offsetbytes) {
2056 sampleoffset = u_endian_read5(&ptfunxored[m], false);
2059 sampleoffset = (uint64_t)u_endian_read4(&ptfunxored[m], false);
2062 sampleoffset = (uint64_t)u_endian_read3(&ptfunxored[m], false);
2065 sampleoffset = (uint64_t)u_endian_read2(&ptfunxored[m], false);
2068 sampleoffset = (uint64_t)(ptfunxored[m]);
2075 switch (offsetbytes) {
2077 start = u_endian_read5(&ptfunxored[m], false);
2080 start = (uint64_t)u_endian_read4(&ptfunxored[m], false);
2083 start = (uint64_t)u_endian_read3(&ptfunxored[m], false);
2086 start = (uint64_t)u_endian_read2(&ptfunxored[m], false);
2089 start = (uint64_t)(ptfunxored[m]);
2096 switch (lengthbytes) {
2098 length = u_endian_read5(&ptfunxored[m], false);
2101 length = (uint64_t)u_endian_read4(&ptfunxored[m], false);
2104 length = (uint64_t)u_endian_read3(&ptfunxored[m], false);
2107 length = (uint64_t)u_endian_read2(&ptfunxored[m], false);
2110 length = (uint64_t)(ptfunxored[m]);
2116 findex3 = ptfunxored[m] | (ptfunxored[m+1] << 8);
2117 sampleoffset -= 1000000000000ULL;
2118 start -= 1000000000000ULL;
2121 // Find wav with correct findex
2122 vector<wav_t>::iterator wave = actualwavs.end();
2123 for (vector<wav_t>::iterator aw = actualwavs.begin();
2124 aw != actualwavs.end(); ++aw) {
2125 if (aw->index == (glookup.begin()+findex2)->startpos) {
2129 if (wave == actualwavs.end())
2131 // findex is the true source
2132 std::vector<midi_ev_t> md;
2136 (int64_t)findex, //(start*ratefactor),
2137 (int64_t)findex2, //(sampleoffset*ratefactor),
2138 (int64_t)findex3, //(length*ratefactor),
2142 groups.push_back(r);
2144 vector<compound_t>::iterator g = groupmap.begin()+findex2;
2145 if (g >= groupmap.end())
2148 c.name = string(g->name);
2149 c.curr_index = compoundcount;
2151 c.ontopof_index = findex3;
2152 c.next_index = g->next_index;
2153 c.unknown1 = g->unknown1;
2154 compounds.push_back(c);
2155 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);
2164 // Start pure regions
2165 k = m != 0 ? m : k - 1;
2166 if (!jumpto(&k, ptfunxored, k+64, (const unsigned char *)"\x5a\x05", 2))
2167 jumpto(&k, ptfunxored, k+0x400, (const unsigned char *)"\x5a\x02", 2);
2169 verbose_printf("pure regions k=0x%x\n", k);
2171 maxregions = u_endian_read4(&ptfunxored[k-4], is_bigendian);
2173 verbose_printf("maxregions=%u\n", maxregions);
2175 for (i = k; rindex < maxregions && i < len; i++) {
2176 if ( (ptfunxored[i ] == 0xff) &&
2177 (ptfunxored[i+1] == 0x5a) &&
2178 (ptfunxored[i+2] == 0x01)) {
2181 //if ( (ptfunxored[i ] == 0x5a) &&
2182 // (ptfunxored[i+1] == 0x03)) {
2185 if ( (ptfunxored[i ] == 0x5a) &&
2186 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
2188 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
2189 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
2191 uint8_t lengthofname = ptfunxored[i+9];
2192 if (ptfunxored[i+13] == 0x5a) {
2195 char name[256] = {0};
2196 for (j = 0; j < lengthofname; j++) {
2197 name[j] = ptfunxored[i+13+j];
2202 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
2203 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
2204 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
2205 somethingbytes = (ptfunxored[j+3] & 0xf);
2206 skipbytes = ptfunxored[j+4];
2207 findex = ptfunxored[j+5
2222 uint64_t sampleoffset = 0;
2223 switch (offsetbytes) {
2225 sampleoffset = u_endian_read5(&ptfunxored[j+5], false);
2228 sampleoffset = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
2231 sampleoffset = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
2234 sampleoffset = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
2237 sampleoffset = (uint64_t)(ptfunxored[j+5]);
2243 uint64_t length = 0;
2244 switch (lengthbytes) {
2246 length = u_endian_read5(&ptfunxored[j+5], false);
2249 length = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
2252 length = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
2255 length = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
2258 length = (uint64_t)(ptfunxored[j+5]);
2265 switch (startbytes) {
2267 start = u_endian_read5(&ptfunxored[j+5], false);
2270 start = (uint64_t)u_endian_read4(&ptfunxored[j+5], false);
2273 start = (uint64_t)u_endian_read3(&ptfunxored[j+5], false);
2276 start = (uint64_t)u_endian_read2(&ptfunxored[j+5], false);
2279 start = (uint64_t)(ptfunxored[j+5]);
2286 if (offsetbytes == 5)
2287 sampleoffset -= 1000000000000ULL;
2288 if (startbytes == 5)
2289 start -= 1000000000000ULL;
2291 std::string filename = string(name);
2295 (int64_t)(start*ratefactor),
2296 (int64_t)(length*ratefactor),
2299 if (strlen(name) == 0) {
2305 // Regular region mapping to a source
2307 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2309 //printf("XXX=%d\n", ptfunxored[n+12] | ptfunxored[n+13]<<8);
2311 // Find wav with correct findex
2312 vector<wav_t>::iterator wave = actualwavs.end();
2313 for (vector<wav_t>::iterator aw = actualwavs.begin();
2314 aw != actualwavs.end(); ++aw) {
2315 if (aw->index == findex) {
2319 if (wave == actualwavs.end()) {
2320 verbose_printf("missing source with findex\n");
2323 //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);
2324 verbose_printf("REGION\tg(NA)\tr(%d)\tw(%d) %s(%s)\n", rindex, findex, name, wave->filename.c_str());
2325 std::vector<midi_ev_t> md;
2329 (int64_t)(start*ratefactor),
2330 (int64_t)(sampleoffset*ratefactor),
2331 (int64_t)(length*ratefactor),
2335 regions.push_back(r);
2341 vector<uint16_t> rootnodes;
2345 for (vector<compound_t>::iterator cmp = compounds.begin();
2346 cmp != compounds.end(); ++cmp) {
2348 for (vector<compound_t>::iterator tmp = compounds.begin();
2349 tmp != compounds.end(); ++tmp) {
2352 if (tmp->ontopof_index == cmp->curr_index)
2355 // Collect a vector of all the root nodes (no others point to)
2357 rootnodes.push_back(cmp->curr_index);
2360 for (vector<uint16_t>::iterator rt = rootnodes.begin();
2361 rt != rootnodes.end(); ++rt) {
2362 vector<compound_t>::iterator cmp = compounds.begin()+(*rt);
2363 // Now we are at a root node, follow to leaf
2364 if (cmp >= compounds.end())
2367 verbose_printf("----\n");
2369 for (; cmp < compounds.end() && cmp->curr_index != cmp->next_index;
2370 cmp = compounds.begin()+cmp->next_index) {
2373 vector<region_t>::iterator r = regions.end();
2374 for (vector<region_t>::iterator rs = regions.begin();
2375 rs != regions.end(); rs++) {
2376 if (rs->index == cmp->unknown1 + cmp->level) {
2380 if (r == regions.end())
2382 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());
2385 vector<region_t>::iterator r = regions.end();
2386 for (vector<region_t>::iterator rs = regions.begin();
2387 rs != regions.end(); rs++) {
2388 if (rs->index == cmp->unknown1 + cmp->level) {
2392 if (r == regions.end())
2394 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());
2397 // Start grouped regions
2399 // Print region groups mapped to sources
2400 for (vector<region_t>::iterator a = groups.begin(); a != groups.end(); ++a) {
2401 // Find wav with findex
2402 vector<wav_t>::iterator wav = audiofiles.end();
2403 for (vector<wav_t>::iterator ws = audiofiles.begin();
2404 ws != audiofiles.end(); ws++) {
2405 if (ws->index == a->startpos) {
2409 if (wav == audiofiles.end())
2412 // Find wav with findex2
2413 vector<wav_t>::iterator wav2 = audiofiles.end();
2414 for (vector<wav_t>::iterator ws = audiofiles.begin();
2415 ws != audiofiles.end(); ws++) {
2416 if (ws->index == a->sampleoffset) {
2420 if (wav2 == audiofiles.end())
2423 verbose_printf("Group: %s -> %s OR %s\n", a->name.c_str(), wav->filename.c_str(), wav2->filename.c_str());
2431 uint32_t tracknumber = 0;
2432 uint32_t regionspertrack = 0;
2436 if (!jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x03\x00", 3))
2438 //maxtracks = u_endian_read4(&ptfunxored[j-4]);
2440 // Jump to start of region -> track mappings
2441 if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x08", 2)) {
2442 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
2444 } else if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x0a", 2)) {
2445 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2450 verbose_printf("tracks k=0x%x\n", k);
2452 for (;k < len; k++) {
2453 if ( (ptfunxored[k ] == 0x5a) &&
2454 (ptfunxored[k+1] & 0x04)) {
2457 if ( (ptfunxored[k ] == 0x5a) &&
2458 (ptfunxored[k+1] & 0x02)) {
2460 uint8_t lengthofname = 0;
2461 lengthofname = ptfunxored[k+9];
2462 if (lengthofname == 0x5a) {
2467 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
2469 //printf("regions/track=%d\n", regionspertrack);
2470 char name[256] = {0};
2471 for (j = 0; j < lengthofname; j++) {
2472 name[j] = ptfunxored[j+k+13];
2475 tr.name = string(name);
2476 tr.index = tracknumber++;
2478 for (j = k+18+lengthofname; regionspertrack > 0 && j < len; j++) {
2479 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a", 1);
2480 bool isgroup = ptfunxored[j+27] > 0;
2482 tr.reg.name = string("");
2484 //tr.reg.index = 0xffff;
2485 verbose_printf("TRACK: t(%d) g(%d) G(%s) -> T(%s)\n",
2486 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2488 tr.reg.index = ((uint16_t)(ptfunxored[j+11]) & 0xff)
2489 | (((uint16_t)(ptfunxored[j+12]) << 8) & 0xff00);
2490 vector<region_t>::iterator begin = regions.begin();
2491 vector<region_t>::iterator finish = regions.end();
2492 vector<region_t>::iterator found;
2493 if ((found = std::find(begin, finish, tr.reg)) != finish) {
2496 verbose_printf("TRACK: t(%d) r(%d) R(%s) -> T(%s)\n",
2497 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2500 offset = u_endian_read4(&ptfunxored[i], is_bigendian);
2501 tr.reg.startpos = (int64_t)(offset*ratefactor);
2502 if (tr.reg.length > 0) {
2503 tracks.push_back(tr);
2507 jumpto(&j, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);