From a7acf244ae14a9dc2b44d94dab9bc6a4307d72ce Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:24:25 +0200 Subject: [PATCH 01/12] Fix HCA crash bug when testing keys --- src/meta/hca.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/meta/hca.c b/src/meta/hca.c index 7417c225..0dd76970 100644 --- a/src/meta/hca.c +++ b/src/meta/hca.c @@ -94,7 +94,7 @@ fail: /* Tries to find the decryption key from a list. Simply decodes a few frames and checks if there aren't too many * clipped samples, as it's common for invalid keys (though possible with valid keys in poorly mastered files). */ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffer, int header_size, unsigned int * out_key1, unsigned int * out_key2) { - sample testbuf[clHCA_samplesPerBlock]; + sample testbuf[clHCA_samplesPerBlock * 16]; /* max 16 channels, let's be generous */ int i; size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info); @@ -124,6 +124,10 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe if (clHCA_Decode(hca, buffer, header_size, 0) < 0) continue; if (clHCA_getInfo(hca, &hca_data->info) < 0) continue; + if (hca_data->info.channelCount > 16) { + VGM_LOG("HCA: too many channels, cannot test keys\n"); + goto end; + } /* test enough frames, but not too many */ while (f < HCA_KEY_MAX_TEST_FRAMES && f < hca_data->info.blockCount) { @@ -164,7 +168,7 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe hca_data->curblock = 0; hca_data->sample_ptr = clHCA_samplesPerBlock; read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile); - +end: VGM_LOG("HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count); *out_key2 = best_key2; *out_key1 = best_key1; From 0bb62ce57d1654352ccf804ad90461cc3dd52338 Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:26:42 +0200 Subject: [PATCH 02/12] Minor comments/documentation --- src/coding/coding_utils.c | 4 ++-- src/meta/fsb.c | 2 +- src/meta/fsb5.c | 6 +++--- src/meta/hca_keys.h | 8 +++++--- src/meta/vawx.c | 31 ++++++++++++++----------------- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/coding/coding_utils.c b/src/coding/coding_utils.c index 308180c7..9a7f481d 100644 --- a/src/coding/coding_utils.c +++ b/src/coding/coding_utils.c @@ -243,7 +243,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s put_16bitLE(buf+0x26, streams); /* number of streams */ put_32bitLE(buf+0x28, speakers); /* speaker position */ put_32bitLE(buf+0x2c, bytecount); /* PCM samples */ - put_32bitLE(buf+0x30, block_size); /* XMA block size */ + put_32bitLE(buf+0x30, block_size); /* XMA block size (can be zero, it's for seeking only) */ /* (looping values not set, expected to be handled externally) */ put_32bitLE(buf+0x34, 0); /* play begin */ put_32bitLE(buf+0x38, 0); /* play length */ @@ -251,7 +251,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s put_32bitLE(buf+0x40, 0); /* loop length */ put_8bit(buf+0x44, 0); /* loop count */ put_8bit(buf+0x45, 4); /* encoder version */ - put_16bitLE(buf+0x46, block_count); /* blocks count = entries in seek table */ + put_16bitLE(buf+0x46, block_count); /* blocks count (entries in seek table, can be zero) */ memcpy(buf+0x48, "data", 4); put_32bitLE(buf+0x4c, data_size); /* data size */ diff --git a/src/meta/fsb.c b/src/meta/fsb.c index 733ae293..cd84c40c 100644 --- a/src/meta/fsb.c +++ b/src/meta/fsb.c @@ -332,7 +332,7 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { uint8_t buf[FAKE_RIFF_BUFFER_SIZE]; size_t bytes, block_size, block_count; /* not accurate but not needed by FFmpeg */ - block_size = 2048; + block_size = 0x8000; /* FSB default */ block_count = fsbh.datasize / block_size; /* read_32bitLE(custom_data_offset +0x14) -1? */ /* make a fake riff so FFmpeg can parse the XMA2 */ diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index f358cf31..f6395b69 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -251,13 +251,13 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case 0x0A: {/* FMOD_SOUND_FORMAT_XMA */ - uint8_t buf[100]; + uint8_t buf[0x100]; int bytes, block_size, block_count; - block_size = 0x10000; /* XACT default */ + block_size = 0x8000; /* FSB default */ block_count = StreamSize / block_size + (StreamSize % block_size ? 1 : 0); - bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, StreamSize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, StreamSize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); if (bytes <= 0) goto fail; vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, StartOffset,StreamSize); diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 3d1cba9b..48ac3394 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -5,7 +5,11 @@ typedef struct { uint64_t key; } hcakey_info; -/* CRI's tools expect an unsigned 64 bit number, but keys are commonly found online in hex form */ +/** + * List of known keys, extracted from the game files (mostly found in 2ch.net). + * CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form. + * Keys only use 56 bits though, so the upper 8 bits can be ignored. + */ static const hcakey_info hcakey_list[] = { // HCA Decoder default @@ -14,8 +18,6 @@ static const hcakey_info hcakey_list[] = { // Phantasy Star Online 2 (multi?) // used by most console games {0xCC55463930DBE1AB}, // CC55463930DBE1AB / 14723751768204501419 - // variation from VGAudio, but some 2ch poster says the above works with CRI's tools; seems to decode the same - {24002584467202475}, // 0055463930DBE1AB // Old Phantasy Star Online 2 (multi?) {61891147883431481}, // 30DBE1ABCC554639 diff --git a/src/meta/vawx.c b/src/meta/vawx.c index 9812f50b..befdaef2 100644 --- a/src/meta/vawx.c +++ b/src/meta/vawx.c @@ -1,14 +1,11 @@ #include "meta.h" #include "../coding/coding.h" -#define FAKE_RIFF_BUFFER_SIZE 100 -/** - * VAWX - found in feelplus games: No More Heroes Heroes Paradise, Moon Diver - */ +/* VAWX - found in feelplus games (No More Heroes Heroes Paradise, Moon Diver) */ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset, datasize; + off_t start_offset, data_size; int loop_flag = 0, channel_count, type; @@ -52,17 +49,17 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case 1: { /* XMA2 */ ffmpeg_codec_data *ffmpeg_data = NULL; - uint8_t buf[FAKE_RIFF_BUFFER_SIZE]; + uint8_t buf[0x100]; int32_t bytes, block_size, block_count; - /* todo not accurate (needed for >2ch) */ - datasize = get_streamfile_size(streamFile)-start_offset; - block_size = 2048; - block_count = datasize / block_size; /* read_32bitLE(custom_data_offset +0x14) -1? */ - bytes = ffmpeg_make_riff_xma2(buf, FAKE_RIFF_BUFFER_SIZE, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + data_size = get_streamfile_size(streamFile)-start_offset; + block_size = 0x10000; /* VAWX default */ + block_count = (uint16_t)read_16bitBE(0x3A, streamFile); /* also at 0x56 */ + + bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if ( !ffmpeg_data ) goto fail; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; @@ -75,22 +72,22 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { } case 7: { /* ATRAC3 */ - uint8_t buf[FAKE_RIFF_BUFFER_SIZE]; + uint8_t buf[0x100]; int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples; - datasize = read_32bitBE(0x54,streamFile); + data_size = read_32bitBE(0x54,streamFile); block_size = 0x98 * vgmstream->channels; joint_stereo = 0; - max_samples = atrac3_bytes_to_samples(datasize, block_size); + max_samples = atrac3_bytes_to_samples(data_size, block_size); encoder_delay = 0x0; //max_samples - vgmstream->num_samples; /* todo not correct */ vgmstream->num_samples = max_samples; /* use calc samples since loop points are too, breaks looping in some files otherwise */ /* make a fake riff so FFmpeg can parse the ATRAC3 */ - bytes = ffmpeg_make_riff_atrac3(buf, FAKE_RIFF_BUFFER_SIZE, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); + bytes = ffmpeg_make_riff_atrac3(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); if (bytes <= 0) goto fail; - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; From 8dfac7c4652ce94e8141050592146b2676a42ea6 Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:27:21 +0200 Subject: [PATCH 03/12] Fix minor size bug in Wwise Vorbis --- src/meta/wwise.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/meta/wwise.c b/src/meta/wwise.c index 435377c9..ecf9fe01 100644 --- a/src/meta/wwise.c +++ b/src/meta/wwise.c @@ -265,6 +265,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { cfg.blocksize_1_exp = read_8bit(vorb_offset + block_offsets + 0x00, streamFile); /* small */ cfg.blocksize_0_exp = read_8bit(vorb_offset + block_offsets + 0x01, streamFile); /* big */ } + ww.data_size -= audio_offset; /* detect setup type: * - full inline: ~2009, ex. The King of Fighters XII X360, The Saboteur PC @@ -284,8 +285,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { } } - //ww.data_size -= audio_offset; //todo test - vgmstream->codec_data = init_vorbis_custom_codec_data(streamFile, start_offset + setup_offset, VORBIS_WWISE, &cfg); if (!vgmstream->codec_data) goto fail; } @@ -319,6 +318,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { audio_offset = read_32bit(extra_offset + data_offsets + 0x04, streamFile); /* within data */ cfg.blocksize_1_exp = read_8bit(extra_offset + block_offsets + 0x00, streamFile); /* small */ cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */ + ww.data_size -= audio_offset; /* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! PSV). They are hard to detect (decoding * will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */ @@ -329,8 +329,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { cfg.packet_type = STANDARD; } - //ww.data_size -= audio_offset; //todo test - /* try with the selected codebooks */ vgmstream->codec_data = init_vorbis_custom_codec_data(streamFile, start_offset + setup_offset, VORBIS_WWISE, &cfg); if (!vgmstream->codec_data) { @@ -349,7 +347,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { /* Vorbis is VBR so this is very approximate, meh */ if (ww.truncated) vgmstream->num_samples = vgmstream->num_samples * (ww.file_size - start_offset) / ww.data_size; - +VGM_LOG("so=%lx, ds=%x\n", start_offset, ww.data_size); break; } #endif @@ -482,7 +480,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { size_t seek_size; vgmstream->num_samples += read_32bit(ww.fmt_offset + 0x18, streamFile); - //todo 0x1c and 0x20: related to samples/looping? + /* 0x1c: null? 0x20: data_size without seek_size */ seek_size = read_32bit(ww.fmt_offset + 0x24, streamFile); start_offset += seek_size; From 8aae6ed794c2829409b4d27508722dabfa6a3ff3 Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:28:27 +0200 Subject: [PATCH 04/12] Fix multichannel EA-XMA [Dante's Inferno (X360)] --- src/coding/coding.h | 2 +- src/coding/ffmpeg_decoder_utils_ea_xma.c | 172 ++++++++++++++++++----- src/meta/ea_snu.c | 16 ++- src/vgmstream.h | 1 + 4 files changed, 146 insertions(+), 45 deletions(-) diff --git a/src/coding/coding.h b/src/coding/coding.h index 0c21a18d..af164bd0 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -214,7 +214,7 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples); size_t ffmpeg_make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate); -size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAMFILE *streamFile); +size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t real_size, STREAMFILE *streamFile); #endif /* coding_utils */ diff --git a/src/coding/ffmpeg_decoder_utils_ea_xma.c b/src/coding/ffmpeg_decoder_utils_ea_xma.c index 84e69fd7..6c79a60b 100644 --- a/src/coding/ffmpeg_decoder_utils_ea_xma.c +++ b/src/coding/ffmpeg_decoder_utils_ea_xma.c @@ -3,58 +3,121 @@ #ifdef VGM_USE_FFMPEG -#define EAXMA_XMA_BLOCK_SIZE 0x800 +#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 3 /* only seen up to 3 (Dante's Inferno) */ +#define EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK 4 /* XMA2 max is 8ch = 4 * 2ch */ +#define EAXMA_XMA_PACKET_SIZE 0x800 +#define EAXMA_XMA_BUFFER_SIZE (EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK * EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK * EAXMA_XMA_PACKET_SIZE) /** - * EA-XMA is XMA with padding removed (so a real 0x450 block would be padded to a virtual 0x800 block). - * //todo missing multichannel (packet multistream) support, unknown layout + * EA-XMA is XMA2 with padding removed (so a real 0x450 block would be padded to a virtual 0x800 block). + * Each EA-XMA SNS block contains 1~3 packets per stream, and multistream uses fully separate streams + * (no packet_skip set). We'll pad and reinterleave packets so it resembles standard XMA2. + * + * XMA2 data layout (XMA1 is the same but doesn't use blocks, they are only for seeking): + * - frames (containing 1..4 subframes): decode into 128*4 samples + * - packets: size 0x800, containing N frames (last frame can spill into next packet), must be padded + * - blocks: fixed size, containing N packets (last packet's frames won't spill into next block) + * - stream: N interleaved packets (1/2ch) for multichannel (Nch) audio. Interleave is not fixed: + * at file start/new block has one packet per stream, then must follow the "packet_skip" value + * in the XMA packet header to find its next packet (skiping packets from other streams). + * ex.: s1_p1 skip1, s2_p1 skip2, s1_p2 skip0 s1_p3 skip1, s2_p2 skip1, s1_p4... */ +static int get_block_max_packets(int num_streams, off_t packets_offset, STREAMFILE * streamfile); + int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) { - uint8_t v_buf[0x8000]; /* intermediate buffer, could be simplified */ + uint8_t v_buf[EAXMA_XMA_BUFFER_SIZE]; /* intermediate buffer, could be simplified */ int buf_done = 0; uint64_t real_offset = data->real_offset; uint64_t virtual_offset = data->virtual_offset - data->header_size; uint64_t virtual_base = data->virtual_base; + /* EA-XMA always uses late XMA2 streams (2ch + ... + 1/2ch) */ + int num_streams = (data->config.channels / 2) + (data->config.channels % 2 ? 1 : 0); - /* read and transform SNS/EA-XMA block into XMA block by adding padding */ + /* read and transform SNS/EA-XMA blocks into XMA packets */ while (buf_done < buf_size) { - int bytes_to_copy; - size_t data_size, extra_size = 0, gap_size = 0; + int s, p, bytes_to_copy, max_packets; + size_t data_size = 0, gap_size = 0; size_t block_size = read_32bitBE(real_offset, data->streamfile); - /* 0x04(4): some kind of size? 0x08(4): decoded samples */ + /* 0x04(4): decoded samples */ + off_t packets_offset = real_offset + 0x08; - /* setup */ - data_size = (block_size & 0x00FFFFFF) - 0x0c; //todo last block size may be slightly off? - if (data_size % EAXMA_XMA_BLOCK_SIZE) /* aligned padding */ - extra_size = EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE); - if (buf_done == 0) /* first read */ - gap_size = virtual_offset - virtual_base; /* might start a few bytes into the block */ + max_packets = get_block_max_packets(num_streams, packets_offset, data->streamfile); + if (max_packets == 0) goto fail; - if (data_size + extra_size > 0x8000) { - VGM_LOG("EA-XMA: total size bigger than buffer at %lx\n", (off_t)real_offset); - return 0; + if (max_packets * num_streams * EAXMA_XMA_PACKET_SIZE > EAXMA_XMA_BUFFER_SIZE) { + VGM_LOG("EA XMA: block too big at %lx\n", (off_t)real_offset); + goto fail; } - bytes_to_copy = data_size + extra_size - gap_size; + /* data is divided into a sub-block per stream (N packets), can be smaller than block_size (= has padding) + * copy XMA data re-interleaving for multichannel. To simplify some calcs fills the same number of packets + * per stream and adjusts packet headers (see above for XMA2 multichannel layout). */ + //to-do this doesn't make correct blocks sizes (but blocks are not needed to decode) + for (s = 0; s < num_streams; s++) { + size_t packets_size; + size_t packets_size4 = read_32bitBE(packets_offset, data->streamfile); /* size * 4, no idea */ + + packets_size = (packets_size4 / 4) - 0x04; + + /* Re-interleave all packets in order, one per stream. If one stream has more packets than + * others we add empty packets to keep the same number for all, avoiding packet_skip calcs */ + for (p = 0; p < max_packets; p++) { + off_t packet_offset = packets_offset + 0x04 + p * EAXMA_XMA_PACKET_SIZE; /* can be off but will copy 0 */ + off_t v_buf_offset = p * EAXMA_XMA_PACKET_SIZE * num_streams + s * EAXMA_XMA_PACKET_SIZE; + size_t packet_to_do = packets_size - p * EAXMA_XMA_PACKET_SIZE; + size_t extra_size = 0; + uint32_t header; + + if (packets_size < p * EAXMA_XMA_PACKET_SIZE) + packet_to_do = 0; /* empty packet */ + else if (packet_to_do > EAXMA_XMA_PACKET_SIZE) + packet_to_do = EAXMA_XMA_PACKET_SIZE; + + /* padding will be full size if packet_to_do is 0 */ + if (packet_to_do < EAXMA_XMA_PACKET_SIZE) + extra_size = EAXMA_XMA_PACKET_SIZE - (packet_to_do % EAXMA_XMA_PACKET_SIZE); + + /* copy data (or fully pad if empty packet) */ + read_streamfile(v_buf + v_buf_offset, packet_offset, packet_to_do, data->streamfile); + memset(v_buf + v_buf_offset + packet_to_do, 0xFF, extra_size); /* add padding, typically 0xFF */ + + /* rewrite packet header to add packet skips for multichannel (EA XMA streams are fully separate and have none) + * header bits: 6=num_frames, 15=first_frame_bits_offset, 3=metadata, 8=packet_skip */ + if (packet_to_do == 0) + header = 0x3FFF800; /* new empty packet header (0 num_frames, first_frame_bits_offset set to max) */ + else + header = (uint32_t)read_32bitBE(packet_offset, data->streamfile); + + /* get base header + change packet_skip since we know interleave is always 1 packet per stream */ + header = (header & 0xFFFFFF00) | ((header & 0x000000FF) + num_streams - 1); + put_32bitBE(v_buf + v_buf_offset, header); + } + + packets_offset += (packets_size4 / 4); + } + + if (buf_done == 0) /* first read */ + gap_size = virtual_offset - virtual_base; /* might start a few bytes into the XMA */ + + data_size = max_packets * num_streams * EAXMA_XMA_PACKET_SIZE; + + bytes_to_copy = data_size - gap_size; if (bytes_to_copy > buf_size - buf_done) bytes_to_copy = buf_size - buf_done; - /* transform */ - read_streamfile(v_buf, real_offset + 0x0c, data_size, data->streamfile); - memset(v_buf + data_size, 0xFF, extra_size); /* padding can be any value, typically 0xFF */ + /* pad + copy */ memcpy(buf + buf_done, v_buf + gap_size, bytes_to_copy); + buf_done += bytes_to_copy; /* move when block is fully done */ - if (data_size + extra_size == bytes_to_copy + gap_size) { + if (data_size == bytes_to_copy + gap_size) { real_offset += (block_size & 0x00FFFFFF); - virtual_base += data_size + extra_size; + virtual_base += data_size; } - buf_done += bytes_to_copy; - /* exit on last block just in case, though should reach file size */ if (block_size & 0x80000000) break; @@ -64,6 +127,9 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size data->real_offset = real_offset; data->virtual_base = virtual_base; return buf_size; + +fail: + return 0; } int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) { @@ -89,8 +155,8 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset size_t block_size = read_32bitBE(real_offset, data->streamfile); data_size = (block_size & 0x00FFFFFF) - 0x0c; - if (data_size % EAXMA_XMA_BLOCK_SIZE) - extra_size = EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE); + if (data_size % EAXMA_XMA_PACKET_SIZE) + extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE); /* stop if virtual_offset lands inside current block */ if (data_size + extra_size > virtual_offset) @@ -117,26 +183,32 @@ int64_t ffmpeg_custom_size_eaxma(ffmpeg_codec_data *data) { } /* needed to know in meta for fake RIFF */ -size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAMFILE *streamFile) { +size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t real_size, STREAMFILE *streamFile) { size_t virtual_size = 0; + size_t real_end_offset = real_offset + real_size; + /* EA-XMA always uses late XMA2 streams (2ch + ... + 1/2ch) */ + int num_streams = (channels / 2) + (channels % 2 ? 1 : 0); + /* count all SNS/EAXMA blocks size + padding size */ - while (real_offset < real_size) { - size_t data_size; - size_t block_size = read_32bitBE(real_offset, streamFile); - - data_size = (block_size & 0x00FFFFFF) - 0x0c; + while (real_offset < real_end_offset) { + int max_packets; + size_t block_size = read_32bitBE(real_offset + 0x00, streamFile); + /* 0x04(4): decoded samples */ + off_t packets_offset = real_offset + 0x08; if ((block_size & 0xFF000000) && !(block_size & 0x80000000)) { VGM_LOG("EA-XMA: unknown flag found at %lx\n", (off_t)real_offset); goto fail; } - real_offset += (block_size & 0x00FFFFFF); + max_packets = get_block_max_packets(num_streams, packets_offset, streamFile); + if (max_packets == 0) goto fail; - virtual_size += data_size; - if (data_size % EAXMA_XMA_BLOCK_SIZE) /* XMA block padding */ - virtual_size += EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE); + /* fixed data_size per block for multichannel, see reads */ + virtual_size += max_packets * num_streams * EAXMA_XMA_PACKET_SIZE; + + real_offset += (block_size & 0x00FFFFFF); /* exit on last block just in case, though should reach real_size */ if (block_size & 0x80000000) @@ -147,7 +219,33 @@ size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAM fail: return 0; +} +/* a block can have N streams each with a varying number of packets, get max */ +static int get_block_max_packets(int num_streams, off_t packets_offset, STREAMFILE * streamfile) { + int s; + int max_packets = 0; + + for (s = 0; s < num_streams; s++) { + size_t packets_size; + size_t packets_size4 = read_32bitBE(packets_offset, streamfile); /* size * 4, no idea */ + int num_packets; + + if (packets_size4 == 0) { + VGM_LOG("EA XMA: null packets in stream %i at %lx\n", s, (off_t)packets_offset); + goto fail; + } + packets_size = (packets_size4 / 4) - 0x04; + + num_packets = (int)(packets_size / EAXMA_XMA_PACKET_SIZE) + 1; + if (num_packets > max_packets) + max_packets = num_packets; + } + + return max_packets; + +fail: + return 0; } #endif diff --git a/src/meta/ea_snu.c b/src/meta/ea_snu.c index c21a7252..31fd41eb 100644 --- a/src/meta/ea_snu.c +++ b/src/meta/ea_snu.c @@ -18,15 +18,15 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { /* check header (the first 0x10 are BE/LE depending on platform) */ /* 0x00(1): related to sample rate? (03=48000) - * 0x01(1): flags? (when set seems to be a bank and has extra data before start_offset) //todo + * 0x01(1): flags/count? (when set has extra block data before start_offset) * 0x02(1): always 0? * 0x03(1): channels? (usually matches but rarely may be 0) * 0x04(4): some size, maybe >>2 ~= number of frames * 0x08(4): start offset - * 0x0c(4): some sub-offset? (0x20, found when 0x01 is set) */ + * 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */ - /* use start offset as endianness flag */ - if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x00F00000) { + /* use start_offset as endianness flag */ + if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x0000FFFF) { read_32bit = read_32bitBE; } else { read_32bit = read_32bitLE; @@ -48,6 +48,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { #if 0 //todo not working ok with blocks in XAS + //todo check if EA-XMA loops (Dante's Inferno doesn't) if (flags & 0x60) { /* full loop, seen in ambient tracks */ loop_flag = 1; loop_start = 0; @@ -81,7 +82,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { vgmstream->meta_type = meta_EA_SNU; switch(codec) { - case 0x04: /* "Xas1": EA-XAS (Dead Space) */ + case 0x04: /* "Xas1": EA-XAS (Dead Space PC/PS3) */ vgmstream->coding_type = coding_EA_XAS; vgmstream->layout_type = layout_ea_sns_blocked; break; @@ -112,8 +113,8 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { ffmpeg_custom_config cfg; stream_size = get_streamfile_size(streamFile) - start_offset; - virtual_size = ffmpeg_get_eaxma_virtual_size(start_offset,stream_size, streamFile); - block_size = 0x8000; /* ? */ + virtual_size = ffmpeg_get_eaxma_virtual_size(vgmstream->channels, start_offset,stream_size, streamFile); + block_size = 0x10000; /* todo unused and not correctly done by the parser */ block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0); bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, virtual_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); @@ -122,6 +123,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { memset(&cfg, 0, sizeof(ffmpeg_custom_config)); cfg.type = FFMPEG_EA_XMA; cfg.virtual_size = virtual_size; + cfg.channels = vgmstream->channels; vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,stream_size, &cfg); if (!vgmstream->codec_data) goto fail; diff --git a/src/vgmstream.h b/src/vgmstream.h index 90c4da86..71fd7bb7 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -1039,6 +1039,7 @@ typedef enum { typedef struct { int stream_index; /* FFmpeg's sub-stream (as opposed to an internal stream in custom read/seeks) */ int codec_endian; + int channels; ffmpeg_custom_t type; /* ffmpeg subtype */ size_t virtual_size; /* external value, if meta needs to know/supply it */ From c63866aad629079a6170d0ac1949978215ec545d Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:29:06 +0200 Subject: [PATCH 05/12] Fix Wwise Opus abrupt end --- src/coding/ffmpeg_decoder_utils_wwise_opus.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coding/ffmpeg_decoder_utils_wwise_opus.c b/src/coding/ffmpeg_decoder_utils_wwise_opus.c index 37770132..f635ca87 100644 --- a/src/coding/ffmpeg_decoder_utils_wwise_opus.c +++ b/src/coding/ffmpeg_decoder_utils_wwise_opus.c @@ -140,11 +140,11 @@ int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_o int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data) { uint64_t real_offset = data->real_start; - uint64_t real_size = data->real_size; + uint64_t real_end_offset = data->real_start + data->real_size; uint64_t virtual_size = data->header_size; /* count all Wwise Opus blocks size + OggS page size */ - while (real_offset < real_size) { + while (real_offset < real_end_offset) { size_t extra_size; size_t data_size = read_32bitBE(real_offset, data->streamfile); /* 0x00: data size, 0x04: ? (not a sequence or CRC), 0x08+: data */ @@ -316,8 +316,8 @@ fail: static size_t make_opus_comment(uint8_t * buf, int buf_size) { size_t comment_size; int vendor_string_length, user_comment_0_length; - char * vendor_string = "libopus 1.0.2"; - char * user_comment_0_string = "ENCODER=opusenc from opus-tools 0.1.6"; + char * vendor_string = "vgmstream"; + char * user_comment_0_string = "vgmstream Opus converter"; vendor_string_length = strlen(vendor_string); user_comment_0_length = strlen(user_comment_0_string); From 8a8ebe3e249535a3f94a8fa66c505f44e3908f3c Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Fri, 29 Sep 2017 23:37:20 +0200 Subject: [PATCH 06/12] Minor renames for style (ps3_xvag > xvag, x360_nub > nub_xma) --- src/formats.c | 2 +- src/libvgmstream.vcproj | 16 ++++++++-------- src/libvgmstream.vcxproj | 4 ++-- src/libvgmstream.vcxproj.filters | 12 ++++++------ src/meta/meta.h | 4 ++-- src/meta/{x360_nub.c => nub_xma.c} | 2 +- src/meta/{ps3_xvag.c => xvag.c} | 4 ++-- src/vgmstream.c | 4 ++-- src/vgmstream.h | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) rename src/meta/{x360_nub.c => nub_xma.c} (95%) rename src/meta/{ps3_xvag.c => xvag.c} (96%) diff --git a/src/formats.c b/src/formats.c index 658bc7b5..08df838c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -811,7 +811,7 @@ static const meta_info meta_info_list[] = { {meta_FFW, "Freedom Fighters BGM header"}, {meta_DSP_DSPW, "DSPW dsp header"}, {meta_PS2_JSTM, "JSTM Header"}, - {meta_PS3_XVAG, "XVAG Header"}, + {meta_XVAG, "Sony XVAG header"}, {meta_PS3_CPS, "tri-Crescendo CPS Header"}, {meta_SQEX_SCD, "Square-Enix SCD header"}, {meta_NGC_NST_DSP, "Animaniacs NST header"}, diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 76bdce31..d469f3d4 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -626,6 +626,10 @@ RelativePath=".\meta\nub_vag.c" > </File> + <File + RelativePath=".\meta\nub_xma.c" + > + </File> <File RelativePath=".\meta\nwa.c" > @@ -998,10 +1002,6 @@ RelativePath=".\meta\vawx.c" > </File> - <File - RelativePath=".\meta\ps3_xvag.c" - > - </File> <File RelativePath=".\meta\psx_cdxa.c" > @@ -1230,10 +1230,6 @@ RelativePath=".\meta\x360_cxs.c" > </File> - <File - RelativePath=".\meta\x360_nub.c" - > - </File> <File RelativePath=".\meta\x360_pasx.c" > @@ -1278,6 +1274,10 @@ RelativePath=".\meta\xss.c" > </File> + <File + RelativePath=".\meta\xvag.c" + > + </File> <File RelativePath=".\meta\xwb.c" > diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index f5511888..49d64b48 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -281,6 +281,7 @@ <ClCompile Include="meta\ngc_tydsp.c" /> <ClCompile Include="meta\ngc_ymf.c" /> <ClCompile Include="meta\ngc_ulw.c" /> + <ClCompile Include="meta\nub_xma.c" /> <ClCompile Include="meta\nwa.c" /> <ClCompile Include="meta\ogg_vorbis_file.c" /> <ClCompile Include="meta\ogl.c" /> @@ -359,7 +360,6 @@ <ClCompile Include="meta\ps3_cps.c" /> <ClCompile Include="meta\ps3_msf.c" /> <ClCompile Include="meta\ps3_mta2.c" /> - <ClCompile Include="meta\ps3_xvag.c" /> <ClCompile Include="meta\psx_cdxa.c" /> <ClCompile Include="meta\psx_fag.c" /> <ClCompile Include="meta\psx_gms.c" /> @@ -416,9 +416,9 @@ <ClCompile Include="meta\xbox_xvas.c" /> <ClCompile Include="meta\xbox_xwav.c" /> <ClCompile Include="meta\x360_pasx.c" /> - <ClCompile Include="meta\x360_nub.c" /> <ClCompile Include="meta\xma.c" /> <ClCompile Include="meta\xss.c" /> + <ClCompile Include="meta\xvag.c" /> <ClCompile Include="meta\xwb.c" /> <ClCompile Include="meta\ydsp.c" /> <ClCompile Include="meta\zsd.c" /> diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 6927059d..f8f49919 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -373,6 +373,9 @@ <ClCompile Include="meta\ngc_ulw.c"> <Filter>meta\Source Files</Filter> </ClCompile> + <ClCompile Include="meta\nub_xma.c"> + <Filter>meta\Source Files</Filter> + </ClCompile> <ClCompile Include="meta\nwa.c"> <Filter>meta\Source Files</Filter> </ClCompile> @@ -607,9 +610,6 @@ <ClCompile Include="meta\ps3_mta2.c"> <Filter>meta\Source Files</Filter> </ClCompile> - <ClCompile Include="meta\ps3_xvag.c"> - <Filter>meta\Source Files</Filter> - </ClCompile> <ClCompile Include="meta\psx_cdxa.c"> <Filter>meta\Source Files</Filter> </ClCompile> @@ -754,9 +754,6 @@ <ClCompile Include="meta\wwise.c"> <Filter>meta\Source Files</Filter> </ClCompile> - <ClCompile Include="meta\x360_nub.c"> - <Filter>meta\Source Files</Filter> - </ClCompile> <ClCompile Include="meta\x360_pasx.c"> <Filter>meta\Source Files</Filter> </ClCompile> @@ -784,6 +781,9 @@ <ClCompile Include="meta\xss.c"> <Filter>meta\Source Files</Filter> </ClCompile> + <ClCompile Include="meta\xvag.c"> + <Filter>meta\Source Files</Filter> + </ClCompile> <ClCompile Include="meta\xwb.c"> <Filter>meta\Source Files</Filter> </ClCompile> diff --git a/src/meta/meta.h b/src/meta/meta.h index fbbb0699..a5194d87 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -536,7 +536,7 @@ VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_xvag(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile); @@ -645,7 +645,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile); diff --git a/src/meta/x360_nub.c b/src/meta/nub_xma.c similarity index 95% rename from src/meta/x360_nub.c rename to src/meta/nub_xma.c index 3c4cae95..cb33d551 100644 --- a/src/meta/x360_nub.c +++ b/src/meta/nub_xma.c @@ -2,7 +2,7 @@ #include "../coding/coding.h" /* Namco NUB xma - from Tekken 6, Galaga Legions DX */ -VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset, chunk_offset; size_t data_size, chunk_size; diff --git a/src/meta/ps3_xvag.c b/src/meta/xvag.c similarity index 96% rename from src/meta/ps3_xvag.c rename to src/meta/xvag.c index 009376ee..987db2f1 100644 --- a/src/meta/ps3_xvag.c +++ b/src/meta/xvag.c @@ -5,7 +5,7 @@ static int ps_adpcm_find_loop_offsets(STREAMFILE *streamFile, int channel_count, off_t start_offset, off_t * loop_start, off_t * loop_end); /* XVAG - Sony's (second party?) format (God of War III, Ratchet & Clank Future, The Last of Us, Uncharted) */ -VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int loop_flag = 0, channel_count, codec; @@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) { vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; - vgmstream->meta_type = meta_PS3_XVAG; + vgmstream->meta_type = meta_XVAG; switch (codec) { case 0x06: /* PS ADPCM: God of War III, Uncharted 1/2, Ratchet and Clank Future */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 2ef7dbe0..f1d330b4 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -292,7 +292,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ffw, init_vgmstream_dsp_dspw, init_vgmstream_ps2_jstm, - init_vgmstream_ps3_xvag, + init_vgmstream_xvag, init_vgmstream_ps3_cps, init_vgmstream_sqex_scd, init_vgmstream_ngc_nst_dsp, @@ -350,7 +350,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_wwise, init_vgmstream_ubi_raki, init_vgmstream_x360_pasx, - init_vgmstream_x360_nub, + init_vgmstream_nub_xma, init_vgmstream_xma, init_vgmstream_sxd, init_vgmstream_ogl, diff --git a/src/vgmstream.h b/src/vgmstream.h index 71fd7bb7..76b92009 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -556,7 +556,7 @@ typedef enum { meta_SQEX_SCD, /* Square-Enix SCD */ meta_NGC_NST_DSP, /* Animaniacs [NGC] */ meta_BAF, /* Bizarre Creations (Blur, James Bond) */ - meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */ + meta_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */ meta_PS3_CPS, /* Eternal Sonata (PS3) */ meta_PS3_MSF, /* MSF header */ meta_NUB_VAG, /* Namco VAG from NUB archives */ From abaefd17cd04f3d5522b9930c64da60b51951c4e Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 00:16:40 +0200 Subject: [PATCH 07/12] Rename wwise_opus to switch_opus as it's apparently so --- src/coding/ffmpeg_decoder.c | 30 +++++++++---------- src/coding/ffmpeg_decoder_utils.h | 6 ++-- ...s.c => ffmpeg_decoder_utils_switch_opus.c} | 6 ++-- src/libvgmstream.vcproj | 2 +- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 2 +- src/meta/wwise.c | 2 +- src/vgmstream.h | 4 +-- 8 files changed, 27 insertions(+), 27 deletions(-) rename src/coding/{ffmpeg_decoder_utils_wwise_opus.c => ffmpeg_decoder_utils_switch_opus.c} (95%) diff --git a/src/coding/ffmpeg_decoder.c b/src/coding/ffmpeg_decoder.c index 1dc44550..fd703699 100644 --- a/src/coding/ffmpeg_decoder.c +++ b/src/coding/ffmpeg_decoder.c @@ -218,11 +218,11 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) { /* main read */ switch(data->config.type) { - case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break; - case FFMPEG_WWISE_OPUS: ret = ffmpeg_custom_read_wwise_opus(data, buf, buf_size); break; - //case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break; - //case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break; - default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break; + case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break; + case FFMPEG_SWITCH_OPUS: ret = ffmpeg_custom_read_switch_opus(data, buf, buf_size); break; + //case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break; + //case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break; + default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break; } data->virtual_offset += ret; //data->real_offset = ; /* must be updated in function */ @@ -285,11 +285,11 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) { /* main seek */ switch(data->config.type) { - case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break; - case FFMPEG_WWISE_OPUS: offset = ffmpeg_custom_seek_wwise_opus(data, offset); break; - //case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break; - //case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break; - default: offset = ffmpeg_custom_seek_standard(data, offset); break; + case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break; + case FFMPEG_SWITCH_OPUS: offset = ffmpeg_custom_seek_switch_opus(data, offset); break; + //case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break; + //case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break; + default: offset = ffmpeg_custom_seek_standard(data, offset); break; } data->virtual_offset = offset; //data->real_offset = ; /* must be updated in function */ @@ -302,11 +302,11 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) { static int64_t ffmpeg_size(ffmpeg_codec_data * data) { int64_t bytes; switch(data->config.type) { - case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break; - case FFMPEG_WWISE_OPUS: bytes = ffmpeg_custom_size_wwise_opus(data); break; - //case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break; - //case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break; - default: bytes = ffmpeg_custom_size_standard(data); break; + case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break; + case FFMPEG_SWITCH_OPUS: bytes = ffmpeg_custom_size_switch_opus(data); break; + //case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break; + //case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break; + default: bytes = ffmpeg_custom_size_standard(data); break; } return bytes; diff --git a/src/coding/ffmpeg_decoder_utils.h b/src/coding/ffmpeg_decoder_utils.h index 18957e3c..64461fe9 100644 --- a/src/coding/ffmpeg_decoder_utils.h +++ b/src/coding/ffmpeg_decoder_utils.h @@ -27,9 +27,9 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset); int64_t ffmpeg_custom_size_eaxma(ffmpeg_codec_data *data); -int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size); -int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_offset); -int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data); +int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size); +int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset); +int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data); //int ffmpeg_custom_read_ea_schl(ffmpeg_codec_data *data, uint8_t *buf, int buf_size); //int64_t ffmpeg_custom_seek_ea_schl(ffmpeg_codec_data *data, int64_t virtual_offset); diff --git a/src/coding/ffmpeg_decoder_utils_wwise_opus.c b/src/coding/ffmpeg_decoder_utils_switch_opus.c similarity index 95% rename from src/coding/ffmpeg_decoder_utils_wwise_opus.c rename to src/coding/ffmpeg_decoder_utils_switch_opus.c index f635ca87..8af6a7f5 100644 --- a/src/coding/ffmpeg_decoder_utils_wwise_opus.c +++ b/src/coding/ffmpeg_decoder_utils_switch_opus.c @@ -44,7 +44,7 @@ fail: } -int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) { +int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) { uint8_t v_buf[0x8000]; /* intermediate buffer, could be simplified */ int buf_done = 0; uint64_t real_offset = data->real_offset; @@ -98,7 +98,7 @@ int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf return buf_size; } -int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_offset) { +int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset) { int64_t real_offset, virtual_base; int64_t current_virtual_offset = data->virtual_offset; @@ -138,7 +138,7 @@ int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_o return virtual_offset; } -int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data) { +int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data) { uint64_t real_offset = data->real_start; uint64_t real_end_offset = data->real_start + data->real_size; uint64_t virtual_size = data->header_size; diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index d469f3d4..b0c7d1a6 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -1379,7 +1379,7 @@ > </File> <File - RelativePath=".\coding\ffmpeg_decoder_utils_wwise_opus.c" + RelativePath=".\coding\ffmpeg_decoder_utils_switch_opus.c" > </File> <File diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 49d64b48..9e0ff19b 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -133,7 +133,7 @@ <ClCompile Include="coding\coding_utils.c" /> <ClCompile Include="coding\ffmpeg_decoder.c" /> <ClCompile Include="coding\ffmpeg_decoder_utils_ea_xma.c" /> - <ClCompile Include="coding\ffmpeg_decoder_utils_wwise_opus.c" /> + <ClCompile Include="coding\ffmpeg_decoder_utils_switch_opus.c" /> <ClCompile Include="coding\ffmpeg_decoder_utils.c" /> <ClCompile Include="coding\lsf_decoder.c" /> <ClCompile Include="coding\mp4_aac_decoder.c" /> diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f8f49919..e9e9e3ad 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1147,7 +1147,7 @@ <ClCompile Include="coding\ffmpeg_decoder_utils_ea_xma.c"> <Filter>coding\Source Files</Filter> </ClCompile> - <ClCompile Include="coding\ffmpeg_decoder_utils_wwise_opus.c"> + <ClCompile Include="coding\ffmpeg_decoder_utils_switch_opus.c"> <Filter>coding\Source Files</Filter> </ClCompile> <ClCompile Include="coding\ffmpeg_decoder_utils.c"> diff --git a/src/meta/wwise.c b/src/meta/wwise.c index ecf9fe01..a9cf6775 100644 --- a/src/meta/wwise.c +++ b/src/meta/wwise.c @@ -496,7 +496,7 @@ VGM_LOG("so=%lx, ds=%x\n", start_offset, ww.data_size); if (bytes <= 0) goto fail; memset(&cfg, 0, sizeof(ffmpeg_custom_config)); - cfg.type = FFMPEG_WWISE_OPUS; + cfg.type = FFMPEG_SWITCH_OPUS; //cfg.big_endian = ww.big_endian; /* internally BE */ vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,ww.data_size, &cfg); diff --git a/src/vgmstream.h b/src/vgmstream.h index 76b92009..4457b420 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -1028,8 +1028,8 @@ typedef struct { /* Custom FFMPEG modes */ typedef enum { FFMPEG_STANDARD, /* default FFmpeg */ - FFMPEG_WWISE_OPUS, /* Opus without Ogg layer */ - FFMPEG_EA_XMA, /* XMA with padding removed in SNS blocks */ + FFMPEG_SWITCH_OPUS, /* Opus without Ogg layer */ + FFMPEG_EA_XMA, /* XMA with padding removed and custom streams in SNS blocks */ //FFMPEG_EA_SCHL, /* Normal header+data (ex. ATRAC3) in SCxx blocks */ //FFMPEG_SFH, /* ATRAC3plus header+data in SFH blocks */ //FFMPEG_AWC_XMA, /* XMA data in AWC blocks, 1 streams per channel */ From c3568ffd26bc5e3f6f9a48c34cf895bf1c8bf90f Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 01:26:44 +0200 Subject: [PATCH 08/12] Fix MSVC compiling, remove UNICODE as there may be issues with MSVC --- winamp/in_vgmstream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index 9f092ad6..9ca571bd 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -5,7 +5,7 @@ /* Normally Winamp opens unicode files by their DOS 8.3 name. #define this to use wchar_t filenames, * which must be opened with _wfopen in a WINAMP_STREAMFILE (needed for dual files like .pos). * Only for Winamp paths, other parts would need #define UNICODE for Windows. */ -#define UNICODE_INPUT_PLUGIN +//#define UNICODE_INPUT_PLUGIN #ifdef _MSC_VER @@ -106,7 +106,7 @@ in_char lastfn[PATH_LIMIT] = {0}; /* name of the currently playing file */ #define wa_strlen wcslen #define wa_strchr wcschr #define wa_sscanf swscanf -#define wa_snprintf snwprintf +#define wa_snprintf _snwprintf #define wa_fileinfo fileinfoW #define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAMEW #define wa_L(x) L ##x From 16786b78d4702a43db92a180c77967a99bdaa10e Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 01:27:47 +0200 Subject: [PATCH 09/12] Add .opus [Lego City Undercover] --- fb2k/foo_filetypes.h | 1 + src/coding/coding.h | 3 + src/coding/ffmpeg_decoder_utils_switch_opus.c | 17 ++++- src/formats.c | 2 + src/libvgmstream.vcproj | 4 ++ src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 3 + src/meta/meta.h | 2 + src/meta/nsw_opus.c | 64 +++++++++++++++++++ src/vgmstream.c | 1 + src/vgmstream.h | 1 + 11 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/meta/nsw_opus.c diff --git a/fb2k/foo_filetypes.h b/fb2k/foo_filetypes.h index 657d20a9..5093ba36 100644 --- a/fb2k/foo_filetypes.h +++ b/fb2k/foo_filetypes.h @@ -207,6 +207,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("NWA", nwa); VGMSTREAM_DECLARE_FILE_TYPE("OGL", ogl); VGMSTREAM_DECLARE_FILE_TYPE("OMA", oma); VGMSTREAM_DECLARE_FILE_TYPE("OMU", omu); +VGMSTREAM_DECLARE_FILE_TYPE("OPUS", opus); VGMSTREAM_DECLARE_FILE_TYPE("OTM", otm); VGMSTREAM_DECLARE_FILE_TYPE("P2BT", p2bt); diff --git a/src/coding/coding.h b/src/coding/coding.h index af164bd0..dc95cd9f 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -215,6 +215,9 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples); size_t ffmpeg_make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate); size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t real_size, STREAMFILE *streamFile); + +size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile); + #endif /* coding_utils */ diff --git a/src/coding/ffmpeg_decoder_utils_switch_opus.c b/src/coding/ffmpeg_decoder_utils_switch_opus.c index 8af6a7f5..d8ce46db 100644 --- a/src/coding/ffmpeg_decoder_utils_switch_opus.c +++ b/src/coding/ffmpeg_decoder_utils_switch_opus.c @@ -159,7 +159,23 @@ int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data) { return virtual_size; } +size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) { + size_t num_samples = 0; + off_t end_offset = offset + data_size; + /* count by reading all frames */ + while (offset < end_offset) { + uint8_t buf[4]; + size_t block_size = read_32bitBE(offset, streamFile); + + read_streamfile(buf, offset+4, 4, streamFile); + num_samples += get_opus_samples_per_frame(buf, sample_rate); + + offset += 0x08 + block_size; + } + + return num_samples; +} /* ************************************************** */ @@ -342,5 +358,4 @@ fail: return 0; } - #endif diff --git a/src/formats.c b/src/formats.c index 08df838c..504f6b3e 100644 --- a/src/formats.c +++ b/src/formats.c @@ -200,6 +200,7 @@ static const char* extension_list[] = { "ogl", "oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "omu", + "opus", "otm", "p1d", //txth/reserved [Farming Simulator 18 (3DS)] @@ -888,6 +889,7 @@ static const meta_info meta_info_list[] = { {meta_BINK, "RAD Game Tools Bink header"}, {meta_EA_SNU, "Electronic Arts SNU header"}, {meta_AWC, "Rockstar AWC header"}, + {meta_NSW_OPUS, ".OPUS header"}, #ifdef VGM_USE_VORBIS {meta_OGG_VORBIS, "Ogg Vorbis"}, diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index b0c7d1a6..94aae551 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -622,6 +622,10 @@ RelativePath=".\meta\ngca.c" > </File> + <File + RelativePath=".\meta\nsw_opus.c" + > + </File> <File RelativePath=".\meta\nub_vag.c" > diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 9e0ff19b..4e407b38 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -157,6 +157,7 @@ <ClCompile Include="meta\mn_str.c" /> <ClCompile Include="meta\mp4.c" /> <ClCompile Include="meta\ngca.c" /> + <ClCompile Include="meta\nsw_opus.c" /> <ClCompile Include="meta\nub_vag.c" /> <ClCompile Include="meta\pc_adp.c" /> <ClCompile Include="meta\pc_snds.c" /> diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index e9e9e3ad..83392562 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1012,6 +1012,9 @@ <ClCompile Include="meta\ngca.c"> <Filter>meta\Source Files</Filter> </ClCompile> + <ClCompile Include="meta\nsw_opus.c"> + <Filter>meta\Source Files</Filter> + </ClCompile> <ClCompile Include="meta\ps2_mtaf.c"> <Filter>meta\Source Files</Filter> </ClCompile> diff --git a/src/meta/meta.h b/src/meta/meta.h index a5194d87..4afb986e 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -682,4 +682,6 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile); + #endif /*_META_H*/ diff --git a/src/meta/nsw_opus.c b/src/meta/nsw_opus.c new file mode 100644 index 00000000..9339d477 --- /dev/null +++ b/src/meta/nsw_opus.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +/* .OPUS - from Lego City Undercover (Switch) */ +VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channel_count; + + /* check extension, case insensitive */ + if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */ + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x01000080) + goto fail; + + start_offset = 0x28; + channel_count = read_8bit(0x09,streamFile); /* assumed */ + /* other values in the header: no idea */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + vgmstream->meta_type = meta_NSW_OPUS; + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + size_t bytes, skip, data_size; + ffmpeg_custom_config cfg; + + data_size = get_streamfile_size(streamFile) - start_offset; + skip = 0; //todo + + bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate); + if (bytes <= 0) goto fail; + + memset(&cfg, 0, sizeof(ffmpeg_custom_config)); + cfg.type = FFMPEG_SWITCH_OPUS; + + vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg); + if (!vgmstream->codec_data) goto fail; + + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile); + } +#else + goto fail; +#endif + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index f1d330b4..517d345d 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -369,6 +369,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_stm, init_vgmstream_ea_snu, init_vgmstream_awc, + init_vgmstream_nsw_opus, init_vgmstream_txth, /* should go at the end (lower priority) */ #ifdef VGM_USE_FFMPEG diff --git a/src/vgmstream.h b/src/vgmstream.h index 4457b420..a3c106b6 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -626,6 +626,7 @@ typedef enum { meta_BINK, /* RAD Game Tools BINK audio/video */ meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */ meta_AWC, /* Rockstar AWC (GTA5, RDR) */ + meta_NSW_OPUS, /* Lego City Undercover (Switch) */ #ifdef VGM_USE_VORBIS meta_OGG_VORBIS, /* Ogg Vorbis */ From 14957d6269d42137e1365009349baf671eefc08a Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 01:52:49 +0200 Subject: [PATCH 10/12] Fix XWB split bug with some codecs --- src/meta/xwb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/xwb.c b/src/meta/xwb.c index 99f251df..83c44fe6 100644 --- a/src/meta/xwb.c +++ b/src/meta/xwb.c @@ -455,7 +455,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { } - start_offset = xwb.data_offset; + start_offset = xwb.stream_offset; if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) goto fail; From 6c5a97c8ed68aa76139cbcb12df99b9a96fbcdf7 Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 19:20:09 +0200 Subject: [PATCH 11/12] Fix compiling in GCC (false not defined) --- src/meta/ps2_rxws.c | 2 +- src/meta/sgxd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meta/ps2_rxws.c b/src/meta/ps2_rxws.c index 862bfc53..01b0ea90 100644 --- a/src/meta/ps2_rxws.c +++ b/src/meta/ps2_rxws.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { STREAMFILE * streamHeader = NULL; off_t start_offset, chunk_offset, name_offset = 0; size_t data_size, chunk_size; - int loop_flag = 0, channel_count, is_separate = false, type, sample_rate; + int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate; int32_t loop_start, loop_end; int total_streams, target_stream = streamFile->stream_index; diff --git a/src/meta/sgxd.c b/src/meta/sgxd.c index e820718b..07cfba50 100644 --- a/src/meta/sgxd.c +++ b/src/meta/sgxd.c @@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) { off_t start_offset, data_offset, chunk_offset, name_offset = 0; size_t data_size; - int is_sgx, is_sgb = false; + int is_sgx, is_sgb = 0; int loop_flag, channels, type; int sample_rate, num_samples, loop_start_sample, loop_end_sample; int total_streams, target_stream = streamFile->stream_index; From 07a6fba10f0959bd59de36ea4986e64d46a66fb1 Mon Sep 17 00:00:00 2001 From: bnnm <bananaman255@gmail.com> Date: Sat, 30 Sep 2017 19:36:13 +0200 Subject: [PATCH 12/12] Free HCA testbuf and reduce allocs --- src/meta/hca.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/meta/hca.c b/src/meta/hca.c index ad133da6..2f99ab2e 100644 --- a/src/meta/hca.c +++ b/src/meta/hca.c @@ -95,7 +95,7 @@ fail: * clipped samples, as it's common for invalid keys (though possible with valid keys in poorly mastered files). */ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffer, int header_size, unsigned int * out_key1, unsigned int * out_key2) { sample *testbuf = NULL, *temp; - int i, j; + int i, j, bufsize = 0, tempsize; size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info); int min_clip_count = -1; @@ -123,13 +123,15 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe clHCA_clear(hca, key1, key2); if (clHCA_Decode(hca, buffer, header_size, 0) < 0) continue; if (clHCA_getInfo(hca, &hca_data->info) < 0) continue; + if (hca_data->info.channelCount > 32) continue; /* nonsense don't alloc too much */ - temp = (sample *)realloc(testbuf, sizeof(sample) * clHCA_samplesPerBlock * hca_data->info.channelCount); - if (!temp) { - if (testbuf) free(testbuf); - return; + tempsize = sizeof(sample) * clHCA_samplesPerBlock * hca_data->info.channelCount; + if (tempsize > bufsize) { /* should happen once */ + temp = (sample *)realloc(testbuf, tempsize); + if (!temp) goto end; + testbuf = temp; + bufsize = tempsize; } - testbuf = temp; /* test enough frames, but not too many */ while (f < HCA_KEY_MAX_TEST_FRAMES && f < hca_data->info.blockCount) { @@ -172,8 +174,10 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe hca_data->curblock = 0; hca_data->sample_ptr = clHCA_samplesPerBlock; read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile); + end: VGM_LOG("HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count); *out_key2 = best_key2; *out_key1 = best_key1; + free(testbuf);//free(temp); }