2 Copyright (C) 2015 Damien Zammit
3 Copyright (C) 2015 Robin Gareus
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
23 #include <glib/gstdio.h>
25 #include "ptfformat.h"
28 #define verbose_printf(...) printf(__VA_ARGS__)
30 #define verbose_printf(...)
35 static bool wavidx_compare(PTFFormat::wav_t& w1, PTFFormat::wav_t& w2) {
36 return w1.index < w2.index;
39 static bool wavname_compare(PTFFormat::wav_t& w1, PTFFormat::wav_t& w2) {
40 return (strcasecmp(w1.filename.c_str(), w2.filename.c_str()) < 0);
43 static bool regidx_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) {
44 return r1.index < r2.index;
47 static bool regname_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) {
48 return (strcasecmp(r1.name.c_str(), r2.name.c_str()) < 0);
52 hexdump(uint8_t *data, int len)
56 for (i = 0; i < len; i += step) {
57 printf("0x%02X: ", i);
59 if (end > len) end = len;
60 for (j = i; j < end; j++) {
61 printf("0x%02X ", data[j]);
63 for (j = i; j < end; j++) {
64 if (data[j] < 128 && data[j] > 32)
65 printf("%c", data[j]);
73 PTFFormat::PTFFormat() : version(0), product(NULL) {
76 PTFFormat::~PTFFormat() {
83 PTFFormat::foundat(unsigned char *haystack, uint64_t n, const char *needle) {
85 uint64_t i, j, needle_n;
86 needle_n = strlen(needle);
88 for (i = 0; i < n; i++) {
90 for (j = 0; j < needle_n; j++) {
91 if (haystack[i+j] != needle[j]) {
103 PTFFormat::jumpto(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
105 uint64_t k = *currpos;
106 while (k + needlelen < maxoffset) {
107 bool foundall = true;
108 for (i = 0; i < needlelen; i++) {
109 if (buf[k+i] != needle[i]) {
124 PTFFormat::jumpback(uint32_t *currpos, unsigned char *buf, const uint32_t maxoffset, const unsigned char *needle, const uint32_t needlelen) {
126 uint64_t k = *currpos;
127 while (k > 0 && k + needlelen < maxoffset) {
128 bool foundall = true;
129 for (i = 0; i < needlelen; i++) {
130 if (buf[k+i] != needle[i]) {
145 PTFFormat::foundin(std::string haystack, std::string needle) {
146 size_t found = haystack.find(needle);
147 if (found != std::string::npos) {
154 /* Return values: 0 success
155 -1 could not decrypt pt session
158 PTFFormat::unxor(std::string path) {
160 unsigned char xxor[256];
168 if (! (fp = g_fopen(path.c_str(), "rb"))) {
172 fseek(fp, 0, SEEK_END);
179 if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) {
180 /* Silently fail -- out of memory*/
186 /* The first 20 bytes are always unencrypted */
187 fseek(fp, 0x00, SEEK_SET);
188 i = fread(ptfunxored, 1, 0x14, fp);
194 xor_type = ptfunxored[0x12];
195 xor_value = ptfunxored[0x13];
198 // xor_type 0x01 = ProTools 5, 6, 7, 8 and 9
199 // xor_type 0x05 = ProTools 10, 11, 12
202 xor_delta = gen_xor_delta(xor_value, 53, false);
205 xor_delta = gen_xor_delta(xor_value, 11, true);
212 /* Generate the xor_key */
213 for (i=0; i < xor_len; i++)
214 xxor[i] = (i * xor_delta) & 0xff;
216 /* hexdump(xxor, xor_len); */
218 /* Read file and decrypt rest of file */
220 fseek(fp, i, SEEK_SET);
221 while (fread(&ct, 1, 1, fp) != 0) {
222 uint8_t xor_index = (xor_type == 0x01) ? i & 0xff : (i >> 12) & 0xff;
223 ptfunxored[i++] = ct ^ xxor[xor_index];
229 /* Return values: 0 success
230 -1 could not parse pt session
233 PTFFormat::load(std::string path, int64_t targetsr) {
240 if (version < 5 || version > 12)
243 targetrate = targetsr;
252 PTFFormat::parse_version() {
253 uint32_t seg_len,str_len;
254 uint8_t *data = ptfunxored + 0x14;
255 uintptr_t data_end = ((uintptr_t)ptfunxored) + 0x100;
257 bool success = false;
259 while( ((uintptr_t)data < data_end) && (success == false) ) {
261 if (data[0] != 0x5a) {
267 /* Skip segment header */
269 if (data[0] == 0 && data[1] == 0) {
271 seg_len = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
274 seg_len = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
278 if (!(seg_type == 0x04 || seg_type == 0x03) || data[0] != 0x03) {
279 /* Go to next segment */
283 /* Skip 0x03 0x00 0x00 */
286 str_len = (*(uint8_t *)data);
287 if (! (product = (uint8_t *)malloc((str_len+1) * sizeof(uint8_t)))) {
296 memcpy(product, data, str_len);
297 product[str_len] = 0;
301 /* Skip 0x03 0x00 0x00 0x00 */
313 /* If the above does not work, try other heuristics */
314 if ((uintptr_t)data >= data_end - seg_len) {
315 version = ptfunxored[0x40];
317 version = ptfunxored[0x3d];
320 version = ptfunxored[0x3a] + 2;
330 PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) {
332 for (i = 0; i < 256; i++) {
333 if (((i * mul) & 0xff) == xor_value) {
334 return (negative) ? i * (-1) : i;
342 PTFFormat::parse(void) {
346 if (sessionrate < 44100 || sessionrate > 192000)
351 } else if (version == 7) {
354 if (sessionrate < 44100 || sessionrate > 192000)
359 } else if (version == 8) {
362 if (sessionrate < 44100 || sessionrate > 192000)
367 } else if (version == 9) {
370 if (sessionrate < 44100 || sessionrate > 192000)
375 } else if (version == 10 || version == 11 || version == 12) {
378 if (sessionrate < 44100 || sessionrate > 192000)
391 PTFFormat::setrates(void) {
393 if (sessionrate != 0) {
394 ratefactor = (float)targetrate / sessionrate;
399 PTFFormat::parse5header(void) {
402 // Find session sample rate
405 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x02", 3);
408 sessionrate |= ptfunxored[k+12] << 16;
409 sessionrate |= ptfunxored[k+13] << 8;
410 sessionrate |= ptfunxored[k+14];
414 PTFFormat::parse7header(void) {
417 // Find session sample rate
420 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x05", 3);
423 sessionrate |= ptfunxored[k+12] << 16;
424 sessionrate |= ptfunxored[k+13] << 8;
425 sessionrate |= ptfunxored[k+14];
429 PTFFormat::parse8header(void) {
432 // Find session sample rate
435 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x05", 2);
438 sessionrate |= ptfunxored[k+11];
439 sessionrate |= ptfunxored[k+12] << 8;
440 sessionrate |= ptfunxored[k+13] << 16;
444 PTFFormat::parse9header(void) {
447 // Find session sample rate
450 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2);
453 sessionrate |= ptfunxored[k+11];
454 sessionrate |= ptfunxored[k+12] << 8;
455 sessionrate |= ptfunxored[k+13] << 16;
459 PTFFormat::parse10header(void) {
462 // Find session sample rate
465 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x09", 2);
468 sessionrate |= ptfunxored[k+11];
469 sessionrate |= ptfunxored[k+12] << 8;
470 sessionrate |= ptfunxored[k+13] << 16;
474 PTFFormat::parserest5(void) {
476 uint64_t regionspertrack, lengthofname;
477 uint64_t startbytes, lengthbytes, offsetbytes;
478 uint16_t tracknumber = 0;
483 for (i = 0; i < 5; i++) {
484 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x03", 3);
489 for (i = 0; i < 2; i++) {
490 jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
498 if ( (ptfunxored[k ] == 0xff) &&
499 (ptfunxored[k+1] == 0xff)) {
502 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x01", 3);
504 lengthofname = ptfunxored[k+12];
505 if (ptfunxored[k+13] == 0x5a) {
509 char name[256] = {0};
510 for (j = 0; j < lengthofname; j++) {
511 name[j] = ptfunxored[k+13+j];
514 regionspertrack = ptfunxored[k+13+j+3];
515 for (i = 0; i < regionspertrack; i++) {
516 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x00\x03", 3);
518 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
519 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
520 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
521 //somethingbytes = (ptfunxored[j+1] & 0xf);
522 findex = ptfunxored[k+14];
525 switch (startbytes) {
527 start |= (uint32_t)(ptfunxored[j+8] << 24);
529 start |= (uint32_t)(ptfunxored[j+7] << 16);
531 start |= (uint32_t)(ptfunxored[j+6] << 8);
533 start |= (uint32_t)(ptfunxored[j+5]);
539 switch (lengthbytes) {
541 length |= (uint32_t)(ptfunxored[j+8] << 24);
543 length |= (uint32_t)(ptfunxored[j+7] << 16);
545 length |= (uint32_t)(ptfunxored[j+6] << 8);
547 length |= (uint32_t)(ptfunxored[j+5]);
552 uint32_t sampleoffset = 0;
553 switch (offsetbytes) {
555 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
557 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
559 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
561 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
567 //printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex);
569 std::string filename = string(name);
573 (int64_t)(start*ratefactor),
574 (int64_t)(length*ratefactor),
577 vector<wav_t>::iterator begin = audiofiles.begin();
578 vector<wav_t>::iterator finish = audiofiles.end();
579 vector<wav_t>::iterator found;
581 if ((found = std::find(begin, finish, f)) != finish) {
582 f.filename = (*found).filename;
583 std::vector<midi_ev_t> m;
587 (int64_t)(start*ratefactor),
588 (int64_t)(sampleoffset*ratefactor),
589 (int64_t)(length*ratefactor),
593 regions.push_back(r);
594 vector<track_t>::iterator ti;
595 vector<track_t>::iterator bt = tracks.begin();
596 vector<track_t>::iterator et = tracks.end();
597 track_t tr = { name, 0, 0, r };
598 if ((ti = std::find(bt, et, tr)) != et) {
599 tracknumber = (*ti).index;
601 tracknumber = tracks.size() + 1;
605 (uint16_t)tracknumber,
611 std::vector<midi_ev_t> m;
615 (int64_t)(start*ratefactor),
616 (int64_t)(sampleoffset*ratefactor),
617 (int64_t)(length*ratefactor),
621 regions.push_back(r);
622 vector<track_t>::iterator ti;
623 vector<track_t>::iterator bt = tracks.begin();
624 vector<track_t>::iterator et = tracks.end();
625 track_t tr = { name, 0, 0, r };
626 if ((ti = std::find(bt, et, tr)) != et) {
627 tracknumber = (*ti).index;
629 tracknumber = tracks.size() + 1;
633 (uint16_t)tracknumber,
647 PTFFormat::resort(std::vector<wav_t>& ws) {
649 std::sort(ws.begin(), ws.end());
650 for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) {
657 PTFFormat::resort(std::vector<region_t>& rs) {
659 //std::sort(rs.begin(), rs.end());
660 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
667 PTFFormat::filter(std::vector<region_t>& rs) {
668 for (std::vector<region_t>::iterator i = rs.begin(); i != rs.end(); ++i) {
675 PTFFormat::parseaudio5(void) {
677 uint64_t lengthofname, wavnumber;
679 // Find end of wav file list
681 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
683 jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5f\x50\x35", 3);
685 // Find actual wav names
686 uint16_t numberofwavs = ptfunxored[k-23];
689 jumpto(&i, ptfunxored, len, (const unsigned char *)"Files", 5);
694 while (i < len && numberofwavs > 0) {
696 if ( (ptfunxored[i ] == 0x5a) &&
697 (ptfunxored[i+1] == 0x00) &&
698 (ptfunxored[i+2] == 0x05)) {
701 lengthofname = ptfunxored[i];
704 while (l < lengthofname) {
705 wavname[l] = ptfunxored[i+l];
709 ext[0] = ptfunxored[i++];
710 ext[1] = ptfunxored[i++];
711 ext[2] = ptfunxored[i++];
712 ext[3] = ptfunxored[i++];
716 if (foundin(wavname, ".L") || foundin(wavname, ".R")) {
717 extension = string("");
718 } else if (foundin(wavname, ".wav") || foundin(ext, "WAVE")) {
719 extension = string(".wav");
720 } else if (foundin(wavname, ".aif") || foundin(ext, "AIFF")) {
721 extension = string(".aif");
723 extension = string("");
726 std::string wave = string(wavname);
727 wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
729 if (foundin(wave, string(".grp"))) {
733 actualwavs.push_back(f);
734 audiofiles.push_back(f);
744 mchunk (uint64_t zt, uint64_t ml, std::vector<PTFFormat::midi_ev_t> const& c)
751 std::vector<PTFFormat::midi_ev_t> chunk;
755 PTFFormat::parsemidi(void) {
757 uint64_t tr, n_midi_events, zero_ticks;
758 uint64_t midi_pos, midi_len, max_pos, region_pos;
759 uint8_t midi_velocity, midi_note;
761 uint16_t nmiditracks, regionnumber = 0;
762 uint32_t nregions, mr;
764 std::vector<mchunk> midichunks;
770 // Parse all midi chunks, not 1:1 mapping to regions yet
771 while (k + 35 < len) {
773 std::vector<midi_ev_t> midi;
775 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
779 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
780 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
783 zero_ticks = (uint64_t)ptfunxored[k] |
784 (uint64_t)ptfunxored[k+1] << 8 |
785 (uint64_t)ptfunxored[k+2] << 16 |
786 (uint64_t)ptfunxored[k+3] << 24 |
787 (uint64_t)ptfunxored[k+4] << 32;
788 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
789 midi_pos = (uint64_t)ptfunxored[k] |
790 (uint64_t)ptfunxored[k+1] << 8 |
791 (uint64_t)ptfunxored[k+2] << 16 |
792 (uint64_t)ptfunxored[k+3] << 24 |
793 (uint64_t)ptfunxored[k+4] << 32;
794 midi_pos -= zero_ticks;
795 midi_note = ptfunxored[k+8];
796 midi_len = (uint64_t)ptfunxored[k+9] |
797 (uint64_t)ptfunxored[k+10] << 8 |
798 (uint64_t)ptfunxored[k+11] << 16 |
799 (uint64_t)ptfunxored[k+12] << 24 |
800 (uint64_t)ptfunxored[k+13] << 32;
801 midi_velocity = ptfunxored[k+17];
803 if (midi_pos + midi_len > max_pos) {
804 max_pos = midi_pos + midi_len;
810 m.velocity = midi_velocity;
812 // stop gap measure to prevent crashes in ardour,
813 // remove when decryption is fully solved for .ptx
814 if ((m.velocity & 0x80) || (m.note & 0x80) ||
815 (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
821 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
824 // Map midi chunks to regions
826 char midiregionname[256];
829 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
836 nregions |= ptfunxored[k];
837 nregions |= ptfunxored[k+1] << 8;
839 for (mr = 0; mr < nregions; mr++) {
840 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x0c", 2)) {
846 namelen = ptfunxored[k];
847 for (i = 0; i < namelen; i++) {
848 midiregionname[i] = ptfunxored[k+4+i];
850 midiregionname[namelen] = '\0';
855 region_pos = (uint64_t)ptfunxored[k] |
856 (uint64_t)ptfunxored[k+1] << 8 |
857 (uint64_t)ptfunxored[k+2] << 16 |
858 (uint64_t)ptfunxored[k+3] << 24 |
859 (uint64_t)ptfunxored[k+4] << 32;
861 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\xff\xff", 4)) {
867 ridx = ptfunxored[k];
868 ridx |= ptfunxored[k+1] << 8;
870 struct mchunk mc = *(midichunks.begin()+ridx);
872 wav_t w = { std::string(""), 0, 0, 0 };
877 (int64_t)0xe8d4a51000ull,
879 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
884 midiregions.push_back(r);
888 // Put midi regions on midi tracks
889 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
896 nmiditracks |= ptfunxored[k];
897 nmiditracks |= ptfunxored[k+1] << 8;
901 for (tr = 0; tr < nmiditracks; tr++) {
902 char miditrackname[256];
904 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
908 namelen = ptfunxored[k+9];
909 for (i = 0; i < namelen; i++) {
910 miditrackname[i] = ptfunxored[k+13+i];
912 miditrackname[namelen] = '\0';
915 nregions |= ptfunxored[k];
916 nregions |= ptfunxored[k+1] << 8;
918 for (i = 0; (i < nregions) && (k < len); i++) {
922 ridx |= ptfunxored[k];
923 ridx |= ptfunxored[k+1] << 8;
927 region_pos = (uint64_t)ptfunxored[k] |
928 (uint64_t)ptfunxored[k+1] << 8 |
929 (uint64_t)ptfunxored[k+2] << 16 |
930 (uint64_t)ptfunxored[k+3] << 24 |
931 (uint64_t)ptfunxored[k+4] << 32;
936 mtr.name = string(miditrackname);
939 // Find the midi region with index 'ridx'
940 std::vector<region_t>::iterator begin = midiregions.begin();
941 std::vector<region_t>::iterator finish = midiregions.end();
942 std::vector<region_t>::iterator mregion;
943 wav_t w = { std::string(""), 0, 0, 0 };
944 std::vector<midi_ev_t> m;
945 region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
946 if ((mregion = std::find(begin, finish, r)) != finish) {
948 mtr.reg.startpos = labs(region_pos - mtr.reg.startpos);
949 miditracks.push_back(mtr);
956 PTFFormat::parsemidi12(void) {
958 uint64_t tr, n_midi_events, zero_ticks;
959 uint64_t midi_pos, midi_len, max_pos, region_pos;
960 uint8_t midi_velocity, midi_note;
962 uint16_t nmiditracks, regionnumber = 0;
963 uint32_t nregions, mr;
965 std::vector<mchunk> midichunks;
970 // Parse all midi chunks, not 1:1 mapping to regions yet
971 while (k + 35 < len) {
973 std::vector<midi_ev_t> midi;
976 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdNLB", 5)) {
981 n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 |
982 ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24;
985 zero_ticks = (uint64_t)ptfunxored[k] |
986 (uint64_t)ptfunxored[k+1] << 8 |
987 (uint64_t)ptfunxored[k+2] << 16 |
988 (uint64_t)ptfunxored[k+3] << 24 |
989 (uint64_t)ptfunxored[k+4] << 32;
990 for (i = 0; i < n_midi_events && k < len; i++, k += 35) {
991 midi_pos = (uint64_t)ptfunxored[k] |
992 (uint64_t)ptfunxored[k+1] << 8 |
993 (uint64_t)ptfunxored[k+2] << 16 |
994 (uint64_t)ptfunxored[k+3] << 24 |
995 (uint64_t)ptfunxored[k+4] << 32;
996 midi_pos -= zero_ticks;
997 midi_note = ptfunxored[k+8];
998 midi_len = (uint64_t)ptfunxored[k+9] |
999 (uint64_t)ptfunxored[k+10] << 8 |
1000 (uint64_t)ptfunxored[k+11] << 16 |
1001 (uint64_t)ptfunxored[k+12] << 24 |
1002 (uint64_t)ptfunxored[k+13] << 32;
1003 midi_velocity = ptfunxored[k+17];
1005 if (midi_pos + midi_len > max_pos) {
1006 max_pos = midi_pos + midi_len;
1010 m.length = midi_len;
1012 m.velocity = midi_velocity;
1014 // stop gap measure to prevent crashes in ardour,
1015 // remove when decryption is fully solved for .ptx
1016 if ((m.velocity & 0x80) || (m.note & 0x80) ||
1017 (m.pos & 0xff00000000LL) || (m.length & 0xff00000000LL)) {
1023 midichunks.push_back(mchunk (zero_ticks, max_pos, midi));
1026 // Map midi chunks to regions
1028 char midiregionname[256];
1031 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"MdTEL", 5)) {
1038 nregions |= ptfunxored[k];
1039 nregions |= ptfunxored[k+1] << 8;
1041 for (mr = 0; mr < nregions; mr++) {
1042 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2)) {
1047 namelen = ptfunxored[k];
1048 for (i = 0; i < namelen; i++) {
1049 midiregionname[i] = ptfunxored[k+4+i];
1051 midiregionname[namelen] = '\0';
1056 region_pos = (uint64_t)ptfunxored[k] |
1057 (uint64_t)ptfunxored[k+1] << 8 |
1058 (uint64_t)ptfunxored[k+2] << 16 |
1059 (uint64_t)ptfunxored[k+3] << 24 |
1060 (uint64_t)ptfunxored[k+4] << 32;
1062 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xfe\xff\x00\x00", 4)) {
1068 ridx = ptfunxored[k];
1069 ridx |= ptfunxored[k+1] << 8;
1072 struct mchunk mc = *(midichunks.begin()+ridx);
1074 wav_t w = { std::string(""), 0, 0, 0 };
1079 (int64_t)0xe8d4a51000ull,
1081 //(int64_t)(max_pos*sessionrate*60/(960000*120)),
1086 midiregions.push_back(r);
1090 // Put midi regions on midi tracks
1091 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1098 nmiditracks |= ptfunxored[k];
1099 nmiditracks |= ptfunxored[k+1] << 8;
1103 for (tr = 0; tr < nmiditracks; tr++) {
1104 char miditrackname[256];
1106 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1110 namelen = ptfunxored[k+9];
1111 for (i = 0; i < namelen; i++) {
1112 miditrackname[i] = ptfunxored[k+13+i];
1114 miditrackname[namelen] = '\0';
1117 nregions |= ptfunxored[k];
1118 nregions |= ptfunxored[k+1] << 8;
1122 for (i = 0; (i < nregions) && (k < len); i++) {
1124 if ( (ptfunxored[k] == 0x5a) &&
1125 (ptfunxored[k+1] & 0x08)) {
1133 ridx |= ptfunxored[k];
1134 ridx |= ptfunxored[k+1] << 8;
1138 region_pos = (uint64_t)ptfunxored[k] |
1139 (uint64_t)ptfunxored[k+1] << 8 |
1140 (uint64_t)ptfunxored[k+2] << 16 |
1141 (uint64_t)ptfunxored[k+3] << 24 |
1142 (uint64_t)ptfunxored[k+4] << 32;
1145 mtr.name = string(miditrackname);
1148 // Find the midi region with index 'ridx'
1149 std::vector<region_t>::iterator begin = midiregions.begin();
1150 std::vector<region_t>::iterator finish = midiregions.end();
1151 std::vector<region_t>::iterator mregion;
1152 wav_t w = { std::string(""), 0, 0, 0 };
1153 std::vector<midi_ev_t> m;
1154 region_t r = { std::string(""), ridx, 0, 0, 0, w, m};
1155 if ((mregion = std::find(begin, finish, r)) != finish) {
1157 mtr.reg.startpos = std::labs(region_pos - mtr.reg.startpos);
1158 miditracks.push_back(mtr);
1160 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8)) {
1168 PTFFormat::parseaudio(void) {
1173 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Audio Files", 11))
1176 // Find end of wav file list
1177 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1180 // Find number of wave files
1181 uint16_t numberofwavs;
1183 if (!jumpback(&j, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
1187 numberofwavs |= (uint32_t)(ptfunxored[j-1] << 24);
1188 numberofwavs |= (uint32_t)(ptfunxored[j-2] << 16);
1189 numberofwavs |= (uint32_t)(ptfunxored[j-3] << 8);
1190 numberofwavs |= (uint32_t)(ptfunxored[j-4]);
1191 //printf("%d wavs\n", numberofwavs);
1193 // Find actual wav names
1196 for (i = 0; i < numberofwavs; i++) {
1198 if ( ((ptfunxored[j ] == 'W') || (ptfunxored[j ] == 'A') || ptfunxored[j ] == '\0') &&
1199 ((ptfunxored[j-1] == 'A') || (ptfunxored[j-1] == 'I') || ptfunxored[j-1] == '\0') &&
1200 ((ptfunxored[j-2] == 'V') || (ptfunxored[j-2] == 'F') || ptfunxored[j-2] == '\0')) {
1207 while (ptfunxored[j] != '\0') {
1208 wavname[l] = ptfunxored[j];
1214 // Must be at least "vaw.z\0"
1220 // and skip "zWAVE" or "zAIFF"
1221 if ( ( (wavname[1] == 'W') &&
1222 (wavname[2] == 'A') &&
1223 (wavname[3] == 'V') &&
1224 (wavname[4] == 'E')) ||
1225 ( (wavname[1] == 'A') &&
1226 (wavname[2] == 'I') &&
1227 (wavname[3] == 'F') &&
1228 (wavname[4] == 'F'))) {
1229 wave = string(&wavname[5]);
1231 wave = string(wavname);
1233 //uint8_t playlist = ptfunxored[j-8];
1235 std::reverse(wave.begin(), wave.end());
1236 wav_t f = { wave, (uint16_t)(numberofwavs - i - 1), 0, 0 };
1238 if (foundin(wave, string("Audio Files"))) {
1243 actualwavs.push_back(f);
1244 audiofiles.push_back(f);
1246 //printf(" %d:%s \n", numberofwavs - i - 1, wave.c_str());
1248 std::reverse(audiofiles.begin(), audiofiles.end());
1249 std::reverse(actualwavs.begin(), actualwavs.end());
1250 //resort(audiofiles);
1251 //resort(actualwavs);
1255 PTFFormat::parserest89(void) {
1257 uint8_t startbytes = 0;
1258 uint8_t lengthbytes = 0;
1259 uint8_t offsetbytes = 0;
1260 uint8_t somethingbytes = 0;
1261 uint8_t skipbytes = 0;
1265 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4)) {
1269 uint16_t rindex = 0;
1270 uint32_t findex = 0;
1271 for (i = k; i < len-70; i++) {
1272 if ( (ptfunxored[i ] == 0x5a) &&
1273 (ptfunxored[i+1] == 0x0a)) {
1276 if ( (ptfunxored[i ] == 0x5a) &&
1277 (ptfunxored[i+1] == 0x0c)) {
1279 uint8_t lengthofname = ptfunxored[i+9];
1281 char name[256] = {0};
1282 for (j = 0; j < lengthofname; j++) {
1283 name[j] = ptfunxored[i+13+j];
1287 //uint8_t disabled = ptfunxored[j];
1289 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1290 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1291 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1292 somethingbytes = (ptfunxored[j+3] & 0xf);
1293 skipbytes = ptfunxored[j+4];
1294 findex = ptfunxored[j+5
1301 /*rindex = ptfunxored[j+5
1309 uint32_t sampleoffset = 0;
1310 switch (offsetbytes) {
1312 sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24);
1314 sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16);
1316 sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8);
1318 sampleoffset |= (uint32_t)(ptfunxored[j+5]);
1323 uint32_t length = 0;
1324 switch (lengthbytes) {
1326 length |= (uint32_t)(ptfunxored[j+8] << 24);
1328 length |= (uint32_t)(ptfunxored[j+7] << 16);
1330 length |= (uint32_t)(ptfunxored[j+6] << 8);
1332 length |= (uint32_t)(ptfunxored[j+5]);
1338 switch (startbytes) {
1340 start |= (uint32_t)(ptfunxored[j+8] << 24);
1342 start |= (uint32_t)(ptfunxored[j+7] << 16);
1344 start |= (uint32_t)(ptfunxored[j+6] << 8);
1346 start |= (uint32_t)(ptfunxored[j+5]);
1352 uint32_t something = 0;
1353 switch (somethingbytes) {
1355 something |= (uint32_t)(ptfunxored[j+8] << 24);
1357 something |= (uint32_t)(ptfunxored[j+7] << 16);
1359 something |= (uint32_t)(ptfunxored[j+6] << 8);
1361 something |= (uint32_t)(ptfunxored[j+5]);
1367 std::string filename = string(name);
1371 (int64_t)(start*ratefactor),
1372 (int64_t)(length*ratefactor),
1375 //printf("something=%d\n", something);
1377 vector<wav_t>::iterator begin = actualwavs.begin();
1378 vector<wav_t>::iterator finish = actualwavs.end();
1379 vector<wav_t>::iterator found;
1380 // Add file to list only if it is an actual wav
1381 if ((found = std::find(begin, finish, f)) != finish) {
1382 f.filename = (*found).filename;
1383 audiofiles.push_back(f);
1384 // Also add plain wav as region
1385 std::vector<midi_ev_t> m;
1389 (int64_t)(start*ratefactor),
1390 (int64_t)(sampleoffset*ratefactor),
1391 (int64_t)(length*ratefactor),
1395 regions.push_back(r);
1398 if (foundin(filename, string(".grp"))) {
1401 std::vector<midi_ev_t> m;
1405 (int64_t)(start*ratefactor),
1406 (int64_t)(sampleoffset*ratefactor),
1407 (int64_t)(length*ratefactor),
1411 regions.push_back(r);
1417 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x03", 2)) {
1420 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
1427 uint32_t tracknumber = 0;
1428 uint32_t regionspertrack = 0;
1429 for (;k < len; k++) {
1430 if ( (ptfunxored[k ] == 0x5a) &&
1431 (ptfunxored[k+1] == 0x04)) {
1434 if ( (ptfunxored[k ] == 0x5a) &&
1435 (ptfunxored[k+1] == 0x02)) {
1437 uint8_t lengthofname = 0;
1438 lengthofname = ptfunxored[k+9];
1439 if (lengthofname == 0x5a) {
1444 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
1446 //printf("regions/track=%d\n", regionspertrack);
1447 char name[256] = {0};
1448 for (j = 0; j < lengthofname; j++) {
1449 name[j] = ptfunxored[j+k+13];
1452 tr.name = string(name);
1453 tr.index = tracknumber++;
1455 for (j = k; regionspertrack > 0 && j < len; j++) {
1456 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x07", 2);
1457 tr.reg.index = (uint16_t)(ptfunxored[j+11] & 0xff)
1458 | (uint16_t)((ptfunxored[j+12] << 8) & 0xff00);
1459 vector<region_t>::iterator begin = regions.begin();
1460 vector<region_t>::iterator finish = regions.end();
1461 vector<region_t>::iterator found;
1462 if ((found = std::find(begin, finish, tr.reg)) != finish) {
1467 offset |= (uint32_t)(ptfunxored[i+3] << 24);
1468 offset |= (uint32_t)(ptfunxored[i+2] << 16);
1469 offset |= (uint32_t)(ptfunxored[i+1] << 8);
1470 offset |= (uint32_t)(ptfunxored[i]);
1471 tr.reg.startpos = (int64_t)(offset*ratefactor);
1472 if (tr.reg.length > 0) {
1473 tracks.push_back(tr);
1482 PTFFormat::parserest12(void) {
1483 uint32_t i,j,k,l,m,n;
1484 uint8_t startbytes = 0;
1485 uint8_t lengthbytes = 0;
1486 uint8_t offsetbytes = 0;
1487 uint8_t somethingbytes = 0;
1488 uint8_t skipbytes = 0;
1489 uint32_t maxregions = 0;
1490 uint32_t findex = 0;
1491 uint32_t findex2 = 0;
1492 uint32_t findex3 = 0;
1493 uint16_t rindex = 0;
1494 vector<region_t> groups;
1495 uint16_t groupcount, compoundcount, groupmax;
1496 uint16_t gindex, gindex2;
1500 vector<compound_t> groupmap;
1501 // Find region group total
1503 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1506 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1509 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1512 jumpto(&k, ptfunxored, k+0x500, (const unsigned char *)"\x5a\x03", 2);
1516 for (i = k; i < len - 0x500; i++) {
1517 if (!jumpto(&i, ptfunxored, i+0x500, (const unsigned char *)"\x5a\x03", 2))
1521 verbose_printf("groupcount=%d\n", groupcount);
1523 // Find start of group names -> group indexes
1525 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Custom 1\0\0\x5a", 11))
1528 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff", 4))
1531 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1535 // Skip total number of groups
1536 for (i = 0; i < groupcount; i++) {
1538 if ( (ptfunxored[k ] == 0x5a) &&
1539 ((ptfunxored[k+1] == 0x03) || (ptfunxored[k+1] == 0x0a))) {
1548 if ( (ptfunxored[k ] == 0x5a) &&
1549 (ptfunxored[k+1] & 0x02)) {
1557 if ( (ptfunxored[k ] == 0x5a) &&
1558 (ptfunxored[k+1] & 0x02)) {
1565 verbose_printf("start of groups k=0x%x\n", k);
1566 // Loop over all groups and associate the compound index/name
1567 for (i = 0; i < groupcount; i++) {
1569 if ( (ptfunxored[k ] == 0x5a) &&
1570 (ptfunxored[k+1] & 0x02)) {
1577 gindex = ptfunxored[k+9] | ptfunxored[k+10] << 8;
1578 gindex2 = ptfunxored[k+3] | ptfunxored[k+4] << 8;
1580 uint8_t lengthofname = ptfunxored[k+13];
1581 char name[256] = {0};
1582 for (l = 0; l < lengthofname; l++) {
1583 name[l] = ptfunxored[k+17+l];
1587 if (strlen(name) == 0) {
1593 (uint16_t)i, // curr_index
1597 gindex2, // next_index
1600 groupmap.push_back(c);
1604 // Sort lookup table by group index
1605 //std::sort(glookup.begin(), glookup.end(), regidx_compare);
1607 // print compounds as flattened tree
1609 for (std::vector<compound_t>::iterator i = groupmap.begin(); i != groupmap.end(); ++i) {
1610 verbose_printf("g(%u) uk(%u) ni(%u) %s\n", i->curr_index, i->unknown1, i->next_index, i->name.c_str());
1615 // Find region groups
1617 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"Snap", 4))
1620 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a\x06", 2))
1622 for (l = 0; l < 11; l++) {
1623 if (!jumpto(&k, ptfunxored, len, (const unsigned char *)"\x5a", 1))
1629 // Hack to find actual start of region group information
1631 if ((ptfunxored[k+13] == 0x5a) && (ptfunxored[k+14] & 0xf)) {
1635 if ((ptfunxored[k+9] == 0x5a) && (ptfunxored[k+10] & 0xf)) {
1640 if ((ptfunxored[k] == 0x5a) && (ptfunxored[k+1] & 0xf))
1645 verbose_printf("hack region groups k=0x%x\n", k);
1650 if (!jumpto(&j, ptfunxored, j+100, (const unsigned char *)"\x5a\x09", 2)) {
1653 groupmax = ptfunxored[j+3] | ptfunxored[j+4] << 8;
1656 for (; (groupcount < groupmax) && (i < len-70); i++) {
1657 if ( (ptfunxored[i ] == 0x5a) &&
1658 (ptfunxored[i+1] == 0x03)) {
1661 if ( (ptfunxored[i ] == 0x5a) &&
1662 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1664 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1665 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1667 uint8_t lengthofname = ptfunxored[i+9];
1668 if (ptfunxored[i+13] == 0x5a) {
1671 char name[256] = {0};
1672 for (j = 0; j < lengthofname; j++) {
1673 name[j] = ptfunxored[i+13+j];
1678 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1679 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1680 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1681 somethingbytes = (ptfunxored[j+3] & 0xf);
1682 skipbytes = ptfunxored[j+4];
1683 uint16_t regionsingroup = ptfunxored[j+5
1698 findex = ptfunxored[j+5
1713 uint64_t sampleoffset = 0;
1714 switch (offsetbytes) {
1716 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
1718 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
1720 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
1722 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
1724 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
1729 uint64_t length = 0;
1730 switch (lengthbytes) {
1732 length |= (uint64_t)(ptfunxored[j+9]) << 32;
1734 length |= (uint64_t)(ptfunxored[j+8]) << 24;
1736 length |= (uint64_t)(ptfunxored[j+7]) << 16;
1738 length |= (uint64_t)(ptfunxored[j+6]) << 8;
1740 length |= (uint64_t)(ptfunxored[j+5]);
1746 switch (startbytes) {
1748 start |= (uint64_t)(ptfunxored[j+9]) << 32;
1750 start |= (uint64_t)(ptfunxored[j+8]) << 24;
1752 start |= (uint64_t)(ptfunxored[j+7]) << 16;
1754 start |= (uint64_t)(ptfunxored[j+6]) << 8;
1756 start |= (uint64_t)(ptfunxored[j+5]);
1762 if (offsetbytes == 5)
1763 sampleoffset -= 1000000000000ul;
1764 if (startbytes == 5)
1765 start -= 1000000000000ul;
1767 std::string filename = string(name);
1771 (int64_t)(start*ratefactor),
1772 (int64_t)(length*ratefactor),
1775 if (strlen(name) == 0) {
1781 //if (foundin(filename, string(".grp")) && !regionsingroup && !findex) {
1782 // // Empty region group
1783 // verbose_printf(" EMPTY: %s\n", name);
1785 if (regionsingroup) {
1786 // Active region grouping
1787 // Iterate parsing all the regions in the group
1788 verbose_printf("\nGROUP\t%d %s\n", groupcount, name);
1792 for (l = 0; l < regionsingroup; l++) {
1793 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2)) {
1799 //printf("n=0x%x\n", n+112);
1800 //findex = ptfunxored[n+112] | (ptfunxored[n+113] << 8);
1801 findex = ptfunxored[i-11] | ptfunxored[i-10] << 8;
1802 findex2 = ptfunxored[n+108] | (ptfunxored[n+109] << 8);
1803 //findex2= rindex; //XXX
1804 // Find wav with correct findex
1805 vector<wav_t>::iterator wave = actualwavs.end();
1806 for (vector<wav_t>::iterator aw = actualwavs.begin();
1807 aw != actualwavs.end(); ++aw) {
1808 if (aw->index == findex) {
1812 if (wave == actualwavs.end())
1815 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1818 //rindex = ptfunxored[n] | (ptfunxored[n+1] << 8);
1819 for (l = 0; l < regionsingroup; l++) {
1820 if (!jumpto(&m, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
1824 rindex = ptfunxored[m] | (ptfunxored[m+1] << 8);
1828 switch (offsetbytes) {
1830 sampleoffset |= (uint64_t)(ptfunxored[m+4]) << 32;
1832 sampleoffset |= (uint64_t)(ptfunxored[m+3]) << 24;
1834 sampleoffset |= (uint64_t)(ptfunxored[m+2]) << 16;
1836 sampleoffset |= (uint64_t)(ptfunxored[m+1]) << 8;
1838 sampleoffset |= (uint64_t)(ptfunxored[m]);
1844 switch (offsetbytes) {
1846 start |= (uint64_t)(ptfunxored[m+4]) << 32;
1848 start |= (uint64_t)(ptfunxored[m+3]) << 24;
1850 start |= (uint64_t)(ptfunxored[m+2]) << 16;
1852 start |= (uint64_t)(ptfunxored[m+1]) << 8;
1854 start |= (uint64_t)(ptfunxored[m]);
1860 switch (lengthbytes) {
1862 length |= (uint64_t)(ptfunxored[m+4]) << 32;
1864 length |= (uint64_t)(ptfunxored[m+3]) << 24;
1866 length |= (uint64_t)(ptfunxored[m+2]) << 16;
1868 length |= (uint64_t)(ptfunxored[m+1]) << 8;
1870 length |= (uint64_t)(ptfunxored[m]);
1875 findex3 = ptfunxored[m] | (ptfunxored[m+1] << 8);
1876 sampleoffset -= 1000000000000ul;
1877 start -= 1000000000000ul;
1880 // Find wav with correct findex
1881 vector<wav_t>::iterator wave = actualwavs.end();
1882 for (vector<wav_t>::iterator aw = actualwavs.begin();
1883 aw != actualwavs.end(); ++aw) {
1884 if (aw->index == (glookup.begin()+findex2)->startpos) {
1888 if (wave == actualwavs.end())
1890 // findex is the true source
1891 std::vector<midi_ev_t> md;
1895 (int64_t)findex, //(start*ratefactor),
1896 (int64_t)findex2, //(sampleoffset*ratefactor),
1897 (int64_t)findex3, //(length*ratefactor),
1901 groups.push_back(r);
1903 vector<compound_t>::iterator g = groupmap.begin()+findex2;
1904 if (g >= groupmap.end())
1907 c.name = string(g->name);
1908 c.curr_index = compoundcount;
1910 c.ontopof_index = findex3;
1911 c.next_index = g->next_index;
1912 c.unknown1 = g->unknown1;
1913 compounds.push_back(c);
1914 verbose_printf("COMPOUND\tc(%d) %s (%d %d) -> c(%u) %s\n", c.curr_index, c.name.c_str(), c.level, c.ontopof_index, c.next_index, name);
1923 // Start pure regions
1924 k = m != 0 ? m : k - 1;
1925 if (!jumpto(&k, ptfunxored, k+64, (const unsigned char *)"\x5a\x05", 2))
1926 jumpto(&k, ptfunxored, k+128, (const unsigned char *)"\x5a\x02", 2);
1928 verbose_printf("pure regions k=0x%x\n", k);
1930 maxregions |= (uint32_t)(ptfunxored[k-4]);
1931 maxregions |= (uint32_t)(ptfunxored[k-3]) << 8;
1932 maxregions |= (uint32_t)(ptfunxored[k-2]) << 16;
1933 maxregions |= (uint32_t)(ptfunxored[k-1]) << 24;
1935 verbose_printf("maxregions=%u\n", maxregions);
1937 for (i = k; rindex < maxregions && i < len; i++) {
1938 if ( (ptfunxored[i ] == 0xff) &&
1939 (ptfunxored[i+1] == 0x5a) &&
1940 (ptfunxored[i+2] == 0x01)) {
1943 //if ( (ptfunxored[i ] == 0x5a) &&
1944 // (ptfunxored[i+1] == 0x03)) {
1947 if ( (ptfunxored[i ] == 0x5a) &&
1948 ((ptfunxored[i+1] == 0x01) || (ptfunxored[i+1] == 0x02))) {
1950 //findex = ptfunxored[i-48] | ptfunxored[i-47] << 8;
1951 //rindex = ptfunxored[i+3] | ptfunxored[i+4] << 8;
1953 uint8_t lengthofname = ptfunxored[i+9];
1954 if (ptfunxored[i+13] == 0x5a) {
1957 char name[256] = {0};
1958 for (j = 0; j < lengthofname; j++) {
1959 name[j] = ptfunxored[i+13+j];
1964 offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4;
1965 lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4;
1966 startbytes = (ptfunxored[j+3] & 0xf0) >> 4;
1967 somethingbytes = (ptfunxored[j+3] & 0xf);
1968 skipbytes = ptfunxored[j+4];
1969 findex = ptfunxored[j+5
1984 uint64_t sampleoffset = 0;
1985 switch (offsetbytes) {
1987 sampleoffset |= (uint64_t)(ptfunxored[j+9]) << 32;
1989 sampleoffset |= (uint64_t)(ptfunxored[j+8]) << 24;
1991 sampleoffset |= (uint64_t)(ptfunxored[j+7]) << 16;
1993 sampleoffset |= (uint64_t)(ptfunxored[j+6]) << 8;
1995 sampleoffset |= (uint64_t)(ptfunxored[j+5]);
2000 uint64_t length = 0;
2001 switch (lengthbytes) {
2003 length |= (uint64_t)(ptfunxored[j+9]) << 32;
2005 length |= (uint64_t)(ptfunxored[j+8]) << 24;
2007 length |= (uint64_t)(ptfunxored[j+7]) << 16;
2009 length |= (uint64_t)(ptfunxored[j+6]) << 8;
2011 length |= (uint64_t)(ptfunxored[j+5]);
2017 switch (startbytes) {
2019 start |= (uint64_t)(ptfunxored[j+9]) << 32;
2021 start |= (uint64_t)(ptfunxored[j+8]) << 24;
2023 start |= (uint64_t)(ptfunxored[j+7]) << 16;
2025 start |= (uint64_t)(ptfunxored[j+6]) << 8;
2027 start |= (uint64_t)(ptfunxored[j+5]);
2033 if (offsetbytes == 5)
2034 sampleoffset -= 1000000000000ul;
2035 if (startbytes == 5)
2036 start -= 1000000000000ul;
2038 std::string filename = string(name);
2042 (int64_t)(start*ratefactor),
2043 (int64_t)(length*ratefactor),
2046 if (strlen(name) == 0) {
2052 // Regular region mapping to a source
2054 if (!jumpto(&n, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2056 //printf("XXX=%d\n", ptfunxored[n+12] | ptfunxored[n+13]<<8);
2058 // Find wav with correct findex
2059 vector<wav_t>::iterator wave = actualwavs.end();
2060 for (vector<wav_t>::iterator aw = actualwavs.begin();
2061 aw != actualwavs.end(); ++aw) {
2062 if (aw->index == findex) {
2066 if (wave == actualwavs.end()) {
2067 verbose_printf("missing source with findex\n");
2070 //verbose_printf("\n+r(%d) w(%d) REGION: %s st(%lx)x%u of(%lx)x%u ln(%lx)x%u\n", rindex, findex, name, start, startbytes, sampleoffset, offsetbytes, length, lengthbytes);
2071 verbose_printf("REGION\tg(NA)\tr(%d)\tw(%d) %s(%s)\n", rindex, findex, name, wave->filename.c_str());
2072 std::vector<midi_ev_t> md;
2076 (int64_t)(start*ratefactor),
2077 (int64_t)(sampleoffset*ratefactor),
2078 (int64_t)(length*ratefactor),
2082 regions.push_back(r);
2088 vector<uint16_t> rootnodes;
2092 for (vector<compound_t>::iterator cmp = compounds.begin();
2093 cmp != compounds.end(); ++cmp) {
2095 for (vector<compound_t>::iterator tmp = compounds.begin();
2096 tmp != compounds.end(); ++tmp) {
2099 if (tmp->ontopof_index == cmp->curr_index)
2102 // Collect a vector of all the root nodes (no others point to)
2104 rootnodes.push_back(cmp->curr_index);
2107 for (vector<uint16_t>::iterator rt = rootnodes.begin();
2108 rt != rootnodes.end(); ++rt) {
2109 vector<compound_t>::iterator cmp = compounds.begin()+(*rt);
2110 // Now we are at a root node, follow to leaf
2111 if (cmp >= compounds.end())
2114 verbose_printf("----\n");
2116 for (; cmp < compounds.end() && cmp->curr_index != cmp->next_index;
2117 cmp = compounds.begin()+cmp->next_index) {
2120 vector<region_t>::iterator r = regions.end();
2121 for (vector<region_t>::iterator rs = regions.begin();
2122 rs != regions.end(); rs++) {
2123 if (rs->index == cmp->unknown1 + cmp->level) {
2127 if (r == regions.end())
2129 verbose_printf("\t->cidx(%u) pl(%u)+ridx(%u) cflags(0x%x) ?(%u) grp(%s) reg(%s)\n", cmp->curr_index, cmp->level, cmp->unknown1, cmp->ontopof_index, cmp->next_index, cmp->name.c_str(), r->name.c_str());
2132 vector<region_t>::iterator r = regions.end();
2133 for (vector<region_t>::iterator rs = regions.begin();
2134 rs != regions.end(); rs++) {
2135 if (rs->index == cmp->unknown1 + cmp->level) {
2139 if (r == regions.end())
2141 verbose_printf("\tLEAF->cidx(%u) pl(%u)+ridx(%u) cflags(0x%x) ?(%u) grp(%s) reg(%s)\n", cmp->curr_index, cmp->level, cmp->unknown1, cmp->ontopof_index, cmp->next_index, cmp->name.c_str(), r->name.c_str());
2144 // Start grouped regions
2146 // Print region groups mapped to sources
2147 for (vector<region_t>::iterator a = groups.begin(); a != groups.end(); ++a) {
2148 // Find wav with findex
2149 vector<wav_t>::iterator wav = audiofiles.end();
2150 for (vector<wav_t>::iterator ws = audiofiles.begin();
2151 ws != audiofiles.end(); ws++) {
2152 if (ws->index == a->startpos) {
2156 if (wav == audiofiles.end())
2159 // Find wav with findex2
2160 vector<wav_t>::iterator wav2 = audiofiles.end();
2161 for (vector<wav_t>::iterator ws = audiofiles.begin();
2162 ws != audiofiles.end(); ws++) {
2163 if (ws->index == a->sampleoffset) {
2167 if (wav2 == audiofiles.end())
2170 verbose_printf("Group: %s -> %s OR %s\n", a->name.c_str(), wav->filename.c_str(), wav2->filename.c_str());
2178 uint32_t tracknumber = 0;
2179 uint32_t regionspertrack = 0;
2180 uint32_t maxtracks = 0;
2184 if (!jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a\x03\x00", 3))
2186 maxtracks |= (uint32_t)(ptfunxored[j-4]);
2187 maxtracks |= (uint32_t)(ptfunxored[j-3]) << 8;
2188 maxtracks |= (uint32_t)(ptfunxored[j-2]) << 16;
2189 maxtracks |= (uint32_t)(ptfunxored[j-1]) << 24;
2191 // Jump to start of region -> track mappings
2192 if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x08", 2)) {
2193 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x02", 2))
2195 } else if (jumpto(&k, ptfunxored, k + regions.size() * 0x400, (const unsigned char *)"\x5a\x0a", 2)) {
2196 if (!jumpback(&k, ptfunxored, len, (const unsigned char *)"\x5a\x01", 2))
2201 verbose_printf("tracks k=0x%x\n", k);
2203 for (;k < len; k++) {
2204 if ( (ptfunxored[k ] == 0x5a) &&
2205 (ptfunxored[k+1] & 0x04)) {
2208 if ( (ptfunxored[k ] == 0x5a) &&
2209 (ptfunxored[k+1] & 0x02)) {
2211 uint8_t lengthofname = 0;
2212 lengthofname = ptfunxored[k+9];
2213 if (lengthofname == 0x5a) {
2218 regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]);
2220 //printf("regions/track=%d\n", regionspertrack);
2221 char name[256] = {0};
2222 for (j = 0; j < lengthofname; j++) {
2223 name[j] = ptfunxored[j+k+13];
2226 tr.name = string(name);
2227 tr.index = tracknumber++;
2229 for (j = k+18+lengthofname; regionspertrack > 0 && j < len; j++) {
2230 jumpto(&j, ptfunxored, len, (const unsigned char *)"\x5a", 1);
2231 bool isgroup = ptfunxored[j+27] > 0;
2233 tr.reg.name = string("");
2235 //tr.reg.index = 0xffff;
2236 verbose_printf("TRACK: t(%d) g(%d) G(%s) -> T(%s)\n",
2237 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2239 tr.reg.index = ((uint16_t)(ptfunxored[j+11]) & 0xff)
2240 | (((uint16_t)(ptfunxored[j+12]) << 8) & 0xff00);
2241 vector<region_t>::iterator begin = regions.begin();
2242 vector<region_t>::iterator finish = regions.end();
2243 vector<region_t>::iterator found;
2244 if ((found = std::find(begin, finish, tr.reg)) != finish) {
2247 verbose_printf("TRACK: t(%d) r(%d) R(%s) -> T(%s)\n",
2248 tracknumber, tr.reg.index, tr.reg.name.c_str(), tr.name.c_str());
2252 offset |= (uint32_t)(ptfunxored[i+3] << 24);
2253 offset |= (uint32_t)(ptfunxored[i+2] << 16);
2254 offset |= (uint32_t)(ptfunxored[i+1] << 8);
2255 offset |= (uint32_t)(ptfunxored[i]);
2256 tr.reg.startpos = (int64_t)(offset*ratefactor);
2257 if (tr.reg.length > 0) {
2258 tracks.push_back(tr);
2262 jumpto(&j, ptfunxored, len, (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff", 8);