Encrypted ADX playback, currently assumed Clover Stuios key without any checking

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@533 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-12-24 07:19:15 +00:00
parent 4b578db302
commit c70680a1e6
5 changed files with 95 additions and 1 deletions

View File

@ -33,3 +33,49 @@ void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
stream->adpcm_history1_32 = hist1; stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2; stream->adpcm_history2_32 = hist2;
} }
void adx_next_key(VGMSTREAMCHANNEL * stream)
{
stream->adx_xor = ( stream->adx_xor * stream->adx_mult + stream->adx_add ) & 0x7fff;
}
void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int framesin = first_sample/32;
int32_t scale = (read_16bitBE(stream->offset+framesin*18,stream->streamfile) ^ stream->adx_xor) + 1;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int coef1 = stream->adpcm_coef[0];
int coef2 = stream->adpcm_coef[1];
first_sample = first_sample%32;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(stream->offset+framesin*18+2+i/2,stream->streamfile);
outbuf[sample_count] = clamp16(
(i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale +
((coef1 * hist1 + coef2 * hist2) >> 12)
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
if (!(i % 32)) {
for (i=0;i<stream->adx_channels;i++)
{
adx_next_key(stream);
}
}
}

View File

@ -4,6 +4,9 @@
#include "../vgmstream.h" #include "../vgmstream.h"
void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void adx_next_key(VGMSTREAMCHANNEL * stream);
void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void g72x_init_state(struct g72x_state *state_ptr); void g72x_init_state(struct g72x_state *state_ptr);

View File

@ -3,6 +3,7 @@
#endif #endif
#include <math.h> #include <math.h>
#include "meta.h" #include "meta.h"
#include "../coding/coding.h"
#include "../util.h" #include "../util.h"
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
@ -20,6 +21,8 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
int16_t coef1, coef2; int16_t coef1, coef2;
uint16_t cutoff; uint16_t cutoff;
char filename[260]; char filename[260];
int coding_type = coding_CRI_ADX;
uint16_t xor_start=0,xor_mult=0,xor_add=0;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -49,6 +52,16 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
/* check version signature, read loop info */ /* check version signature, read loop info */
version_signature = read_16bitBE(0x12,streamFile); version_signature = read_16bitBE(0x12,streamFile);
/* encryption */
if (version_signature == 0x0408) {
/* TODO: check key */
coding_type = coding_CRI_ADX_enc;
/* Clover Studio (GOD HAND, Okami), 2nd result from guessadx */
xor_start = 0x49e1;
xor_mult = 0x4a57;
xor_add = 0x553d;
version_signature = 0x0400;
}
if (version_signature == 0x0300) { /* type 03 */ if (version_signature == 0x0300) { /* type 03 */
header_type = meta_ADX_03; header_type = meta_ADX_03;
if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */ if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */
@ -94,7 +107,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
vgmstream->loop_start_sample = loop_start_sample; vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample; vgmstream->loop_end_sample = loop_end_sample;
vgmstream->coding_type = coding_CRI_ADX; vgmstream->coding_type = coding_type;
if (channel_count==1) if (channel_count==1)
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
else else
@ -136,6 +149,18 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
vgmstream->ch[i].adpcm_coef[0] = coef1; vgmstream->ch[i].adpcm_coef[0] = coef1;
vgmstream->ch[i].adpcm_coef[1] = coef2; vgmstream->ch[i].adpcm_coef[1] = coef2;
if (coding_type == coding_CRI_ADX_enc)
{
int j;
vgmstream->ch[i].adx_channels = channel_count;
vgmstream->ch[i].adx_xor = xor_start;
vgmstream->ch[i].adx_mult = xor_mult;
vgmstream->ch[i].adx_add = xor_add;
for (j=0;j<i;j++)
adx_next_key(&vgmstream->ch[i]);
}
} }
} }

View File

@ -558,6 +558,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) { switch (vgmstream->coding_type) {
case coding_CRI_ADX: case coding_CRI_ADX:
case coding_CRI_ADX_enc:
return 32; return 32;
case coding_NGC_DSP: case coding_NGC_DSP:
return 14; return 14;
@ -643,6 +644,7 @@ int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) { switch (vgmstream->coding_type) {
case coding_CRI_ADX: case coding_CRI_ADX:
case coding_CRI_ADX_enc:
return 18; return 18;
case coding_NGC_DSP: case coding_NGC_DSP:
return 8; return 8;
@ -735,6 +737,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do); samples_to_do);
} }
break;
case coding_CRI_ADX_enc:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_adx_enc(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break; break;
case coding_NGC_DSP: case coding_NGC_DSP:
for (chan=0;chan<vgmstream->channels;chan++) { for (chan=0;chan<vgmstream->channels;chan++) {
@ -1172,6 +1182,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_CRI_ADX: case coding_CRI_ADX:
snprintf(temp,TEMPSIZE,"CRI ADX 4-bit ADPCM"); snprintf(temp,TEMPSIZE,"CRI ADX 4-bit ADPCM");
break; break;
case coding_CRI_ADX_enc:
snprintf(temp,TEMPSIZE,"encrypted CRI ADX 4-bit ADPCM");
break;
case coding_NDS_IMA: case coding_NDS_IMA:
snprintf(temp,TEMPSIZE,"NDS-style 4-bit IMA ADPCM"); snprintf(temp,TEMPSIZE,"NDS-style 4-bit IMA ADPCM");
break; break;

View File

@ -43,6 +43,7 @@ typedef enum {
/* 4-bit ADPCM */ /* 4-bit ADPCM */
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
coding_CRI_ADX, /* CRI ADX */ coding_CRI_ADX, /* CRI ADX */
coding_CRI_ADX_enc, /* encrypted CRI ADX */
coding_NGC_DSP, /* NGC ADPCM, called DSP */ coding_NGC_DSP, /* NGC ADPCM, called DSP */
coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */ coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */
coding_G721, /* CCITT G.721 ADPCM */ coding_G721, /* CCITT G.721 ADPCM */
@ -384,6 +385,12 @@ typedef struct {
int samples_done; int samples_done;
int16_t loop_history1,loop_history2; int16_t loop_history1,loop_history2;
#endif #endif
/* ADX encryption */
int adx_channels;
uint16_t adx_xor;
uint16_t adx_mult;
uint16_t adx_add;
} VGMSTREAMCHANNEL; } VGMSTREAMCHANNEL;
typedef struct { typedef struct {