mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Tweak ADX meta code
This commit is contained in:
parent
0dfe352c7b
commit
eb753846c8
265
src/meta/adx.c
265
src/meta/adx.c
@ -3,14 +3,15 @@
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "meta.h"
|
||||
#include "adx_keys.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
#define MAX_TEST_FRAMES (INT_MAX/0x8000)
|
||||
|
||||
static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
||||
#define ADX_KEY_MAX_TEST_FRAMES 32768
|
||||
#define ADX_KEY_TEST_BUFFER_SIZE 0x8000
|
||||
|
||||
static int find_adx_key(STREAMFILE *sf, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
||||
|
||||
/* ADX - CRI Middleware format */
|
||||
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
@ -18,7 +19,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
off_t start_offset, hist_offset = 0;
|
||||
int loop_flag = 0, channel_count;
|
||||
int32_t loop_start_sample = 0, loop_end_sample = 0;
|
||||
uint16_t version_signature;
|
||||
uint16_t version;
|
||||
uint8_t encoding_type;
|
||||
uint8_t frame_size;
|
||||
|
||||
@ -29,79 +30,77 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
/* checks*/
|
||||
/* .adx: standard, .adp: Headhunter (DC) */
|
||||
/* .adx: standard
|
||||
* .adp: Headhunter (DC) */
|
||||
if (!check_extensions(streamFile,"adx,adp"))
|
||||
goto fail;
|
||||
|
||||
/* check first 2 bytes */
|
||||
if ((uint16_t)read_16bitBE(0x00,streamFile)!=0x8000) goto fail;
|
||||
if ((uint16_t)read_16bitBE(0x00,streamFile) != 0x8000)
|
||||
goto fail;
|
||||
|
||||
/* get stream offset, check for CRI signature just before */
|
||||
start_offset = (uint16_t)read_16bitBE(0x02,streamFile) + 4;
|
||||
if ((uint16_t)read_16bitBE(start_offset-6,streamFile)!=0x2863 || /* "(c" */
|
||||
(uint32_t)read_32bitBE(start_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
||||
) goto fail;
|
||||
start_offset = (uint16_t)read_16bitBE(0x02,streamFile) + 0x04;
|
||||
if ((uint16_t)read_16bitBE(start_offset - 0x06,streamFile) != 0x2863 || /* "(c" */
|
||||
(uint32_t)read_32bitBE(start_offset - 0x04,streamFile) != 0x29435249) /* ")CRI" */
|
||||
goto fail;
|
||||
|
||||
/* check for encoding type */
|
||||
/* 0x02 is for some unknown fixed filter, 0x03 is standard ADX, 0x04 is
|
||||
* ADX with exponential scale, 0x10 is AHX for DC, 0x11 is AHX */
|
||||
encoding_type = read_8bit(0x04, streamFile);
|
||||
|
||||
switch (encoding_type) {
|
||||
case 2:
|
||||
case 0x02:
|
||||
coding_type = coding_CRI_ADX_fixed;
|
||||
break;
|
||||
case 3:
|
||||
case 0x03:
|
||||
coding_type = coding_CRI_ADX;
|
||||
break;
|
||||
case 4:
|
||||
case 0x04:
|
||||
coding_type = coding_CRI_ADX_exp;
|
||||
break;
|
||||
default:
|
||||
default: /* 0x10 is AHX for DC, 0x11 is AHX */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* ADX encoders can't set this value, but is honored by ADXPlay if changed and multiple of 0x12,
|
||||
* though output is unusual and may not be fully supported (works in mono so not an interleave) */
|
||||
frame_size = read_8bit(0x05, streamFile);
|
||||
|
||||
/* check for bits per sample? (only 4 makes sense for ADX) */
|
||||
if (read_8bit(0x06,streamFile) != 4) goto fail;
|
||||
if (read_8bit(0x06,streamFile) != 4) /* bits per sample */
|
||||
goto fail;
|
||||
|
||||
/* older ADX (adxencd) up to 2ch, newer ADX (criatomencd) up to 8 */
|
||||
channel_count = read_8bit(0x07,streamFile);
|
||||
/* 0x08: sample rate */
|
||||
/* 0x0c: samples */
|
||||
/* 0x10: high-pass frequency */
|
||||
|
||||
/* check version signature, read loop info */
|
||||
version_signature = read_16bitBE(0x12,streamFile);
|
||||
|
||||
version = read_16bitBE(0x12,streamFile);
|
||||
|
||||
/* encryption */
|
||||
if (version_signature == 0x0408) {
|
||||
if (version == 0x0408) {
|
||||
if (find_adx_key(streamFile, 8, &xor_start, &xor_mult, &xor_add)) {
|
||||
coding_type = coding_CRI_ADX_enc_8;
|
||||
version_signature = 0x0400;
|
||||
version = 0x0400;
|
||||
}
|
||||
}
|
||||
else if (version_signature == 0x0409) {
|
||||
else if (version == 0x0409) {
|
||||
if (find_adx_key(streamFile, 9, &xor_start, &xor_mult, &xor_add)) {
|
||||
coding_type = coding_CRI_ADX_enc_9;
|
||||
version_signature = 0x0400;
|
||||
version = 0x0400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* version + extra data */
|
||||
if (version_signature == 0x0300) { /* early ADX (~2004?) */
|
||||
if (version == 0x0300) { /* early ADX (~1998) [Grandia (SAT), Baroque (SAT)] */
|
||||
size_t base_size = 0x14, loops_size = 0x18;
|
||||
|
||||
header_type = meta_ADX_03;
|
||||
|
||||
/* no sample history */
|
||||
|
||||
if (start_offset - 6 >= base_size + loops_size) { /* enough space for loop info? */
|
||||
if (start_offset - 0x06 >= base_size + loops_size) { /* enough space for loop info? */
|
||||
off_t loops_offset = base_size;
|
||||
|
||||
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
/* 0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||
* 0x02 (2): loop sample(?) flag (always 1) */
|
||||
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||
@ -109,37 +108,40 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||
}
|
||||
}
|
||||
else if (version_signature == 0x0400) { /* common */
|
||||
else if (version == 0x0400) { /* common */
|
||||
size_t base_size = 0x18, hist_size, ainf_size = 0, loops_size = 0x18;
|
||||
off_t ainf_offset;
|
||||
|
||||
header_type = meta_ADX_04;
|
||||
|
||||
hist_offset = base_size; /* always present but often blank */
|
||||
hist_size = (channel_count > 1 ? 4*channel_count : 4+4); /* min is 8, even in 1ch files */
|
||||
hist_size = (channel_count > 1 ? 0x04 * channel_count : 0x04 + 0x04); /* min is 8, even in 1ch files */
|
||||
|
||||
ainf_offset = base_size + hist_size + 0x4; /* not seen with >2ch though */
|
||||
ainf_offset = base_size + hist_size + 0x04; /* not seen with >2ch though */
|
||||
if ((uint32_t)read_32bitBE(ainf_offset+0x00,streamFile) == 0x41494E46) /* "AINF" */
|
||||
ainf_size = read_32bitBE(ainf_offset+0x04,streamFile);
|
||||
|
||||
if (start_offset - ainf_size - 6 >= hist_offset + hist_size + loops_size) { /* enough space for loop info? */
|
||||
if (start_offset - ainf_size - 0x06 >= hist_offset + hist_size + loops_size) { /* enough space for loop info? */
|
||||
off_t loops_offset = base_size + hist_size;
|
||||
|
||||
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
/* 0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||
* 0x02 (2): loop sample(?) flag (always 1) */
|
||||
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||
loop_end_sample = read_32bitBE(loops_offset+0x10,streamFile);
|
||||
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||
}
|
||||
|
||||
/* AINF header info (may be inserted by CRI's tools but is rarely used)
|
||||
* Can also start right after the loop points (base_size + hist_size + loops_size)
|
||||
* 0x00 (4): "AINF"; 0x04 (4): size; 0x08 (10): str_id
|
||||
* 0x00 (4): "AINF"
|
||||
* 0x04 (4): size
|
||||
* 0x08 (10): str_id
|
||||
* 0x18 (2): volume (0=base/max?, negative=reduce)
|
||||
* 0x1c (2): pan l; 0x1e (2): pan r (0=base, max +-128) */
|
||||
* 0x1c (2): pan l
|
||||
* 0x1e (2): pan r (0=base, max +-128) */
|
||||
|
||||
/* CINF header info (very rare, found after loops) [Sakura Taisen 3 (PS2)]
|
||||
* 0x00 (4): "CINF"
|
||||
@ -149,7 +151,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
* 0x48 (-): file name, null terminated
|
||||
*/
|
||||
}
|
||||
else if (version_signature == 0x0500) { /* found in some SFD: Buggy Heat, appears to have no loop */
|
||||
else if (version == 0x0500) { /* found in some SFD: Buggy Heat, appears to have no loop */
|
||||
header_type = meta_ADX_05;
|
||||
}
|
||||
else { /* not a known/supported version signature */
|
||||
@ -161,13 +163,13 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
|
||||
vgmstream->sample_rate = read_32bitBE(0x8,streamFile);
|
||||
vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->num_samples = read_32bitBE(0x0c,streamFile);
|
||||
vgmstream->loop_start_sample = loop_start_sample;
|
||||
vgmstream->loop_end_sample = loop_end_sample;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = frame_size;
|
||||
vgmstream->meta_type = header_type;
|
||||
|
||||
@ -175,6 +177,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
/* calculate filter coefficients */
|
||||
if (coding_type == coding_CRI_ADX_fixed) {
|
||||
int i;
|
||||
/* standard XA coefs * (2<<11) */
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
vgmstream->ch[i].adpcm_coef[0] = 0x0000;
|
||||
vgmstream->ch[i].adpcm_coef[1] = 0x0000;
|
||||
@ -194,14 +197,14 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
|
||||
x = cutoff;
|
||||
y = vgmstream->sample_rate;
|
||||
z = cos(2.0*M_PI*x/y);
|
||||
z = cos(2.0 * M_PI * x / y);
|
||||
|
||||
a = M_SQRT2-z;
|
||||
b = M_SQRT2-1.0;
|
||||
c = (a-sqrt((a+b)*(a-b)))/b;
|
||||
a = M_SQRT2 - z;
|
||||
b = M_SQRT2 - 1.0;
|
||||
c = (a - sqrt((a + b) * (a - b))) / b;
|
||||
|
||||
coef1 = (short)(c*8192);
|
||||
coef2 = (short)(c*c*-4096);
|
||||
coef1 = (short)(c * 8192);
|
||||
coef2 = (short)(c * c * -4096);
|
||||
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
vgmstream->ch[i].adpcm_coef[0] = coef1;
|
||||
@ -213,7 +216,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
/* 2 hist shorts per ch, corresponding to the very first original sample repeated (verified with CRI's encoders).
|
||||
* Not vital as their effect is small, after a few samples they don't matter, and most songs start in silence. */
|
||||
if (hist_offset) {
|
||||
@ -228,7 +231,7 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||
vgmstream->ch[i].adx_mult = xor_mult;
|
||||
vgmstream->ch[i].adx_add = xor_add;
|
||||
|
||||
for (j=0;j<i;j++)
|
||||
for (j = 0; j < i; j++)
|
||||
adx_next_key(&vgmstream->ch[i]);
|
||||
}
|
||||
}
|
||||
@ -245,12 +248,14 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
/* return 0 if not found, 1 if found and set parameters */
|
||||
static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) {
|
||||
uint16_t * scales = NULL;
|
||||
uint16_t * prescales = NULL;
|
||||
int bruteframe = 0, bruteframe_count = -1;
|
||||
int startoff, endoff;
|
||||
/* ADX key detection works by reading XORed ADPCM scales in frames, and un-XORing with keys in
|
||||
* a list. If resulting values are within the expected range for N scales we accept that key. */
|
||||
static int find_adx_key(STREAMFILE *sf, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) {
|
||||
const int frame_size = 0x12;
|
||||
uint16_t *scales = NULL;
|
||||
uint16_t *prescales = NULL;
|
||||
int bruteframe_start = 0, bruteframe_count = -1;
|
||||
off_t start_offset;
|
||||
int i, rc = 0;
|
||||
|
||||
|
||||
@ -260,7 +265,7 @@ static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_star
|
||||
size_t key_size;
|
||||
|
||||
/* handle type8 keystrings, key9 keycodes and derived keys too */
|
||||
key_size = read_key_file(keybuf,0x20, streamFile);
|
||||
key_size = read_key_file(keybuf,0x20, sf);
|
||||
|
||||
if (key_size > 0) {
|
||||
int i, is_ascii = 0;
|
||||
@ -299,77 +304,90 @@ static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_star
|
||||
/* setup totals */
|
||||
{
|
||||
int frame_count;
|
||||
int channels = read_8bit(0x07, sf);
|
||||
int num_samples = read_32bitBE(0x0c, sf);
|
||||
off_t end_offset;
|
||||
|
||||
startoff = read_16bitBE(2, streamFile) + 4;
|
||||
endoff = (read_32bitBE(12, streamFile) + 31) / 32 * 18 * read_8bit(7, streamFile) + startoff;
|
||||
start_offset = read_16bitBE(0x02, sf) + 0x4;
|
||||
end_offset = (num_samples + 31) / 32 * frame_size * channels + start_offset; /* samples-to-bytes */
|
||||
|
||||
frame_count = (endoff - startoff) / 18;
|
||||
frame_count = (end_offset - start_offset) / frame_size;
|
||||
if (frame_count < bruteframe_count || bruteframe_count < 0)
|
||||
bruteframe_count = frame_count;
|
||||
}
|
||||
|
||||
/* find longest run of nonzero frames */
|
||||
/* find longest run of non-zero frames (zero frames aren't good for key testing) */
|
||||
{
|
||||
int longest = -1, longest_length = -1;
|
||||
int length = 0;
|
||||
static const uint8_t zeroes[0x12] = {0};
|
||||
uint8_t frame[0x12];
|
||||
int longest_start = -1, longest_count = -1;
|
||||
int count = 0;
|
||||
|
||||
for (i = 0; i < bruteframe_count; i++) {
|
||||
static const unsigned char zeroes[18] = {0};
|
||||
unsigned char buf[18];
|
||||
read_streamfile(buf, startoff + i * 18, 18, streamFile);
|
||||
if (memcmp(zeroes, buf, 18))
|
||||
length++;
|
||||
read_streamfile(frame, start_offset + i*frame_size, frame_size, sf);
|
||||
if (memcmp(zeroes, frame, frame_size) != 0)
|
||||
count++;
|
||||
else
|
||||
length = 0;
|
||||
if (length > longest_length) {
|
||||
longest_length = length;
|
||||
longest = i - length + 1;
|
||||
if (longest_length >= 0x8000)
|
||||
count = 0;
|
||||
|
||||
/* update new record of non-zero frames */
|
||||
if (count > longest_count) {
|
||||
longest_count = count;
|
||||
longest_start = i - count + 1;
|
||||
if (longest_count >= ADX_KEY_MAX_TEST_FRAMES)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (longest == -1) {
|
||||
goto find_key_cleanup;
|
||||
|
||||
/* no non-zero frames */
|
||||
if (longest_start == -1) {
|
||||
goto done;
|
||||
}
|
||||
bruteframe_count = longest_length;
|
||||
bruteframe = longest;
|
||||
|
||||
bruteframe_start = longest_start;
|
||||
bruteframe_count = longest_count;
|
||||
if (bruteframe_count > ADX_KEY_MAX_TEST_FRAMES) //?
|
||||
bruteframe_count = ADX_KEY_MAX_TEST_FRAMES;
|
||||
}
|
||||
|
||||
/* try to guess key */
|
||||
/* pre-load scales in a table, to avoid re-reading them per key */
|
||||
{
|
||||
const adxkey_info * keys = NULL;
|
||||
int keycount = 0, keymask = 0;
|
||||
int scales_to_do;
|
||||
int key_id;
|
||||
|
||||
/* allocate storage for scales */
|
||||
scales_to_do = (bruteframe_count > MAX_TEST_FRAMES ? MAX_TEST_FRAMES : bruteframe_count);
|
||||
scales = malloc(scales_to_do*sizeof(uint16_t));
|
||||
if (!scales) goto find_key_cleanup;
|
||||
scales = malloc(bruteframe_count * sizeof(uint16_t));
|
||||
if (!scales) goto done;
|
||||
|
||||
/* prescales are those scales before the first frame we test
|
||||
* against, we use these to compute the actual start */
|
||||
if (bruteframe > 0) {
|
||||
/* allocate memory for the prescales */
|
||||
prescales = malloc(bruteframe*sizeof(uint16_t));
|
||||
if (!prescales) goto find_key_cleanup;
|
||||
/* prescales are scales before the first test frame, with some blank frames no good
|
||||
* for key testing, but we must read to compute XOR value at bruteframe_start */
|
||||
if (bruteframe_start > 0) {
|
||||
/* allocate storage for prescales */
|
||||
prescales = malloc(bruteframe_start * sizeof(uint16_t));
|
||||
if (!prescales) goto done;
|
||||
|
||||
/* read the prescales */
|
||||
for (i=0; i<bruteframe; i++) {
|
||||
prescales[i] = read_16bitBE(startoff+i*18, streamFile);
|
||||
for (i = 0; i < bruteframe_start; i++) {
|
||||
prescales[i] = read_16bitBE(start_offset + i*frame_size, sf);
|
||||
}
|
||||
}
|
||||
|
||||
/* read in the scales */
|
||||
for (i=0; i < scales_to_do; i++) {
|
||||
scales[i] = read_16bitBE(startoff+(bruteframe+i)*18, streamFile);
|
||||
for (i = 0; i < bruteframe_count; i++) {
|
||||
scales[i] = read_16bitBE(start_offset + (bruteframe_start + i)*frame_size, sf);
|
||||
}
|
||||
}
|
||||
|
||||
/* try to guess key */
|
||||
{
|
||||
const adxkey_info *keys = NULL;
|
||||
int keycount = 0, keymask = 0;
|
||||
int key_id;
|
||||
|
||||
/* setup test mask (used to check high bits that signal un-XORed scale would be too high to be valid) */
|
||||
if (type == 8) {
|
||||
keys = adxkey8_list;
|
||||
keycount = adxkey8_list_count;
|
||||
keymask = 0x6000;
|
||||
}
|
||||
else if (type == 9) {
|
||||
else { //if (type == 9)
|
||||
/* smarter XOR as seen in PSO2. The scale is technically 13 bits,
|
||||
* but the maximum value assigned by the encoder is 0x1000.
|
||||
* This is written to the ADX file as 0xFFF, leaving the high bit
|
||||
@ -379,7 +397,7 @@ static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_star
|
||||
keymask = 0x1000;
|
||||
}
|
||||
|
||||
/* try all keys until one decrypts correctly vs expected values */
|
||||
/* try all keys until one decrypts correctly vs expected scales */
|
||||
for (key_id = 0; key_id < keycount; key_id++) {
|
||||
uint16_t key_xor, key_mul, key_add;
|
||||
uint16_t xor, mul, add;
|
||||
@ -400,6 +418,7 @@ static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_star
|
||||
VGM_LOG("ADX: incorrectly defined key id=%i\n", key_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* temp test values */
|
||||
xor = key_xor;
|
||||
mul = key_mul;
|
||||
@ -428,30 +447,34 @@ static int find_adx_key(STREAMFILE *streamFile, uint8_t type, uint16_t *xor_star
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* test vs prescales while xor looks valid */
|
||||
for (i = 0; i < bruteframe && ((prescales[i] & keymask) == (xor & keymask) || prescales[i] == 0); i++) {
|
||||
/* test vs prescales while XOR looks valid */
|
||||
for (i = 0; i < bruteframe_start; i++) {
|
||||
if ((prescales[i] & keymask) != (xor & keymask) && prescales[i] != 0)
|
||||
break;
|
||||
xor = xor * mul + add;
|
||||
}
|
||||
if (i == bruteframe) {
|
||||
/* test vs scales while xor looks valid */
|
||||
for (i = 0; i < scales_to_do && (scales[i] & keymask) == (xor & keymask); i++) {
|
||||
xor = xor * mul + add;
|
||||
}
|
||||
/* key is good */
|
||||
if (i == scales_to_do) {
|
||||
*xor_start = key_xor;
|
||||
*xor_mult = key_mul;
|
||||
*xor_add = key_add;
|
||||
if (i != bruteframe_start)
|
||||
continue;
|
||||
|
||||
rc = 1;
|
||||
goto find_key_cleanup;
|
||||
}
|
||||
/* test vs scales while XOR looks valid */
|
||||
for (i = 0; i < bruteframe_count; i++) {
|
||||
if ((scales[i] & keymask) != (xor & keymask))
|
||||
break;
|
||||
xor = xor * mul + add;
|
||||
}
|
||||
if (i != bruteframe_count)
|
||||
continue;
|
||||
|
||||
/* all scales are valid, key is good */
|
||||
*xor_start = key_xor;
|
||||
*xor_mult = key_mul;
|
||||
*xor_add = key_add;
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
find_key_cleanup:
|
||||
done:
|
||||
free(scales);
|
||||
free(prescales);
|
||||
return rc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user