diff options
author | Damien Zammit <damien@zamaudio.com> | 2017-02-15 21:08:22 +1100 |
---|---|---|
committer | Damien Zammit <damien@zamaudio.com> | 2017-02-15 21:08:22 +1100 |
commit | 6e9bf3af79bec6cf605cd52ae243c2035b40de52 (patch) | |
tree | 5d6018f902965784e6add8e2fca4fc04988d9db7 | |
parent | 5dd312def4945efa8accfdd3c22de6c00cf2cb9e (diff) |
Make compatible with Ardour lib
Signed-off-by: Damien Zammit <damien@zamaudio.com>
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | ptfformat.cc | 1279 |
2 files changed, 1284 insertions, 4 deletions
@@ -1,13 +1,14 @@ +INCL=$(shell pkg-config --cflags glib-2.0) STRICT=-Wall -Wcast-align -Wextra -Wwrite-strings -Wunsafe-loop-optimizations -Wlogical-op -Wno-unused-function CLANGSTRICT=-Woverloaded-virtual -Wno-mismatched-tags -ansi -Wnon-virtual-dtor -Woverloaded-virtual -fstrict-overflow -Wall -Wcast-align -Wextra -Wwrite-strings -Wno-unused-function all: - $(CXX) -o ptftool -g ${STRICT} ptftool.cc ptfformat.cc - $(CXX) -o ptunxor -g ${STRICT} ptunxor.cc ptfformat.cc + $(CXX) -o ptftool -g ${INCL} ${STRICT} ptftool.cc ptfformat.cc + $(CXX) -o ptunxor -g ${INCL} ${STRICT} ptunxor.cc ptfformat.cc clangall: - clang++ -o ptftool -g ${CLANGSTRICT} ptftool.cc ptfformat.cc - clang++ -o ptunxor -g ${CLANGSTRICT} ptunxor.cc ptfformat.cc + clang++ -o ptftool -g ${INCL} ${CLANGSTRICT} ptftool.cc ptfformat.cc + clang++ -o ptunxor -g ${INCL} ${CLANGSTRICT} ptunxor.cc ptfformat.cc clean: rm ptftool ptunxor diff --git a/ptfformat.cc b/ptfformat.cc index 40cd571..ac3a02f 100644 --- a/ptfformat.cc +++ b/ptfformat.cc @@ -0,0 +1,1279 @@ +/* + Copyright (C) 2015 Damien Zammit + Copyright (C) 2015 Robin Gareus + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string> +#include <string.h> +#include <assert.h> + +#include <glib/gstdio.h> + +#include "ptfformat.h" + +using namespace std; + +static void +hexdump(uint8_t *data, int len) +{ + int i,j,end,step=16; + + for (i = 0; i < len; i += step) { + printf("0x%02X: ", i); + end = i + step; + if (end > len) end = len; + for (j = i; j < end; j++) { + printf("0x%02X ", data[j]); + } + for (j = i; j < end; j++) { + if (data[j] < 128 && data[j] > 32) + printf("%c", data[j]); + else + printf("."); + } + printf("\n"); + } +} + +PTFFormat::PTFFormat() : version(0), product(NULL) { +} + +PTFFormat::~PTFFormat() { + if (ptfunxored) { + free(ptfunxored); + } +} + +bool +PTFFormat::foundin(std::string haystack, std::string needle) { + size_t found = haystack.find(needle); + if (found != std::string::npos) { + return true; + } else { + return false; + } +} + +/* Return values: 0 success + 0x01 to 0xff value of missing lut + -1 could not open file as ptf +*/ +int +PTFFormat::load(std::string path, int64_t targetsr) { + FILE *fp; + unsigned char xxor[256]; + unsigned char ct; + uint64_t i; + uint8_t xor_type; + uint8_t xor_value; + uint8_t xor_delta; + uint16_t xor_len; + int err; + + if (! (fp = g_fopen(path.c_str(), "rb"))) { + return -1; + } + + fseek(fp, 0, SEEK_END); + len = ftell(fp); + if (len < 0x14) { + fclose(fp); + return -1; + } + + if (! (ptfunxored = (unsigned char*) malloc(len * sizeof(unsigned char)))) { + /* Silently fail -- out of memory*/ + fclose(fp); + ptfunxored = 0; + return -1; + } + + /* The first 20 bytes are always unencrypted */ + fseek(fp, 0x00, SEEK_SET); + i = fread(ptfunxored, 1, 0x14, fp); + if (i < 0x14) { + fclose(fp); + return -1; + } + + xor_type = ptfunxored[0x12]; + xor_value = ptfunxored[0x13]; + + // xor_type 0x01 = ProTools 5, 6, 7, 8 and 9 + // xor_type 0x05 = ProTools 10, 11, 12 + switch(xor_type) { + case 0x01: + xor_delta = gen_xor_delta(xor_value, 53, false); + xor_len = 256; + break; + case 0x05: + xor_delta = gen_xor_delta(xor_value, 11, true); + xor_len = 128; + break; + default: + fclose(fp); + return -1; + } + + /* Generate the xor_key */ + for (i=0; i < xor_len; i++) + xxor[i] = (i * xor_delta) & 0xff; + + /* hexdump(xxor, xor_len); */ + + /* Read file and decrypt rest of file */ + i = 0x14; + fseek(fp, i, SEEK_SET); + while (fread(&ct, 1, 1, fp) != 0) { + uint8_t xor_index = (xor_type == 0x01) ? i & 0xff : (i >> 12) & 0x7f; + ptfunxored[i++] = ct ^ xxor[xor_index]; + } + fclose(fp); + + if (!parse_version()) + return -1; + + if (version < 5 || version > 12) + return -1; + + targetrate = targetsr; + err = parse(); + if (err) + return -1; + + return 0; +} + +bool +PTFFormat::parse_version() { + uint32_t seg_len,str_len; + uint8_t *data = ptfunxored + 0x14; + uintptr_t data_end = ((uintptr_t)ptfunxored) + 0x100; + uint8_t seg_type; + bool success = false; + + while( ((uintptr_t)data < data_end) && (success == false) ) { + + if (data[0] != 0x5a) { + success = false; + break; + } + + seg_type = data[1]; + /* Skip segment header */ + data += 3; + if (data[0] == 0 && data[1] == 0) { + /* LE */ + seg_len = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + } else { + /* BE */ + seg_len = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; + } + /* Skip seg_len */ + data += 4; + if (!(seg_type == 0x04 || seg_type == 0x03) || data[0] != 0x03) { + /* Go to next segment */ + data += seg_len; + continue; + } + /* Skip 0x03 0x00 0x00 */ + data += 3; + seg_len -= 3; + str_len = (*(uint8_t *)data); + if (! (product = (uint8_t *)malloc((str_len+1) * sizeof(uint8_t)))) { + success = false; + break; + } + + /* Skip str_len */ + data += 4; + seg_len -= 4; + + memcpy(product, data, str_len); + product[str_len] = 0; + data += str_len; + seg_len -= str_len; + + /* Skip 0x03 0x00 0x00 0x00 */ + data += 4; + seg_len -= 4; + + version = data[0]; + if (version == 0) { + version = data[3]; + } + data += seg_len; + success = true; + } + + /* If the above does not work, assume old version 5,6,7 */ + if ((uintptr_t)data >= data_end - seg_len) { + version = ptfunxored[0x40]; + success = true; + } + return success; +} + +uint8_t +PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) { + uint16_t i; + for (i = 0; i < 256; i++) { + if (((i * mul) & 0xff) == xor_value) { + return (negative) ? i * (-1) : i; + } + } + // Should not occur + return 0; +} + +int +PTFFormat::parse(void) { + if (version == 5) { + parse5header(); + setrates(); + if (sessionrate < 44100 || sessionrate > 192000) + return -1; + parseaudio5(); + parserest5(); + } else if (version == 7) { + parse7header(); + setrates(); + if (sessionrate < 44100 || sessionrate > 192000) + return -1; + parseaudio(); + parserest89(); + } else if (version == 8) { + parse8header(); + setrates(); + if (sessionrate < 44100 || sessionrate > 192000) + return -1; + parseaudio(); + parserest89(); + } else if (version == 9) { + parse9header(); + setrates(); + if (sessionrate < 44100 || sessionrate > 192000) + return -1; + parseaudio(); + parserest89(); + } else if (version == 10 || version == 11 || version == 12) { + parse10header(); + setrates(); + if (sessionrate < 44100 || sessionrate > 192000) + return -1; + parseaudio(); + parserest10(); + } else { + // Should not occur + return -1; + } + return 0; +} + +void +PTFFormat::setrates(void) { + ratefactor = 1.f; + if (sessionrate != 0) { + ratefactor = (float)targetrate / sessionrate; + } +} + +void +PTFFormat::parse5header(void) { + uint32_t k; + + // Find session sample rate + k = 0x100; + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x02)) { + break; + } + k++; + } + + sessionrate = 0; + sessionrate |= ptfunxored[k+12] << 16; + sessionrate |= ptfunxored[k+13] << 8; + sessionrate |= ptfunxored[k+14]; +} + +void +PTFFormat::parse7header(void) { + uint64_t k; + + // Find session sample rate + k = 0x100; + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x05)) { + break; + } + k++; + } + + sessionrate = 0; + sessionrate |= ptfunxored[k+12] << 16; + sessionrate |= ptfunxored[k+13] << 8; + sessionrate |= ptfunxored[k+14]; +} + +void +PTFFormat::parse8header(void) { + uint64_t k; + + // Find session sample rate + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x05)) { + break; + } + k++; + } + + sessionrate = 0; + sessionrate |= ptfunxored[k+11]; + sessionrate |= ptfunxored[k+12] << 8; + sessionrate |= ptfunxored[k+13] << 16; +} + +void +PTFFormat::parse9header(void) { + uint64_t k; + + // Find session sample rate + k = 0x100; + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x06)) { + break; + } + k++; + } + + sessionrate = 0; + sessionrate |= ptfunxored[k+11]; + sessionrate |= ptfunxored[k+12] << 8; + sessionrate |= ptfunxored[k+13] << 16; +} + +void +PTFFormat::parse10header(void) { + uint64_t k; + + // Find session sample rate + k = 0x100; + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x09)) { + break; + } + k++; + } + + sessionrate = 0; + sessionrate |= ptfunxored[k+11]; + sessionrate |= ptfunxored[k+12] << 8; + sessionrate |= ptfunxored[k+13] << 16; +} + +void +PTFFormat::parserest5(void) { + uint64_t i, j, k; + uint64_t regionspertrack, lengthofname; + uint64_t startbytes, lengthbytes, offsetbytes; + uint16_t tracknumber = 0; + uint16_t findex; + uint16_t rindex; + + k = 0; + for (i = 0; i < 5; i++) { + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x03)) { + break; + } + k++; + } + k++; + } + k--; + + for (i = 0; i < 2; i++) { + while (k) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x01)) { + break; + } + k--; + } + if (k) + k--; + } + k++; + + rindex = 0; + while (k < len) { + if ( (ptfunxored[k ] == 0xff) && + (ptfunxored[k+1] == 0xff)) { + break; + } + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x01)) { + break; + } + k++; + } + + lengthofname = ptfunxored[k+12]; + if (ptfunxored[k+13] == 0x5a) { + k++; + break; + } + char name[256] = {0}; + for (j = 0; j < lengthofname; j++) { + name[j] = ptfunxored[k+13+j]; + } + name[j] = '\0'; + regionspertrack = ptfunxored[k+13+j+3]; + for (i = 0; i < regionspertrack; i++) { + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x00) && + (ptfunxored[k+2] == 0x03)) { + break; + } + k++; + } + j = k+16; + startbytes = (ptfunxored[j+3] & 0xf0) >> 4; + lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4; + offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4; + //somethingbytes = (ptfunxored[j+1] & 0xf); + findex = ptfunxored[k+14]; + j--; + uint32_t start = 0; + switch (startbytes) { + case 4: + start |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + start |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + start |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + start |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=startbytes; + uint32_t length = 0; + switch (lengthbytes) { + case 4: + length |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + length |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + length |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + length |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=lengthbytes; + uint32_t sampleoffset = 0; + switch (offsetbytes) { + case 4: + sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + sampleoffset |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=offsetbytes; + + //printf("name=`%s` start=%04x length=%04x offset=%04x findex=%d\n", name,start,length,sampleoffset,findex); + + std::string filename = string(name) + extension; + wav_t f = { + filename, + findex, + (int64_t)(start*ratefactor), + (int64_t)(length*ratefactor), + }; + + vector<wav_t>::iterator begin = audiofiles.begin(); + vector<wav_t>::iterator finish = audiofiles.end(); + vector<wav_t>::iterator found; + // Add file to lists + if ((found = std::find(begin, finish, f)) != finish) { + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + *found, + }; + regions.push_back(r); + vector<track_t>::iterator ti; + vector<track_t>::iterator bt = tracks.begin(); + vector<track_t>::iterator et = tracks.end(); + track_t tr = { name, 0, 0, r }; + if ((ti = std::find(bt, et, tr)) != et) { + tracknumber = (*ti).index; + } else { + tracknumber = tracks.size() + 1; + } + track_t t = { + name, + (uint16_t)tracknumber, + uint8_t(0), + r + }; + tracks.push_back(t); + } else { + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + f, + }; + regions.push_back(r); + vector<track_t>::iterator ti; + vector<track_t>::iterator bt = tracks.begin(); + vector<track_t>::iterator et = tracks.end(); + track_t tr = { name, 0, 0, r }; + if ((ti = std::find(bt, et, tr)) != et) { + tracknumber = (*ti).index; + } else { + tracknumber = tracks.size() + 1; + } + track_t t = { + name, + (uint16_t)tracknumber, + uint8_t(0), + r + }; + tracks.push_back(t); + } + rindex++; + k++; + } + k++; + } +} + +void +PTFFormat::resort(std::vector<wav_t>& ws) { + int j = 0; + std::sort(ws.begin(), ws.end()); + for (std::vector<wav_t>::iterator i = ws.begin(); i != ws.end(); ++i) { + (*i).index = j; + j++; + } +} + +void +PTFFormat::parseaudio5(void) { + uint64_t i,k,l; + uint64_t lengthofname, wavnumber; + + // Find end of wav file list + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 0x5f) && + (ptfunxored[k+1] == 0x50) && + (ptfunxored[k+2] == 0x35)) { + break; + } + k++; + } + k++; + while (k < len) { + if ( (ptfunxored[k ] == 0x5f) && + (ptfunxored[k+1] == 0x50) && + (ptfunxored[k+2] == 0x35)) { + break; + } + k++; + } + + // Find actual wav names + uint16_t numberofwavs = ptfunxored[k-23]; + char wavname[256]; + for (i = k; i < len; i++) { + if ( (ptfunxored[i ] == 'F') && + (ptfunxored[i+1] == 'i') && + (ptfunxored[i+2] == 'l') && + (ptfunxored[i+3] == 'e') && + (ptfunxored[i+4] == 's')) { + break; + } + } + + wavnumber = 0; + i+=16; + char ext[5]; + while (i < len && numberofwavs > 0) { + i++; + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x00) && + (ptfunxored[i+2] == 0x05)) { + break; + } + lengthofname = ptfunxored[i]; + i++; + l = 0; + while (l < lengthofname) { + wavname[l] = ptfunxored[i+l]; + l++; + } + i+=lengthofname; + ext[0] = ptfunxored[i++]; + ext[1] = ptfunxored[i++]; + ext[2] = ptfunxored[i++]; + ext[3] = ptfunxored[i++]; + ext[4] = '\0'; + + wavname[l] = 0; + if (foundin(wavname, ".L") || foundin(wavname, ".R")) { + extension = string(""); + } else if (foundin(wavname, ".wav") || foundin(ext, "WAVE")) { + extension = string(".wav"); + } else if (foundin(wavname, ".aif") || foundin(ext, "AIFF")) { + extension = string(".aif"); + } else { + extension = string(""); + } + + std::string wave = string(wavname); + wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 }; + + if (foundin(wave, string(".grp"))) { + continue; + } + + actualwavs.push_back(f); + audiofiles.push_back(f); + //printf("done\n"); + numberofwavs--; + i += 7; + } + resort(actualwavs); + resort(audiofiles); +} + +void +PTFFormat::parseaudio(void) { + uint64_t i,j,k,l; + + // Find end of wav file list + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 0xff) && + (ptfunxored[k+1] == 0xff) && + (ptfunxored[k+2] == 0xff) && + (ptfunxored[k+3] == 0xff)) { + break; + } + k++; + } + + // Find actual wav names + bool first = true; + uint16_t numberofwavs; + char wavname[256]; + for (i = k; i > 4; i--) { + if ( ((ptfunxored[i ] == 'W') || (ptfunxored[i ] == 'A')) && + ((ptfunxored[i-1] == 'A') || (ptfunxored[i-1] == 'I')) && + ((ptfunxored[i-2] == 'V') || (ptfunxored[i-2] == 'F')) && + ((ptfunxored[i-3] == 'E') || (ptfunxored[i-3] == 'F'))) { + j = i-4; + l = 0; + while (ptfunxored[j] != '\0') { + wavname[l] = ptfunxored[j]; + l++; + j--; + } + wavname[l] = 0; + if (ptfunxored[i] == 'W') { + extension = string(".wav"); + } else { + extension = string(".aif"); + } + //uint8_t playlist = ptfunxored[j-8]; + + if (first) { + first = false; + for (j = k; j > 4; j--) { + if ( (ptfunxored[j ] == 0x01) && + (ptfunxored[j-1] == 0x5a)) { + + numberofwavs = 0; + numberofwavs |= (uint32_t)(ptfunxored[j-2] << 24); + numberofwavs |= (uint32_t)(ptfunxored[j-3] << 16); + numberofwavs |= (uint32_t)(ptfunxored[j-4] << 8); + numberofwavs |= (uint32_t)(ptfunxored[j-5]); + //printf("%d wavs\n", numberofwavs); + break; + } + k--; + } + } + + std::string wave = string(wavname); + std::reverse(wave.begin(), wave.end()); + wav_t f = { wave, (uint16_t)(numberofwavs - 1), 0, 0 }; + + if (foundin(wave, string(".grp"))) { + continue; + } + + actualwavs.push_back(f); + + numberofwavs--; + if (numberofwavs <= 0) + break; + } + } +} + +void +PTFFormat::parserest89(void) { + uint64_t i,j,k,l; + // Find Regions + uint8_t startbytes = 0; + uint8_t lengthbytes = 0; + uint8_t offsetbytes = 0; + uint8_t somethingbytes = 0; + uint8_t skipbytes = 0; + + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 'S') && + (ptfunxored[k+1] == 'n') && + (ptfunxored[k+2] == 'a') && + (ptfunxored[k+3] == 'p')) { + break; + } + k++; + } + uint16_t rindex = 0; + uint32_t findex = 0; + for (i = k; i < len-70; i++) { + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x0a)) { + break; + } + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x0c)) { + + uint8_t lengthofname = ptfunxored[i+9]; + + char name[256] = {0}; + for (j = 0; j < lengthofname; j++) { + name[j] = ptfunxored[i+13+j]; + } + name[j] = '\0'; + j += i+13; + //uint8_t disabled = ptfunxored[j]; + + offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4; + lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4; + startbytes = (ptfunxored[j+3] & 0xf0) >> 4; + somethingbytes = (ptfunxored[j+3] & 0xf); + skipbytes = ptfunxored[j+4]; + findex = ptfunxored[j+5 + +startbytes + +lengthbytes + +offsetbytes + +somethingbytes + +skipbytes + +40]; + /*rindex = ptfunxored[j+5 + +startbytes + +lengthbytes + +offsetbytes + +somethingbytes + +skipbytes + +24]; + */ + uint32_t sampleoffset = 0; + switch (offsetbytes) { + case 4: + sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + sampleoffset |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=offsetbytes; + uint32_t length = 0; + switch (lengthbytes) { + case 4: + length |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + length |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + length |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + length |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=lengthbytes; + uint32_t start = 0; + switch (startbytes) { + case 4: + start |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + start |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + start |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + start |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=startbytes; + /* + uint32_t something = 0; + switch (somethingbytes) { + case 4: + something |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + something |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + something |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + something |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=somethingbytes; + */ + std::string filename = string(name) + extension; + wav_t f = { + filename, + 0, + (int64_t)(start*ratefactor), + (int64_t)(length*ratefactor), + }; + + f.index = findex; + //printf("something=%d\n", something); + + vector<wav_t>::iterator begin = actualwavs.begin(); + vector<wav_t>::iterator finish = actualwavs.end(); + vector<wav_t>::iterator found; + // Add file to list only if it is an actual wav + if ((found = std::find(begin, finish, f)) != finish) { + audiofiles.push_back(f); + // Also add plain wav as region + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + f + }; + regions.push_back(r); + // Region only + } else { + if (foundin(filename, string(".grp"))) { + continue; + } + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + f + }; + regions.push_back(r); + } + rindex++; + } + } + + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x03)) { + break; + } + k++; + } + while (k < len) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x02)) { + break; + } + k++; + } + k++; + + // Tracks + uint32_t offset; + uint32_t tracknumber = 0; + uint32_t regionspertrack = 0; + for (;k < len; k++) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x04)) { + break; + } + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x02)) { + + uint8_t lengthofname = 0; + lengthofname = ptfunxored[k+9]; + if (lengthofname == 0x5a) { + continue; + } + track_t tr; + + regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]); + + //printf("regions/track=%d\n", regionspertrack); + char name[256] = {0}; + for (j = 0; j < lengthofname; j++) { + name[j] = ptfunxored[j+k+13]; + } + name[j] = '\0'; + tr.name = string(name); + tr.index = tracknumber++; + + for (j = k; regionspertrack > 0 && j < len; j++) { + for (l = j; l < len; l++) { + if ( (ptfunxored[l ] == 0x5a) && + (ptfunxored[l+1] == 0x07)) { + j = l; + break; + } + } + + + if (regionspertrack == 0) { + // tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5]; + break; + } else { + + tr.reg.index = (uint8_t)(ptfunxored[l+11]); + vector<region_t>::iterator begin = regions.begin(); + vector<region_t>::iterator finish = regions.end(); + vector<region_t>::iterator found; + if ((found = std::find(begin, finish, tr.reg)) != finish) { + tr.reg = (*found); + } + i = l+16; + offset = 0; + offset |= (uint32_t)(ptfunxored[i+3] << 24); + offset |= (uint32_t)(ptfunxored[i+2] << 16); + offset |= (uint32_t)(ptfunxored[i+1] << 8); + offset |= (uint32_t)(ptfunxored[i]); + tr.reg.startpos = (int64_t)(offset*ratefactor); + if (tr.reg.length > 0) { + tracks.push_back(tr); + } + regionspertrack--; + } + } + } + } +} + +void +PTFFormat::parserest10(void) { + uint64_t i,j,k,l; + // Find Regions + uint8_t startbytes = 0; + uint8_t lengthbytes = 0; + uint8_t offsetbytes = 0; + uint8_t somethingbytes = 0; + uint8_t skipbytes = 0; + + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 'S') && + (ptfunxored[k+1] == 'n') && + (ptfunxored[k+2] == 'a') && + (ptfunxored[k+3] == 'p')) { + break; + } + k++; + } + for (i = k; i < len-70; i++) { + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x02)) { + k = i; + break; + } + } + k++; + for (i = k; i < len-70; i++) { + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x02)) { + k = i; + break; + } + } + k++; + uint16_t rindex = 0; + uint32_t findex = 0; + for (i = k; i < len-70; i++) { + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x08)) { + break; + } + if ( (ptfunxored[i ] == 0x5a) && + (ptfunxored[i+1] == 0x01)) { + + uint8_t lengthofname = ptfunxored[i+9]; + if (ptfunxored[i+13] == 0x5a) { + continue; + } + char name[256] = {0}; + for (j = 0; j < lengthofname; j++) { + name[j] = ptfunxored[i+13+j]; + } + name[j] = '\0'; + j += i+13; + //uint8_t disabled = ptfunxored[j]; + //printf("%s\n", name); + + offsetbytes = (ptfunxored[j+1] & 0xf0) >> 4; + lengthbytes = (ptfunxored[j+2] & 0xf0) >> 4; + startbytes = (ptfunxored[j+3] & 0xf0) >> 4; + somethingbytes = (ptfunxored[j+3] & 0xf); + skipbytes = ptfunxored[j+4]; + findex = ptfunxored[j+5 + +startbytes + +lengthbytes + +offsetbytes + +somethingbytes + +skipbytes + +37]; + /*rindex = ptfunxored[j+5 + +startbytes + +lengthbytes + +offsetbytes + +somethingbytes + +skipbytes + +24]; + */ + uint32_t sampleoffset = 0; + switch (offsetbytes) { + case 4: + sampleoffset |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + sampleoffset |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + sampleoffset |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + sampleoffset |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=offsetbytes; + uint32_t length = 0; + switch (lengthbytes) { + case 4: + length |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + length |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + length |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + length |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=lengthbytes; + uint32_t start = 0; + switch (startbytes) { + case 4: + start |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + start |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + start |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + start |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=startbytes; + /* + uint32_t something = 0; + switch (somethingbytes) { + case 4: + something |= (uint32_t)(ptfunxored[j+8] << 24); + case 3: + something |= (uint32_t)(ptfunxored[j+7] << 16); + case 2: + something |= (uint32_t)(ptfunxored[j+6] << 8); + case 1: + something |= (uint32_t)(ptfunxored[j+5]); + default: + break; + } + j+=somethingbytes; + */ + std::string filename = string(name) + extension; + wav_t f = { + filename, + 0, + (int64_t)(start*ratefactor), + (int64_t)(length*ratefactor), + }; + + if (strlen(name) == 0) { + continue; + } + if (length == 0) { + continue; + } + f.index = findex; + //printf("something=%d\n", something); + + vector<wav_t>::iterator begin = actualwavs.begin(); + vector<wav_t>::iterator finish = actualwavs.end(); + vector<wav_t>::iterator found; + // Add file to list only if it is an actual wav + if ((found = std::find(begin, finish, f)) != finish) { + audiofiles.push_back(f); + // Also add plain wav as region + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + f + }; + regions.push_back(r); + // Region only + } else { + if (foundin(filename, string(".grp"))) { + continue; + } + region_t r = { + name, + rindex, + (int64_t)(start*ratefactor), + (int64_t)(sampleoffset*ratefactor), + (int64_t)(length*ratefactor), + f + }; + regions.push_back(r); + } + rindex++; + //printf("%s\n", name); + } + } + // Tracks + uint32_t offset; + uint32_t tracknumber = 0; + uint32_t regionspertrack = 0; + for (;k < len; k++) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x08)) { + break; + } + } + k++; + for (;k < len; k++) { + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x04)) { + break; + } + if ( (ptfunxored[k ] == 0x5a) && + (ptfunxored[k+1] == 0x02)) { + + uint8_t lengthofname = 0; + lengthofname = ptfunxored[k+9]; + if (lengthofname == 0x5a) { + continue; + } + track_t tr; + + regionspertrack = (uint8_t)(ptfunxored[k+13+lengthofname]); + + //printf("regions/track=%d\n", regionspertrack); + char name[256] = {0}; + for (j = 0; j < lengthofname; j++) { + name[j] = ptfunxored[j+k+13]; + } + name[j] = '\0'; + tr.name = string(name); + tr.index = tracknumber++; + + for (j = k; regionspertrack > 0 && j < len; j++) { + for (l = j; l < len; l++) { + if ( (ptfunxored[l ] == 0x5a) && + (ptfunxored[l+1] == 0x08)) { + j = l+1; + break; + } + } + + + if (regionspertrack == 0) { + // tr.reg.index = (uint8_t)ptfunxored[j+13+lengthofname+5]; + break; + } else { + + tr.reg.index = (uint8_t)(ptfunxored[l+11]); + vector<region_t>::iterator begin = regions.begin(); + vector<region_t>::iterator finish = regions.end(); + vector<region_t>::iterator found; + if ((found = std::find(begin, finish, tr.reg)) != finish) { + tr.reg = (*found); + } + i = l+16; + offset = 0; + offset |= (uint32_t)(ptfunxored[i+3] << 24); + offset |= (uint32_t)(ptfunxored[i+2] << 16); + offset |= (uint32_t)(ptfunxored[i+1] << 8); + offset |= (uint32_t)(ptfunxored[i]); + tr.reg.startpos = (int64_t)(offset*ratefactor); + if (tr.reg.length > 0) { + tracks.push_back(tr); + } + regionspertrack--; + } + } + } + } +} |