diff --git a/src/formats.c b/src/formats.c index 67400c09..8498e1b7 100644 --- a/src/formats.c +++ b/src/formats.c @@ -204,6 +204,7 @@ static const char* extension_list[] = { "lac3", //fake extension for .ac3, FFmpeg/not parsed "leg", "lflac", //fake extension for .flac, FFmpeg/not parsed + "lin", "lmp2", //fake extension for .mp2, FFmpeg/not parsed "lmp3", //fake extension for .mp3, FFmpeg/not parsed "lmp4", //fake extension for .mp4 @@ -220,6 +221,7 @@ static const char* extension_list[] = { "lwma", //fake extension for .wma, FFmpeg/not parsed "mab", + "map", "matx", "mc3", "mca", @@ -240,6 +242,7 @@ static const char* extension_list[] = { //"mpc", //common "mpdsp", "mpds", + "mpf", "mps", //txth/reserved [Scandal (PS2)] "ms", "msa", diff --git a/src/meta/ea_eaac.c b/src/meta/ea_eaac.c index 80f3f370..8c0d274d 100644 --- a/src/meta/ea_eaac.c +++ b/src/meta/ea_eaac.c @@ -462,6 +462,85 @@ fail: return NULL; } +/* EA MPF/MUS combo - used in older 7th gen games for storing music */ +VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE *streamFile) { + uint32_t num_sounds; + uint8_t version, sub_version, block_id; + off_t table_offset, entry_offset, snr_offset, sns_offset; + size_t snr_size, sns_size; + int32_t(*read_32bit)(off_t, STREAMFILE*); + int16_t(*read_16bit)(off_t, STREAMFILE*); + STREAMFILE *musFile = NULL; + VGMSTREAM *vgmstream = NULL; + int target_stream = streamFile->stream_index; + + /* check extension */ + if (!check_extensions(streamFile, "mpf")) + goto fail; + + /* detect endianness */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */ + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } else { + goto fail; + } + + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) goto fail; + + /* MPF format is unchanged but we don't really care about its contents since + * MUS conveniently contains sound offset table */ + + version = read_8bit(0x04, streamFile); + sub_version = read_8bit(0x05, streamFile); + if (version != 0x05 || sub_version != 0x03) goto fail; + + /* number of files is always little endian */ + num_sounds = read_32bitLE(0x04, musFile); + table_offset = 0x28; + + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || num_sounds == 0 || target_stream > num_sounds) + goto fail; + + /* + * 0x00: hash? + * 0x04: index + * 0x06: zero + * 0x08: SNR offset + * 0x0c: SNS offset + * 0x10: SNR size + * 0x14: SNS size + * 0x18: zero + */ + entry_offset = table_offset + (target_stream - 1) * 0x1c; + snr_offset = read_32bit(entry_offset + 0x08, musFile) * 0x10; + sns_offset = read_32bit(entry_offset + 0x0c, musFile) * 0x80; + snr_size = read_32bit(entry_offset + 0x10, musFile); + sns_size = read_32bit(entry_offset + 0x14, musFile); + + block_id = read_8bit(sns_offset, musFile); + if (block_id != EAAC_BLOCKID0_DATA && block_id != EAAC_BLOCKID0_END) + goto fail; + + vgmstream = init_vgmstream_eaaudiocore_header(musFile, musFile, snr_offset, sns_offset, meta_EA_SNR_SNS); + if (!vgmstream) + goto fail; + + vgmstream->num_streams = num_sounds; + vgmstream->stream_size = sns_size; + close_streamfile(musFile); + return vgmstream; + +fail: + close_streamfile(musFile); + return NULL; +} + /* ************************************************************************* */ typedef struct { diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index e3d04679..d8b6e6de 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -102,13 +102,13 @@ typedef struct { int codec_config; } ea_header; -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams); -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams); +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int standalone); +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded); static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length, int bnk_version); static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset); -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream); static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea); -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk, int total_streams); +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk, int standalone); +static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream, int standalone); /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { @@ -136,7 +136,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { /* Stream is divided into blocks/chunks: SCHl=audio header, SCCl=count of SCDl, SCDl=data xN, SCLl=loop end, SCEl=end. * Video uses picture blocks (MVhd/MV0K/etc) and sometimes multiaudio blocks (SHxx/SCxx/SDxx/SExx where xx=language). * The number/size is affected by: block rate setting, sample rate, channels, CPU location (SPU/main/DSP/others), etc */ - return parse_schl_block(streamFile, 0x00, 0); + return parse_schl_block(streamFile, 0x00, 1); fail: return NULL; @@ -271,7 +271,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { goto fail; bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1; - vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, total_sounds); + vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, 1); if (!vgmstream) goto fail; break; @@ -290,7 +290,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(astData, schl_offset, total_sounds); + vgmstream = parse_schl_block(astData, schl_offset, 0); if (!vgmstream) goto fail; break; @@ -300,6 +300,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { break; } + vgmstream->num_streams = total_sounds; close_streamfile(astData); return vgmstream; @@ -349,10 +350,11 @@ VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, datFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(datFile, schl_offset, total_sounds); + vgmstream = parse_schl_block(datFile, schl_offset, 0); if (!vgmstream) goto fail; + vgmstream->num_streams = total_sounds; close_streamfile(datFile); return vgmstream; @@ -361,97 +363,162 @@ fail: return NULL; } -/* EA IDX/BIG combo - basically a set of HDR/DAT compiled into one file */ -VGMSTREAM * init_vgmstream_ea_idx_big(STREAMFILE *streamFile) { - int target_stream = streamFile->stream_index, total_sounds, subsound_index; - uint32_t i, num_hdr; - uint16_t hdr_id, hdr_subid; - uint8_t userdata_size, hdr_sounds; - off_t entry_offset, hdr_offset, base_offset, schl_offset, offset_mult; - //size_t hdr_size; - char stream_name[STREAM_NAME_SIZE]; - STREAMFILE *bigFile = NULL; +/* EA MAP/MUS combo - used in some old games for interactive music info */ +VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) { + uint8_t num_sounds, num_userdata; + off_t section_offset, schl_offset; + STREAMFILE *musFile = NULL; VGMSTREAM *vgmstream = NULL; - int32_t (*read_32bit)(off_t,STREAMFILE*); - int16_t (*read_16bit)(off_t,STREAMFILE*); + int target_stream = streamFile->stream_index; - /* seems to always start with 0x00000001 */ - if (read_32bitLE(0x00, streamFile) != 0x00000001 && - read_32bitBE(0x00, streamFile) != 0x00000001) + /* check extension */ + if (!check_extensions(streamFile, "map,lin")) goto fail; - bigFile = open_streamfile_by_ext(streamFile, "big"); - if (!bigFile) + /* always big endian */ + if (read_32bitBE(0x00, streamFile) != 0x50464478) /* "PFDx" */ goto fail; - if (read_32bitBE(0x00, bigFile) != EA_BLOCKID_HEADER) - goto fail; + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) goto fail; - /* use number of files for endianness check */ - if (guess_endianness32bit(0x04,streamFile)) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } + /* + * 0x04: ??? + * 0x05: intro segment + * 0x06: number of segments + * 0x07: userdata entry size (incorrect?) + * 0x08: three zeroes + * 0x0b: number of userdata entries + * 0x0c: section 1 start + */ + num_sounds = read_8bit(0x06, streamFile); + num_userdata = read_8bit(0x0b, streamFile); + section_offset = 0x0c; - num_hdr = read_32bit(0x04, streamFile); - if (read_32bit(0x54,streamFile) != num_hdr) - goto fail; + /* section 1: contains information about segment playback order */ + section_offset += num_sounds * 0x1c; + + /* section 2: userdata, specific to game and track */ + section_offset += num_userdata * 0x10; if (target_stream == 0) target_stream = 1; - schl_offset = 0; - total_sounds = 0; - schl_offset = 0xFFFFFFFF; - - for (i = 0; i < num_hdr; i++) { - entry_offset = 0x58 + 0x10 * i; - //hdr_size = read_32bit(entry_offset + 0x04, streamFile); - hdr_offset = read_32bit(entry_offset + 0x08, streamFile); - base_offset = read_32bit(entry_offset + 0x0C, streamFile); - - hdr_id = read_16bit(hdr_offset + 0x00, streamFile); - hdr_subid = read_16bit(hdr_offset + 0x02, streamFile); - userdata_size = read_8bit(hdr_offset + 0x04, streamFile) & 0x0F; - hdr_sounds = read_8bit(hdr_offset + 0x05, streamFile); - offset_mult = (off_t)read_8bit(hdr_offset + 0x07, streamFile) * 0x0100 + 0x0100; - - if (target_stream > total_sounds && target_stream <= total_sounds + hdr_sounds) { - schl_offset = base_offset + (off_t)read_16bitBE(hdr_offset + 0x0C + (0x02+userdata_size) * (target_stream-total_sounds-1), streamFile) * offset_mult; - subsound_index = target_stream - total_sounds; - - /* There are no filenames but we can add IDs to stream name for better organization */ - if (hdr_subid != 0xFFFF) - snprintf(stream_name, STREAM_NAME_SIZE, "%03d_%02d_%d", hdr_id, hdr_subid, subsound_index); - else - snprintf(stream_name, STREAM_NAME_SIZE, "%03d_%d", hdr_id, subsound_index); - } - - total_sounds += hdr_sounds; - } - - if (schl_offset == 0xFFFFFFFF) + if (target_stream < 0 || num_sounds == 0 || target_stream > num_sounds) goto fail; - if (read_32bitBE(schl_offset, bigFile) != EA_BLOCKID_HEADER) + /* section 3: sound offset table */ + schl_offset = read_32bitBE(section_offset + (target_stream - 1) * 0x04, streamFile); + if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(bigFile, schl_offset, total_sounds); + vgmstream = parse_schl_block(musFile, schl_offset, 0); if (!vgmstream) goto fail; - strncpy(vgmstream->stream_name, stream_name, STREAM_NAME_SIZE); - close_streamfile(bigFile); + vgmstream->num_streams = num_sounds; + close_streamfile(musFile); return vgmstream; fail: - close_streamfile(bigFile); + close_streamfile(musFile); + return NULL; +} + +/* EA MPF/MUS combo - used in newer 6th gen games for storing music */ +VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) { + off_t section_offset, entry_offset, subentry_num, eof_offset, schl_offset; + uint16_t sec1_num; + uint8_t version, sub_version, sec2_num; + int32_t(*read_32bit)(off_t, STREAMFILE*); + int16_t(*read_16bit)(off_t, STREAMFILE*); + STREAMFILE *musFile = NULL; + VGMSTREAM *vgmstream = NULL; + int target_stream = streamFile->stream_index, total_streams; + + /* check extension */ + if (!check_extensions(streamFile, "mpf")) + goto fail; + + /* detect endianness */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */ + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } else { + goto fail; + } + + musFile = open_streamfile_by_ext(streamFile, "mus"); + if (!musFile) goto fail; + + version = read_8bit(0x04, streamFile); + sub_version = read_8bit(0x05, streamFile); + + if (version < 0x04 || version > 0x05) goto fail; + if (version == 0x05 && sub_version > 0x02) goto fail; /* newer version using SNR/SNS */ + + if (version == 0x04) { + /* we need to go through the first two sections to find sound table */ + sec1_num = read_16bit(0x12, streamFile); + sec2_num = read_8bit(0x0f, streamFile); + + /* get the last entry offset */ + section_offset = 0x20; + entry_offset = read_16bit(section_offset + (sec1_num - 1) * 0x02, streamFile) * 0x04; + + /* HACK: there's some weird bitstream here that's stored differently in LE and BE */ + /* I can't figure it out, so let's just use a workaround for now */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 15) & 0xFF; + } else { + subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 20) & 0xFF; + } + + section_offset = entry_offset + 0x10 + subentry_num * 0x04; + entry_offset = read_16bit(section_offset + (sec2_num - 1) * 0x02, streamFile) * 0x04; + + /* more weird stuff */ + if (read_32bitBE(0x00, streamFile) == 0x50464478) { + subentry_num = (read_32bitBE(entry_offset + 0x0c, streamFile) >> 10) & 0xFF; + } else { + subentry_num = (read_32bitBE(entry_offset + 0x0c, streamFile) >> 8) & 0xFF; + } + + section_offset = entry_offset + 0x10 + subentry_num * 0x10; + entry_offset = read_32bit(section_offset, streamFile) * 0x04; + section_offset = read_32bit(entry_offset + 0x00, streamFile) * 0x04; + eof_offset = read_32bit(entry_offset + 0x04, streamFile) * 0x04; + total_streams = (eof_offset - section_offset) / 0x08; + } else if (version == 0x05) { + section_offset = read_32bit(0x34, streamFile); + eof_offset = read_32bit(0x38, streamFile); + total_streams = (eof_offset - section_offset) / 0x08; + } + + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || total_streams == 0 || target_stream > total_streams) + goto fail; + + schl_offset = read_32bit(section_offset + (target_stream - 1) * 0x08 + 0x00, streamFile) * 0x80; + if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) + goto fail; + + vgmstream = parse_schl_block(musFile, schl_offset, 0); + if (!vgmstream) + goto fail; + + vgmstream->num_streams = total_streams; + close_streamfile(musFile); + return vgmstream; + +fail: + close_streamfile(musFile); return NULL; } /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams) { +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int standalone) { off_t start_offset, header_offset; size_t header_size; ea_header ea = { 0 }; @@ -472,19 +539,20 @@ static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int to start_offset = offset + header_size; /* starts in "SCCl" (skipped in block layout) or very rarely "SCDl" and maybe movie blocks */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0, total_streams); + return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0, standalone); fail: return NULL; } /* EA BNK with variable header - from EA games SFXs; also created by sx.exe */ -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams) { +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded) { off_t header_offset, start_offset, test_offset, table_offset; size_t header_size; ea_header ea = {0}; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + VGMSTREAM *vgmstream = NULL; int i, bnk_version; int total_bnk_sounds, real_bnk_sounds = 0; @@ -535,7 +603,7 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta real_bnk_sounds++; /* ABK points at absolute indexes, i.e. with dummies included */ - if (total_streams != 0) { + if (is_embedded != 0) { if (target_stream - 1 == i) header_offset = offset + table_offset + 0x04 * i + test_offset; } @@ -562,14 +630,20 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta start_offset = ea.offsets[0]; /* first channel, presumably needed for MPEG */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, total_streams ? total_streams : real_bnk_sounds); + vgmstream = init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, 0); + if (!vgmstream) goto fail; + if (!is_embedded) { + vgmstream->num_streams = real_bnk_sounds; + } + + return vgmstream; fail: return NULL; } /* inits VGMSTREAM from a EA header */ -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version, int total_streams) { +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version, int standalone) { VGMSTREAM * vgmstream = NULL; int i, ch; int is_bnk = bnk_version; @@ -616,9 +690,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ vgmstream->layout_type = layout_blocked_ea_schl; } - vgmstream->num_streams = total_streams; - //vgmstream->stream_size = ; //todo needed for kbps info - /* EA usually implements their codecs in all platforms (PS2/WII do EAXA/MT/EALAYER3) and * favors them over platform's natives (ex. EAXA vs VAG/DSP). * Unneeded codecs are removed over time (ex. LAYER3 when EALAYER3 was introduced). */ @@ -800,15 +871,11 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ vgmstream->ch[i].offset = ea->offsets[i]; } } + + /* TODO: Figure out how to get stream size for BNK sounds */ } - else if (vgmstream->layout_type == layout_blocked_ea_schl) { - /* regular SCHls, except ATRAC3plus */ - if (total_streams == 0) { - /* HACK: fix num_samples for streams with multiple SCHl. Need to eventually get rid of this */ - int total_samples = get_ea_stream_total_samples(streamFile, start_offset, vgmstream); - if (total_samples > vgmstream->num_samples) - vgmstream->num_samples = total_samples; - } + else { + update_ea_stream_size_and_samples(streamFile, start_offset, vgmstream, standalone); } return vgmstream; @@ -1198,38 +1265,52 @@ fail: return 0; } -/* Get total samples by parsing block headers, needed when multiple files are stitched together. - * Some EA files (.mus/eam/sng/etc) concat many small subfiles, used for interactive/mapped - * music (.map/lin). Subfiles always share header, except num_samples. */ -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream) { - int num_samples = 0; - int multiple_schl = 0; +static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM *vgmstream, int standalone) { + uint32_t block_id; + int32_t num_samples; + size_t stream_size, file_size; + int multiple_schl; - /* calc num_samples as playable data size varies between files/blocks */ - { - vgmstream->next_block_offset = start_offset; - do { - uint32_t block_id = read_32bitBE(vgmstream->next_block_offset+0x00,streamFile); - if (block_id == EA_BLOCKID_HEADER) /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ - multiple_schl = 1; + stream_size = 0, num_samples = 0, multiple_schl = 0; + file_size = get_streamfile_size(streamFile); + vgmstream->next_block_offset = start_offset; - block_update_ea_schl(vgmstream->next_block_offset,vgmstream); - num_samples += vgmstream->current_block_samples; + while (vgmstream->next_block_offset < file_size) { + block_update_ea_schl(vgmstream->next_block_offset, vgmstream); + + block_id = read_32bitBE(vgmstream->current_block_offset + 0x00, streamFile); + if (block_id == EA_BLOCKID_END) { /* banks should never contain movie "SHxx" */ + if (!standalone) + break; + } + else if (block_id == EA_BLOCKID_HEADER) { /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ + multiple_schl = 1; } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - /* reset after getting samples */ - block_update(start_offset,vgmstream); + /* HACK: fix num_samples for streams with multiple SCHl. Need to eventually get rid of this. + * Get total samples by parsing block headers, needed when multiple files are stitched together. + * Some EA files (.mus/eam/sng/etc) concat many small subfiles, used for interactive/mapped + * music (.map/lin). Subfiles always share header, except num_samples. */ + num_samples += vgmstream->current_block_samples; + + /* Stream size is almost never provided in bank files so we have to calc it manually */ + if (vgmstream->current_block_samples != 0) { + stream_size += vgmstream->next_block_offset - vgmstream->current_block_offset - 0x0c; + } } + /* reset once we're done */ + block_update(start_offset, vgmstream); + /* only use calculated samples with multiple subfiles (rarely header samples may be less due to padding) */ - if (multiple_schl) { - ;VGM_LOG("EA SCHl: multiple SCHl found\n"); - return num_samples; - } - else { - return 0; + if (standalone && multiple_schl) { + VGM_LOG("EA SCHl: multiple SCHl found\n"); + if (num_samples > vgmstream->num_samples) { + vgmstream->num_samples = num_samples; + } } + + vgmstream->stream_size = stream_size; } /* find data start offset inside the first SCDl; not very elegant but oh well */ diff --git a/src/meta/meta.h b/src/meta/meta.h index 9b392cea..a16a651c 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -645,7 +645,8 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_idx_big(STREAMFILE * steeamFile); +VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE * steeamFile); +VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE * steeamFile); VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); @@ -683,6 +684,7 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_abk_new(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_hdr_sth_dat(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index e2b36462..4655076b 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -352,7 +352,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ea_bnk, init_vgmstream_ea_abk, init_vgmstream_ea_hdr_dat, - init_vgmstream_ea_idx_big, + init_vgmstream_ea_map_mus, + init_vgmstream_ea_mpf_mus, init_vgmstream_ea_schl_fixed, init_vgmstream_sk_aud, init_vgmstream_stm, @@ -377,6 +378,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ea_sps, init_vgmstream_ea_abk_new, init_vgmstream_ea_hdr_sth_dat, + init_vgmstream_ea_mpf_mus_new, init_vgmstream_ngc_vid1, init_vgmstream_flx, init_vgmstream_mogg,