*/
-#include "ptfformat.h"
-
#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 const uint32_t baselut[16] = {
if (idx & 0x20) {
lo ^= 0xaaaaaaab;
- xk ^= 0x10000000;
+ xk ^= 0x10000000;
}
uint32_t hi = swapbytes32 (lo) ^ xk;
return ((uint64_t)hi << 32) | (lo ^ xor_lo);
FILE *fp;
unsigned char xxor[256];
unsigned char ct;
- unsigned char px;
+ unsigned char v;
+ unsigned char voff;
uint64_t key;
- uint16_t i;
- int j;
+ uint64_t i;
+ uint64_t j;
int inv;
- unsigned char message;
+ int err;
- if (! (fp = fopen(path.c_str(), "rb"))) {
+ if (! (fp = g_fopen(path.c_str(), "rb"))) {
return -1;
}
return -1;
}
- fseek(fp, 0x0, SEEK_SET);
-
switch (c0) {
case 0x00:
// Success! easy one
xxor[0] = c0;
xxor[1] = c1;
- //fprintf(stderr, "%02x %02x", c0, c1);
+ //fprintf(stderr, "0 %02x\n1 %02x\n", c0, c1);
- for (i = 2; i < 64; i++) {
- xxor[i] = (xxor[i-1] + c1 - c0) & 0xff;
- //fprintf(stderr, "%02x ", xxor[i]);
- }
- px = xxor[0];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[0] = message;
- px = xxor[1];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[1] = message;
- i = 2;
- j = 2;
- while (fread(&ct, 1, 1, fp) != 0) {
+ for (i = 2; i < 256; i++) {
if (i%64 == 0) {
- i = 0;
+ xxor[i] = c0;
+ } else {
+ xxor[i] = (xxor[i-1] + c1 - c0) & 0xff;
+ //fprintf(stderr, "%x %02x\n", i, xxor[i]);
}
- message = xxor[i] ^ ct;
- ptfunxored[j] = message;
- i++;
- j++;
}
break;
case 0x80:
for (i = 128; i < 192; i++) {
xxor[i] ^= 0x80;
}
- px = xxor[0];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[0] = message;
- px = xxor[1];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[1] = message;
- i = 2;
- j = 2;
- while (fread(&ct, 1, 1, fp) != 0) {
- if (i%256 == 0) {
- i = 0;
- }
- message = xxor[i] ^ ct;
- ptfunxored[j] = message;
- i++;
- j++;
- }
break;
case 0x40:
case 0xc0:
}
key = gen_secret(c1);
+
for (i = 0; i < 64; i++) {
xxor[i] ^= (((key >> i) & 1) * 2 * 0x40) + 0x40;
}
for (i = 192; i < 256; i++) {
xxor[i] ^= 0x80;
}
- px = xxor[0];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[0] = message;
- px = xxor[1];
- fread(&ct, 1, 1, fp);
- message = px ^ ct;
- ptfunxored[1] = message;
- i = 2;
- j = 2;
- while (fread(&ct, 1, 1, fp) != 0) {
- if (i%256 == 0) {
- i = 0;
- }
- message = xxor[i] ^ ct;
- ptfunxored[j] = message;
- i++;
- j++;
- }
break;
break;
default:
return -1;
break;
}
+
+ /* Read file */
+ i = 0;
+ fseek(fp, 0, SEEK_SET);
+ while (fread(&ct, 1, 1, fp) != 0) {
+ ptfunxored[i++] = ct;
+ }
fclose(fp);
+
+ /* version detection */
+ voff = 0x36;
+ v = ptfunxored[voff];
+ if (v == 0x20) {
+ voff += 7;
+ } else if (v == 0x03) {
+ voff += 4;
+ } else {
+ voff = 0;
+ }
+ v = ptfunxored[voff];
+ if (v == 10 || v == 11 || v == 12) {
+ version = v;
+ unxor10();
+ }
+
+ // Special case when ptx is exported to ptf in PT
+ if (v == 3) {
+ version = 11;
+ unxor_ptx_to_ptf();
+ }
+
+ if (version == 0 || version == 5 || version == 7) {
+ /* Haven't detected version yet so decipher */
+ j = 0;
+ for (i = 0; i < len; i++) {
+ if (j%256 == 0) {
+ j = 0;
+ }
+ ptfunxored[i] ^= xxor[j];
+ j++;
+ }
+
+ /* version detection */
+ voff = 0x36;
+ v = ptfunxored[voff];
+ if (v == 0x20) {
+ voff += 7;
+ } else if (v == 0x03) {
+ voff += 4;
+ } else {
+ voff = 0;
+ }
+ v = ptfunxored[voff];
+ if (v == 5 || v == 7 || v == 8 || v == 9) {
+ version = v;
+ }
+ }
+
+ if (version < 5 || version > 12)
+ return -1;
targetrate = targetsr;
- parse();
+ err = parse();
+ if (err)
+ return -1;
return 0;
}
-void
-PTFFormat::unxor10(void)
+uint8_t
+PTFFormat::mostfrequent(uint32_t start, uint32_t stop)
{
- key10a = ptfunxored[0x9f];
- key10b = ptfunxored[0x9e] - ptfunxored[0x9b];
- int j, k, currkey;
+ uint32_t counts[256] = {0};
+ uint64_t i;
+ uint32_t max = 0;
+ uint8_t maxi = 0;
- k = 0x1000;
- for (j = k; j < k + 0x1000 && j < len; j++) {
- ptfunxored[j] ^= key10a;
+ for (i = start; i < stop; i++) {
+ counts[ptfunxored[i]]++;
}
- k = 0x2000;
- for (j = k; j < k + 0x1000 && j < len; j++) {
- ptfunxored[j] ^= key10b;
+
+ for (i = 0; i < 256; i++) {
+ if (counts[i] > max) {
+ maxi = i;
+ max = counts[i];
+ }
}
- currkey = key10b;
- while (k < len) {
- k += 0x1000;
- currkey = (key10a + currkey) & 0xff;
- for (j = k; j < k + 0x1000 && j < len; j++) {
- ptfunxored[j] ^= currkey;
+ return maxi;
+}
+
+void
+PTFFormat::unxor10(void)
+{
+ uint64_t j;
+ uint8_t x = mostfrequent(0x1000, 0x2000);
+ uint8_t dx = 0x100-x;
+
+ for (j = 0x1000; j < len; j++) {
+ if(j % 0x1000 == 0xfff) {
+ x = (x - dx) & 0xff;
}
+ ptfunxored[j] ^= x;
}
}
void
-PTFFormat::parse(void) {
- version = (version == 0) ? ptfunxored[61] : version;
+PTFFormat::unxor_ptx_to_ptf(void)
+{
+ unsigned char keyy[16] = { 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
+ 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
+ };
+ uint64_t j;
+ uint8_t i;
+
+ for (i = 0, j = 0x10; j < len; j++,i++) {
+ ptfunxored[j] ^= keyy[i];
+ if ((j % 16) == 0) {
+ i = 0;
+ if (ptfunxored[j] % 2 == 0) {
+ ptfunxored[j]++;
+ } else {
+ ptfunxored[j]--;
+ }
+ }
+ }
+}
+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) {
- unxor10();
+ } 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
void
PTFFormat::parse5header(void) {
- int k;
+ uint32_t k;
// Find session sample rate
k = 0x100;
void
PTFFormat::parse7header(void) {
- int k;
+ uint64_t k;
// Find session sample rate
k = 0x100;
void
PTFFormat::parse8header(void) {
- int k;
+ uint64_t k;
// Find session sample rate
k = 0;
void
PTFFormat::parse9header(void) {
- int k;
+ uint64_t k;
// Find session sample rate
k = 0x100;
void
PTFFormat::parse10header(void) {
- int k;
+ uint64_t k;
// Find session sample rate
- k = 0;
+ k = 0x100;
while (k < len) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x09)) {
void
PTFFormat::parserest5(void) {
- int i, j, k;
- int regionspertrack, lengthofname;
- int startbytes, lengthbytes, offsetbytes, somethingbytes;
+ 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--;
for (i = 0; i < 2; i++) {
- while (k > 0) {
+ while (k) {
if ( (ptfunxored[k ] == 0x5a) &&
(ptfunxored[k+1] == 0x00) &&
(ptfunxored[k+2] == 0x01)) {
}
k--;
}
- k--;
+ if (k)
+ k--;
}
k++;
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[j+4
- +startbytes
- +lengthbytes
- +offsetbytes
- +somethingbytes
- ];
+ //somethingbytes = (ptfunxored[j+1] & 0xf);
+ findex = ptfunxored[k+14];
j--;
uint32_t start = 0;
switch (startbytes) {
//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 = {
+ wav_t f = {
filename,
findex,
(int64_t)(start*ratefactor),
};
tracks.push_back(t);
} else {
- audiofiles.push_back(f);
region_t r = {
name,
rindex,
}
}
+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) {
- int i,j,k,l;
+ uint64_t i,k,l;
+ uint64_t lengthofname, wavnumber;
// Find end of wav file list
k = 0;
while (k < len) {
- if ( (ptfunxored[k ] == 0x5a) &&
- (ptfunxored[k+1] == 0x00) &&
- (ptfunxored[k+2] == 0x05)) {
+ 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
- bool first = true;
- uint16_t numberofwavs;
+ uint16_t numberofwavs = ptfunxored[k-23];
char wavname[256];
- for (i = k; i > 4; i--) {
- if ( ((ptfunxored[i ] == 'W') || (ptfunxored[i ] == 'F')) &&
- ((ptfunxored[i-1] == 'A') || (ptfunxored[i-1] == 'F')) &&
- ((ptfunxored[i-2] == 'V') || (ptfunxored[i-2] == 'I')) &&
- ((ptfunxored[i-3] == 'E') || (ptfunxored[i-3] == 'A'))) {
- 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] == 0x00) &&
- (ptfunxored[j-2] == 0x5a)) {
-
- numberofwavs = 0;
- numberofwavs |= (uint32_t)(ptfunxored[j-6] << 24);
- numberofwavs |= (uint32_t)(ptfunxored[j-5] << 16);
- numberofwavs |= (uint32_t)(ptfunxored[j-4] << 8);
- numberofwavs |= (uint32_t)(ptfunxored[j-3]);
- //printf("%d wavs\n", numberofwavs);
- break;
- }
- k--;
- }
- }
+ 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;
+ }
+ }
- std::string wave = string(wavname);
- std::reverse(wave.begin(), wave.end());
- wav_t f = { wave, (uint16_t)(numberofwavs - 1), 0, 0 };
+ 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("");
+ }
- if (foundin(wave, string(".grp"))) {
- continue;
- }
+ std::string wave = string(wavname);
+ wav_t f = { wave, (uint16_t)(wavnumber++), 0, 0 };
- actualwavs.push_back(f);
- //printf("done\n");
- numberofwavs--;
- if (numberofwavs <= 0)
- break;
+ 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) {
- int i,j,k,l;
+ uint64_t i,j,k,l;
// Find end of wav file list
k = 0;
void
PTFFormat::parserest89(void) {
- int i,j,k,l;
+ uint64_t i,j,k,l;
// Find Regions
uint8_t startbytes = 0;
uint8_t lengthbytes = 0;
uint8_t somethingbytes = 0;
uint8_t skipbytes = 0;
+ k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 'S') &&
(ptfunxored[k+1] == 'n') &&
j+=somethingbytes;
*/
std::string filename = string(name) + extension;
- wav_t f = {
+ wav_t f = {
filename,
0,
(int64_t)(start*ratefactor),
void
PTFFormat::parserest10(void) {
- int i,j,k,l;
+ uint64_t i,j,k,l;
// Find Regions
uint8_t startbytes = 0;
uint8_t lengthbytes = 0;
uint8_t somethingbytes = 0;
uint8_t skipbytes = 0;
+ k = 0;
while (k < len) {
if ( (ptfunxored[k ] == 'S') &&
(ptfunxored[k+1] == 'n') &&
j+=somethingbytes;
*/
std::string filename = string(name) + extension;
- wav_t f = {
+ wav_t f = {
filename,
0,
(int64_t)(start*ratefactor),