From 693842ea099753bab2e9515651b72c4c660b96dd Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 22:25:15 +0200 Subject: [PATCH 01/10] Fix short .mds coefs [T3: The Redemption (GC), MI: Operation Surma (GC)] --- src/meta/ngc_dsp_mpds.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/meta/ngc_dsp_mpds.c b/src/meta/ngc_dsp_mpds.c index 68e43df8..fc492dce 100644 --- a/src/meta/ngc_dsp_mpds.c +++ b/src/meta/ngc_dsp_mpds.c @@ -9,30 +9,30 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) { int loop_flag = 0, channel_count, short_mpds; - /* check extension, case insensitive */ + /* checks */ /* .dsp: Big Air Freestyle */ /* .mds: Terminator 3 The Redemption, Mission Impossible: Operation Surma */ - if (!check_extensions(streamFile, "dsp,mds")) goto fail; - - /* check header */ + if (!check_extensions(streamFile, "dsp,mds")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x4D504453) /* "MPDS" */ goto fail; - short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && check_extensions(streamFile, "mds"); /* version byte? */ + short_mpds = read_32bitBE(0x04,streamFile) != 0x00010000 && /* version byte? */ + check_extensions(streamFile, "mds"); channel_count = short_mpds ? read_16bitBE(0x0a, streamFile) : read_32bitBE(0x14, streamFile); if (channel_count > 2) goto fail; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->coding_type = coding_NGC_DSP; vgmstream->meta_type = meta_NGC_DSP_MPDS; - vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; if (!short_mpds) { /* Big Air Freestyle */ start_offset = 0x80; @@ -50,17 +50,22 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) { vgmstream->num_samples = read_32bitBE(0x04,streamFile); vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile); vgmstream->interleave_block_size = channel_count==1 ? 0 : 0x200; + /* some kind of hist after 0x0c? */ -#if 0 //unknown coeffs/hist, related to data after 0x0c? (only coefs 0..7 seem to be needed) + /* set coefs, debugged from the MI:OS ELF (helpfully marked as "sMdsCoefs") */ { - off_t offset = 0x0c; - int i,ch; - for (ch=0; ch < vgmstream->channels; ch++) { - for (i=0; i < 16; i++) - vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(offset + i*2); + static const int16_t coefs[16] = { + 0x0000,0x0000,0x0780,0x0000,0x0e60,0xf980,0x0c40,0xf920, + 0x0f40,0xf880,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 + }; + int i, ch; + + for (ch = 0; ch < channel_count; ch++) { + for (i = 0; i < 16; i++) { + vgmstream->ch[ch].adpcm_coef[i] = coefs[i]; + } } } -#endif } From 2d968064dc75612ead6419ab0bc9ca69af53549b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 22:25:45 +0200 Subject: [PATCH 02/10] Fix some FFX .vs --- src/meta/vs_ffx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/meta/vs_ffx.c b/src/meta/vs_ffx.c index a7e71e94..6fbb095b 100644 --- a/src/meta/vs_ffx.c +++ b/src/meta/vs_ffx.c @@ -5,7 +5,7 @@ /* .vs/VS - from Final Fantasy X voices (PS2) */ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - int channel_count, loop_flag; + int channel_count, loop_flag, pitch; off_t start_offset; @@ -20,6 +20,7 @@ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { loop_flag = 0; channel_count = 1; start_offset = 0x00; + pitch = read_32bitLE(0x10,streamFile); /* build the VGMSTREAM */ @@ -27,7 +28,7 @@ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { if (!vgmstream) goto fail; vgmstream->meta_type = meta_VS_FFX; - vgmstream->sample_rate = 48000; + vgmstream->sample_rate = (48000 * pitch) / 4096; /* needed for rare files, sounds ok */ vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_blocked_vs_ffx; From fb3091502c8ceaa8936678e5e073b4f917786a02 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 22:26:21 +0200 Subject: [PATCH 03/10] Fix some truncated .wem --- src/meta/wwise.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/meta/wwise.c b/src/meta/wwise.c index 9f96f87b..174f08e3 100644 --- a/src/meta/wwise.c +++ b/src/meta/wwise.c @@ -369,9 +369,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { start_offset += audio_offset; - /* Vorbis is VBR so this is very approximate, meh */ + /* Vorbis is VBR so this is very approximate percent, meh */ if (ww.truncated) - vgmstream->num_samples = vgmstream->num_samples * (ww.file_size - start_offset) / ww.data_size; + vgmstream->num_samples = (int32_t)(vgmstream->num_samples * + (double)(ww.file_size - start_offset) / (double)ww.data_size); break; } From 7cde6bdf8b8f1554bad89b5a95c1cb081c3f028a Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 22:33:26 +0200 Subject: [PATCH 04/10] Add .str SPSD extension [Shenmue (DC)] --- src/meta/naomi_spsd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/meta/naomi_spsd.c b/src/meta/naomi_spsd.c index 5780774b..f9b5e768 100644 --- a/src/meta/naomi_spsd.c +++ b/src/meta/naomi_spsd.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -/* SPSD - Naomi (arcade) streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */ +/* SPSD - Naomi (arcade) and early Dreamcast streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; @@ -10,8 +10,9 @@ VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { /* checks */ - /* .spsd: header id */ - if (!check_extensions(streamFile, "spsd")) + /* .str: actual extension, rare [Shenmue (DC)] + * .spsd: header id */ + if (!check_extensions(streamFile, "str,spsd")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */ goto fail; From 0e16a309e2726026dfa8cc8b7a3cb16b542e4abc Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 23:10:03 +0200 Subject: [PATCH 05/10] Add 2MSF and clean WMSF [Super Robot Taisen OG: The Moon Dwellers (PS4)] --- src/coding/coding.h | 4 +++ src/coding/coding_utils.c | 28 +++++++++++++++ src/libvgmstream.vcproj | 4 +++ src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 3 ++ src/meta/meta.h | 3 ++ src/meta/msf_banpresto.c | 62 ++++++++++++++++++++++++++++++++ src/meta/ps3_msf.c | 48 ++++++++++++------------- src/vgmstream.c | 2 ++ 9 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 src/meta/msf_banpresto.c diff --git a/src/coding/coding.h b/src/coding/coding.h index 6dcd1784..79b3b816 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -352,4 +352,8 @@ typedef struct { int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value); int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value); + +/* helper to pass a wrapped, clamped, fake extension-ed, SF to another meta */ +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension); + #endif /*_CODING_H*/ diff --git a/src/coding/coding_utils.c b/src/coding/coding_utils.c index 38915e1d..b63e65d6 100644 --- a/src/coding/coding_utils.c +++ b/src/coding/coding_utils.c @@ -1080,3 +1080,31 @@ int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) { else return w_bits_msf(ob,num_bits,value); } + +/* ******************************************** */ +/* CUSTOM STREAMFILES */ +/* ******************************************** */ + +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + if (extension) { + new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,extension); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + } + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 660cb833..82ad20b7 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -1073,6 +1073,10 @@ + + + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 74f584ab..5e67de9a 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1390,6 +1390,9 @@ meta\Source Files + + meta\Source Files + coding\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 08ce7489..cde39f62 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -801,4 +801,7 @@ VGMSTREAM * init_vgmstream_xopus(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE * streamFile); + #endif /*_META_H*/ diff --git a/src/meta/msf_banpresto.c b/src/meta/msf_banpresto.c new file mode 100644 index 00000000..ca63a961 --- /dev/null +++ b/src/meta/msf_banpresto.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */ +VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t subfile_offset = 0x10; + size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; + + + /* checks */ + if ( !check_extensions(streamFile,"msf")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x574D5346) /* "WMSF" */ + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null? */ + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_ps3_msf(temp_streamFile); + if (!vgmstream) goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} + +/* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */ +VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t subfile_offset = 0x14; + size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; + + + /* checks */ + if ( !check_extensions(streamFile,"at9")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x324D5346) /* "2MSF" */ + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */ + + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); + if (!temp_streamFile) goto fail; + + vgmstream = init_vgmstream_riff(temp_streamFile); + if (!vgmstream) goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/ps3_msf.c b/src/meta/ps3_msf.c index d76850ef..52e10b06 100644 --- a/src/meta/ps3_msf.c +++ b/src/meta/ps3_msf.c @@ -4,32 +4,30 @@ /* MSF - Sony's PS3 SDK format (MultiStream File) */ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset, header_offset = 0; + off_t start_offset; uint32_t data_size, loop_start = 0, loop_end = 0; uint32_t id, codec_id, flags; int loop_flag = 0, channel_count; /* checks */ - /* .msf: standard, .at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection */ + /* .msf: standard + * .at3: Silent Hill HD Collection (PS3) + * .mp3: Darkstalkers Resurrection (PS3) */ if (!check_extensions(streamFile,"msf,at3,mp3")) goto fail; - /* "WMSF" variation with a mini header over the MSFC header [Dai-2-Ji Super Robot Generations (PS3)] */ - if (read_32bitBE(0x00,streamFile) == 0x574D5346) { - header_offset = 0x10; - } - start_offset = header_offset+0x40; /* MSF header is always 0x40 */ + start_offset = 0x40; - /* check header "MSF" + version-char - * usually "MSF\0\1", "MSF\0\2", "MSF0"(\3\0), "MSF5"(\3\5), "MSFC"(\4\3) (last/common version) */ - id = read_32bitBE(header_offset+0x00,streamFile); + /* check header "MSF" + version-char, usually: + * 0x01, 0x02, 0x30 ("0"), 0x35 ("5"), 0x43 ("C") (last/most common version) */ + id = read_32bitBE(0x00,streamFile); if ((id & 0xffffff00) != 0x4D534600) goto fail; - codec_id = read_32bitBE(header_offset+0x04,streamFile); - channel_count = read_32bitBE(header_offset+0x08,streamFile); - data_size = read_32bitBE(header_offset+0x0C,streamFile); /* without header */ + codec_id = read_32bitBE(0x04,streamFile); + channel_count = read_32bitBE(0x08,streamFile); + data_size = read_32bitBE(0x0C,streamFile); /* without header */ if (data_size == 0xFFFFFFFF) /* unneeded? */ data_size = get_streamfile_size(streamFile) - start_offset; @@ -39,15 +37,15 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { * 0x20: VBR MP3 source (changed into simplified 0x1a1 CBR) * 0x40: joint stereo MP3 (apparently interleaved stereo for other formats) * 0x80+: (none/reserved) */ - flags = read_32bitBE(header_offset+0x14,streamFile); + flags = read_32bitBE(0x14,streamFile); /* sometimes loop_start/end is set with flag 0x10, but from tests it only loops if 0x01/02 is set * 0x10 often goes with 0x01 but not always (Castlevania HoD); Malicious PS3 uses flag 0x2 instead */ loop_flag = flags != 0xffffffff && ((flags & 0x01) || (flags & 0x02)); /* loop markers (marker N @ 0x18 + N*(4+4), but in practice only marker 0 is used) */ if (loop_flag) { - loop_start = read_32bitBE(header_offset+0x18,streamFile); - loop_end = read_32bitBE(header_offset+0x1C,streamFile); /* loop duration */ + loop_start = read_32bitBE(0x18,streamFile); + loop_end = read_32bitBE(0x1C,streamFile); /* loop duration */ loop_end = loop_start + loop_end; /* usually equals data_size but not always */ if (loop_end > data_size)/* not seen */ loop_end = data_size; @@ -58,9 +56,9 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* sample rate hack for strange MSFv1 files that don't have it */ - vgmstream->sample_rate = read_32bitBE(header_offset+0x10,streamFile); - if (vgmstream->sample_rate == 0x00000000) /* PS ADPCM only? */ + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + /* sample rate hack for strange MSFv1 files (PS ADPCM only?) */ + if (vgmstream->sample_rate == 0x00000000) vgmstream->sample_rate = 48000; vgmstream->meta_type = meta_PS3_MSF; @@ -115,12 +113,10 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { * (note that encoder may add a fade-in with looping/resampling enabled but should be skipped) */ encoder_delay = 1162; vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_size) - encoder_delay; - if (vgmstream->sample_rate==0xFFFFFFFF) /* some MSFv1 (Digi World SP) */ - vgmstream->sample_rate = 44100;//voice tracks seems to use 44khz, not sure about other tracks + if (vgmstream->sample_rate == 0xFFFFFFFF) /* some MSFv1 (Digi World SP) */ + vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */ bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); - if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); if (!ffmpeg_data) goto fail; vgmstream->codec_data = ffmpeg_data; @@ -156,7 +152,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { if (loop_flag) { vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - /* loops are always CBR frame beginnings */ + /* loops are always aligned to CBR frame beginnings */ } /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ @@ -164,7 +160,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { } #endif #ifdef VGM_USE_MPEG - case 0x07: { /* MPEG (CBR LAME MP3) []Dengeki Bunko Fighting Climax (PS3) */ + case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */ mpeg_codec_data *mpeg_data = NULL; mpeg_data = init_mpeg(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels); @@ -176,7 +172,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { if (loop_flag) { vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); - /* loops are always CBR frame beginnings */ + /* loops are always aligned to CBR frame beginnings */ } /* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 9bda15d1..320afdb6 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -445,6 +445,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_xwma, init_vgmstream_xopus, init_vgmstream_vs_ffx, + init_vgmstream_msf_banpresto_wmsf, + init_vgmstream_msf_banpresto_2msf, /* 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 */ From 466f3af458c4964a76d2c4c60014a7dc42bfd4c3 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 23:49:08 +0200 Subject: [PATCH 06/10] Subfile streamfile cleanup --- src/coding/coding.h | 2 +- src/coding/coding_utils.c | 2 +- src/meta/aax.c | 27 +-------------------------- src/meta/atsl.c | 27 +-------------------------- src/meta/nus3bank.c | 27 +-------------------------- src/meta/opus_ppp.c | 27 +-------------------------- src/meta/ps2_ads.c | 27 --------------------------- src/meta/sps_n1.c | 29 ++--------------------------- src/meta/ubi_jade.c | 30 ++---------------------------- src/meta/xwb.c | 26 -------------------------- 10 files changed, 10 insertions(+), 214 deletions(-) diff --git a/src/coding/coding.h b/src/coding/coding.h index 79b3b816..aa9d0827 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -354,6 +354,6 @@ int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value); /* helper to pass a wrapped, clamped, fake extension-ed, SF to another meta */ -STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension); +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* extension); #endif /*_CODING_H*/ diff --git a/src/coding/coding_utils.c b/src/coding/coding_utils.c index b63e65d6..158c5e4e 100644 --- a/src/coding/coding_utils.c +++ b/src/coding/coding_utils.c @@ -1085,7 +1085,7 @@ int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) { /* CUSTOM STREAMFILES */ /* ******************************************** */ -STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension) { +STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* extension) { STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; new_streamFile = open_wrap_streamfile(streamFile); diff --git a/src/meta/aax.c b/src/meta/aax.c index 1ad4dbaa..3418620e 100644 --- a/src/meta/aax.c +++ b/src/meta/aax.c @@ -3,8 +3,6 @@ #include "../coding/coding.h" #include "aax_utf.h" -static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - #define MAX_SEGMENTS 2 /* usually segment0=intro, segment1=loop/main */ @@ -77,7 +75,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { /* open each segment subfile */ for (i = 0; i < segment_count; i++) { - STREAMFILE* temp_streamFile = setup_aax_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx")); + STREAMFILE* temp_streamFile = setup_subfile_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx")); if (!temp_streamFile) goto fail; data->segments[i] = is_hca ? @@ -138,29 +136,6 @@ fail: return NULL; } -static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - /* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { diff --git a/src/meta/atsl.c b/src/meta/atsl.c index 7ec19024..b469c2da 100644 --- a/src/meta/atsl.c +++ b/src/meta/atsl.c @@ -1,7 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_atsl_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); typedef enum { ATRAC3, ATRAC9, KOVS, KTSS } atsl_codec; /* .ATSL - Koei Tecmo audio container [One Piece Pirate Warriors (PS3), Warriors All-Stars (PC)] */ @@ -110,7 +109,7 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) { /* some kind of seek/switch table may follow (optional, found in .atsl3) */ - temp_streamFile = setup_atsl_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); if (!temp_streamFile) goto fail; /* init the VGMSTREAM */ @@ -144,27 +143,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - - -static STREAMFILE* setup_atsl_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/nus3bank.c b/src/meta/nus3bank.c index f47919ae..48b749d7 100644 --- a/src/meta/nus3bank.c +++ b/src/meta/nus3bank.c @@ -1,7 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); typedef enum { /*XMA_RAW, ATRAC3,*/ IDSP, ATRAC9, OPUS, BNSF, /*PCM, XMA_RIFF*/ } nus3bank_codec; /* .nus3bank - Namco's newest audio container [Super Smash Bros (Wii U), idolmaster (PS4))] */ @@ -144,7 +143,7 @@ VGMSTREAM * init_vgmstream_nus3bank(STREAMFILE *streamFile) { //;VGM_LOG("NUS3BANK: subfile=%lx, size=%x\n", subfile_offset, subfile_size); - temp_streamFile = setup_nus3bank_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); if (!temp_streamFile) goto fail; /* init the VGMSTREAM */ @@ -182,27 +181,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - - -static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/opus_ppp.c b/src/meta/opus_ppp.c index 2adc0c4e..0ff9a26a 100644 --- a/src/meta/opus_ppp.c +++ b/src/meta/opus_ppp.c @@ -2,8 +2,6 @@ #include "../coding/coding.h" #include "../layout/layout.h" -static STREAMFILE* setup_opus_ppp_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - /* Nippon Ichi SPS wrapper (segmented) [Penny-Punching Princess (Switch)] */ VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; @@ -43,7 +41,7 @@ VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile) { if (!segment_size) goto fail; - temp_streamFile = setup_opus_ppp_streamfile(streamFile, segment_offset,segment_size, "opus"); + temp_streamFile = setup_subfile_streamfile(streamFile, segment_offset,segment_size, "opus"); if (!temp_streamFile) goto fail; data->segments[i] = init_vgmstream_opus_std(temp_streamFile); @@ -93,26 +91,3 @@ fail: free_layout_segmented(data); return NULL; } - -static STREAMFILE* setup_opus_ppp_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/ps2_ads.c b/src/meta/ps2_ads.c index 4b280dd5..b72fb885 100644 --- a/src/meta/ps2_ads.c +++ b/src/meta/ps2_ads.c @@ -313,8 +313,6 @@ fail: /* ****************************************************************************** */ -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); - /* ADS in containers */ VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; @@ -356,28 +354,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (fake_ext) { - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/sps_n1.c b/src/meta/sps_n1.c index f6857797..d75101ba 100644 --- a/src/meta/sps_n1.c +++ b/src/meta/sps_n1.c @@ -1,8 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_sps_streamfile(STREAMFILE *streamfile, off_t subfile_offset, size_t subfile_size, char* extension); - /* .SPS - Nippon Ichi wrapper [ClaDun (PSP)] */ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; @@ -26,7 +24,7 @@ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { /* init the VGMSTREAM */ switch(type) { case 1: /* .vag */ - temp_streamFile = setup_sps_streamfile(streamFile, subfile_offset, subfile_size, "vag"); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "vag"); if (!temp_streamFile) goto fail; vgmstream = init_vgmstream_vag(temp_streamFile); @@ -34,7 +32,7 @@ VGMSTREAM * init_vgmstream_sps_n1(STREAMFILE *streamFile) { break; case 2: /* .at3 */ - temp_streamFile = setup_sps_streamfile(streamFile, subfile_offset, subfile_size, "at3"); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "at3"); if (!temp_streamFile) goto fail; vgmstream = init_vgmstream_riff(temp_streamFile); @@ -54,26 +52,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_sps_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, char* extension) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,extension); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/ubi_jade.c b/src/meta/ubi_jade.c index a3b48435..054c8714 100644 --- a/src/meta/ubi_jade.c +++ b/src/meta/ubi_jade.c @@ -1,7 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -static STREAMFILE* setup_jade_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); /* Jade RIFF - from Ubisoft Jade engine games [Beyond Good & Evil (multi), Rayman Raving Rabbids 1/2 (multi)] */ @@ -231,7 +230,7 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) { if (read_32bitBE(start_offset, streamFile) != 0x4D534643) /* "MSF\43" */ goto fail; - temp_streamFile = setup_jade_streamfile(streamFile, start_offset, data_size, "msf"); + temp_streamFile = setup_subfile_streamfile(streamFile, start_offset, data_size, "msf"); if (!temp_streamFile) goto fail; temp_vgmstream = init_vgmstream_ps3_msf(temp_streamFile); @@ -362,7 +361,7 @@ VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) { subfile_size = read_32bitLE(subfile_offset+0x04,streamFile) + 0x04+0x04; - temp_streamFile = setup_jade_streamfile(streamFile, subfile_offset,subfile_size, NULL); + temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); if (!temp_streamFile) goto fail; if (check_extensions(streamFile,"xma")) { @@ -379,28 +378,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -static STREAMFILE* setup_jade_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - if (fake_ext) { - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - } - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} diff --git a/src/meta/xwb.c b/src/meta/xwb.c index d7cf3340..339a03e1 100644 --- a/src/meta/xwb.c +++ b/src/meta/xwb.c @@ -72,7 +72,6 @@ typedef struct { } xwb_header; static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile); -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); /* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */ @@ -600,31 +599,6 @@ fail: /* ****************************************************************************** */ -static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -/* ****************************************************************************** */ - /* try to get the stream name in the .xwb, though they are very rarely included */ static int get_xwb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) { size_t read; From 7259bcc0f244e2b0120bd359963b554f56058796 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 27 Oct 2018 23:49:52 +0200 Subject: [PATCH 07/10] Remove unused value warning --- src/meta/ps2_va3.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/meta/ps2_va3.c b/src/meta/ps2_va3.c index dd67f621..616b3774 100644 --- a/src/meta/ps2_va3.c +++ b/src/meta/ps2_va3.c @@ -1,15 +1,13 @@ #include "meta.h" #include "../coding/coding.h" -/* VA3 - Konami / Sont Atrac3 Container */ - -/* PS2 DDR Supernova 2 Arcade */ +/* VA3 - Konami / Sony Atrac3 Container [PS2 DDR Supernova 2 Arcade] */ VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; - uint32_t data_size, loop_start, loop_end, codec_id; + uint32_t data_size, loop_start, loop_end; /* check extension, case insensitive */ if (!check_extensions(streamFile, "va3")) From 1380faf5bb4ee6b9b79ceeb5b8ae96b336f3d00e Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 1 Nov 2018 16:34:53 +0100 Subject: [PATCH 08/10] Add PC/X360/Wii .seg and fixes [The Spiderwick Chronicles (multi)] --- src/formats.c | 3 +- src/meta/seg.c | 144 +++++++++++++++++++++++++++--------------------- src/vgmstream.h | 3 +- 3 files changed, 82 insertions(+), 68 deletions(-) diff --git a/src/formats.c b/src/formats.c index fb2fc8bd..abc8d33c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -853,8 +853,7 @@ static const meta_info meta_info_list[] = { {meta_IDSP_NL, "Next Level IDSP header"}, {meta_IDSP_IE, "Inevitable Entertainment IDSP Header"}, {meta_UBI_JADE, "Ubisoft Jade RIFF header"}, - {meta_PS2_SEG, "SEG (PS2) Header"}, - {meta_XBOX_SEG, "SEG (XBOX) Header"}, + {meta_SEG, "Stormfront SEG header"}, {meta_NDS_STRM_FFTA2, "Final Fantasy Tactics A2 RIFF Header"}, {meta_STR_ASR, "Donkey Kong Jet Race KNON/WII Header"}, {meta_ZWDSP, "Zack and Wiki custom DSP Header"}, diff --git a/src/meta/seg.c b/src/meta/seg.c index 7aa3cbea..cdf2683a 100644 --- a/src/meta/seg.c +++ b/src/meta/seg.c @@ -1,94 +1,110 @@ #include "meta.h" #include "../coding/coding.h" - -/* SEG - found in Eragon */ +/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag; - int channel_count; - coding_t coding; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("seg",filename_extension(filename))) goto fail; + int loop_flag, channel_count; + size_t data_size; + uint32_t codec; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */ + /* checks */ + if (!check_extensions(streamFile, "seg")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */ goto fail; - if (read_32bitBE(0x04,streamFile) == 0x70733200) /* "ps2\0" */ - { - coding = coding_PSX; - } - else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */ - { - coding = coding_XBOX_IMA; - } - else goto fail; - loop_flag = 0; - channel_count = read_32bitLE(0x24,streamFile); - - /* build the VGMSTREAM */ + codec = read_32bitBE(0x04,streamFile); + /* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */ + if (guess_endianness32bit(0x08,streamFile)) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; + } + /* 0x0c: file size */ + data_size = read_32bit(0x10, streamFile); /* including interleave padding */ + /* 0x14: null */ + + loop_flag = read_32bit(0x20,streamFile); /* rare */ + channel_count = read_32bit(0x24,streamFile); + /* 0x28: extradata 1 entries (0x08 per entry, unknown) */ + /* 0x2c: extradata 1 offset */ + /* 0x30: extradata 2 entries (0x10 or 0x14 per entry, seek/hist table?) */ + /* 0x34: extradata 2 offset */ + + start_offset = 0x4000; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x4000; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x18,streamFile); - vgmstream->coding_type = coding; - + vgmstream->meta_type = meta_SEG; + vgmstream->sample_rate = read_32bit(0x18,streamFile); + vgmstream->num_samples = read_32bit(0x1c,streamFile); if (loop_flag) { vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; } + read_string(vgmstream->stream_name,0x20+1, 0x38,streamFile); - vgmstream->interleave_block_size = 0; + switch(codec) { + case 0x70733200: /* "ps2\0" */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; + break; - if (coding_PSX == coding) - { - vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)*28/16/channel_count; - vgmstream->meta_type = meta_PS2_SEG; + case 0x78627800: /* "xbx\0" */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + break; - if (channel_count == 1) { - vgmstream->layout_type = layout_none; - } else if (channel_count == 2) { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2000; - } - } - else if (coding_XBOX_IMA == coding) - { - vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset, channel_count); - vgmstream->meta_type = meta_XBOX_SEG; - vgmstream->layout_type = layout_none; - } - else goto fail; + case 0x77696900: /* "wii\0" */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; + /* standard dsp header at start_offset */ + dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x1c, vgmstream->interleave_block_size); + dsp_read_hist_be(vgmstream, streamFile, start_offset+0x40, vgmstream->interleave_block_size); + //todo first_interleave: 0x2000 - 60 + break; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; + case 0x70635F00: /* "pc_\0" */ + vgmstream->coding_type = coding_IMA; + vgmstream->layout_type = layout_none; + break; +#ifdef VGM_USE_FFMPEG + case 0x78623300: { /* "xb3\0" */ + uint8_t buf[0x100]; + int bytes, block_size, block_count; + + block_size = 0x4000; + block_count = data_size / block_size + (data_size % block_size ? 1 : 0); + + bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + 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; + break; } +#endif + + default: + goto fail; } + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/vgmstream.h b/src/vgmstream.h index 3a1d2ec6..555fb1fd 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -432,8 +432,7 @@ typedef enum { meta_RSD6WMA, /* RSD6WMA */ meta_PS2_ASS, /* ASS */ - meta_PS2_SEG, /* Eragon */ - meta_XBOX_SEG, /* Eragon */ + meta_SEG, /* Eragon */ meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */ meta_STR_ASR, /* Donkey Kong Jet Race */ meta_ZWDSP, /* Zack and Wiki */ From ec63b8ff38bdcbe0d879d0798d1bfb080782a94a Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 1 Nov 2018 16:39:53 +0100 Subject: [PATCH 09/10] Tweak .svs sample rate --- src/formats.c | 2 +- src/meta/svs.c | 73 ++++++++++++++++++++----------------------------- src/vgmstream.h | 2 +- 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/src/formats.c b/src/formats.c index abc8d33c..ac340d35 100644 --- a/src/formats.c +++ b/src/formats.c @@ -758,7 +758,7 @@ static const meta_info meta_info_list[] = { {meta_WS_AUD, "Westwood Studios .aud header"}, {meta_WS_AUD_old, "Westwood Studios .aud (old) header"}, {meta_PS2_IVB, "IVB/BVII header"}, - {meta_PS2_SVS, "Square SVS header"}, + {meta_SVS, "Square SVS header"}, {meta_RIFF_WAVE, "RIFF WAVE header"}, {meta_RIFF_WAVE_POS, "RIFF WAVE header and .pos for looping"}, {meta_NWA, "VisualArt's NWA header"}, diff --git a/src/meta/svs.c b/src/meta/svs.c index f78b6f0c..d9845359 100644 --- a/src/meta/svs.c +++ b/src/meta/svs.c @@ -1,69 +1,54 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SVS (from Unlimited Saga) */ -/* probably Square Vag Stream */ + +/* SVS - SeqVagStream from Square games [Unlimited Saga (PS2) music] */ VGMSTREAM * init_vgmstream_svs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int channel_count, loop_flag, pitch; - int loop_flag = 0; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("svs",filename_extension(filename))) goto fail; - - /* check header */ + /* checks */ + /* .svs: header id (probably ok like The Bouncer's .vs) */ + if (!check_extensions(streamFile, "svs")) + goto fail; if (read_32bitBE(0x00,streamFile) != 0x53565300) /* "SVS\0" */ goto fail; - loop_flag = (read_32bitLE(0x08,streamFile)!=0); - /* 63.SVS has start and end on the same sample, which crashes stuff */ - if (read_32bitLE(0x08,streamFile)==read_32bitLE(0x0c,streamFile)) - loop_flag = 0; + /* 0x04: flags (1=stereo?, 2=loop) */ + pitch = read_32bitLE(0x10,streamFile); /* usually 0x1000 = 48000 */ + /* 0x14: volume? */ + /* 0x18: file id (may be null) */ + /* 0x1c: null */ + + loop_flag = (read_32bitLE(0x08,streamFile) > 0); /* loop start frame, min is 1 */ channel_count = 2; - - /* build the VGMSTREAM */ + start_offset = 0x20; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-0x40)*28/16/channel_count; + vgmstream->meta_type = meta_SVS; + vgmstream->sample_rate = (48000 * pitch) / 4096; /* music = ~44100, ambience = 48000 */ + vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitLE(0x08,streamFile)-1)*28; - vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-1)*28; + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile) * 28; /* frame count (0x10*ch) */ + vgmstream->loop_end_sample = read_32bitLE(0x0c,streamFile) * 28; /* frame count, (not exact num_samples when no loop) */ + /* start/end on the same frame rarely happens too (ex. file_id 63 SVS), perhaps loop should be +1 */ } + vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS2_SVS; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/vgmstream.h b/src/vgmstream.h index 555fb1fd..acf8136f 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -342,7 +342,7 @@ typedef enum { meta_PS2_BMDX, /* Beatmania thing */ meta_PS2_IVB, /* Langrisser 3 IVB */ meta_PS2_SND, /* some Might & Magics SSND header */ - meta_PS2_SVS, /* Square SVS */ + meta_SVS, /* Square SVS */ meta_XSS, /* Dino Crisis 3 */ meta_SL3, /* Test Drive Unlimited */ meta_HGC1, /* Knights of the Temple 2 */ From 2e2eeb87239d1e9c8f9d24ba4c7b99fbc7b92a24 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 1 Nov 2018 16:41:23 +0100 Subject: [PATCH 10/10] Tweak .vs doc --- src/formats.c | 4 ++-- src/layout/blocked_vs_ffx.c | 13 ++----------- src/meta/vs_ffx.c | 15 +++++++++++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/formats.c b/src/formats.c index ac340d35..cee7b0fd 100644 --- a/src/formats.c +++ b/src/formats.c @@ -686,7 +686,7 @@ static const layout_info layout_info_list[] = { {layout_blocked_sthd, "blocked (STHD)"}, {layout_blocked_h4m, "blocked (H4M)"}, {layout_blocked_xa_aiff, "blocked (XA AIFF)"}, - {layout_blocked_vs_ffx, "blocked (Final Fantasy X VS)"}, + {layout_blocked_vs_ffx, "blocked (Square VS)"}, }; static const meta_info meta_info_list[] = { @@ -1106,7 +1106,7 @@ static const meta_info meta_info_list[] = { {meta_XWMA, "Microsoft XWMA RIFF header"}, {meta_VA3, "Konami VA3 header" }, {meta_XOPUS, "Exient XOPUS header"}, - {meta_VS_FFX, "Final Fantasy X VS header"}, + {meta_VS_FFX, "Square VS header"}, }; diff --git a/src/layout/blocked_vs_ffx.c b/src/layout/blocked_vs_ffx.c index 7c7c620b..d7a924a1 100644 --- a/src/layout/blocked_vs_ffx.c +++ b/src/layout/blocked_vs_ffx.c @@ -1,24 +1,15 @@ #include "layout.h" #include "../vgmstream.h" -/* Final Fantasy X VS headered blocks */ +/* Square "VS" headered blocks */ void block_update_vs_ffx(off_t block_offset, VGMSTREAM * vgmstream) { int i; size_t block_size = 0x800; - /* 0x00: header id - * 0x04: null - * 0x08: block number - * 0x0c: blocks left in the subfile - * 0x10: always 0x1000 - * 0x14: always 0x64 - * 0x18: null - * 0x1c: null */ - vgmstream->current_block_offset = block_offset; vgmstream->current_block_size = block_size - 0x20; vgmstream->next_block_offset = block_offset + block_size; - /* 0x08: number of remaning blocks, 0x10: some id/size? (shared in all blocks) */ + /* 0x08: number of remaning blocks, 0x0c: blocks left */ for (i = 0; i < vgmstream->channels; i++) { vgmstream->ch[i].offset = block_offset + 0x20 + 0x800*i; diff --git a/src/meta/vs_ffx.c b/src/meta/vs_ffx.c index 6fbb095b..f91fa656 100644 --- a/src/meta/vs_ffx.c +++ b/src/meta/vs_ffx.c @@ -2,7 +2,8 @@ #include "../layout/layout.h" #include "../coding/coding.h" -/* .vs/VS - from Final Fantasy X voices (PS2) */ + +/* VS - VagStream from Square games [Final Fantasy X (PS2) voices, Unlimited Saga (PS2) voices] */ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int channel_count, loop_flag, pitch; @@ -13,14 +14,20 @@ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { /* .vs: header id (probably ok like The Bouncer's .vs, very similar) */ if (!check_extensions(streamFile, "vs")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x56530000) /* "VS\0\0" */ + if (read_32bitBE(0x00,streamFile) != 0x56530000) /* "VS\0\0" */ goto fail; + /* 0x04: null (flags? used in SVS) */ + /* 0x08: block number */ + /* 0x0c: blocks left in the subfile */ + pitch = read_32bitLE(0x10,streamFile); /* usually 0x1000 = 48000 */ + /* 0x14: volume, usually 0x64 = 100 but be bigger/smaller (up to 128?) */ + /* 0x18: null */ + /* 0x1c: null */ loop_flag = 0; channel_count = 1; start_offset = 0x00; - pitch = read_32bitLE(0x10,streamFile); /* build the VGMSTREAM */ @@ -28,7 +35,7 @@ VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) { if (!vgmstream) goto fail; vgmstream->meta_type = meta_VS_FFX; - vgmstream->sample_rate = (48000 * pitch) / 4096; /* needed for rare files, sounds ok */ + vgmstream->sample_rate = (48000 * pitch) / 4096; /* verified, needed for rare files */ vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_blocked_vs_ffx;