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::cleanup(void) {
103 PTFFormat::foundat(unsigned char *haystack, uint64_t n, const char *needle) {
105 uint64_t i, j, needle_n;
106 needle_n = strlen(needle);
108 for (i = 0; i < n; i++) {
110 for (j = 0; j < needle_n; j++) {
111 if (haystack[i+j] != needle[j]) {
123 PTFFormat::jumpto(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
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]) {
144 PTFFormat::jumpback(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
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]) {
165 PTFFormat::foundin(std::string haystack, std::string needle) {
166 size_t found = haystack.find(needle);
167 if (found != std::string::npos) {
174 /* Return values: 0 success
175 -1 could not decrypt pt session
178 PTFFormat::unxor(std::string path) {
180 unsigned char xxor[256];
188 if (! (fp = g_fopen(path.c_str(), "rb"))) {
192 fseek(fp, 0, SEEK_END);
199 if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
200 /* Silently fail -- out of memory*/
206 /* The first 20 bytes are always unencrypted */
207 fseek(fp, 0x00, SEEK_SET);
208 i = fread(ptfunxored, 1, 0x14, fp);
214 xor_type = ptfunxored[0x12];
215 xor_value = ptfunxored[0x13];
218 // xor_type 0x01 = ProTools 5, 6, 7, 8 and 9
219 // xor_type 0x05 = ProTools 10, 11, 12
222 xor_delta = gen_xor_delta(xor_value, 53, false);
225 xor_delta = gen_xor_delta(xor_value, 11, true);
232 /* Generate the xor_key */
233 for (i=0; i < xor_len; i++)
234 xxor[i] = (i * xor_delta) & 0xff;
236 /* hexdump(xxor, xor_len); */
238 /* Read file and decrypt rest of file */
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];
249 /* Return values: 0 success
250 -1 could not parse pt session
253 PTFFormat::load(std::string ptf, int64_t targetsr) {
263 if (version < 5 || version > 12)
266 targetrate = targetsr;
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;
280 bool success = false;
282 while( ((uintptr_t)data < data_end) && (success == false) ) {
284 if (data[0] != 0x5a) {
290 /* Skip segment header */
292 if (data[0] == 0 && data[1] == 0) {
294 seg_len = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
297 seg_len = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
301 if (!(seg_type == 0x04 || seg_type == 0x03) || data[0] != 0x03) {
302 /* Go to next segment */
306 /* Skip 0x03 0x00 0x00 */
309 str_len = (*(uint8_t *)data);
310 if (! (product = (uint8_t *)malloc((str_len+1) * sizeof(uint8_t)))) {
319 memcpy(product, data, str_len);
320 product[str_len] = 0;
324 /* Skip 0x03 0x00 0x00 0x00 */
336 /* If the above does not work, try other heuristics */
337 if ((uintptr_t)data >= data_end - seg_len) {
338 version = ptfunxored[0x40];
340 version = ptfunxored[0x3d];
343 version = ptfunxored[0x3a] + 2;
353 PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) {
355 for (i = 0; i < 256; i++) {
356 if (((i * mul) & 0xff) == xor_value) {
357 return (negative) ? i * (-1) : i;
365 PTFFormat::parse(void) {
369 if (sessionrate < 44100 || sessionrate > 192000)
374 } else if (version == 7) {
377 if (sessionrate < 44100 || sessionrate > 192000)
382 } else if (version == 8) {
385 if (sessionrate < 44100 || sessionrate > 192000)
390 } else if (version == 9) {
393 if (sessionrate < 44100 || sessionrate > 192000)
398 } else if (version == 10 || version == 11 || version == 12) {
401 if (sessionrate < 44100 || sessionrate > 192000)
414 PTFFormat::setrates(void) {
416 if (sessionrate != 0) {
417 ratefactor = (float)targetrate / sessionrate;
422 PTFFormat::parse5header(void) {
425 // Find session sample rate
428 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x02", 3);
431 sessionrate |= ptfunxored[k+12] << 16;
432 sessionrate |= ptfunxored[k+13] << 8;
433 sessionrate |= ptfunxored[k+14];
437 PTFFormat::parse7header(void) {
440 // Find session sample rate
443 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x05", 3);
446 sessionrate |= ptfunxored[k+12] << 16;
447 sessionrate |= ptfunxored[k+13] << 8;
448 sessionrate |= ptfunxored[k+14];
452 PTFFormat::parse8header(void) {
455 // Find session sample rate
458 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x05", 2);
461 sessionrate |= ptfunxored[k+11];
462 sessionrate |= ptfunxored[k+12] << 8;
463 sessionrate |= ptfunxored[k+13] << 16;
467 PTFFormat::parse9header(void) {
470 // Find session sample rate
473 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2);
476 sessionrate |= ptfunxored[k+11];
477 sessionrate |= ptfunxored[k+12] << 8;
478 sessionrate |= ptfunxored[k+13] << 16;
482 PTFFormat::parse10header(void) {
485 // Find session sample rate
488 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x09", 2);
491 sessionrate |= ptfunxored[k+11];
492 sessionrate |= ptfunxored[k+12] << 8;
493 sessionrate |= ptfunxored[k+13] << 16;
497 PTFFormat::parserest5(void) {
499 uint64_t regionspertrack, lengthofname;
500 uint64_t startbytes, lengthbytes, offsetbytes;
501 uint16_t tracknumber = 0;
506 for (i = 0; i < 5; i++) {
507 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x03", 3);
512 for (i = 0; i < 2; i++) {
513 jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
521 if ( (ptfunxored[k ] == 0xff) &&
522 (ptfunxored[k+1] == 0xff)) {
525 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
527 lengthofname = ptfunxored[k+12];
528 if (ptfunxored[k+13] == 0x5a) {
532 char name[256] = {0};
533 for (j = 0; j < lengthofname; j++) {
534 name[j] = ptfunxored[k+13+j];
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);
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];
548 switch (startbytes) {
550 start |= (uint32_t)(ptfunxored[j+8] << 24);
552 start |= (uint32_t)(ptfunxored[j+7] << 16);
554 start |= (uint32_t)(ptfunxored[j+6] << 8);
556 start |= (uint32_t)(ptfunxored[j+5]);
562 switch (lengthbytes) {
564 length |= (uint32_t)(ptfunxored[j+8] << 24);
566 length |= (uint32_t)(ptfunxored[j+7] << 16);
568 length |= (uint32_t)(ptfunxored[j+6] << 8);
570 length |= (uint32_t)(ptfunxored[j+5]);
575 uint32_t sampleoffset = 0;
576 switch (offsetbytes) {
578 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
580 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
582 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
584 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
590 //printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex);
592 std::string filename = string(name);
596 (int64_t)(start*ratefactor),
597 (int64_t)(length*ratefactor),
600 vector<wav_t>::iterator begin = audiofiles.begin();
601 vector<wav_t>::iterator finish = audiofiles.end();
602 vector<wav_t>::iterator found;
604 if ((found = std::find(begin, finish, f)) != finish) {
605 f.filename = (*found).filename;
606 std::vector<midi_ev_t> m;
610 (int64_t)(start*ratefactor),
611 (int64_t)(sampleoffset*ratefactor),
612 (int64_t)(length*ratefactor),
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;
624 tracknumber = tracks.size() + 1;
628 (uint16_t)tracknumber,
634 std::vector<midi_ev_t> m;
638 (int64_t)(start*ratefactor),
639 (int64_t)(sampleoffset*ratefactor),
640 (int64_t)(length*ratefactor),
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;
652 tracknumber = tracks.size() + 1;
656 (uint16_t)tracknumber,
670 PTFFormat::resort(std::vector<wav_t>& ws) {
672 std::sort(ws.begin(), ws.end());
673 for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) {
680 PTFFormat::resort(std::vector<region_t>& rs) {
682 //std::sort(rs.begin(), rs.end());
683 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
690 PTFFormat::filter(std::vector<region_t>& rs) {
691 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
698 PTFFormat::parseaudio5(void) {
700 uint64_t lengthofname, wavnumber;
702 // Find end of wav file list
704 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
706 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
708 // Find actual wav names
709 uint16_t numberofwavs = ptfunxored[k-23];
712 jumpto(&i, ptfunxored, len, (const unsigned char *)"Files", 5);
717 while (i < len && numberofwavs > 0) {
719 if ( (ptfunxored[i ] == 0x5a) &&
720 (ptfunxored[i+1] == 0x00) &&
721 (ptfunxored[i+2] == 0x05)) {
724 lengthofname = ptfunxored[i];
727 while (l < lengthofname) {
728 wavname[l] = ptfunxored[i+l];
732 ext[0] = ptfunxored[i++];
733 ext[1] = ptfunxored[i++];
734 ext[2] = ptfunxored[i++];
735 ext[3] = ptfunxored[i++];
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");
746 extension = string("");
749 std::string wave = string(wavname);
750 wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
752 if (foundin(wave, string(".grp"))) {
756 actualwavs.push_back(f);
757 audiofiles.push_back(f);
767 mchunk (uint64_t zt, uint64_t ml, std::vector<PTFFormat::midi_ev_t> const& c)
774 std::vector<PTFFormat::midi_ev_t> chunk;
778 PTFFormat::parsemidi(void) {
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;
784 uint16_t nmiditracks, regionnumber = 0;
785 uint32_t nregions, mr;
787 std::vector<mchunk> midichunks;
793 // Parse all midi chunks, not 1:1 mapping to regions yet
794 while (k + 35 < len) {
796 std::vector<midi_ev_t> midi;
798 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
802 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
803 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
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];
826 if (midi_pos + midi_len > max_pos) {
827 max_pos = midi_pos + midi_len;
833 m.velocity = midi_velocity;
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)) {
844 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
847 // Map midi chunks to regions
849 char midiregionname[256];
852 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
859 nregions |= ptfunxored[k];
860 nregions |= ptfunxored[k+1] << 8;
862 for (mr = 0; mr < nregions; mr++) {
863 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x0c", 2)) {
869 namelen = ptfunxored[k];
870 for (i = 0; i < namelen; i++) {
871 midiregionname[i] = ptfunxored[k+4+i];
873 midiregionname[namelen] = '\0';
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;
884 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\xff\xff", 4)) {
890 ridx = ptfunxored[k];
891 ridx |= ptfunxored[k+1] << 8;
893 struct mchunk mc = *(midichunks.begin()+ridx);
895 wav_t w = { std::string(""), 0, 0, 0 };
900 (int64_t)0xe8d4a51000ULL,
902 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
907 midiregions.push_back(r);
911 // Put midi regions on midi tracks
912 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
919 nmiditracks |= ptfunxored[k];
920 nmiditracks |= ptfunxored[k+1] << 8;
924 for (tr = 0; tr < nmiditracks; tr++) {
925 char miditrackname[256];
927 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
931 namelen = ptfunxored[k+9];
932 for (i = 0; i < namelen; i++) {
933 miditrackname[i] = ptfunxored[k+13+i];
935 miditrackname[namelen] = '\0';
938 nregions |= ptfunxored[k];
939 nregions |= ptfunxored[k+1] << 8;
941 for (i = 0; (i < nregions) && (k < len); i++) {
945 ridx |= ptfunxored[k];
946 ridx |= ptfunxored[k+1] << 8;
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;
959 mtr.name = string(miditrackname);
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) {
971 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
972 miditracks.push_back(mtr);
979 PTFFormat::parsemidi12(void) {
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;
985 uint16_t nmiditracks, regionnumber = 0;
986 uint32_t nregions, mr;
988 std::vector<mchunk> midichunks;
993 // Parse all midi chunks, not 1:1 mapping to regions yet
994 while (k + 35 < len) {
996 std::vector<midi_ev_t> midi;
999 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
1004 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
1005 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
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];
1028 if (midi_pos + midi_len > max_pos) {
1029 max_pos = midi_pos + midi_len;
1033 m.length = midi_len;
1035 m.velocity = midi_velocity;
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)) {
1046 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
1049 // Map midi chunks to regions
1051 char midiregionname[256];
1054 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
1061 nregions |= ptfunxored[k];
1062 nregions |= ptfunxored[k+1] << 8;
1064 for (mr = 0; mr < nregions; mr++) {
1065 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2)) {
1070 namelen = ptfunxored[k];
1071 for (i = 0; i < namelen; i++) {
1072 midiregionname[i] = ptfunxored[k+4+i];
1074 midiregionname[namelen] = '\0';
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;
1085 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\x00\x00", 4)) {
1091 ridx = ptfunxored[k];
1092 ridx |= ptfunxored[k+1] << 8;
1095 struct mchunk mc = *(midichunks.begin()+ridx);
1097 wav_t w = { std::string(""), 0, 0, 0 };
1102 (int64_t)0xe8d4a51000ULL,
1104 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
1109 midiregions.push_back(r);
1113 // Put midi regions on midi tracks
1114 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1121 nmiditracks |= ptfunxored[k];
1122 nmiditracks |= ptfunxored[k+1] << 8;
1126 for (tr = 0; tr < nmiditracks; tr++) {
1127 char miditrackname[256];
1129 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1133 namelen = ptfunxored[k+9];
1134 for (i = 0; i < namelen; i++) {
1135 miditrackname[i] = ptfunxored[k+13+i];
1137 miditrackname[namelen] = '\0';
1140 nregions |= ptfunxored[k];
1141 nregions |= ptfunxored[k+1] << 8;
1145 for (i = 0; (i < nregions) && (k < len); i++) {
1147 if ( (ptfunxored[k] == 0x5a) &&
1148 (ptfunxored[k+1] & 0x08)) {
1156 ridx |= ptfunxored[k];
1157 ridx |= ptfunxored[k+1] << 8;
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;
1168 mtr.name = string(miditrackname);
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) {
1180 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
1181 miditracks.push_back(mtr);
1183 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8)) {
1191 PTFFormat::parseaudio(void) {
1196 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Audio Files", 11))
1199 // Find end of wav file list
1200 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1203 // Find number of wave files
1204 uint16_t numberofwavs;
1206 if (!jumpback(&j, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
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);
1216 // Find actual wav names
1219 for (i = 0; i < numberofwavs; i++) {
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')) {
1230 while (ptfunxored[j] != '\0') {
1231 wavname[l] = ptfunxored[j];
1237 // Must be at least "vaw.z\0"
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]);
1254 wave = string(wavname);
1256 //uint8_t playlist = ptfunxored[j-8];
1258 std::reverse(wave.begin(), wave.end());
1259 wav_t f = { wave, (uint16_t)(numberofwavs - i - 1), 0, 0 };
1261 if (foundin(wave, string("Audio Files")) ||
1262 foundin(wave, string("Fade Files"))) {
1267 actualwavs.push_back(f);
1268 audiofiles.push_back(f);
1270 //printf(" %d:%s \n", numberofwavs - i - 1, wave.c_str());
1272 std::reverse(audiofiles.begin(), audiofiles.end());
1273 std::reverse(actualwavs.begin(), actualwavs.end());
1274 //resort(audiofiles);
1275 //resort(actualwavs);
1277 // Jump to end of wav file list
1278 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
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))
1286 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1289 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
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]);
1301 PTFFormat::parserest89(void) {
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;
1311 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4)) {
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)) {
1322 if ( (ptfunxored[i ] == 0x5a) &&
1323 (ptfunxored[i+1] == 0x0c)) {
1325 uint8_t lengthofname = ptfunxored[i+9];
1327 char name[256] = {0};
1328 for (j = 0; j < lengthofname; j++) {
1329 name[j] = ptfunxored[i+13+j];
1333 //uint8_t disabled = ptfunxored[j];
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
1347 /*rindex = ptfunxored[j+5
1355 uint32_t sampleoffset = 0;
1356 switch (offsetbytes) {
1358 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
1360 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
1362 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
1364 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
1369 uint32_t length = 0;
1370 switch (lengthbytes) {
1372 length |= (uint32_t)(ptfunxored[j+8] << 24);
1374 length |= (uint32_t)(ptfunxored[j+7] << 16);
1376 length |= (uint32_t)(ptfunxored[j+6] << 8);
1378 length |= (uint32_t)(ptfunxored[j+5]);
1384 switch (startbytes) {
1386 start |= (uint32_t)(ptfunxored[j+8] << 24);
1388 start |= (uint32_t)(ptfunxored[j+7] << 16);
1390 start |= (uint32_t)(ptfunxored[j+6] << 8);
1392 start |= (uint32_t)(ptfunxored[j+5]);
1398 uint32_t something = 0;
1399 switch (somethingbytes) {
1401 something |= (uint32_t)(ptfunxored[j+8] << 24);
1403 something |= (uint32_t)(ptfunxored[j+7] << 16);
1405 something |= (uint32_t)(ptfunxored[j+6] << 8);
1407 something |= (uint32_t)(ptfunxored[j+5]);
1413 std::string filename = string(name);
1417 (int64_t)(start*ratefactor),
1418 (int64_t)(length*ratefactor),
1421 //printf("something=%d\n", something);
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;
1434 (int64_t)(start*ratefactor),
1435 (int64_t)(sampleoffset*ratefactor),
1436 (int64_t)(length*ratefactor),
1440 regions.push_back(r);
1443 if (foundin(filename, string(".grp"))) {
1446 std::vector<midi_ev_t> m;
1450 (int64_t)(start*ratefactor),
1451 (int64_t)(sampleoffset*ratefactor),
1452 (int64_t)(length*ratefactor),
1456 regions.push_back(r);
1462 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1465 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
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)) {
1479 if ( (ptfunxored[k ] == 0x5a) &&
1480 (ptfunxored[k+1] == 0x02)) {
1482 uint8_t lengthofname = 0;
1483 lengthofname = ptfunxored[k+9];
1484 if (lengthofname == 0x5a) {
1489 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
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];
1497 tr.name = string(name);
1498 tr.index = tracknumber++;
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) {
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);
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;
1545 vector<compound_t> groupmap;
1546 // Find region group total
1548 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1551 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1554 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1557 jumpto(&k, ptfunxored, k+0x2000, (const unsigned char *)"\x5a\x03", 2);
1561 for (i = k; i < len; i++) {
1562 if (!jumpto(&i, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2))
1566 verbose_printf("groupcount=%d\n", groupcount);
1568 // Find start of group names -> group indexes
1570 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1573 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1576 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1580 // Skip total number of groups
1581 for (i = 0; i < groupcount; i++) {
1583 if ( (ptfunxored[k ] == 0x5a) &&
1584 ((ptfunxored[k+1] == 0x03) || (ptfunxored[k+1] == 0x0a))) {
1593 if ( (ptfunxored[k ] == 0x5a) &&
1594 (ptfunxored[k+1] & 0x02)) {
1602 if ( (ptfunxored[k ] == 0x5a) &&
1603 (ptfunxored[k+1] & 0x02)) {
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++) {
1614 if ( (ptfunxored[k ] == 0x5a) &&
1615 (ptfunxored[k+1] & 0x02)) {
1622 gindex = ptfunxored[k+9] | ptfunxored[k+10] << 8;
1623 gindex2 = ptfunxored[k+3] | ptfunxored[k+4] << 8;
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];
1632 if (strlen(name) == 0) {
1638 (uint16_t)i, // curr_index
1642 gindex2, // next_index
1645 groupmap.push_back(c);
1649 // Sort lookup table by group index
1650 //std::sort(glookup.begin(), glookup.end(), regidx_compare);
1652 // print compounds as flattened tree
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());
1660 // Find region groups
1662 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4))
1665 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2))
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))
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))
1677 // Hack to find actual start of region group information
1679 if ((ptfunxored[k+13] == 0x5a) && (ptfunxored[k+14] & 0xf)) {
1683 if ((ptfunxored[k+9] == 0x5a) && (ptfunxored[k+10] & 0xf)) {
1688 if ((ptfunxored[k] == 0x5a) && (ptfunxored[k+1] & 0xf))
1692 verbose_printf("hack region groups k=0x%x\n", k);
1696 groupmax = groupcount == 0 ? 0 : ptfunxored[j+3] | ptfunxored[j+4] << 8;
1698 for (i = k; (groupcount < groupmax) && (i < len-70); i++) {
1699 if ( (ptfunxored[i ] == 0x5a) &&
1700 (ptfunxored[i+1] == 0x03)) {
1703 if ( (ptfunxored[i ] == 0x5a) &&
1704 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1706 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1707 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1709 uint8_t lengthofname = ptfunxored[i+9];
1710 if (ptfunxored[i+13] == 0x5a) {
1713 char name[256] = {0};
1714 for (j = 0; j < lengthofname; j++) {
1715 name[j] = ptfunxored[i+13+j];
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
1740 findex = ptfunxored[j+5
1755 uint64_t sampleoffset = 0;
1756 switch (offsetbytes) {
1758 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
1760 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
1762 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
1764 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
1766 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
1771 uint64_t length = 0;
1772 switch (lengthbytes) {
1774 length |= (uint64_t)(ptfunxored[j+9]) << 32;
1776 length |= (uint64_t)(ptfunxored[j+8]) << 24;
1778 length |= (uint64_t)(ptfunxored[j+7]) << 16;
1780 length |= (uint64_t)(ptfunxored[j+6]) << 8;
1782 length |= (uint64_t)(ptfunxored[j+5]);
1788 switch (startbytes) {
1790 start |= (uint64_t)(ptfunxored[j+9]) << 32;
1792 start |= (uint64_t)(ptfunxored[j+8]) << 24;
1794 start |= (uint64_t)(ptfunxored[j+7]) << 16;
1796 start |= (uint64_t)(ptfunxored[j+6]) << 8;
1798 start |= (uint64_t)(ptfunxored[j+5]);
1804 if (offsetbytes == 5)
1805 sampleoffset -= 1000000000000ULL;
1806 if (startbytes == 5)
1807 start -= 1000000000000ULL;
1809 std::string filename = string(name);
1813 (int64_t)(start*ratefactor),
1814 (int64_t)(length*ratefactor),
1817 if (strlen(name) == 0) {
1823 //if (foundin(filename, string(".grp")) && !regionsingroup && !findex) {
1824 // // Empty region group
1825 // verbose_printf(" EMPTY: %s\n", name);
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);
1834 for (l = 0; l < regionsingroup; l++) {
1835 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
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) {
1854 if (wave == actualwavs.end())
1857 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
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))
1866 rindex = ptfunxored[m] | (ptfunxored[m+1] << 8);
1870 switch (offsetbytes) {
1872 sampleoffset |= (uint64_t)(ptfunxored[m+4]) << 32;
1874 sampleoffset |= (uint64_t)(ptfunxored[m+3]) << 24;
1876 sampleoffset |= (uint64_t)(ptfunxored[m+2]) << 16;
1878 sampleoffset |= (uint64_t)(ptfunxored[m+1]) << 8;
1880 sampleoffset |= (uint64_t)(ptfunxored[m]);
1886 switch (offsetbytes) {
1888 start |= (uint64_t)(ptfunxored[m+4]) << 32;
1890 start |= (uint64_t)(ptfunxored[m+3]) << 24;
1892 start |= (uint64_t)(ptfunxored[m+2]) << 16;
1894 start |= (uint64_t)(ptfunxored[m+1]) << 8;
1896 start |= (uint64_t)(ptfunxored[m]);
1902 switch (lengthbytes) {
1904 length |= (uint64_t)(ptfunxored[m+4]) << 32;
1906 length |= (uint64_t)(ptfunxored[m+3]) << 24;
1908 length |= (uint64_t)(ptfunxored[m+2]) << 16;
1910 length |= (uint64_t)(ptfunxored[m+1]) << 8;
1912 length |= (uint64_t)(ptfunxored[m]);
1917 findex3 = ptfunxored[m] | (ptfunxored[m+1] << 8);
1918 sampleoffset -= 1000000000000ULL;
1919 start -= 1000000000000ULL;
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) {
1930 if (wave == actualwavs.end())
1932 // findex is the true source
1933 std::vector<midi_ev_t> md;
1937 (int64_t)findex, //(start*ratefactor),
1938 (int64_t)findex2, //(sampleoffset*ratefactor),
1939 (int64_t)findex3, //(length*ratefactor),
1943 groups.push_back(r);
1945 vector<compound_t>::iterator g = groupmap.begin()+findex2;
1946 if (g >= groupmap.end())
1949 c.name = string(g->name);
1950 c.curr_index = compoundcount;
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);
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);
1970 verbose_printf("pure regions k=0x%x\n", k);
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;
1977 verbose_printf("maxregions=%u\n", maxregions);
1979 for (i = k; rindex < maxregions && i < len; i++) {
1980 if ( (ptfunxored[i ] == 0xff) &&
1981 (ptfunxored[i+1] == 0x5a) &&
1982 (ptfunxored[i+2] == 0x01)) {
1985 //if ( (ptfunxored[i ] == 0x5a) &&
1986 // (ptfunxored[i+1] == 0x03)) {
1989 if ( (ptfunxored[i ] == 0x5a) &&
1990 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1992 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1993 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1995 uint8_t lengthofname = ptfunxored[i+9];
1996 if (ptfunxored[i+13] == 0x5a) {
1999 char name[256] = {0};
2000 for (j = 0; j < lengthofname; j++) {
2001 name[j] = ptfunxored[i+13+j];
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
2026 uint64_t sampleoffset = 0;
2027 switch (offsetbytes) {
2029 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
2031 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
2033 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
2035 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
2037 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
2042 uint64_t length = 0;
2043 switch (lengthbytes) {
2045 length |= (uint64_t)(ptfunxored[j+9]) << 32;
2047 length |= (uint64_t)(ptfunxored[j+8]) << 24;
2049 length |= (uint64_t)(ptfunxored[j+7]) << 16;
2051 length |= (uint64_t)(ptfunxored[j+6]) << 8;
2053 length |= (uint64_t)(ptfunxored[j+5]);
2059 switch (startbytes) {
2061 start |= (uint64_t)(ptfunxored[j+9]) << 32;
2063 start |= (uint64_t)(ptfunxored[j+8]) << 24;
2065 start |= (uint64_t)(ptfunxored[j+7]) << 16;
2067 start |= (uint64_t)(ptfunxored[j+6]) << 8;
2069 start |= (uint64_t)(ptfunxored[j+5]);
2075 if (offsetbytes == 5)
2076 sampleoffset -= 1000000000000ULL;
2077 if (startbytes == 5)
2078 start -= 1000000000000ULL;
2080 std::string filename = string(name);
2084 (int64_t)(start*ratefactor),
2085 (int64_t)(length*ratefactor),
2088 if (strlen(name) == 0) {
2094 // Regular region mapping to a source
2096 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2098 //printf("XXX=%d\n", ptfunxored[n+12] | ptfunxored[n+13]<<8);
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) {
2108 if (wave == actualwavs.end()) {
2109 verbose_printf("missing source with findex\n");
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;
2118 (int64_t)(start*ratefactor),
2119 (int64_t)(sampleoffset*ratefactor),
2120 (int64_t)(length*ratefactor),
2124 regions.push_back(r);
2130 vector<uint16_t> rootnodes;
2134 for (vector<compound_t>::iterator cmp = compounds.begin();
2135 cmp != compounds.end(); ++cmp) {
2137 for (vector<compound_t>::iterator tmp = compounds.begin();
2138 tmp != compounds.end(); ++tmp) {
2141 if (tmp->ontopof_index == cmp->curr_index)
2144 // Collect a vector of all the root nodes (no others point to)
2146 rootnodes.push_back(cmp->curr_index);
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())
2156 verbose_printf("----\n");
2158 for (; cmp < compounds.end() && cmp->curr_index != cmp->next_index;
2159 cmp = compounds.begin()+cmp->next_index) {
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) {
2169 if (r == regions.end())
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());
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) {
2181 if (r == regions.end())
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());
2186 // Start grouped regions
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) {
2198 if (wav == audiofiles.end())
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) {
2209 if (wav2 == audiofiles.end())
2212 verbose_printf("Group: %s -> %s OR %s\n", a->name.c_str(), wav->filename.c_str(), wav2->filename.c_str());
2220 uint32_t tracknumber = 0;
2221 uint32_t regionspertrack = 0;
2222 uint32_t maxtracks = 0;
2226 if (!jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x03\x00", 3))
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;
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))
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))
2243 verbose_printf("tracks k=0x%x\n", k);
2245 for (;k < len; k++) {
2246 if ( (ptfunxored[k ] == 0x5a) &&
2247 (ptfunxored[k+1] & 0x04)) {
2250 if ( (ptfunxored[k ] == 0x5a) &&
2251 (ptfunxored[k+1] & 0x02)) {
2253 uint8_t lengthofname = 0;
2254 lengthofname = ptfunxored[k+9];
2255 if (lengthofname == 0x5a) {
2260 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
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];
2268 tr.name = string(name);
2269 tr.index = tracknumber++;
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;
2275 tr.reg.name = string("");
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());
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) {
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());
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);
2304 jumpto(&j, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);