mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 09:40:51 +01:00
Fix ciph-1 HCA and add errors [DQ Monsters: Super Light (Mobile)]
This commit is contained in:
parent
7b0e18171d
commit
0c53449df1
@ -26,7 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define HCA_MASK 0x7F7F7F7F /* chunk obfuscation when the HCA is encrypted (ciph type > 0) */
|
||||
#define HCA_MASK 0x7F7F7F7F /* chunk obfuscation when the HCA is encrypted with key */
|
||||
#define HCA_SUBFRAMES_PER_FRAME 8
|
||||
#define HCA_SAMPLES_PER_SUBFRAME 128
|
||||
#define HCA_SAMPLES_PER_FRAME (HCA_SUBFRAMES_PER_FRAME*HCA_SAMPLES_PER_SUBFRAME)
|
||||
@ -34,6 +34,13 @@
|
||||
|
||||
#define HCA_MAX_CHANNELS 16 /* internal max? in practice only 8 can be encoded */
|
||||
|
||||
#define HCA_ERROR_PARAMS -1
|
||||
#define HCA_ERROR_HEADER -2
|
||||
#define HCA_ERROR_CHECKSUM -3
|
||||
#define HCA_ERROR_SYNC -4
|
||||
#define HCA_ERROR_UNPACK -5
|
||||
#define HCA_ERROR_BITREADER -6
|
||||
|
||||
//--------------------------------------------------
|
||||
// Decoder config/state
|
||||
//--------------------------------------------------
|
||||
@ -239,7 +246,7 @@ int clHCA_isOurFile(const void *data, unsigned int size) {
|
||||
unsigned int header_size = 0;
|
||||
|
||||
if (!data || size < 0x08)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
bitreader_init(&br, data, 8);
|
||||
if ((bitreader_peek(&br, 32) & HCA_MASK) == 0x48434100) {/*'HCA\0'*/
|
||||
@ -248,13 +255,13 @@ int clHCA_isOurFile(const void *data, unsigned int size) {
|
||||
}
|
||||
|
||||
if (header_size == 0)
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
return header_size;
|
||||
}
|
||||
|
||||
int clHCA_getInfo(clHCA *hca, clHCA_stInfo *info) {
|
||||
if (!hca || !info || !hca->is_valid)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
info->version = hca->version;
|
||||
info->headerSize = hca->header_size;
|
||||
@ -424,7 +431,7 @@ static int ath_init(unsigned char *ath_curve, int type, unsigned int sample_rate
|
||||
ath_init1(ath_curve, sample_rate);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -455,7 +462,7 @@ static void cipher_init1(unsigned char *cipher_table) {
|
||||
const int add = 11;
|
||||
unsigned int i, v = 0;
|
||||
|
||||
/* keyless encryption (unused?) */
|
||||
/* keyless encryption (rare) */
|
||||
for (i = 1; i < 256 - 1; i++) {
|
||||
v = (v * mul + add) & 0xFF;
|
||||
if (v == 0 || v == 0xFF)
|
||||
@ -542,7 +549,7 @@ static void cipher_init56(unsigned char *cipher_table, unsigned long long keycod
|
||||
}
|
||||
|
||||
static int cipher_init(unsigned char *cipher_table, int type, unsigned long long keycode) {
|
||||
if (!(keycode))
|
||||
if (type == 56 && !(keycode))
|
||||
type = 0;
|
||||
|
||||
switch (type) {
|
||||
@ -556,7 +563,7 @@ static int cipher_init(unsigned char *cipher_table, int type, unsigned long long
|
||||
cipher_init56(cipher_table, keycode);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -570,14 +577,15 @@ static unsigned int header_ceil2(unsigned int a, unsigned int b) {
|
||||
|
||||
int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
clData br;
|
||||
int res;
|
||||
|
||||
if (!hca || !data)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
hca->is_valid = 0;
|
||||
|
||||
if (size < 0x08)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
bitreader_init(&br, data, size);
|
||||
|
||||
@ -594,18 +602,18 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->version != 0x0102 &&
|
||||
hca->version != 0x0103 &&
|
||||
hca->version != 0x0200)
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
#endif
|
||||
if (size < hca->header_size)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
if (crc16_checksum(data,hca->header_size))
|
||||
return -1;
|
||||
return HCA_ERROR_CHECKSUM;
|
||||
|
||||
size -= 0x08;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
}
|
||||
|
||||
/* format info */
|
||||
@ -618,18 +626,18 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->encoder_padding = bitreader_read(&br, 16);
|
||||
|
||||
if (!(hca->channels >= 1 && hca->channels <= HCA_MAX_CHANNELS))
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
if (hca->frame_count == 0)
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
if (!(hca->sample_rate >= 1 && hca->sample_rate <= 0x7FFFFF)) /* encoder max seems 48000 */
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
size -= 0x10;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
}
|
||||
|
||||
/* compression (v2.0) or decode (v1.x) info */
|
||||
@ -668,7 +676,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
size -= 0x0c;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
}
|
||||
|
||||
/* VBR (variable bit rate) info */
|
||||
@ -678,7 +686,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->vbr_noise_Level = bitreader_read(&br, 16);
|
||||
|
||||
if (!(hca->frame_size == 0 && hca->vbr_max_frame_size > 8 && hca->vbr_max_frame_size <= 0x1FF))
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
size -= 0x08;
|
||||
}
|
||||
@ -710,7 +718,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
|
||||
if (!(hca->loop_start_frame >= 0 && hca->loop_start_frame <= hca->loop_end_frame
|
||||
&& hca->loop_end_frame < hca->frame_count))
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
size -= 0x10;
|
||||
}
|
||||
@ -729,7 +737,7 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->ciph_type = bitreader_read(&br, 16);
|
||||
|
||||
if (!(hca->ciph_type == 0 || hca->ciph_type == 1 || hca->ciph_type == 56))
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
size -= 0x06;
|
||||
}
|
||||
@ -760,11 +768,11 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->comment_len = bitreader_read(&br, 8);
|
||||
|
||||
if (hca->comment_len > size)
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
temp = realloc(hca->comment, hca->comment_len + 1);
|
||||
if (!temp)
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
hca->comment = temp;
|
||||
for (i = 0; i < hca->comment_len; ++i)
|
||||
hca->comment[i] = bitreader_read(&br, 8);
|
||||
@ -782,17 +790,17 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
size -= (size - 0x02); /* fills up to header_size, sans checksum */
|
||||
}
|
||||
|
||||
/* should be fully read, but allow data buffer may be bigger than header_size */
|
||||
/* should be fully read, but allow as data buffer may be bigger than header_size */
|
||||
//if (size != 0x02)
|
||||
// return -1;
|
||||
// return HCA_ERROR_HEADER;
|
||||
|
||||
|
||||
/* extra validations */
|
||||
if (!(hca->frame_size >= 0x08 && hca->frame_size <= 0xFFFF)) /* actual max seems 0x155*channels */
|
||||
return -1; /* theoretically can be 0 if VBR (not seen) */
|
||||
return HCA_ERROR_HEADER; /* theoretically can be 0 if VBR (not seen) */
|
||||
|
||||
if (!(hca->min_resolution == 1 && hca->max_resolution == 15))
|
||||
return -1;
|
||||
return HCA_ERROR_HEADER;
|
||||
|
||||
|
||||
/* inits state */
|
||||
@ -803,10 +811,12 @@ int clHCA_DecodeHeader(clHCA *hca, void *data, unsigned int size) {
|
||||
hca->total_band_count - hca->base_band_count - hca->stereo_band_count,
|
||||
hca->bands_per_hfr_group);
|
||||
|
||||
if (ath_init(hca->ath_curve, hca->ath_type, hca->sample_rate) < 0)
|
||||
return -1;
|
||||
if (cipher_init(hca->cipher_table, hca->ciph_type, hca->keycode) < 0)
|
||||
return -1;
|
||||
res = ath_init(hca->ath_curve, hca->ath_type, hca->sample_rate);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res = cipher_init(hca->cipher_table, hca->ciph_type, hca->keycode);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
|
||||
/* init channels */
|
||||
@ -1002,19 +1012,19 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) {
|
||||
unsigned int subframe, ch;
|
||||
|
||||
if (!data || !hca || !hca->is_valid)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
if (size < hca->frame_size)
|
||||
return -1;
|
||||
return HCA_ERROR_PARAMS;
|
||||
|
||||
bitreader_init(&br, data, hca->frame_size);
|
||||
|
||||
/* test sync (not encrypted) */
|
||||
sync = bitreader_read(&br, 16);
|
||||
if (sync != 0xFFFF)
|
||||
return -1;
|
||||
return HCA_ERROR_SYNC;
|
||||
|
||||
if (crc16_checksum(data, hca->frame_size))
|
||||
return -1;
|
||||
return HCA_ERROR_CHECKSUM;
|
||||
|
||||
cipher_decrypt(hca->cipher_table, data, hca->frame_size);
|
||||
|
||||
@ -1029,7 +1039,7 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) {
|
||||
int unpack = decode1_unpack_channel(&hca->channel[ch], &br,
|
||||
hca->hfr_group_count, packed_noise_level, hca->ath_curve);
|
||||
if (unpack < 0)
|
||||
return -1;
|
||||
return unpack;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1060,9 +1070,8 @@ int clHCA_DecodeBlock(clHCA *hca, void *data, unsigned int size) {
|
||||
}
|
||||
|
||||
/* should read all frame sans checksum at most */
|
||||
if (br.bit > br.size - 16) {
|
||||
return -1;
|
||||
}
|
||||
if (br.bit > br.size - 16)
|
||||
return HCA_ERROR_BITREADER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1132,7 +1141,7 @@ static int decode1_unpack_channel(stChannel *ch, clData *br,
|
||||
/* may happen with bad keycodes, scalefactors must be 6b indexes */
|
||||
int scalefactor_test = (int)scalefactor_prev + ((int)delta - (int)extra_delta);
|
||||
if (scalefactor_test < 0 || scalefactor_test > 64) {
|
||||
return -1;
|
||||
return HCA_ERROR_UNPACK;
|
||||
}
|
||||
|
||||
scalefactor_prev += delta - extra_delta;
|
||||
@ -1160,7 +1169,7 @@ static int decode1_unpack_channel(stChannel *ch, clData *br,
|
||||
}
|
||||
/* 15 may be an invalid value? */
|
||||
//else {
|
||||
// return -1;
|
||||
// return HCA_ERROR_INSENSITY;
|
||||
//}
|
||||
}
|
||||
else {
|
||||
|
Loading…
Reference in New Issue
Block a user