diff --git a/src/coding/adx_decoder.c b/src/coding/adx_decoder.c index 338d82c4..ccac0b46 100644 --- a/src/coding/adx_decoder.c +++ b/src/coding/adx_decoder.c @@ -45,7 +45,7 @@ void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci int framesin = first_sample/32; - int32_t scale = (read_16bitBE(stream->offset+framesin*18,stream->streamfile) ^ stream->adx_xor) + 1; + int32_t scale = ((read_16bitBE(stream->offset+framesin*18,stream->streamfile) ^ stream->adx_xor)&0x1fff) + 1; int32_t hist1 = stream->adpcm_history1_32; int32_t hist2 = stream->adpcm_history2_32; int coef1 = stream->adpcm_coef[0]; diff --git a/src/meta/adx_header.c b/src/meta/adx_header.c index 3106f68d..59fa2d3b 100644 --- a/src/meta/adx_header.c +++ b/src/meta/adx_header.c @@ -9,7 +9,7 @@ #include "../coding/coding.h" #include "../util.h" -static int find_key(STREAMFILE *file, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add); +static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add); VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; @@ -59,12 +59,20 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) { version_signature = read_16bitBE(0x12,streamFile); /* encryption */ if (version_signature == 0x0408) { - if (find_key(streamFile, &xor_start, &xor_mult, &xor_add)) + if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add)) { - coding_type = coding_CRI_ADX_enc; + coding_type = coding_CRI_ADX_enc_8; version_signature = 0x0400; } } + else if (version_signature == 0x0409) { + if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add)) + { + coding_type = coding_CRI_ADX_enc_9; + version_signature = 0x0400; + } + } + if (version_signature == 0x0300) { /* type 03 */ header_type = meta_ADX_03; if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */ @@ -157,7 +165,8 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) { vgmstream->ch[i].adpcm_coef[0] = coef1; vgmstream->ch[i].adpcm_coef[1] = coef2; - if (coding_type == coding_CRI_ADX_enc) + if (coding_type == coding_CRI_ADX_enc_8 || + coding_type == coding_CRI_ADX_enc_9) { int j; vgmstream->ch[i].adx_channels = channel_count; @@ -181,9 +190,10 @@ fail: /* guessadx stuff */ +/* type 8 keys */ static struct { uint16_t start,mult,add; -} keys[] = { +} keys_8[] = { /* Clover Studio (GOD HAND, Okami) */ /* I'm pretty sure this is right, based on a decrypted version of some GOD HAND tracks. */ /* Also it is the 2nd result from guessadx */ @@ -343,10 +353,20 @@ static struct { {0x4c73,0x4d8d,0x5827}, }; -static const int key_count = sizeof(keys)/sizeof(keys[0]); +/* type 9 keys */ +static struct { + uint16_t start,mult,add; +} keys_9[] = { + /* Phantasy Star Online 2 + * guessed with degod */ + {0x07d2,0x1ec5,0x0c7f}, +}; + +static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]); +static const int keys_9_count = sizeof(keys_9)/sizeof(keys_9[0]); /* return 0 if not found, 1 if found and set parameters */ -static int find_key(STREAMFILE *file, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) +static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) { uint16_t * scales = NULL; uint16_t * prescales = NULL; @@ -423,39 +443,86 @@ static int find_key(STREAMFILE *file, uint16_t *xor_start, uint16_t *xor_mult, u } } - /* guess each of the keys */ - for (key_id=0;key_idcoding_type) { case coding_CRI_ADX: - case coding_CRI_ADX_enc: + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: case coding_L5_555: return 32; case coding_NGC_DSP: @@ -896,7 +897,8 @@ int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) { int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { switch (vgmstream->coding_type) { case coding_CRI_ADX: - case coding_CRI_ADX_enc: + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: case coding_L5_555: return 18; case coding_NGC_DSP: @@ -1016,7 +1018,8 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to } break; - case coding_CRI_ADX_enc: + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: for (chan=0;chanchannels;chan++) { decode_adx_enc(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, @@ -1623,8 +1626,11 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { case coding_CRI_ADX: snprintf(temp,TEMPSIZE,"CRI ADX 4-bit ADPCM"); break; - case coding_CRI_ADX_enc: - snprintf(temp,TEMPSIZE,"encrypted CRI ADX 4-bit ADPCM"); + case coding_CRI_ADX_enc_8: + snprintf(temp,TEMPSIZE,"encrypted (type 8) CRI ADX 4-bit ADPCM"); + break; + case coding_CRI_ADX_enc_9: + snprintf(temp,TEMPSIZE,"encrypted (type 9) CRI ADX 4-bit ADPCM"); break; case coding_NDS_IMA: snprintf(temp,TEMPSIZE,"NDS-style 4-bit IMA ADPCM"); diff --git a/src/vgmstream.h b/src/vgmstream.h index 1dd01118..fdfe076f 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -50,7 +50,8 @@ typedef enum { /* 4-bit ADPCM */ coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_CRI_ADX, /* CRI ADX */ - coding_CRI_ADX_enc, /* encrypted CRI ADX */ + coding_CRI_ADX_enc_8, /* encrypted CRI ADX, type 8 (God Hand) */ + coding_CRI_ADX_enc_9, /* encrypted CRI ADX, type 9 (PSO2) */ coding_NGC_DSP, /* NGC ADPCM, called DSP */ coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */ coding_G721, /* CCITT G.721 ADPCM */