|
|
|
@ -28,6 +28,7 @@ |
|
|
|
|
#include "get_bits.h" |
|
|
|
|
#include "hca_data.h" |
|
|
|
|
|
|
|
|
|
#define HCA_MASK 0x7f7f7f7f |
|
|
|
|
#define MAX_CHANNELS 16 |
|
|
|
|
|
|
|
|
|
typedef struct ChannelContext { |
|
|
|
@ -50,8 +51,12 @@ typedef struct HCAContext { |
|
|
|
|
ChannelContext ch[MAX_CHANNELS]; |
|
|
|
|
|
|
|
|
|
uint8_t ath[128]; |
|
|
|
|
uint8_t cipher[256]; |
|
|
|
|
uint64_t key; |
|
|
|
|
uint16_t subkey; |
|
|
|
|
|
|
|
|
|
int ath_type; |
|
|
|
|
int ciph_type; |
|
|
|
|
unsigned hfr_group_count; |
|
|
|
|
uint8_t track_count; |
|
|
|
|
uint8_t channel_config; |
|
|
|
@ -65,6 +70,93 @@ typedef struct HCAContext { |
|
|
|
|
AVFloatDSPContext *fdsp; |
|
|
|
|
} HCAContext; |
|
|
|
|
|
|
|
|
|
static void cipher_init56_create_table(uint8_t *r, uint8_t key) |
|
|
|
|
{ |
|
|
|
|
const int mul = ((key & 1) << 3) | 5; |
|
|
|
|
const int add = (key & 0xE) | 1; |
|
|
|
|
|
|
|
|
|
key >>= 4; |
|
|
|
|
for (int i = 0; i < 16; i++) { |
|
|
|
|
key = (key * mul + add) & 0xF; |
|
|
|
|
r[i] = key; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cipher_init56(uint8_t *cipher, uint64_t keycode) |
|
|
|
|
{ |
|
|
|
|
uint8_t base[256], base_r[16], base_c[16], kc[8], seed[16]; |
|
|
|
|
|
|
|
|
|
/* 56bit keycode encryption (given as a uint64_t number, but upper 8b aren't used) */ |
|
|
|
|
/* keycode = keycode - 1 */ |
|
|
|
|
if (keycode != 0) |
|
|
|
|
keycode--; |
|
|
|
|
|
|
|
|
|
/* init keycode table */ |
|
|
|
|
for (int r = 0; r < (8-1); r++) { |
|
|
|
|
kc[r] = keycode & 0xFF; |
|
|
|
|
keycode = keycode >> 8; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* init seed table */ |
|
|
|
|
seed[ 0] = kc[1]; |
|
|
|
|
seed[ 1] = kc[1] ^ kc[6]; |
|
|
|
|
seed[ 2] = kc[2] ^ kc[3]; |
|
|
|
|
seed[ 3] = kc[2]; |
|
|
|
|
seed[ 4] = kc[2] ^ kc[1]; |
|
|
|
|
seed[ 5] = kc[3] ^ kc[4]; |
|
|
|
|
seed[ 6] = kc[3]; |
|
|
|
|
seed[ 7] = kc[3] ^ kc[2]; |
|
|
|
|
seed[ 8] = kc[4] ^ kc[5]; |
|
|
|
|
seed[ 9] = kc[4]; |
|
|
|
|
seed[10] = kc[4] ^ kc[3]; |
|
|
|
|
seed[11] = kc[5] ^ kc[6]; |
|
|
|
|
seed[12] = kc[5]; |
|
|
|
|
seed[13] = kc[5] ^ kc[4]; |
|
|
|
|
seed[14] = kc[6] ^ kc[1]; |
|
|
|
|
seed[15] = kc[6]; |
|
|
|
|
|
|
|
|
|
/* init base table */ |
|
|
|
|
cipher_init56_create_table(base_r, kc[0]); |
|
|
|
|
for (int r = 0; r < 16; r++) { |
|
|
|
|
uint8_t nb; |
|
|
|
|
cipher_init56_create_table(base_c, seed[r]); |
|
|
|
|
nb = base_r[r] << 4; |
|
|
|
|
for (int c = 0; c < 16; c++) |
|
|
|
|
base[r*16 + c] = nb | base_c[c]; /* combine nibbles */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* final shuffle table */ |
|
|
|
|
{ |
|
|
|
|
unsigned x = 0; |
|
|
|
|
unsigned pos = 1; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 256; i++) { |
|
|
|
|
x = (x + 17) & 0xFF; |
|
|
|
|
if (base[x] != 0 && base[x] != 0xFF) |
|
|
|
|
cipher[pos++] = base[x]; |
|
|
|
|
} |
|
|
|
|
cipher[0] = 0; |
|
|
|
|
cipher[0xFF] = 0xFF; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cipher_init(uint8_t *cipher, int type, uint64_t keycode, uint16_t subkey) |
|
|
|
|
{ |
|
|
|
|
switch (type) { |
|
|
|
|
case 56: |
|
|
|
|
if (keycode) { |
|
|
|
|
if (subkey) |
|
|
|
|
keycode = keycode * (((uint64_t)subkey<<16u)|((uint16_t)~subkey+2u)); |
|
|
|
|
cipher_init56(cipher, keycode); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 0: |
|
|
|
|
for (int i = 0; i < 256; i++) |
|
|
|
|
cipher[i] = i; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ath_init1(uint8_t *ath, int sample_rate) |
|
|
|
|
{ |
|
|
|
|
unsigned int index; |
|
|
|
@ -124,13 +216,13 @@ static int init_hca(AVCodecContext *avctx, const uint8_t *extradata, |
|
|
|
|
|
|
|
|
|
c->ath_type = version >= 0x200 ? 0 : 1; |
|
|
|
|
|
|
|
|
|
if (bytestream2_get_be32u(gb) != MKBETAG('f', 'm', 't', 0)) |
|
|
|
|
if ((bytestream2_get_be32u(gb) & HCA_MASK) != MKBETAG('f', 'm', 't', 0)) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
bytestream2_skipu(gb, 4); |
|
|
|
|
bytestream2_skipu(gb, 4); |
|
|
|
|
bytestream2_skipu(gb, 4); |
|
|
|
|
|
|
|
|
|
chunk = bytestream2_get_be32u(gb); |
|
|
|
|
chunk = bytestream2_get_be32u(gb) & HCA_MASK; |
|
|
|
|
if (chunk == MKBETAG('c', 'o', 'm', 'p')) { |
|
|
|
|
bytestream2_skipu(gb, 2); |
|
|
|
|
bytestream2_skipu(gb, 1); |
|
|
|
@ -160,7 +252,7 @@ static int init_hca(AVCodecContext *avctx, const uint8_t *extradata, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
|
while (bytestream2_get_bytes_left(gb) >= 4) { |
|
|
|
|
chunk = bytestream2_get_be32u(gb); |
|
|
|
|
chunk = bytestream2_get_be32u(gb) & HCA_MASK; |
|
|
|
|
if (chunk == MKBETAG('v', 'b', 'r', 0)) { |
|
|
|
|
bytestream2_skip(gb, 2 + 2); |
|
|
|
|
} else if (chunk == MKBETAG('a', 't', 'h', 0)) { |
|
|
|
@ -170,7 +262,7 @@ static int init_hca(AVCodecContext *avctx, const uint8_t *extradata, |
|
|
|
|
} else if (chunk == MKBETAG('c', 'o', 'm', 'm')) { |
|
|
|
|
bytestream2_skip(gb, bytestream2_get_byte(gb) * 8); |
|
|
|
|
} else if (chunk == MKBETAG('c', 'i', 'p', 'h')) { |
|
|
|
|
bytestream2_skip(gb, 2); |
|
|
|
|
c->ciph_type = bytestream2_get_be16(gb); |
|
|
|
|
} else if (chunk == MKBETAG('l', 'o', 'o', 'p')) { |
|
|
|
|
bytestream2_skip(gb, 4 + 4 + 2 + 2); |
|
|
|
|
} else if (chunk == MKBETAG('p', 'a', 'd', 0)) { |
|
|
|
@ -180,6 +272,14 @@ static int init_hca(AVCodecContext *avctx, const uint8_t *extradata, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (bytestream2_get_bytes_left(gb) >= 10) { |
|
|
|
|
bytestream2_skip(gb, bytestream2_get_bytes_left(gb) - 10); |
|
|
|
|
c->key = bytestream2_get_be64u(gb); |
|
|
|
|
c->subkey = bytestream2_get_be16u(gb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cipher_init(c->cipher, c->ciph_type, c->key, c->subkey); |
|
|
|
|
|
|
|
|
|
ret = ath_init(c->ath, c->ath_type, avctx->sample_rate); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
@ -420,7 +520,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
|
|
if (AV_RN16(avpkt->data) != 0xFFFF) { |
|
|
|
|
if (AV_RL32(avpkt->data) != MKTAG('H','C','A',0)) { |
|
|
|
|
if ((AV_RL32(avpkt->data)) != MKTAG('H','C','A',0)) { |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} else if (AV_RB16(avpkt->data + 6) <= avpkt->size) { |
|
|
|
|
ret = init_hca(avctx, avpkt->data, AV_RB16(avpkt->data + 6)); |
|
|
|
@ -434,6 +534,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (c->key || c->subkey) { |
|
|
|
|
uint8_t *data, *cipher = c->cipher; |
|
|
|
|
|
|
|
|
|
if ((ret = av_packet_make_writable(avpkt)) < 0) |
|
|
|
|
return ret; |
|
|
|
|
data = avpkt->data; |
|
|
|
|
for (int n = 0; n < avpkt->size; n++) |
|
|
|
|
data[n] = cipher[data[n]]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (avctx->err_recognition & AV_EF_CRCCHECK) { |
|
|
|
|
if (av_crc(c->crc_table, 0, avpkt->data + offset, avpkt->size - offset)) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|