diff --git a/Makefile b/Makefile index 6146c87c..00816e86 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ export RMF SHELL CC AR STRIP WINDRES DLLTOOL ############################################################################### ### build defs -DEF_CFLAGS += -ffast-math -O3 -Wall -Werror=format-security -Wdeclaration-after-statement -Wvla -Wimplicit-function-declaration -Wignored-qualifiers +DEF_CFLAGS += -ffast-math -O3 -Wall -Werror=format-security -Wvla -Wimplicit-function-declaration -Wignored-qualifiers VGM_DEBUG_FLAGS = 0 ifeq ($(VGM_DEBUG_FLAGS),1) diff --git a/src/coding/coding.h b/src/coding/coding.h index 013a8ade..01f8cc60 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -473,6 +473,13 @@ typedef enum { MPEG_EAMP3 /* custom frame header + MPEG frame + PCM blocks */ } mpeg_custom_t; +typedef struct { + int type; + uint16_t key1; + uint16_t key2; + uint16_t key3; +} crikey_t; + /* config for the above modes */ typedef struct { int channels; /* max channels */ @@ -485,11 +492,7 @@ typedef struct { int encryption; /* encryption mode */ int big_endian; int skip_samples; - /* for AHX */ - int cri_type; - uint16_t cri_key1; - uint16_t cri_key2; - uint16_t cri_key3; + crikey_t crikey; /* for AHX */ } mpeg_custom_config; mpeg_codec_data* init_mpeg(STREAMFILE* sf, off_t start_offset, coding_t *coding_type, int channels); @@ -504,6 +507,7 @@ long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data* data); uint32_t mpeg_get_tag_size(STREAMFILE* sf, uint32_t offset, uint32_t header); int mpeg_get_frame_info(STREAMFILE* sf, off_t offset, mpeg_frame_info* info); +int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey); #endif diff --git a/src/coding/mpeg_custom_utils_ahx.c b/src/coding/mpeg_custom_utils_ahx.c index 1398707d..9a689432 100644 --- a/src/coding/mpeg_custom_utils_ahx.c +++ b/src/coding/mpeg_custom_utils_ahx.c @@ -1,111 +1,223 @@ -#include "mpeg_decoder.h" - #ifdef VGM_USE_MPEG +#include "mpeg_decoder.h" +#include "../util/bitstream_msb.h" +#include "coding.h" + #define MPEG_AHX_EXPECTED_FRAME_SIZE 0x414 -static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config); +/* AHX is more or less VBR MP2 using a fixed header (0xFFF5E0C0) that sets frame size 0x414 (1ch, 160kbps, 22050Hz) + * but are typically much shorter (ignores padding), output sample rate is also ignored. + * + * MPEG1 Layer II (MP2) bitstream format for reference: + * - MPEG header, 32b + * - 'bit allocation' indexes (MP2's config determines bands and table with bit size per band, in AHX's case 30 bands and total 107 bits) + * - 16-bit CRC if set in header (never in AHX) + * - scale factor selection info (SCFSI), 2b per band/channel (if band has bit alloc set) + * - scale factors, bits depending on selection info (if band has bit alloc set) + * - quantized samples, bits depending on bit alloc info + * - padding (removed in AHX) + */ -/* writes data to the buffer and moves offsets, transforming AHX frames as needed */ -int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) { - mpeg_custom_stream *ms = data->streams[num_stream]; - size_t current_data_size = 0; - size_t file_size = get_streamfile_size(stream->streamfile); - /* AHX has a 0xFFF5E0C0 header with frame size 0x414 (160kbps, 22050Hz) but they actually are much shorter */ +#define AHX_BANDS 30 +#define AHX_GRANULES 12 +static const uint8_t AHX_BITALLOC_TABLE[32] = { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; +static const uint8_t AHX_OFFSET_TABLE[5][16] = { + { 0 }, + { 0 }, + { 0, 1, 3, 4, }, + { 0, 1, 3, 4, 5, 6, 7, 8, }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 } +}; +static const int8_t AHX_QBITS_TABLE[17] = { -5, -7, 3, -10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; - /* read supposed frame size first (to minimize reads) */ - ms->bytes_in_buffer = read_streamfile(ms->buffer, stream->offset, MPEG_AHX_EXPECTED_FRAME_SIZE, stream->streamfile); +/* Decrypts and tests a AHX frame with current by reading all bits, as wrong keys should go over size. Reverse engineered + * from CRI libs. (MPEG1 Layer II code abridged for AHX, which is always mono and has fixed bands/tables, some info from ahx2wav.c) */ +static int ahx_decrypt(uint8_t* buf, int curr_size, crikey_t* crikey) { + uint32_t bit_alloc[AHX_BANDS] = {0}; + uint32_t scfsi[AHX_BANDS] = {0}; + bitstream_t ib = {0}; + bitstream_t ob = {0}; - /* find actual frame size by looking for the next frame header */ - { - uint32_t current_header = get_u32be(ms->buffer); - int next_pos = 0x04; + bm_setup(&ib, buf, curr_size); /* frame */ + bm_setup(&ob, buf, curr_size); /* decrypted frame */ - while (next_pos <= MPEG_AHX_EXPECTED_FRAME_SIZE) { - uint32_t next_header = get_u32be(ms->buffer + next_pos); + /* MPEG header (fixed in AHX, otherwise layer/bitrate/channels sets bands+tables) */ + bm_skip(&ib, 32); + bm_skip(&ob, 32); - if (current_header == next_header) { - current_data_size = next_pos; - break; - } + /* read bit allocs for later */ + for (int i = 0; i < AHX_BANDS; i++) { + int ba_bits = AHX_BITALLOC_TABLE[i]; - /* AHXs end in a 0x0c footer (0x41485845 28632943 52490000 / "AHXE(c)CRI\0\0") */ - if (stream->offset + next_pos + 0x0c >= file_size) { - current_data_size = next_pos; - break; - } + bm_get (&ib, ba_bits, &bit_alloc[i]); + bm_skip(&ob, ba_bits); + } - next_pos++; + /* get first scalefactor info to decide key */ + if (bit_alloc[0]) { + bm_get (&ib, 2, &scfsi[0]); + bm_skip(&ob, 2); + } + + uint16_t key; + switch(scfsi[0]) { + case 1: key = crikey->key1; break; + case 2: key = crikey->key2; break; + case 3: key = crikey->key3; break; + default: key = 0; /* 0: no key (common in null frames) */ + } + + /* decrypt rest of scalefactors (only first ones are encrypted though) */ + for (int i = 1; i < AHX_BANDS; i++) { + if (bit_alloc[i]) { + bm_get (&ib, 2, &scfsi[i]); + scfsi[i] ^= (key & 3); + bm_put(&ob, 2, scfsi[i]); + } + key >>= 2; + } + + /* read scalefactors (past this point no need to decrypt/write frame) */ + for (int i = 0; i < AHX_BANDS; i++) { + if (bit_alloc[i] == 0) + continue; + + switch(scfsi[i]) { + case 0: bm_skip(&ib, 6 * 3); break; + case 1: + case 3: bm_skip(&ib, 6 * 2); break; + case 2: bm_skip(&ib, 6 * 1); break; + default: break; } } - if (current_data_size == 0 || current_data_size > ms->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) { - VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", current_data_size); + /* read quants */ + for (int gr = 0; gr < AHX_GRANULES; gr++) { + for (int i = 0; i < AHX_BANDS; i++) { + int ba_value = bit_alloc[i]; + if (ba_value == 0) + continue; + + int ba_bits = AHX_BITALLOC_TABLE[i]; + int qb_index = AHX_OFFSET_TABLE[ba_bits][ba_value - 1]; + int qbits = AHX_QBITS_TABLE[qb_index]; + + if (qbits < 0) + qbits = -qbits; + else + qbits = qbits * 3; /* 3 qs */ + + int ok = bm_skip(&ib, qbits); + if (!ok) goto fail; + } + } + + /* read padding */ + { + int bpos = bm_pos(&ib); + if (bpos % 8) { + bm_skip(&ib, 8 - (bpos % 8)); + } + } + + /* if file was properly read/decrypted this size should land in next frame header or near EOF */ + return bm_pos(&ib) / 8; +fail: + return 0; +} + + +/* writes data to the buffer and moves offsets, transforming AHX frames as needed */ +int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream) { + mpeg_custom_stream *ms = data->streams[num_stream]; + size_t curr_size = 0; + size_t file_size = get_streamfile_size(stream->streamfile); + + + /* Find actual frame size by looking for the next frame header. Not very elegant but simpler, works with encrypted AHX, + * and possibly faster than reading frame size's bits with ahx_decrypt */ + { + ms->bytes_in_buffer = read_streamfile(ms->buffer, stream->offset, MPEG_AHX_EXPECTED_FRAME_SIZE + 0x04, stream->streamfile); + + uint32_t curr_header = get_u32be(ms->buffer); + int pos = 0x04; + while (pos <= MPEG_AHX_EXPECTED_FRAME_SIZE) { + + /* next sync test */ + if (ms->buffer[pos] == 0xFF) { + uint32_t next_header = get_u32be(ms->buffer + pos); + if (curr_header == next_header) { + curr_size = pos; + break; + } + } + + /* AHX footer (0x8001000C 41485845 28632943 52490000 = 0x8001 tag + size + "AHXE(c)CRI\0\0") */ + if (stream->offset + pos + 0x10 >= file_size) { + curr_size = pos; + break; + } + + pos++; + } + } + + if (curr_size == 0 || curr_size > ms->buffer_size || curr_size > MPEG_AHX_EXPECTED_FRAME_SIZE) { + VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", curr_size); goto fail; } /* 0-fill up to expected size to keep mpg123 happy */ - memset(ms->buffer + current_data_size, 0, MPEG_AHX_EXPECTED_FRAME_SIZE - current_data_size); + memset(ms->buffer + curr_size, 0, MPEG_AHX_EXPECTED_FRAME_SIZE - curr_size); ms->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE; - - /* decrypt if needed */ - switch(data->config.encryption) { - case 0x00: break; - case 0x08: ahx_decrypt_type08(ms->buffer, &data->config); break; - default: - VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption); - break; /* garbled frame */ + /* decrypt if needed (only 0x08 is known but 0x09 is probably the same) */ + if (data->config.encryption == 0x08) { + ahx_decrypt(ms->buffer, curr_size, &data->config.crikey); } /* update offsets */ - stream->offset += current_data_size; - if (stream->offset + 0x0c >= file_size) - stream->offset = file_size; /* skip 0x0c footer to reach EOF (shouldn't happen normally) */ + stream->offset += curr_size; + if (stream->offset + 0x10 >= file_size) + stream->offset = file_size; /* skip footer to reach EOF (shouldn't happen normally) */ return 1; fail: return 0; } -/* Decrypts an AHX type 0x08 (keystring) encrypted frame. Algorithm by Thealexbarney */ -static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config) { - int i, index, encrypted_bits; - uint32_t value; - uint16_t current_key; - /* encryption 0x08 modifies a few bits every frame, here we decrypt and write to data buffer */ +#define AHX_KEY_BUFFER 0x2000 +#define AHX_KEY_TEST_FRAMES 15 /* wrong keys may work ok in some frames */ - /* derive keystring to 3 primes, using the type 0x08 method, and assign each an index of 1/2/3 (0=no key) */ - /* (externally done for now, see: https://github.com/Thealexbarney/VGAudio/blob/2.0/src/VGAudio/Codecs/CriAdx/CriAdxKey.cs) */ +/* check if current key ends properly in frame syncs */ +int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) { + int bytes; + uint8_t buf[AHX_KEY_BUFFER]; + const int buf_size = sizeof(buf); + int pos = 0; + uint32_t base_sync, curr_sync; - /* read 2b from a bitstream offset to decrypt, and use it as an index to get the key. - * AHX encrypted bitstream starts at 107b (0x0d*8+3), every frame, and seem to always use index 2 */ - value = get_u32be(buffer + 0x0d); - index = (value >> (32-3-2)) & 0x03; - switch(index) { - case 0: current_key = 0; break; - case 1: current_key = config->cri_key1; break; - case 2: current_key = config->cri_key2; break; - case 3: current_key = config->cri_key3; break; - default: goto fail; + bytes = read_streamfile(buf, offset, buf_size, sf); + //if (bytes != buf_size) goto fail; /* possible in small AHX */ + + base_sync = get_u32be(buf + 0x00); + for (int i = 0; i < AHX_KEY_TEST_FRAMES; i++) { + + int size = ahx_decrypt(buf + pos, bytes, crikey); + if (size <= 0 || size >= bytes - 0x04) goto fail; + + bytes -= size; + pos += size; + + curr_sync = get_u32be(buf + pos); + if (curr_sync == 0x00800100) /* EOF tag */ + break; + if (base_sync != curr_sync) + goto fail; } - /* AHX for DC: 16b, normal: 6b (no idea, probably some Layer II field) */ - encrypted_bits = config->cri_type == 0x10 ? 16 : 6; - - /* decrypt next bitstream 2b pairs, up to 16b (max key size): - * - read 2b from bitstream (from higher to lower) - * - read 2b from key (from lower to higher) - * - XOR them to decrypt */ - for (i = 0; i < encrypted_bits; i+=2) { - uint32_t xor_2b = (current_key >> i) & 0x03; - value ^= ((xor_2b << (32-3-2-2)) >> i); - } - - /* write output */ - put_32bitBE(buffer + 0x0d, value); - return 1; fail: return 0; diff --git a/src/coding/mpeg_custom_utils_ealayer3.c b/src/coding/mpeg_custom_utils_ealayer3.c index 21f22e72..63c2abe6 100644 --- a/src/coding/mpeg_custom_utils_ealayer3.c +++ b/src/coding/mpeg_custom_utils_ealayer3.c @@ -1,5 +1,5 @@ #include "mpeg_decoder.h" -#include "mpeg_bitreader.h" +#include "../util/bitstream_msb.h" #ifdef VGM_USE_MPEG @@ -108,7 +108,7 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE* sf, off_t start_offset, mpeg_cod { ib.sf = sf; ib.offset = start_offset; - ib.is.buf = ib.buf; + bm_setup(&ib.is, ib.buf, 0); // filled later ok = ealayer3_parse_frame(data, -1, &ib, &eaf); if (!ok) goto fail; @@ -156,7 +156,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data* ib_0.sf = stream->streamfile; ib_0.offset = stream->offset; - ib_0.is.buf = ib_0.buf; + bm_setup(&ib_0.is, ib_0.buf, 0); // filled later ok = ealayer3_parse_frame(data, num_stream, &ib_0, &eaf_0); if (!ok) goto fail; @@ -199,7 +199,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data* ib_1.sf = stream->streamfile; ib_1.offset = stream->offset; - ib_1.is.buf = ib_1.buf; + bm_setup(&ib_1.is, ib_1.buf, 0); // filled later ok = ealayer3_parse_frame(data, num_stream, &ib_1, &eaf_1); if (!ok) goto fail; @@ -222,12 +222,12 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data* { bitstream_t os = {0}; - init_bitstream(&os, ms->buffer, ms->buffer_size); + bm_setup(&os, ms->buffer, ms->buffer_size); ok = ealayer3_rebuild_mpeg_frame(&ib_0.is, &eaf_0, &ib_1.is, &eaf_1, &os); if (!ok) goto fail; - ms->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */ + ms->bytes_in_buffer = bm_pos(&os) / 8; /* wrote full MPEG frame, hopefully */ } return 1; @@ -267,8 +267,8 @@ static void fill_buf(ealayer3_buffer_t* ib, int bits) { //;VGM_LOG("filled: %lx + %x (b=%i, m=%i)\n", ib->offset, bytes_size, bits, (mod > 0 ? 8 - mod : 0)); - read_size = read_streamfile(ib->buf + ib->is.bufsize, ib->offset, bytes_size, ib->sf); - ib->is.bufsize += read_size; + read_size = read_streamfile(ib->buf + ib->is.bufsize, ib->offset, bytes_size, ib->sf); //TODO don't access internals + bm_fill(&ib->is, read_size); ib->offset += read_size; ib->leftover_bits = (mod > 0 ? 8 - mod : 0); } @@ -309,7 +309,7 @@ static int ealayer3_parse_frame_v1(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf, /* read EA-frame V1 header */ fill_buf(ib, 8); - rb_bits(is, 8,&eaf->v1_pcm_flag); + bm_get(is, 8,&eaf->v1_pcm_flag); eaf->pre_size = 1; /* 8b */ @@ -331,15 +331,15 @@ static int ealayer3_parse_frame_v1(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf, /* check PCM block */ if (eaf->v1_pcm_flag == 0xEE) { fill_buf(ib, 32); - rb_bits(is, 16,&eaf->v1_offset_samples); /* PCM block offset in the buffer */ - rb_bits(is, 16,&eaf->v1_pcm_samples); /* number of PCM samples, can be 0 */ + bm_get(is, 16,&eaf->v1_offset_samples); /* PCM block offset in the buffer */ + bm_get(is, 16,&eaf->v1_pcm_samples); /* number of PCM samples, can be 0 */ eaf->pre_size += 2+2; /* 16b+16b */ eaf->pcm_size = (2*eaf->v1_pcm_samples * channels_per_frame); if (is_v1b) { /* extra 32b in v1b */ fill_buf(ib, 32); - rb_bits(is, 32,&eaf->v1_pcm_unknown); + bm_get(is, 32,&eaf->v1_pcm_unknown); eaf->pre_size += 4; /* 32b */ @@ -363,19 +363,19 @@ static int ealayer3_parse_frame_v2(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf) /* read EA-frame V2 header */ fill_buf(ib, 16); - rb_bits(is, 1,&eaf->v2_extended_flag); - rb_bits(is, 1,&eaf->v2_stereo_flag); - rb_bits(is, 2,&eaf->v2_reserved); - rb_bits(is, 12,&eaf->v2_frame_size); + bm_get(is, 1,&eaf->v2_extended_flag); + bm_get(is, 1,&eaf->v2_stereo_flag); + bm_get(is, 2,&eaf->v2_reserved); + bm_get(is, 12,&eaf->v2_frame_size); eaf->pre_size = 2; /* 16b */ if (eaf->v2_extended_flag) { fill_buf(ib, 32); - rb_bits(is, 2,&eaf->v2_offset_mode); - rb_bits(is, 10,&eaf->v2_offset_samples); - rb_bits(is, 10,&eaf->v2_pcm_samples); - rb_bits(is, 10,&eaf->v2_common_size); + bm_get(is, 2,&eaf->v2_offset_mode); + bm_get(is, 10,&eaf->v2_offset_samples); + bm_get(is, 10,&eaf->v2_pcm_samples); + bm_get(is, 10,&eaf->v2_common_size); eaf->pre_size += 4; /* 32b */ } @@ -423,16 +423,16 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t* static const int channel_table[4] = { 2,2,2, 1 }; /* [channel_mode] */ bitstream_t* is = &ib->is; - off_t start_b_off = is->b_off; + off_t start_b_off = bm_pos(is); int i, fill_bits, others_2_bits; /* read main header */ fill_buf(ib, 8); - rb_bits(is, 2,&eaf->version_index); - rb_bits(is, 2,&eaf->sample_rate_index); - rb_bits(is, 2,&eaf->channel_mode); - rb_bits(is, 2,&eaf->mode_extension); + bm_get(is, 2,&eaf->version_index); + bm_get(is, 2,&eaf->sample_rate_index); + bm_get(is, 2,&eaf->channel_mode); + bm_get(is, 2,&eaf->mode_extension); /* check empty frame */ @@ -460,7 +460,7 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t* /* read side info */ fill_buf(ib, 1); - rb_bits(is, 1,&eaf->granule_index); + bm_get(is, 1,&eaf->granule_index); fill_bits = (eaf->mpeg1 && eaf->granule_index == 1) ? 4 * eaf->channels : 0; fill_bits = fill_bits + (12 + 32 + others_2_bits) * eaf->channels; @@ -468,21 +468,21 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t* if (eaf->mpeg1 && eaf->granule_index == 1) { for (i = 0; i < eaf->channels; i++) { - rb_bits(is, 4,&eaf->scfsi[i]); + bm_get(is, 4,&eaf->scfsi[i]); } } for (i = 0; i < eaf->channels; i++) { - rb_bits(is, 12,&eaf->main_data_size[i]); + bm_get(is, 12,&eaf->main_data_size[i]); /* divided in 47b=32+15 (MPEG1) or 51b=32+19 (MPEG2), arbitrarily */ - rb_bits(is, 32,&eaf->others_1[i]); - rb_bits(is, others_2_bits,&eaf->others_2[i]); + bm_get(is, 32,&eaf->others_1[i]); + bm_get(is, others_2_bits,&eaf->others_2[i]); } /* derived */ - eaf->data_offset_b = is->b_off; /* header size + above size */ - eaf->base_size_b = (is->b_off - start_b_off); /* above size without header */ + eaf->data_offset_b = bm_pos(is); /* header size + above size */ + eaf->base_size_b = (bm_pos(is) - start_b_off); /* above size without header */ for (i = 0; i < eaf->channels; i++) { eaf->data_size_b += eaf->main_data_size[i]; /* can be 0, meaning a micro EA-frame */ } @@ -490,7 +490,7 @@ static int ealayer3_parse_frame_common(ealayer3_buffer_t* ib, ealayer3_frame_t* eaf->padding_size_b = 8 - ((eaf->base_size_b+eaf->data_size_b) % 8); fill_buf(ib, eaf->data_size_b + eaf->padding_size_b); /* read MPEG data (not PCM block) */ - is->b_off += eaf->data_size_b + eaf->padding_size_b; + bm_skip(is, eaf->data_size_b + eaf->padding_size_b); eaf->common_size = (eaf->base_size_b + eaf->data_size_b + eaf->padding_size_b)/8; @@ -542,55 +542,55 @@ static int ealayer3_rebuild_mpeg_frame(bitstream_t* is_0, ealayer3_frame_t* eaf_ #endif /* write MPEG1/2 frame header */ - wb_bits(os, 11, 0x7FF); /* sync */ - wb_bits(os, 2, eaf_0->version_index); - wb_bits(os, 2, 0x01); /* layer III index */ - wb_bits(os, 1, 1); /* "no CRC" flag */ - wb_bits(os, 4, expected_bitrate_index); - wb_bits(os, 2, eaf_0->sample_rate_index); - wb_bits(os, 1, 0); /* padding */ - wb_bits(os, 1, 0); /* private */ - wb_bits(os, 2, eaf_0->channel_mode); - wb_bits(os, 2, eaf_0->mode_extension); - wb_bits(os, 1, 1); /* copyrighted */ - wb_bits(os, 1, 1); /* original */ - wb_bits(os, 2, 0); /* emphasis */ + bm_put(os, 11, 0x7FF); /* sync */ + bm_put(os, 2, eaf_0->version_index); + bm_put(os, 2, 0x01); /* layer III index */ + bm_put(os, 1, 1); /* "no CRC" flag */ + bm_put(os, 4, expected_bitrate_index); + bm_put(os, 2, eaf_0->sample_rate_index); + bm_put(os, 1, 0); /* padding */ + bm_put(os, 1, 0); /* private */ + bm_put(os, 2, eaf_0->channel_mode); + bm_put(os, 2, eaf_0->mode_extension); + bm_put(os, 1, 1); /* copyrighted */ + bm_put(os, 1, 1); /* original */ + bm_put(os, 2, 0); /* emphasis */ if (eaf_0->mpeg1) { int private_bits = (eaf_0->channels==1 ? 5 : 3); /* write MPEG1 side info */ - wb_bits(os, 9, 0); /* main data start (no bit reservoir) */ - wb_bits(os, private_bits, 0); + bm_put(os, 9, 0); /* main data start (no bit reservoir) */ + bm_put(os, private_bits, 0); for (i = 0; i < eaf_1->channels; i++) { - wb_bits(os, 4, eaf_1->scfsi[i]); /* saved in granule1 only */ + bm_put(os, 4, eaf_1->scfsi[i]); /* saved in granule1 only */ } for (i = 0; i < eaf_0->channels; i++) { /* granule0 */ - wb_bits(os, 12, eaf_0->main_data_size[i]); - wb_bits(os, 32, eaf_0->others_1[i]); - wb_bits(os, 47-32, eaf_0->others_2[i]); + bm_put(os, 12, eaf_0->main_data_size[i]); + bm_put(os, 32, eaf_0->others_1[i]); + bm_put(os, 47-32, eaf_0->others_2[i]); } for (i = 0; i < eaf_1->channels; i++) { /* granule1 */ - wb_bits(os, 12, eaf_1->main_data_size[i]); - wb_bits(os, 32, eaf_1->others_1[i]); - wb_bits(os, 47-32, eaf_1->others_2[i]); + bm_put(os, 12, eaf_1->main_data_size[i]); + bm_put(os, 32, eaf_1->others_1[i]); + bm_put(os, 47-32, eaf_1->others_2[i]); } /* write MPEG1 main data */ - is_0->b_off = eaf_0->data_offset_b; + bm_set(is_0, eaf_0->data_offset_b); for (i = 0; i < eaf_0->channels; i++) { /* granule0 */ for (j = 0; j < eaf_0->main_data_size[i]; j++) { - rb_bits(is_0, 1, &c); - wb_bits(os, 1, c); + bm_get(is_0, 1, &c); + bm_put(os, 1, c); } } - is_1->b_off = eaf_1->data_offset_b; + bm_set(is_1, eaf_1->data_offset_b); for (i = 0; i < eaf_1->channels; i++) { /* granule1 */ for (j = 0; j < eaf_1->main_data_size[i]; j++) { - rb_bits(is_1, 1, &c); - wb_bits(os, 1, c); + bm_get(is_1, 1, &c); + bm_put(os, 1, c); } } } @@ -598,43 +598,42 @@ static int ealayer3_rebuild_mpeg_frame(bitstream_t* is_0, ealayer3_frame_t* eaf_ int private_bits = (eaf_0->channels==1 ? 1 : 2); /* write MPEG2 side info */ - wb_bits(os, 8, 0); /* main data start (no bit reservoir) */ - wb_bits(os, private_bits, 0); + bm_put(os, 8, 0); /* main data start (no bit reservoir) */ + bm_put(os, private_bits, 0); for (i = 0; i < eaf_0->channels; i++) { - wb_bits(os, 12, eaf_0->main_data_size[i]); - wb_bits(os, 32, eaf_0->others_1[i]); - wb_bits(os, 51-32, eaf_0->others_2[i]); + bm_put(os, 12, eaf_0->main_data_size[i]); + bm_put(os, 32, eaf_0->others_1[i]); + bm_put(os, 51-32, eaf_0->others_2[i]); } /* write MPEG2 main data */ - is_0->b_off = eaf_0->data_offset_b; + bm_set(is_0, eaf_0->data_offset_b); for (i = 0; i < eaf_0->channels; i++) { for (j = 0; j < eaf_0->main_data_size[i]; j++) { - rb_bits(is_0, 1, &c); - wb_bits(os, 1, c); + bm_get(is_0, 1, &c); + bm_put(os, 1, c); } } } /* align to closest 8b */ - if (os->b_off % 8) { - int align_bits = 8 - (os->b_off % 8); - wb_bits(os, align_bits, 0); + if (bm_pos(os) % 8) { + int align_bits = 8 - (bm_pos(os) % 8); + bm_put(os, align_bits, 0); } - if (os->b_off/8 > expected_frame_size) { + if (bm_pos(os) / 8 > expected_frame_size) { /* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */ - VGM_LOG("EAL3: written 0x%x but expected less than 0x%x\n", (uint32_t)(os->b_off/8), expected_frame_size); + VGM_LOG("EAL3: written 0x%x but expected less than 0x%x\n", (uint32_t)(bm_pos(os) / 8), expected_frame_size); } else { /* fill ancillary data (should be ignored, but 0x00 seems to improve mpg123's free bitrate detection) */ - memset(os->buf + os->b_off/8, 0x00, expected_frame_size - os->b_off/8); + memset(os->buf + bm_pos(os) / 8, 0x00, expected_frame_size - bm_pos(os) / 8); } - os->b_off = expected_frame_size*8; - + bm_set(os, expected_frame_size * 8); return 1; fail: @@ -835,7 +834,7 @@ static int ealayer3_skip_data(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, i for (i = 0; i < skips; i++) { ib.sf = stream->streamfile; ib.offset = stream->offset; - ib.is.buf = ib.buf; + bm_setup(&ib.is, ib.buf, 0); // filled later ok = ealayer3_parse_frame(data, num_stream, &ib, &eaf); if (!ok) goto fail; diff --git a/src/formats.c b/src/formats.c index 8a6836aa..6e72bd95 100644 --- a/src/formats.c +++ b/src/formats.c @@ -97,6 +97,7 @@ static const char* extension_list[] = { "bar", "bcstm", "bcwav", + "bcv", //txth/reserved [The Bigs (PSP)] "bd3", "bdsp", "bfstm", @@ -998,7 +999,6 @@ static const meta_info meta_info_list[] = { {meta_DSP_MSS, "Double DSP header stereo by .mss extension"}, {meta_DSP_GCM, "Double DSP header stereo by .gcm extension"}, {meta_IDSP_TT, "Traveller's Tales IDSP header"}, - {meta_RSTM_SPM, "Nintendo RSTM header (brstmspm)"}, {meta_RAW_PCM, "PC .raw raw header"}, {meta_PS2_VAGi, "Sony VAGi header"}, {meta_PS2_VAGp, "Sony VAGp header"}, @@ -1122,7 +1122,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_P2BT, "Pop'n'Music 7 Header"}, {meta_PS2_GBTS, "Pop'n'Music 9 Header"}, {meta_NGC_DSP_IADP, "IADP Header"}, - {meta_RSTM_shrunken, "Nintendo RSTM header, corrupted by Atlus"}, {meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"}, {meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"}, {meta_SAT_BAKA, "Konami BAKA header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index c70dfcf9..cce19dba 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -84,7 +84,7 @@ - + @@ -105,6 +105,7 @@ + @@ -172,6 +173,7 @@ + @@ -736,6 +738,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index be205087..c211f3c3 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -80,6 +80,9 @@ meta\Header Files + + meta\Header Files + meta\Header Files @@ -272,8 +275,8 @@ coding\Header Files - - coding\Header Files + + util\Header Files coding\Header Files @@ -317,6 +320,9 @@ Header Files + + Header Files + Header Files @@ -1990,6 +1996,9 @@ meta\Source Files + + meta\Source Files + Source Files diff --git a/src/meta/adx.c b/src/meta/adx.c index e4bdcd76..51fe4c14 100644 --- a/src/meta/adx.c +++ b/src/meta/adx.c @@ -6,6 +6,7 @@ #include "meta.h" #include "adx_keys.h" #include "../coding/coding.h" +#include "../util/cri_keys.h" #ifdef VGM_DEBUG_OUTPUT @@ -280,39 +281,32 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1 key_size = read_key_file(keybuf, sizeof(keybuf), sf); if (key_size > 0) { - int is_ascii = 0; + int is_keystring = 0; - /* keystrings should be ASCII, also needed to tell apart 0x06 strings from derived keys */ if (type == 8) { - is_ascii = 1; - for (i = 0; i < key_size; i++) { - if (keybuf[i] < 0x20 || keybuf[i] > 0x7f) { - is_ascii = 0; - break; - } - } + is_keystring = cri_key8_valid_keystring(keybuf, key_size); } - if (key_size == 0x06 && !is_ascii) { + if (key_size == 0x06 && !is_keystring) { *xor_start = get_u16be(keybuf + 0x00); *xor_mult = get_u16be(keybuf + 0x02); *xor_add = get_u16be(keybuf + 0x04); return 1; } - else if (type == 8 && is_ascii) { + else if (type == 8 && is_keystring) { const char* keystring = (const char*)keybuf; - derive_adx_key8(keystring, xor_start, xor_mult, xor_add); + cri_key8_derive(keystring, xor_start, xor_mult, xor_add); return 1; } else if (type == 9 && key_size == 0x08) { uint64_t keycode = get_u64be(keybuf); - derive_adx_key9(keycode, subkey, xor_start, xor_mult, xor_add); + cri_key9_derive(keycode, subkey, xor_start, xor_mult, xor_add); return 1; } else if (type == 9 && key_size == 0x08+0x02) { uint64_t file_keycode = get_u64be(keybuf+0x00); uint16_t file_subkey = get_u16be(keybuf+0x08); - derive_adx_key9(file_keycode, file_subkey, xor_start, xor_mult, xor_add); + cri_key9_derive(file_keycode, file_subkey, xor_start, xor_mult, xor_add); return 1; } } @@ -438,7 +432,7 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1 #ifdef ADX_BRUTEFORCE if (buf) { keycode = get_u64be(buf + key_id); - derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add); + cri_key9_derive(keycode, subkey, &key_xor, &key_mul, &key_add); } else #endif @@ -450,11 +444,11 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1 key_add = keys[key_id].add; } else if (type == 8 && keys[key_id].key8) { - derive_adx_key8(keys[key_id].key8, &key_xor, &key_mul, &key_add); + cri_key8_derive(keys[key_id].key8, &key_xor, &key_mul, &key_add); } else if (type == 9 && keys[key_id].key9) { uint64_t keycode = keys[key_id].key9; - derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add); + cri_key9_derive(keycode, subkey, &key_xor, &key_mul, &key_add); } else { VGM_LOG("ADX: incorrectly defined key id=%i\n", key_id); @@ -474,13 +468,13 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1 mul = keys[key_id].mult; add = keys[key_id].add; if (type == 8 && keys[key_id].key8) { - derive_adx_key8(keys[key_id].key8, &test_xor, &test_mul, &test_add); + cri_key8_derive(keys[key_id].key8, &test_xor, &test_mul, &test_add); VGM_LOG("key8: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (\"%s\")\n", xor,mul,add, test_xor,test_mul,test_add, xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key8); } else if (type == 9 && keys[key_id].key9) { - derive_adx_key9(keys[key_id].key9, subkey, &test_xor, &test_mul, &test_add); + cri_key9_derive(keys[key_id].key9, subkey, &test_xor, &test_mul, &test_add); VGM_LOG("key9: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (%"PRIu64")\n", xor,mul,add, test_xor,test_mul,test_add, xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key9); diff --git a/src/meta/adx_keys.h b/src/meta/adx_keys.h index 14d2fb0d..7ddb2d43 100644 --- a/src/meta/adx_keys.h +++ b/src/meta/adx_keys.h @@ -1,6 +1,8 @@ #ifndef _ADX_KEYS_H_ #define _ADX_KEYS_H_ +#include +#include typedef struct { uint16_t start, mult, add; /* XOR values derived from the actual key */ @@ -53,7 +55,7 @@ static const adxkey_info adxkey8_list[] = { {0x55b7,0x6191,0x5a77, "morio",0}, /* Amagami (PS2) [Enterbrain] */ - {0x5a17,0x509f,0x5bfd, "mituba",0}, /* also AHX key */ + {0x5a17,0x509f,0x5bfd, "mituba",0}, /* Yamasa Digi Portable: Matsuri no Tatsujin (PSP) [Yamasa] */ {0x4c01,0x549d,0x676f, "7fa0xB9tw3",0}, @@ -122,7 +124,7 @@ static const adxkey_info adxkey8_list[] = { {0x4c73,0x4d8d,0x5827, "URABOKU-penguin",0}, /* StormLover!! (PSP), StormLover Kai!! (PSP) [Vridge] */ - {0x5a11,0x67e5,0x6751, "HEXDPFMDKPQW",0}, /* unknown AHX key */ + {0x5a11,0x67e5,0x6751, "HEXDPFMDKPQW",0}, /* Sora no Otoshimono: DokiDoki Summer Vacation (PSP) [Kadokawa Shoten] */ {0x5e75,0x4a89,0x4c61, "funen-gomi",0}, @@ -131,25 +133,26 @@ static const adxkey_info adxkey8_list[] = { {0x64ab,0x5297,0x632f, "sonic",0}, /* Lucky Star: Net Idol Meister (PSP) [Vridge, Kadokawa Shoten] */ - {0x4d81,0x5243,0x58c7, "JJOLIFJLE",0}, /* unknown AHX key */ + /* Baka to Test to Shoukanjuu Portable (PSP) */ + {0x4d81,0x5243,0x58c7, "JJOLIFJLE",0}, /* Ishin Renka: Ryouma Gaiden (PSP) [Vridge] */ - {0x54d1,0x526d,0x5e8b, "LQAFJOIEJ",0}, /* unknown AHX key */ + {0x54d1,0x526d,0x5e8b, "LQAFJOIEJ",0}, /* Lucky Star: Ryouou Gakuen Outousai Portable (PSP) [Vridge] */ - {0x4d05,0x663b,0x6343, "IUNOIRU",0}, /* unknown AHX key */ + {0x4d05,0x663b,0x6343, "IUNOIRU",0}, /* Marriage Royale: Prism Story (PSP) [Vridge] */ - {0x40a9,0x46b1,0x62ad, "ROYMAR",0}, /* unknown AHX key */ + {0x40a9,0x46b1,0x62ad, "ROYMAR",0}, /* Nogizaka Haruka no Himitsu: Doujinshi Hajimemashita (PSP) [Vridge] */ - {0x4609,0x671f,0x4b65, "CLKMEOUHFLIE",0}, /* unknown AHX key */ + {0x4609,0x671f,0x4b65, "CLKMEOUHFLIE",0}, /* Slotter Mania P: Mach Go Go Go III (PSP) [Dorart] */ {0x41ef,0x463d,0x5507, "SGGK",0}, /* Nichijou: Uchuujin (PSP) [Vridge] */ - {0x4369,0x486d,0x5461, "LJLOUHIU787",0}, /* unknown AHX key */ + {0x4369,0x486d,0x5461, "LJLOUHIU787",0}, /* R-15 Portable (PSP) [Kadokawa Shoten] */ {0x6809,0x5fd5,0x5bb1, "R-15(Heart)Love",0}, @@ -158,7 +161,7 @@ static const adxkey_info adxkey8_list[] = { {0x5c33,0x4133,0x4ce7, "bi88a#fas",0}, /* StormLover Natsu Koi!! (PSP) [Vridge] */ - {0x4133,0x5a01,0x5723, "LIKDFJUIDJOQ",0}, /* unknown AHX key */ + {0x4133,0x5a01,0x5723, "LIKDFJUIDJOQ",0}, /* Shounen Onmyouji: Tsubasa yo Ima, Sora e Kaere (PS2) [Kadokawa Shoten] */ {0x55d9,0x46d3,0x5b01, "SONMYOJI",0}, @@ -272,129 +275,4 @@ static const adxkey_info adxkey9_list[] = { static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]); static const int adxkey9_list_count = sizeof(adxkey9_list) / sizeof(adxkey9_list[0]); - -/* preloaded list used to derive keystrings from ADX_Decoder, found in executables (see VGAudio for how to calculate) */ -static const uint16_t key8_primes[0x400] = { - 0x401B,0x4021,0x4025,0x402B,0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9, - 0x40B1,0x40B7,0x40BD,0x40DB,0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B, - 0x413F,0x4159,0x4165,0x416B,0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9, - 0x4205,0x4207,0x4219,0x421F,0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285, - 0x4289,0x4291,0x4297,0x429D,0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327, - 0x4333,0x4337,0x4339,0x434F,0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF, - 0x43E1,0x43E7,0x43EB,0x43ED,0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451, - 0x4453,0x4459,0x4465,0x446F,0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9, - 0x44FB,0x4505,0x4511,0x4513,0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3, - 0x45AD,0x45AF,0x45BB,0x45C7,0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633, - 0x4639,0x463D,0x4643,0x4645,0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9, - 0x46CF,0x46D3,0x46D5,0x46DF,0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D, - 0x4751,0x475D,0x476F,0x4771,0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1, - 0x47ED,0x47FB,0x4801,0x4807,0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D, - 0x4879,0x4897,0x489B,0x48A1,0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D, - 0x4945,0x4955,0x4963,0x4969,0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F, - 0x4A1D,0x4A23,0x4A39,0x4A41,0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5, - 0x4AD5,0x4ADB,0x4AED,0x4AEF,0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65, - 0x4B6D,0x4B77,0x4B85,0x4BAD,0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1, - 0x4BF7,0x4C01,0x4C07,0x4C0D,0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73, - 0x4C79,0x4C7F,0x4C8D,0x4C93,0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29, - 0x4D2F,0x4D33,0x4D41,0x4D51,0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF, - 0x4DD7,0x4DE1,0x4DED,0x4DF9,0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53, - 0x4E5F,0x4E67,0x4E79,0x4E85,0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7, - 0x4EE9,0x4EFB,0x4F07,0x4F09,0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85, - 0x4F87,0x4F91,0x4FA5,0x4FA9,0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029, - 0x5035,0x503F,0x5045,0x5047,0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED, - 0x50EF,0x50FB,0x5107,0x510B,0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F, - 0x5197,0x51A1,0x51A3,0x51A7,0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219, - 0x521B,0x521F,0x5227,0x5243,0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1, - 0x52BB,0x52C3,0x52C7,0x52C9,0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D, - 0x5363,0x5381,0x5383,0x5387,0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB, - 0x53FF,0x540D,0x5411,0x5413,0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D, - 0x5471,0x548F,0x5491,0x549D,0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B, - 0x5527,0x552B,0x5539,0x553D,0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7, - 0x55C9,0x55D9,0x55E7,0x55ED,0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B, - 0x564D,0x565D,0x565F,0x566B,0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3, - 0x56FF,0x5701,0x5705,0x5707,0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789, - 0x57A1,0x57A9,0x57AF,0x57B5,0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D, - 0x5855,0x585B,0x585D,0x586D,0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7, - 0x58D3,0x58D5,0x58DF,0x58F1,0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975, - 0x597B,0x5989,0x5999,0x599F,0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01, - 0x5A0D,0x5A11,0x5A13,0x5A17,0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D, - 0x5AA1,0x5AA3,0x5AA9,0x5ABB,0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D, - 0x5B49,0x5B4B,0x5B67,0x5B79,0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09, - 0x5C0B,0x5C0F,0x5C1D,0x5C29,0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87, - 0x5C89,0x5CA7,0x5CBD,0x5CBF,0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19, - 0x5D31,0x5D3D,0x5D41,0x5D47,0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9, - 0x5DC1,0x5DC7,0x5DD3,0x5DD7,0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D, - 0x5E31,0x5E39,0x5E45,0x5E49,0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9, - 0x5EFD,0x5F09,0x5F11,0x5F27,0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99, - 0x5FA1,0x5FB3,0x5FBD,0x5FC5,0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065, - 0x606B,0x6073,0x6079,0x6085,0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113, - 0x611B,0x612D,0x6139,0x614B,0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7, - 0x61C9,0x61CD,0x61E1,0x61F1,0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F, - 0x6265,0x6283,0x628D,0x6295,0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305, - 0x630D,0x6317,0x631D,0x632F,0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1, - 0x63C5,0x63D9,0x63E9,0x63EB,0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449, - 0x644F,0x645D,0x6467,0x6475,0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7, - 0x64F9,0x650B,0x6511,0x6521,0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F, - 0x6593,0x65A1,0x65A5,0x65AD,0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B, - 0x6641,0x6647,0x664D,0x665B,0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD, - 0x66D1,0x66E3,0x66EB,0x66F5,0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F, - 0x6779,0x6781,0x6785,0x6791,0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839, -}; - -static void derive_adx_key8(const char* key8, uint16_t* p_start, uint16_t* p_mult, uint16_t* p_add) { - size_t key_size; - uint16_t start = 0, mult = 0, add = 0; - int i; - - if (key8 == NULL || key8[0] == '\0') /* strlen >= 1 */ - goto end; - - /* calcs as found in exes, though there is some unrolling in the original code */ - key_size = strlen(key8); - start = key8_primes[0x100]; - mult = key8_primes[0x200]; - add = key8_primes[0x300]; - - for (i = 0; i < key_size; i++) { - char c = key8[i]; - start = key8_primes[start * key8_primes[c + 0x80] % 0x400]; - mult = key8_primes[mult * key8_primes[c + 0x80] % 0x400]; - add = key8_primes[add * key8_primes[c + 0x80] % 0x400]; - } - -end: - *p_start = start; - *p_mult = mult; - *p_add = add; -} - - -static void derive_adx_key9(uint64_t key9, uint16_t subkey, uint16_t* p_start, uint16_t* p_mult, uint16_t* p_add) { - uint16_t start = 0, mult = 0, add = 0; - - /* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */ - if (key9 == 0) - goto end; - - if (subkey) { - key9 = key9 * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) ); - } - - key9--; - start = (int)(((key9 >> 27) & 0x7fff)); - mult = (int)(((key9 >> 12) & 0x7ffc) | 1); - add = (int)(((key9 << 1 ) & 0x7fff) | 1); - - /* alt from ADX_Decoder, probably the same */ - //start = ((key9 >> 27) & 0x7FFF); - //mult = ((key9 >> 12) & 0x7FFC) | 1; - //add = ((key9 << 1 ) & 0x7FFE) | 1; - //mult |= add << 16; - -end: - *p_start = start; - *p_mult = mult; - *p_add = add; -} - #endif/*_ADX_KEYS_H_*/ diff --git a/src/meta/ahx.c b/src/meta/ahx.c index 6ea24780..e5c98fe7 100644 --- a/src/meta/ahx.c +++ b/src/meta/ahx.c @@ -1,10 +1,13 @@ #include "meta.h" #include "../coding/coding.h" -#include "../util.h" -#if 0 -#include "adx_keys.h" +#include "ahx_keys.h" +#include "../util/cri_keys.h" + +#ifdef VGM_USE_MPEG +static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey); #endif + /* AHX - CRI voice format */ VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; @@ -23,7 +26,7 @@ VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) { read_u32be(start_offset - 0x04,sf) != 0x29435249) /* ")CRI" */ goto fail; - /* types: 0x10 = AHX for DC with bigger frames, 0x11 = AHX, 0x0N = ADX */ + /* types: 0x10 = AHX for DC with fixed MPEG frame bits (bigger frames), 0x11 = standard AHX, 0x0N = ADX */ type = read_u8(0x04,sf); if (type != 0x10 && type != 0x11) goto fail; @@ -52,40 +55,13 @@ VGMSTREAM* init_vgmstream_ahx(STREAMFILE* sf) { { #ifdef VGM_USE_MPEG mpeg_custom_config cfg = {0}; + crikey_t* crikey = &cfg.crikey; - cfg.encryption = read_u8(0x13,sf); /* 0x08 = keyword encryption */ - cfg.cri_type = type; + cfg.encryption = read_u8(0x13,sf); /* only type 0x08 is known */ + crikey->type = cfg.encryption; if (cfg.encryption) { - uint8_t keybuf[0x10+1] = {0}; /* approximate max for keystrings, +1 extra null for keystrings */ - size_t key_size; - - key_size = read_key_file(keybuf, sizeof(keybuf), sf); - if (key_size > 0) { -#if 0 - int i, is_ascii; - is_ascii = 1; - for (i = 0; i < key_size; i++) { - if (keybuf[i] < 0x20 || keybuf[i] > 0x7f) { - is_ascii = 0; - break; - } - } -#endif - if (key_size == 0x06 /*&& !is_ascii*/) { - cfg.cri_key1 = get_u16be(keybuf + 0x00); - cfg.cri_key2 = get_u16be(keybuf + 0x02); - cfg.cri_key3 = get_u16be(keybuf + 0x04); - } -#if 0 - else if (is_ascii) { - const char* keystring = (const char*)keybuf; - - derive_adx_key8(keystring, &cfg.cri_key1, &cfg.cri_key2, &cfg.cri_key3); - VGM_LOG("ok: %x, %x, %x\n", cfg.cri_key1, cfg.cri_key2, cfg.cri_key3 ); - } -#endif - } + find_ahx_key(sf, start_offset, crikey); } vgmstream->layout_type = layout_none; @@ -104,3 +80,80 @@ fail: close_vgmstream(vgmstream); return NULL; } + +#ifdef VGM_USE_MPEG +static int find_ahx_keyfile(STREAMFILE* sf, crikey_t* crikey) { + uint8_t keybuf[0x10+1] = {0}; /* approximate max for keystrings, +1 extra null for keystrings */ + size_t key_size; + int is_keystring = 0; + + key_size = read_key_file(keybuf, sizeof(keybuf) - 1, sf); + if (key_size <= 0) + goto fail; + + + if (crikey->type == 8) { + is_keystring = cri_key8_valid_keystring(keybuf, key_size); + } + + if (key_size == 0x06 && !is_keystring) { + crikey->key1 = get_u16be(keybuf + 0x00); + crikey->key2 = get_u16be(keybuf + 0x02); + crikey->key3 = get_u16be(keybuf + 0x04); + } + else if (crikey->type == 8 && is_keystring) { + const char* keystring = (const char*)keybuf; + cri_key8_derive(keystring, &crikey->key1, &crikey->key2, &crikey->key3); + } + else { + goto fail; + } + + return 1; +fail: + return 0; +} + +static int find_ahx_keylist(STREAMFILE* sf, off_t offset, crikey_t* crikey) { + int i; + int keycount = ahxkey8_list_count; + const ahxkey_info* keys = ahxkey8_list; + + + for (i = 0; i < keycount; i++) { + if (crikey->type == 0x08) { + cri_key8_derive(keys[i].key8, &crikey->key1, &crikey->key2, &crikey->key3); + //;VGM_LOG("AHX: testing %s [%04x %04x %04x]\n", keys[i].key8, crikey->key1, crikey->key2, crikey->key3); + } + else { + continue; + } + + if (test_ahx_key(sf, offset, crikey)) { + //;VGM_LOG("AHX key found\n"); + return 1; + } + } + + return 0; +} + +static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) { + int ok; + + ok = find_ahx_keyfile(sf, crikey); + if (ok) + return 1; + + ok = find_ahx_keylist(sf, offset, crikey); + if (ok) + return 1; + + + crikey->key1 = 0; + crikey->key2 = 0; + crikey->key3 = 0; + vgm_logi("AHX: decryption key not found\n"); + return 0; +} +#endif diff --git a/src/meta/ahx_keys.h b/src/meta/ahx_keys.h new file mode 100644 index 00000000..aa2316fe --- /dev/null +++ b/src/meta/ahx_keys.h @@ -0,0 +1,52 @@ +#ifndef _AHX_KEYS_H_ +#define _AHX_KEYS_H_ + +#include +#include + +typedef struct { + const char* key8; /* keystring used by type 8 encryption */ + uint64_t key9; /* reserved (not seen) */ +} ahxkey_info; + +/** + * List of known keys, from exes. Generally same as ADX keys as CRI's key init seems shared. + */ +static const ahxkey_info ahxkey8_list[] = { + + /* Amagami (PS2) [Enterbrain] */ + {"mituba",0}, + + /* StormLover!! (PSP), StormLover Kai!! (PSP) [Vridge] */ + {"HEXDPFMDKPQW",0}, + + /* Lucky Star: Net Idol Meister (PSP) [Vridge, Kadokawa Shoten] */ + /* Baka to Test to Shoukanjuu Portable (PSP) */ + {"JJOLIFJLE",0}, + + /* Ishin Renka: Ryouma Gaiden (PSP) [Vridge] */ + {"LQAFJOIEJ",0}, + + /* Lucky Star: Ryouou Gakuen Outousai Portable (PSP) [Vridge] */ + {"IUNOIRU",0}, + + /* Marriage Royale: Prism Story (PSP) [Vridge] */ + {"ROYMAR",0}, + + /* Nogizaka Haruka no Himitsu: Doujinshi Hajimemashita (PSP) [Vridge] */ + {"CLKMEOUHFLIE",0}, + + /* Nichijou: Uchuujin (PSP) [Vridge] */ + {"LJLOUHIU787",0}, + + /* StormLover Natsu Koi!! (PSP) [Vridge] */ + {"LIKDFJUIDJOQ",0}, + + /* Corpse Party: Book of Shadows (PSP) */ + {"\x83\x76\x83\x89\x83\x60\x83\x69Lovers_Day",0}, // "プラチナLovers_Day" in SHIFT-JIS + +}; + +static const int ahxkey8_list_count = sizeof(ahxkey8_list) / sizeof(ahxkey8_list[0]); + +#endif /* _AHX_KEYS_H_ */ diff --git a/src/meta/bfstm.c b/src/meta/bfstm.c index 229cb2e8..86e8dd1c 100644 --- a/src/meta/bfstm.c +++ b/src/meta/bfstm.c @@ -28,10 +28,10 @@ VGMSTREAM* init_vgmstream_bfstm(STREAMFILE* sf) { /* checks */ - if (!check_extensions(sf,"bfstm")) - goto fail; if (!is_id32be(0x00,sf, "FSTM")) goto fail; + if (!check_extensions(sf,"bfstm")) + goto fail; /* 0x06(2): header size (0x40) * 0x08: version (0x00000400) * 0x0c: file size */ diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 896ce0f6..13476ba7 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -54,7 +54,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { data_offset = read_u32(0x10,sf); data_size = read_u32(0x14,sf); /* when sblk_offset >= 0x20: */ - /* 0x18: ZLSD small footer, rare [Yakuza 6's Puyo Puyo (PS4)] */ + /* 0x18: ZLSD small footer, rare in earlier versions [Yakuza 6's Puyo Puyo (PS4)] */ /* 0x1c: ZLSD size */ /* SE banks, also used for music. Most table fields seems reserved/defaults and @@ -66,14 +66,17 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { if (read_u32(sblk_offset+0x00,sf) != get_id32be("klBS")) /* SBlk = SFX block */ goto fail; sblk_version = read_u32(sblk_offset+0x04,sf); - /* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4) + /* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4, 0x05=PS5) * - 04: non-fixed bank? * - 100: has names - * - 200: has user data - */ - /* 0x0c: block id */ - /* 0x10: block number */ - /* 0x11: padding */ + * - 200: has user data */ + /* version < v0x1a: + * - 0x0c: block id + * - 0x10: block number + * - 0x11: padding + * version >= v0x1a: + * - 0x0c: hash (0x10) + * - 0x1c: filename (0x100?) */ //;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, sblk_version %x\n", sblk_offset, data_offset, sblk_version); { @@ -141,6 +144,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { table2_suboffset = 0x00; break; + case 0x1a: /* Demon's Souls (PS5) */ + default: vgm_logi("BNK: unknown version %x (report)\n", sblk_version); goto fail; diff --git a/src/meta/brstm.c b/src/meta/brstm.c index 80f81195..98d3c895 100644 --- a/src/meta/brstm.c +++ b/src/meta/brstm.c @@ -1,168 +1,123 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; +VGMSTREAM* init_vgmstream_brstm(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, head_size, head_offset, info_offset; + int channels, loop_flag, codec, version; - coding_t coding_type; - - off_t head_offset; - int codec_number; - int channel_count; - int loop_flag; - /* Certain Super Paper Mario tracks have a 44.1KHz sample rate in the - * header, but they should be played at 22.05KHz. We will make this - * correction if we see a file with a .brstmspm extension. */ - int spm_flag = 0; - /* Trauma Center Second Opinion has an odd, semi-corrupt header */ - int atlus_shrunken_head = 0; - - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("brstm",filename_extension(filename))) { - if (strcasecmp("brstmspm",filename_extension(filename))) goto fail; - else spm_flag = 1; - } - - /* check header */ - if ((uint32_t)read_32bitBE(0,streamFile)!=0x5253544D) /* "RSTM" */ + /* checks */ + if (!is_id32be(0x00,sf, "RSTM")) goto fail; - if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0100) - { - if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0001) - goto fail; - else - atlus_shrunken_head = 1; + + /* .brstm: standard + * .brstmspm: fake hack */ + if (!check_extensions(sf,"brstm,brstmspm")) + goto fail; + + if (read_u16be(0x04, sf) != 0xFEFF) /* BE BOM for all Wii games */ + goto fail; + + version = read_u16be(0x06, sf); /* 0.1 (Trauma Center), 1.0 (all others) */ + if (read_u32be(0x08, sf) != get_streamfile_size(sf)) + goto fail; + + head_size = read_u16be(0x0c, sf); + /* 0x0e: chunk count */ + + if (version == 0x0001) { + /* smaller simpler header found in some (beta?) files */ + head_offset = head_size; + info_offset = head_offset + 0x08; + } + else { + /* chunk table: offset + sixe x N chunks */ + head_offset = read_u32be(0x10,sf); /* in practice same as head_size */ + info_offset = head_offset + 0x20; + /* HEAD starts with a sub-chunk table (info, )*/ } - /* get head offset, check */ - head_offset = read_32bitBE(0x10,streamFile); - if (atlus_shrunken_head) - { - /* the HEAD chunk is where we would expect to find the offset of that - * chunk... */ + if (!is_id32be(head_offset,sf, "HEAD")) + goto fail; + /* 0x04: chunk size (set to 0x8 in v0.1) */ - if ((uint32_t)head_offset!=0x48454144 || read_32bitBE(0x14,streamFile) != 8) - goto fail; + codec = read_u8(info_offset+0x00,sf); + loop_flag = read_u8(info_offset+0x01,sf); + channels = read_u8(info_offset+0x02,sf); - head_offset = -8; /* most of the normal Nintendo RSTM offsets work - with this assumption */ - } - else - { - if ((uint32_t)read_32bitBE(head_offset,streamFile)!=0x48454144) /* "HEAD" */ - goto fail; - } + start_offset = read_u32be(info_offset+0x10,sf); /* inside DATA chunk */ - /* check type details */ - codec_number = read_8bit(head_offset+0x20,streamFile); - loop_flag = read_8bit(head_offset+0x21,streamFile); - channel_count = read_8bit(head_offset+0x22,streamFile); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; - switch (codec_number) { + vgmstream->meta_type = meta_RSTM; + + vgmstream->sample_rate = read_u16be(info_offset+0x04,sf); + vgmstream->loop_start_sample = read_s32be(info_offset+0x08,sf); + vgmstream->num_samples = read_s32be(info_offset+0x0c,sf); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->interleave_block_size = read_u32be(info_offset+0x18,sf); + vgmstream->interleave_last_block_size = read_u32be(info_offset+0x28,sf); + + /* many Super Paper Mario tracks have a 44.1KHz sample rate in the header, + * but they should be played at 22.05KHz; detect with fake extension */ + if (vgmstream->sample_rate == 44100 && check_extensions(sf, "brstmspm")) //TODO remove + vgmstream->sample_rate = 22050; + + vgmstream->layout_type = (channels == 1) ? layout_none : layout_interleave; + switch(codec) { case 0: - coding_type = coding_PCM8; + vgmstream->coding_type = coding_PCM8; break; case 1: - coding_type = coding_PCM16BE; + vgmstream->coding_type = coding_PCM16BE; break; case 2: - coding_type = coding_NGC_DSP; + vgmstream->coding_type = coding_NGC_DSP; break; default: goto fail; } - if (channel_count < 1) goto fail; - - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(head_offset+0x2c,streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset+0x24,streamFile); - /* channels and loop flag are set by allocate_vgmstream */ - vgmstream->loop_start_sample = read_32bitBE(head_offset+0x28,streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->coding_type = coding_type; - vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave; - vgmstream->meta_type = meta_RSTM; - if (atlus_shrunken_head) - vgmstream->meta_type = meta_RSTM_shrunken; - - if (spm_flag&& vgmstream->sample_rate == 44100) { - vgmstream->meta_type = meta_RSTM_SPM; - vgmstream->sample_rate = 22050; - } - - vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile); - vgmstream->interleave_last_block_size = read_32bitBE(head_offset+0x48,streamFile); - + // TODO read hist if (vgmstream->coding_type == coding_NGC_DSP) { off_t coef_offset; - off_t head_part3_offset; off_t adpcm_header_offset; - int i,j; - int coef_spacing; + int i, ch; - if (atlus_shrunken_head) - { - coef_offset = 0x50; - coef_spacing = 0x30; - - for (j = 0; j < vgmstream->channels; j++) { - for (i = 0; i < 16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(head_offset + coef_offset + j * coef_spacing + i * 2,streamFile); - } - } + if (version == 0x0001) { + /* standard */ + VGM_LOG("ss=%x\n", head_offset + 0x38); + dsp_read_coefs_be(vgmstream, sf, head_offset + 0x38, 0x30); } - else - { - head_part3_offset = read_32bitBE(head_offset + 0x1c, streamFile); + else { + uint32_t head_part3_offset = read_32bitBE(head_offset + 0x1c, sf); - for (j = 0; j < vgmstream->channels; j++) { + /* read from offset table */ + for (ch = 0; ch < vgmstream->channels; ch++) { adpcm_header_offset = head_offset + 0x08 + head_part3_offset + 0x04 /* skip over HEAD part 3 */ - + j * 0x08 /* skip to channel's ADPCM offset table */ + + ch * 0x08 /* skip to channel's ADPCM offset table */ + 0x04; /* ADPCM header offset field */ coef_offset = head_offset + 0x08 - + read_32bitBE(adpcm_header_offset, streamFile) + + read_u32be(adpcm_header_offset, sf) + 0x08; /* coeffs field */ for (i = 0; i < 16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset + i * 2, streamFile); + vgmstream->ch[ch].adpcm_coef[i] = read_s16be(coef_offset + i * 2, sf); } } } } - start_offset = read_32bitBE(head_offset+0x30,streamFile); - - /* open the file for reading by each channel */ - { - int i; - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset= - start_offset + i*vgmstream->interleave_block_size; - } - } - + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/riff.c b/src/meta/riff.c index 213d19ff..f418c1ba 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -95,7 +95,7 @@ typedef struct { int is_at9; } riff_fmt_chunk; -static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk* fmt, int mwv) { +static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk* fmt) { uint32_t (*read_u32)(off_t,STREAMFILE*) = big_endian ? read_u32be : read_u32le; uint16_t (*read_u16)(off_t,STREAMFILE*) = big_endian ? read_u16be : read_u16le; @@ -227,7 +227,6 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk break; case 0x0555: /* Level-5 0x555 ADPCM (unofficial) */ - if (!mwv) goto fail; fmt->coding_type = coding_L5_555; fmt->interleave = 0x12; break; @@ -337,9 +336,8 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0; - int mwv = 0; - off_t mwv_pflt_offset = -1; - off_t mwv_ctrl_offset = -1; + off_t mwv_pflt_offset = 0; + off_t mwv_ctrl_offset = 0; int ignore_riff_size = 0; @@ -347,6 +345,13 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { if (!is_id32be(0x00,sf,"RIFF")) goto fail; + riff_size = read_u32le(0x04,sf); + + if (!is_id32be(0x08,sf, "WAVE")) + goto fail; + + file_size = get_streamfile_size(sf); + /* .lwav: to avoid hijacking .wav * .xwav: fake for Xbox games (not needed anymore) * .da: The Great Battle VI (PS1) @@ -379,24 +384,12 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { * .ogg/logg: Luftrausers (Vita)[ATRAC9] * .p1d: Farming Simulator 15 (Vita)[ATRAC9] * .xms: Ty the Tasmanian Tiger (Xbox) + * .mus: Burnout Legends/Dominator (PSP) */ - if ( check_extensions(sf, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms") ) { - ; - } - else if ( check_extensions(sf, "mwv") ) { - mwv = 1; - } - else { + if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus")) { goto fail; } - riff_size = read_u32le(0x04,sf); - - if (!is_id32be(0x08,sf, "WAVE")) - goto fail; - - file_size = get_streamfile_size(sf); - /* some games have wonky sizes, selectively fix to catch bad rips and new mutations */ if (file_size != riff_size + 0x08) { uint16_t codec = read_u16le(0x14,sf); @@ -425,7 +418,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { else if (codec == 0xFFFE && riff_size + 0x08 + 0x18 == file_size) riff_size += 0x18; /* [F1 2011 (Vita)] (adds a "pada" chunk but RIFF size wasn't updated) */ - else if (mwv) { + else if (codec == 0x0555) { int channels = read_u16le(0x16, sf); /* [Dragon Quest VIII (PS2), Rogue Galaxy (PS2)] */ size_t file_size_fixed = riff_size + 0x08 + 0x04 * (channels - 1); @@ -486,7 +479,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { if (FormatChunkFound) goto fail; /* only one per file */ FormatChunkFound = 1; - if (!read_fmt(0, sf, current_chunk, &fmt, mwv)) + if (!read_fmt(0, sf, current_chunk, &fmt)) goto fail; /* some Dreamcast/Naomi games again [Headhunter (DC), Bomber hehhe (DC), Rayman 2 (DC)] */ @@ -574,12 +567,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { goto fail; /* parsed elsewhere */ case 0x70666c74: /* "pflt" (.mwv extension) */ - if (!mwv) break; /* ignore if not in an mwv */ mwv_pflt_offset = current_chunk; /* predictor filters */ break; case 0x6374726c: /* "ctrl" (.mwv extension) */ - if (!mwv) break; loop_flag = read_32bitLE(current_chunk+0x08, sf); mwv_ctrl_offset = current_chunk; break; @@ -725,7 +716,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { break; case coding_L5_555: - if (!mwv) goto fail; vgmstream->num_samples = data_size / 0x12 / fmt.channels * 32; /* coefs */ @@ -735,7 +725,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { int filter_count = read_32bitLE(mwv_pflt_offset+0x0c, sf); if (filter_count > 0x20) goto fail; - if (mwv_pflt_offset == -1 || + if (!mwv_pflt_offset || read_32bitLE(mwv_pflt_offset+0x08, sf) != filter_order || read_32bitLE(mwv_pflt_offset+0x04, sf) < 8 + filter_count * 4 * filter_order) goto fail; @@ -908,9 +898,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { vgmstream->loop_end_sample = loop_end_wsmp; vgmstream->meta_type = meta_RIFF_WAVE_wsmp; } - else if (mwv && mwv_ctrl_offset != -1) { - vgmstream->loop_start_sample = read_32bitLE(mwv_ctrl_offset+12, sf); + else if (fmt.coding_type == coding_L5_555 && mwv_ctrl_offset) { + vgmstream->loop_start_sample = read_s32le(mwv_ctrl_offset + 0x0c, sf); vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->meta_type = meta_RIFF_WAVE_MWV; } else if (loop_start_cue != -1) { vgmstream->loop_start_sample = loop_start_cue; @@ -927,9 +918,6 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { } } } - if (mwv) { - vgmstream->meta_type = meta_RIFF_WAVE_MWV; - } if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; @@ -1105,7 +1093,7 @@ VGMSTREAM* init_vgmstream_rifx(STREAMFILE* sf) { if (FormatChunkFound) goto fail; FormatChunkFound = 1; - if (!read_fmt(1, sf, current_chunk, &fmt, 0)) + if (!read_fmt(1, sf, current_chunk, &fmt)) goto fail; break; diff --git a/src/meta/rwsd.c b/src/meta/rwsd.c index f4a0a248..a8078261 100644 --- a/src/meta/rwsd.c +++ b/src/meta/rwsd.c @@ -106,6 +106,12 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) { stream_size = read_32bitBE(wave_offset + 0x50,sf); + /* this meta is a hack as WSD is just note info, and data offsets are elsewhere in the brsar, + * while this assumes whatever data follows RWSD must belong to it (common but fails in Wii Sports), + * detect data excess and reject (probably should use brawlbox's info offsets) */ + if (stream_size * channels + 0x10000 < get_streamfile_size(sf) - start_offset) + goto fail; + /* open the file for reading by each channel */ { int i; diff --git a/src/coding/mpeg_bitreader.h b/src/util/bitstream_msb.h similarity index 57% rename from src/coding/mpeg_bitreader.h rename to src/util/bitstream_msb.h index 345f8aba..77fd0f07 100644 --- a/src/coding/mpeg_bitreader.h +++ b/src/util/bitstream_msb.h @@ -1,29 +1,70 @@ -#ifndef _MPEG_BITREADER_H -#define _MPEG_BITREADER_H +#ifndef _BITSTREAM_MSB_H +#define _BITSTREAM_MSB_H + +#include /* Simple bitreader for MPEG/standard bit format. - * Kept in .h since it's slightly faster (compiler can optimize statics better) */ - + * Kept in .h since it's slightly faster (compiler can optimize better) */ typedef struct { uint8_t* buf; /* buffer to read/write */ - size_t bufsize; /* max size of the buffer */ - uint32_t b_off; /* current offset in bits inside the buffer */ + size_t bufsize; /* max size */ + size_t b_max; /* max size in bits */ + uint32_t b_off; /* current offset in bits inside buffer */ } bitstream_t; -/* convenience util */ -static void init_bitstream(bitstream_t* b, uint8_t* buf, size_t bufsize) { - b->buf = buf; - b->bufsize = bufsize; - b->b_off = 0; + +static inline void bm_setup(bitstream_t* bs, uint8_t* buf, size_t bufsize) { + bs->buf = buf; + bs->bufsize = bufsize; + bs->b_max = bufsize * 8; + bs->b_off = 0; } -/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */ -static int rb_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) { +static inline int bm_set(bitstream_t* bs, uint32_t b_off) { + if (bs->b_off > bs->b_max) + goto fail; + + bs->b_off = b_off; + + return 1; +fail: + return 0; +} + +static inline int bm_fill(bitstream_t* bs, uint32_t bytes) { + if (bs->b_off > bs->b_max) + goto fail; + + bs->bufsize += bytes; + bs->b_max += bytes * 8; + + return 1; +fail: + return 0; +} + +static inline int bm_skip(bitstream_t* bs, uint32_t bits) { + if (bs->b_off + bits > bs->b_max) + goto fail; + + bs->b_off += bits; + + return 1; +fail: + return 0; +} + +static inline int bm_pos(bitstream_t* bs) { + return bs->b_off; +} + +/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSB). */ +static inline int bm_get(bitstream_t* ib, uint32_t bits, uint32_t* value) { uint32_t shift, pos, val; int i, bit_buf, bit_val; - if (bits > 32 || ib->b_off + bits > ib->bufsize * 8) + if (bits > 32 || ib->b_off + bits > ib->b_max) goto fail; pos = ib->b_off / 8; /* byte offset */ @@ -48,18 +89,17 @@ static int rb_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) { ib->b_off += bits; return 1; fail: - VGM_LOG("BITREADER: read fail\n"); + //VGM_LOG("BITREADER: read fail\n"); *value = 0; return 0; } -#ifndef BITSTREAM_READ_ONLY -/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */ -static int wb_bits(bitstream_t* ob, uint32_t bits, uint32_t value) { +/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSB). */ +static inline int bm_put(bitstream_t* ob, uint32_t bits, uint32_t value) { uint32_t shift, pos; int i, bit_val, bit_buf; - if (bits > 32 || ob->b_off + bits > ob->bufsize * 8) + if (bits > 32 || ob->b_off + bits > ob->b_max) goto fail; pos = ob->b_off / 8; /* byte offset */ @@ -86,6 +126,5 @@ static int wb_bits(bitstream_t* ob, uint32_t bits, uint32_t value) { fail: return 0; } -#endif #endif diff --git a/src/util/cri_keys.c b/src/util/cri_keys.c new file mode 100644 index 00000000..dbce900f --- /dev/null +++ b/src/util/cri_keys.c @@ -0,0 +1,139 @@ +#include "cri_keys.h" +#include + + +/* preloaded list used to derive keystrings from ADX_Decoder, found in executables (see VGAudio for how to calculate) */ +static const uint16_t key8_primes[0x400] = { + 0x401B,0x4021,0x4025,0x402B,0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9, + 0x40B1,0x40B7,0x40BD,0x40DB,0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B, + 0x413F,0x4159,0x4165,0x416B,0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9, + 0x4205,0x4207,0x4219,0x421F,0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285, + 0x4289,0x4291,0x4297,0x429D,0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327, + 0x4333,0x4337,0x4339,0x434F,0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF, + 0x43E1,0x43E7,0x43EB,0x43ED,0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451, + 0x4453,0x4459,0x4465,0x446F,0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9, + 0x44FB,0x4505,0x4511,0x4513,0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3, + 0x45AD,0x45AF,0x45BB,0x45C7,0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633, + 0x4639,0x463D,0x4643,0x4645,0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9, + 0x46CF,0x46D3,0x46D5,0x46DF,0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D, + 0x4751,0x475D,0x476F,0x4771,0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1, + 0x47ED,0x47FB,0x4801,0x4807,0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D, + 0x4879,0x4897,0x489B,0x48A1,0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D, + 0x4945,0x4955,0x4963,0x4969,0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F, + 0x4A1D,0x4A23,0x4A39,0x4A41,0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5, + 0x4AD5,0x4ADB,0x4AED,0x4AEF,0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65, + 0x4B6D,0x4B77,0x4B85,0x4BAD,0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1, + 0x4BF7,0x4C01,0x4C07,0x4C0D,0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73, + 0x4C79,0x4C7F,0x4C8D,0x4C93,0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29, + 0x4D2F,0x4D33,0x4D41,0x4D51,0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF, + 0x4DD7,0x4DE1,0x4DED,0x4DF9,0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53, + 0x4E5F,0x4E67,0x4E79,0x4E85,0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7, + 0x4EE9,0x4EFB,0x4F07,0x4F09,0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85, + 0x4F87,0x4F91,0x4FA5,0x4FA9,0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029, + 0x5035,0x503F,0x5045,0x5047,0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED, + 0x50EF,0x50FB,0x5107,0x510B,0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F, + 0x5197,0x51A1,0x51A3,0x51A7,0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219, + 0x521B,0x521F,0x5227,0x5243,0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1, + 0x52BB,0x52C3,0x52C7,0x52C9,0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D, + 0x5363,0x5381,0x5383,0x5387,0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB, + 0x53FF,0x540D,0x5411,0x5413,0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D, + 0x5471,0x548F,0x5491,0x549D,0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B, + 0x5527,0x552B,0x5539,0x553D,0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7, + 0x55C9,0x55D9,0x55E7,0x55ED,0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B, + 0x564D,0x565D,0x565F,0x566B,0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3, + 0x56FF,0x5701,0x5705,0x5707,0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789, + 0x57A1,0x57A9,0x57AF,0x57B5,0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D, + 0x5855,0x585B,0x585D,0x586D,0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7, + 0x58D3,0x58D5,0x58DF,0x58F1,0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975, + 0x597B,0x5989,0x5999,0x599F,0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01, + 0x5A0D,0x5A11,0x5A13,0x5A17,0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D, + 0x5AA1,0x5AA3,0x5AA9,0x5ABB,0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D, + 0x5B49,0x5B4B,0x5B67,0x5B79,0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09, + 0x5C0B,0x5C0F,0x5C1D,0x5C29,0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87, + 0x5C89,0x5CA7,0x5CBD,0x5CBF,0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19, + 0x5D31,0x5D3D,0x5D41,0x5D47,0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9, + 0x5DC1,0x5DC7,0x5DD3,0x5DD7,0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D, + 0x5E31,0x5E39,0x5E45,0x5E49,0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9, + 0x5EFD,0x5F09,0x5F11,0x5F27,0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99, + 0x5FA1,0x5FB3,0x5FBD,0x5FC5,0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065, + 0x606B,0x6073,0x6079,0x6085,0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113, + 0x611B,0x612D,0x6139,0x614B,0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7, + 0x61C9,0x61CD,0x61E1,0x61F1,0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F, + 0x6265,0x6283,0x628D,0x6295,0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305, + 0x630D,0x6317,0x631D,0x632F,0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1, + 0x63C5,0x63D9,0x63E9,0x63EB,0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449, + 0x644F,0x645D,0x6467,0x6475,0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7, + 0x64F9,0x650B,0x6511,0x6521,0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F, + 0x6593,0x65A1,0x65A5,0x65AD,0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B, + 0x6641,0x6647,0x664D,0x665B,0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD, + 0x66D1,0x66E3,0x66EB,0x66F5,0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F, + 0x6779,0x6781,0x6785,0x6791,0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839, +}; + +void cri_key8_derive(const char* key8, uint16_t* p_key1, uint16_t* p_key2, uint16_t* p_key3) { + size_t key_size; + uint16_t key1 = 0, key2 = 0, key3 = 0; + int i; + + if (key8 == NULL || key8[0] == '\0') /* strlen >= 1 */ + goto end; + + /* calcs as found in exes, though there is some unrolling in the original code */ + key_size = strlen(key8); + key1 = key8_primes[0x100]; + key2 = key8_primes[0x200]; + key3 = key8_primes[0x300]; + + for (i = 0; i < key_size; i++) { + char c = key8[i]; + key1 = key8_primes[key1 * key8_primes[c + 0x80] % 0x400]; + key2 = key8_primes[key2 * key8_primes[c + 0x80] % 0x400]; + key3 = key8_primes[key3 * key8_primes[c + 0x80] % 0x400]; + } + +end: + *p_key1 = key1; + *p_key2 = key2; + *p_key3 = key3; +} + + +void cri_key9_derive(uint64_t key9, uint16_t subkey, uint16_t* p_key1, uint16_t* p_key2, uint16_t* p_key3) { + uint16_t key1 = 0, key2 = 0, key3 = 0; + + /* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */ + if (key9 == 0) + goto end; + + if (subkey) { + key9 = key9 * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) ); + } + + key9--; + key1 = (int)(((key9 >> 27) & 0x7fff)); + key2 = (int)(((key9 >> 12) & 0x7ffc) | 1); + key3 = (int)(((key9 << 1 ) & 0x7fff) | 1); + + /* alt from ADX_Decoder, probably the same */ + //key1 = ((key9 >> 27) & 0x7FFF); + //key2 = ((key9 >> 12) & 0x7FFC) | 1; + //key3 = ((key9 << 1 ) & 0x7FFE) | 1; + //key2 |= key3 << 16; + +end: + *p_key1 = key1; + *p_key2 = key2; + *p_key3 = key3; +} + +int cri_key8_valid_keystring(uint8_t* buf, int buf_size) { + int i; + + for (i = 0; i < buf_size; i++) { + if (buf[i] < 0x20 || buf[i] > 0x8f) { /* allow 0x8x for (uncommon) cases of SHIFT-JIS */ + return 0; + } + } + + return 1; +} diff --git a/src/util/cri_keys.h b/src/util/cri_keys.h new file mode 100644 index 00000000..7748b9d1 --- /dev/null +++ b/src/util/cri_keys.h @@ -0,0 +1,13 @@ +#ifndef _CRI_KEYS_H_ +#define _CRI_KEYS_H_ + +#include + +/* common CRI key helpers */ + +void cri_key8_derive(const char* key8, uint16_t* p_key1, uint16_t* p_key2, uint16_t* p_key3); +void cri_key9_derive(uint64_t key9, uint16_t subkey, uint16_t* p_key1, uint16_t* p_key2, uint16_t* p_key3); + +int cri_key8_valid_keystring(uint8_t* buf, int buf_size); + +#endif /* _CRI_KEYS_H_ */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 3121e0a4..e0675412 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -38,7 +38,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_gcsw, init_vgmstream_ads, init_vgmstream_nps, - init_vgmstream_rwsd, init_vgmstream_xa, init_vgmstream_rxws, init_vgmstream_ngc_dsp_stm, @@ -542,10 +541,10 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ - init_vgmstream_dtk, + init_vgmstream_dtk, /* semi-raw GC streamed files */ init_vgmstream_mpeg, /* semi-raw MP3 */ - init_vgmstream_encrypted, /* encrypted stuff */ init_vgmstream_btsnd, /* semi-headerless */ + init_vgmstream_encrypted, /* encrypted stuff */ init_vgmstream_raw_int, /* .int raw PCM */ init_vgmstream_ps_headerless, /* tries to detect a bunch of PS-ADPCM formats */ init_vgmstream_raw_snds, /* .snds raw SNDS IMA */ @@ -560,6 +559,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */ init_vgmstream_baf_badrip, /* crap, to be removed */ init_vgmstream_rxws_badrip, /* crap, to be removed */ + init_vgmstream_rwsd, /* crap, to be removed */ #ifdef VGM_USE_FFMPEG init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */ #endif diff --git a/src/vgmstream.h b/src/vgmstream.h index 54d93aaf..4febc140 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -325,9 +325,7 @@ typedef enum { meta_RWAV, /* contents of RWAR */ meta_CWAV, /* contents of CWAR */ meta_FWAV, /* contents of FWAR */ - meta_RSTM_SPM, /* RSTM with 44->22khz hack */ meta_THP, /* THP movie files */ - meta_RSTM_shrunken, /* Atlus' mutant shortened RSTM */ meta_SWAV, meta_NDS_RRDS, /* Ridge Racer DS */ meta_WII_BNS, /* Wii BNS Banner Sound (similar to RSTM) */