Remove PCM16-XOR decoder and use decryption streamfile instead

The encryption is built on top of the data, so this way mimics the
actual setup and removes another superfluous decoder
This commit is contained in:
bnnm 2018-03-27 23:24:24 +02:00
parent 0f529ea1a7
commit 1708dcaf63
6 changed files with 84 additions and 66 deletions

View File

@ -59,7 +59,6 @@ void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
/* pcm_decoder */
void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16BE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm8(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

View File

@ -78,15 +78,6 @@ void decode_pcm16_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
}
}
void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
outbuf[sample_count]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile)^stream->key_xor;
}
}
static int expand_ulaw(uint8_t ulawbyte) {
int sign, segment, quantization, new_sample;
const int bias = 0x84;

View File

@ -436,7 +436,6 @@ typedef struct {
static const coding_info coding_info_list[] = {
{coding_PCM16LE, "Little Endian 16-bit PCM"},
{coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"},
{coding_PCM16BE, "Big Endian 16-bit PCM"},
{coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"},
{coding_PCM8, "8-bit PCM"},

View File

@ -1,63 +1,104 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* JSTM (.STM (renamed .JSTM) from Tantei Jinguji Saburo - Kind of Blue) */
static STREAMFILE* setup_jstm_streamfile(STREAMFILE *streamFile, off_t start_offset);
/* JSTM - from Tantei Jinguji Saburo - Kind of Blue (PS2) */
VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset = 0x20;
int loop_flag;
int channel_count;
char filename[PATH_LIMIT];
STREAMFILE *temp_streamFile = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* check extension */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("stm",filename_extension(filename)) &&
strcasecmp("jstm",filename_extension(filename))) goto fail;
/* check header (JSTM) */
if (read_32bitBE(0x0,streamFile) != 0x4A53544D) goto fail;
/* checks */
/* .stm: original, .jstm: header id */
if (!check_extensions(streamFile, "stm,jstm"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4A53544D) /* "JSTM" */
goto fail;
loop_flag = (read_32bitLE(0x14,streamFile) != 0);
channel_count = read_16bitLE(0x4,streamFile);
// hmm, don't know what 6 is, one is probably bytes per sample and the
// other is channels, but who can say?
if (channel_count != read_16bitLE(0x6,streamFile)) goto fail;
start_offset = 0x20;
channel_count = read_16bitLE(0x04,streamFile);
if (channel_count != read_16bitLE(0x06,streamFile)) /* 0x02, interleave? */
goto fail;
loop_flag = (read_32bitLE(0x14,streamFile) != -1);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the statistics vitale */
vgmstream->sample_rate = read_32bitLE(0x8,streamFile);
vgmstream->coding_type = coding_PCM16LE_XOR_int;
vgmstream->num_samples = read_32bitLE(0xC,streamFile)/2/channel_count;
vgmstream->layout_type = layout_none;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->num_samples = pcm_bytes_to_samples(read_32bitLE(0x0C,streamFile),channel_count,16);
if (loop_flag) {
vgmstream->loop_start_sample = pcm_bytes_to_samples(read_32bitLE(0x14,streamFile),channel_count,16);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->meta_type = meta_PS2_JSTM;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
if (loop_flag) {
vgmstream->loop_start_sample=read_32bitLE(0x14,streamFile)/2/channel_count;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0; i < channel_count; i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset =
vgmstream->ch[i].offset = start_offset + 2*i;
vgmstream->ch[i].key_xor = 0x5A5A;
}
}
temp_streamFile = setup_jstm_streamfile(streamFile, start_offset);
if (!temp_streamFile) goto fail;
if (!vgmstream_open_stream(vgmstream,temp_streamFile,start_offset))
goto fail;
close_streamfile(temp_streamFile);
return vgmstream;
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_streamfile(temp_streamFile);
close_vgmstream(vgmstream);
return NULL;
}
typedef struct {
off_t start_offset;
} jstm_decryption_data;
static size_t jstm_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, jstm_decryption_data* data) {
size_t bytes_read;
int i;
bytes_read = streamfile->read(streamfile, dest, offset, length);
/* decrypt data (xor) */
for (i = 0; i < bytes_read; i++) {
if (offset+i >= data->start_offset) {
//VGM_LOG("xor %x to %x\n", dest[i], dest[i] ^ 0x5A);getchar();
dest[i] = dest[i] ^ 0x5A;
}
}
return bytes_read;
}
static STREAMFILE* setup_jstm_streamfile(STREAMFILE *streamFile, off_t start_offset) {
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
jstm_decryption_data io_data = {0};
size_t io_data_size = sizeof(jstm_decryption_data);
/* setup decryption */
io_data.start_offset = start_offset;
/* setup custom streamfile */
new_streamFile = open_wrap_streamfile(streamFile);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, jstm_decryption_read);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
return temp_streamFile;
fail:
close_streamfile(temp_streamFile);
return NULL;
}

View File

@ -963,7 +963,6 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 1;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
case coding_PCM16_int:
case coding_PCM8:
@ -1131,7 +1130,6 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
case coding_PCM16_int:
return 0x02;
@ -1338,13 +1336,6 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_PCM16LE_XOR_int:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_pcm16LE_XOR_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
case coding_PCM16BE:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_pcm16BE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,

View File

@ -78,7 +78,6 @@ enum { STREAM_NAME_SIZE = 255 }; /* reasonable max */
typedef enum {
/* PCM */
coding_PCM16LE, /* little endian 16-bit PCM */
coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor (for blocks) */
coding_PCM16BE, /* big endian 16-bit PCM */
coding_PCM16_int, /* 16-bit PCM with sample-level interleave (for blocks) */
@ -715,8 +714,6 @@ typedef struct {
uint16_t adx_mult;
uint16_t adx_add;
/* generic encryption */
uint16_t key_xor;
} VGMSTREAMCHANNEL;
/* main vgmstream info */