From d0bb4d964e93d05205e4d41b30748d5b645a3bea Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 10 Mar 2019 11:11:27 +0100 Subject: [PATCH] Add non-demuxed EA SCHl .vp6 videos with multilang subsongs --- src/formats.c | 1 + src/meta/ea_schl.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ src/meta/meta.h | 1 + src/vgmstream.c | 1 + 4 files changed, 86 insertions(+) diff --git a/src/formats.c b/src/formats.c index ced8d4f6..047ecb37 100644 --- a/src/formats.c +++ b/src/formats.c @@ -458,6 +458,7 @@ static const char* extension_list[] = { "vis", "vms", "voi", + "vp6", "vpk", "vs", "vsf", diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index b388b575..16d3c57e 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -160,6 +160,89 @@ fail: return NULL; } +/* EA SCHl inside non-demuxed videos, used in current gen games too */ +VGMSTREAM * init_vgmstream_ea_schl_video(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t offset = 0, start_offset = 0; + int blocks_done = 0; + int total_subsongs, target_subsong = streamFile->stream_index; + int32_t(*read_32bit)(off_t, STREAMFILE*); + + + /* check extension */ + /* .vp6: ~late */ + if (!check_extensions(streamFile,"vp6")) + goto fail; + + /* check initial movie block id */ + if (read_32bitBE(0x00,streamFile) != 0x4D566864) /* "MVhd" */ + goto fail; + + /* use block size to check endianness */ + if (guess_endianness32bit(0x04, streamFile)) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; + } + + /* find starting valid header for the parser */ + while (offset < get_streamfile_size(streamFile)) { + uint32_t block_id = read_32bitBE(offset+0x00,streamFile); + uint32_t block_size = read_32bit (offset+0x04,streamFile); + + /* find "SCHl" or "SHxx" blocks */ + if ((block_id == EA_BLOCKID_HEADER) || ((block_id & 0xFFFF0000) == EA_BLOCKID_LOC_HEADER)) { + start_offset = offset; + break; + } + + if (block_size == 0xFFFFFFFF) + goto fail; + if (blocks_done > 10) + goto fail; /* unlikely to contain music */ + + blocks_done++; + offset += block_size; + } + + if (start_offset == 0) + goto fail; + + /* find target subsong (one per each SHxx multilang block) */ + total_subsongs = 1; + if (target_subsong == 0) target_subsong = 1; + offset = start_offset; + while (offset < get_streamfile_size(streamFile)) { + uint32_t block_id = read_32bitBE(offset+0x00,streamFile); + uint32_t block_size = read_32bit (offset+0x04,streamFile); + + /* no more subsongs (assumes all SHxx headers go together) */ + if (((block_id & 0xFFFF0000) != EA_BLOCKID_LOC_HEADER)) { + break; + } + + if (target_subsong == total_subsongs) { + start_offset = offset; + /* keep counting subsongs */ + } + + total_subsongs++; + offset += block_size; + } + + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + vgmstream = parse_schl_block(streamFile, start_offset, 1); + if (!vgmstream) goto fail; + + vgmstream->num_streams = total_subsongs; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + /* EA BNK with variable header - from EA games SFXs; also created by sx.exe */ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) { off_t offset; diff --git a/src/meta/meta.h b/src/meta/meta.h index 0922d341..9cb2acb2 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -639,6 +639,7 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_txth(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_ea_schl_video(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE * streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index 89134ff3..ff915477 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -472,6 +472,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_mus_vc, init_vgmstream_strm_abylight, init_vgmstream_sfh, + init_vgmstream_ea_schl_video, /* 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 */