From ae66dd42a6f401c19391067ef126fce9afc4ca37 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 12 Mar 2019 00:41:20 +0100 Subject: [PATCH] Add Konami MSF/XWMA [Metal Gear Solid 3 HD (PS3/X360)] --- src/formats.c | 2 + src/libvgmstream.vcproj | 8 ++++ src/libvgmstream.vcxproj | 2 + src/libvgmstream.vcxproj.filters | 6 +++ src/meta/meta.h | 4 ++ src/meta/msf_konami.c | 58 +++++++++++++++++++++++ src/meta/xwma_konami.c | 79 ++++++++++++++++++++++++++++++++ src/vgmstream.c | 2 + src/vgmstream.h | 2 + 9 files changed, 163 insertions(+) create mode 100644 src/meta/msf_konami.c create mode 100644 src/meta/xwma_konami.c diff --git a/src/formats.c b/src/formats.c index 27ae46d6..658713d7 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1175,6 +1175,8 @@ static const meta_info meta_info_list[] = { {meta_DSP_DS2, "LucasArts .DS2 header"}, {meta_MUS_VC, "Vicious Cycle .MUS header"}, {meta_STRM_ABYLIGHT, "Abylight STRM header"}, + {meta_MSF_KONAMI, "Konami MSF header"}, + {meta_XWMA_KONAMI, "Konami XWMA header"}, }; diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index de375571..db855ca6 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -1130,6 +1130,10 @@ RelativePath=".\meta\msf_banpresto.c" > + + @@ -1705,6 +1709,10 @@ + + + @@ -501,6 +502,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index cf529bcc..dcfc64e8 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1042,6 +1042,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1450,6 +1453,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 4b7f8c94..66b4b4a2 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -841,4 +841,8 @@ VGMSTREAM * init_vgmstream_strm_abylight(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sfh(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_msf_konami(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE* streamFile); + #endif /*_META_H*/ diff --git a/src/meta/msf_konami.c b/src/meta/msf_konami.c new file mode 100644 index 00000000..6c8b5fe0 --- /dev/null +++ b/src/meta/msf_konami.c @@ -0,0 +1,58 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (PS3), Metal Gear Solid 3 HD (PS3)] */ +VGMSTREAM * init_vgmstream_msf_konami(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + uint32_t codec; + int loop_flag, channel_count, sample_rate; + size_t data_size; + + + /* checks */ + if (!check_extensions(streamFile,"msf")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x4D534643) /* "MSFC" */ + goto fail; + + start_offset = 0x20; + + codec = read_32bitBE(0x04,streamFile); + channel_count = read_32bitBE(0x08,streamFile); + sample_rate = read_32bitBE(0x0c,streamFile); + data_size = read_32bitBE(0x10,streamFile); /* without header */ + if (data_size + start_offset != get_streamfile_size(streamFile)) + goto fail; + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MSF_KONAMI; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0x01: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); + break; + + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/xwma_konami.c b/src/meta/xwma_konami.c new file mode 100644 index 00000000..b70dda64 --- /dev/null +++ b/src/meta/xwma_konami.c @@ -0,0 +1,79 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (X360), Metal Gear Solid 3 HD (X360)] */ +VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, codec, sample_rate; + size_t data_size; + + + /* checks */ + if (!check_extensions(streamFile,"xwma")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x58574D41) /* "XWMA" */ + goto fail; + + codec = read_32bitBE(0x04,streamFile); + channel_count = read_32bitBE(0x08,streamFile); + sample_rate = read_32bitBE(0x0c,streamFile); + data_size = read_32bitBE(0x10,streamFile); + loop_flag = 0; + start_offset = 0x20; + //if (data_size + start_offset != get_streamfile_size(streamFile)) + // goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->meta_type = meta_XWMA_KONAMI; + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + int bytes, avg_bps, block_align; + + /* 0x10: related to size? */ + avg_bps = read_32bitBE(0x14, streamFile); + block_align = read_32bitBE(0x18, streamFile); + + bytes = ffmpeg_make_riff_xwma(buf,0x100, codec, data_size, channel_count, sample_rate, avg_bps, block_align); + 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; + + /* manually find total samples */ + { + ms_sample_data msd = {0}; + + msd.channels = vgmstream->channels; + msd.data_offset = start_offset; + msd.data_size = data_size; + + if (codec == 0x0162) + ;//wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0); //todo not correct + else + wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F); + + vgmstream->num_samples = msd.num_samples; + if (vgmstream->num_samples == 0) + vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ + //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 + } + } +#else + goto fail; +#endif + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 935a1d37..8da9d92c 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -474,6 +474,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_strm_abylight, init_vgmstream_sfh, init_vgmstream_ea_schl_video, + init_vgmstream_msf_konami, + init_vgmstream_xwma_konami, /* 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 */ diff --git a/src/vgmstream.h b/src/vgmstream.h index 9a3af493..395c9ba5 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -727,6 +727,8 @@ typedef enum { meta_DSP_DS2, meta_MUS_VC, meta_STRM_ABYLIGHT, + meta_MSF_KONAMI, + meta_XWMA_KONAMI, } meta_t;