diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 02cb4c25a..0a2119113 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -198,6 +198,7 @@ static const char* extension_list[] = { "his", "hps", "hsf", + "hwx", //txth/reserved [Star Wars Episode III (Xbox)] "hx2", "hx3", "hxc", @@ -397,6 +398,7 @@ static const char* extension_list[] = { "s3v", //txth/reserved [Sound Voltex 5 (AC)] "sab", "sad", + "saf", "sap", "sb0", "sb1", @@ -563,6 +565,7 @@ static const char* extension_list[] = { "xag", "xau", "xav", + "xb", //txth/reserved [Scooby-Doo! Unmasked (Xbox)] "xen", "xma", "xma2", diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index b8323f9ea..5db362cf6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -965,7 +965,7 @@ typedef struct { static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *sf_data, eaac_header *eaac); static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *streamFile, eaac_header *eaac, off_t start_offset); static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead, STREAMFILE *streamData); -static size_t calculate_eaac_size(STREAMFILE *streamFile, eaac_header *ea, uint32_t num_samples, off_t start_offset); +static size_t calculate_eaac_size(STREAMFILE *streamFile, eaac_header *ea, uint32_t num_samples, off_t start_offset, int is_ram); /* EA newest header from RwAudioCore (RenderWare?) / EAAudioCore library (still generated by sx.exe). * Audio "assets" come in separate RAM headers (.SNR/SPH) and raw blocked streams (.SNS/SPS), @@ -1293,43 +1293,50 @@ fail: return NULL; } -static size_t calculate_eaac_size(STREAMFILE *streamFile, eaac_header *ea, uint32_t num_samples, off_t start_offset) { - uint32_t samples_parsed, block_size, block_samples; +static size_t calculate_eaac_size(STREAMFILE *streamFile, eaac_header *ea, uint32_t num_samples, off_t start_offset, int is_ram) { + uint32_t block_size; uint8_t block_id; size_t stream_size, file_size; off_t block_offset; + int looped; file_size = get_streamfile_size(streamFile); block_offset = start_offset; - stream_size = 0, samples_parsed = 0; + stream_size = 0; + looped = 0; - while (block_offset < file_size && samples_parsed < num_samples) { + while (block_offset < file_size) { block_id = read_8bit(block_offset, streamFile); block_size = read_32bitBE(block_offset, streamFile) & 0x00FFFFFF; + /* stop when we reach the end marker */ if (ea->version == EAAC_VERSION_V0) { if (block_id != EAAC_BLOCKID0_DATA && block_id != EAAC_BLOCKID0_END) goto fail; } else { - if (block_id != EAAC_BLOCKID1_DATA) { - if (block_id == EAAC_BLOCKID1_END && ea->codec == EAAC_CODEC_EATRAX) { - /* number of samples in block header is wrong for EATrax so stop when we reach end marker */ - return stream_size; - } + if (block_id == EAAC_BLOCKID1_END) + break; + if (block_id != EAAC_BLOCKID1_DATA) goto fail; - } } - block_samples = read_32bitBE(block_offset + 0x04, streamFile); - stream_size += block_size; - samples_parsed += block_samples; block_offset += block_size; - } - if (samples_parsed != num_samples) - goto fail; + /* RAM data only consists of one block */ + if (is_ram) + break; + + if (ea->version == EAAC_VERSION_V0 && block_id == EAAC_BLOCKID0_END) { + if (ea->loop_offset > 0) { + if (!looped) looped = 1; + else break; + } else { + break; + } + } + } return stream_size; @@ -1348,7 +1355,7 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead switch (ea->type) { case EAAC_TYPE_RAM: /* both header and data in SNR */ - data_size = calculate_eaac_size(streamHead, ea, ea->num_samples, ea->stream_offset); + data_size = calculate_eaac_size(streamHead, ea, ea->num_samples, ea->stream_offset, 1); if (data_size == 0) goto fail; new_streamFile = open_wrap_streamfile(streamHead); @@ -1361,7 +1368,7 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead break; case EAAC_TYPE_STREAM: /* header in SNR, data in SNS */ - data_size = calculate_eaac_size(streamData, ea, ea->num_samples, ea->stream_offset); + data_size = calculate_eaac_size(streamData, ea, ea->num_samples, ea->stream_offset, 0); if (data_size == 0) goto fail; new_streamFile = open_wrap_streamfile(streamData); @@ -1375,7 +1382,7 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead case EAAC_TYPE_GIGASAMPLE: /* header and prefetched data in SNR, rest of data in SNS */ /* open prefetched data */ - data_size = calculate_eaac_size(streamHead, ea, ea->prefetch_samples, ea->prefetch_offset); + data_size = calculate_eaac_size(streamHead, ea, ea->prefetch_samples, ea->prefetch_offset, 1); if (data_size == 0) goto fail; new_streamFile = open_wrap_streamfile(streamHead); @@ -1387,7 +1394,7 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead stream_segments[0] = new_streamFile; /* open main data */ - data_size = calculate_eaac_size(streamData, ea, ea->num_samples - ea->prefetch_samples, ea->stream_offset); + data_size = calculate_eaac_size(streamData, ea, ea->num_samples - ea->prefetch_samples, ea->stream_offset, 0); if (data_size == 0) goto fail; new_streamFile = open_wrap_streamfile(streamData); @@ -1412,7 +1419,7 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE *streamHead goto fail; } - data_size = calculate_eaac_size(streamHead, ea, ea->num_samples, ea->stream_offset); + data_size = calculate_eaac_size(streamHead, ea, ea->num_samples, ea->stream_offset, ea->type == EAAC_TYPE_RAM); if (data_size == 0) goto fail; new_streamFile = open_wrap_streamfile(streamHead); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index a8f92043b..50222ec81 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -177,11 +177,7 @@ VGMSTREAM * init_vgmstream_ea_schl_video(STREAMFILE *streamFile) { /* .dct: early-mid [ex. Need for Speed II SE (PC), FIFA 98 (PC)] */ /* .mad: mid */ /* .vp6: late */ - if (check_extensions(streamFile, "vp6")) { - /* check initial movie block id */ - if (read_32bitBE(0x00, streamFile) != 0x4D566864) /* "MVhd" */ - goto fail; - } else if (check_extensions(streamFile, "uv,dct")) { + if (check_extensions(streamFile, "uv,dct")) { /* starts with audio header block */ if (read_32bitBE(0x00, streamFile) != EA_BLOCKID_HEADER) /* "SCHl" */ goto fail; @@ -189,6 +185,10 @@ VGMSTREAM * init_vgmstream_ea_schl_video(STREAMFILE *streamFile) { /* check initial movie block id */ if (read_32bitBE(0x00, streamFile) != 0x4D41446B) /* "MADk" */ goto fail; + } else if (check_extensions(streamFile, "vp6")) { + /* check initial movie block id */ + if (read_32bitBE(0x00, streamFile) != 0x4D566864) /* "MVhd" */ + goto fail; } else { goto fail; } @@ -381,7 +381,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { if (target_entry_offset == 0) goto fail; - /* 0x00: type (0x00 - normal, 0x01 - streamed, 0x02 - streamed looped */ + /* 0x00: type (0x00 - normal, 0x01 - streamed, 0x02 - streamed looped) */ /* 0x01: ??? */ /* 0x04: index for normal sounds, offset for streamed sounds */ /* 0x08: loop offset for streamed sounds */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 1c901af63..183d39f1b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -343,8 +343,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { * .rws: Climax games (Silent Hill Origins PSP, Oblivion PSP) ATRAC3 * .aud: EA Replay ATRAC3 * .at9: standard ATRAC9 + * .saf: Whacked! (Xbox) */ - if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9") ) { + if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,saf") ) { ; } else if ( check_extensions(streamFile, "mwv") ) {