From 94057cf4675554065053d68cc3dde1df1700bd90 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Mon, 30 May 2022 18:26:34 -0700 Subject: [PATCH] Updated VGMStream to r1745-22-gf696beb0 Signed-off-by: Christopher Snowhill --- .../libvgmstream.xcodeproj/project.pbxproj | 12 +- .../vgmstream/vgmstream/src/coding/coding.h | 2 +- .../vgmstream/src/coding/ima_decoder.c | 10 +- Frameworks/vgmstream/vgmstream/src/decode.c | 8 +- Frameworks/vgmstream/vgmstream/src/formats.c | 10 +- Frameworks/vgmstream/vgmstream/src/meta/aix.c | 125 +++++++++----- Frameworks/vgmstream/vgmstream/src/meta/alp.c | 54 ++++++ .../vgmstream/vgmstream/src/meta/atsl.c | 160 +++++++++++++----- .../vgmstream/src/meta/bw_mp3_riff.c | 75 ++++++++ .../vgmstream/vgmstream/src/meta/ffmpeg.c | 19 ++- .../vgmstream/vgmstream/src/meta/ktsr.c | 63 ++++--- .../vgmstream/vgmstream/src/meta/meta.h | 5 +- .../vgmstream/vgmstream/src/meta/rwsd.c | 9 +- Frameworks/vgmstream/vgmstream/src/meta/tun.c | 41 ----- .../vgmstream/vgmstream/src/meta/txth.c | 5 + .../vgmstream/vgmstream/src/vgmstream.c | 4 +- .../vgmstream/vgmstream/src/vgmstream.h | 7 +- Info.plist | 3 + 18 files changed, 437 insertions(+), 175 deletions(-) create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/alp.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/bw_mp3_riff.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/tun.c diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 27e8a7022..2ae5c9e4a 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -434,7 +434,7 @@ 836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; }; 836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; }; 836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.c */; }; - 836F703718BDC2190095E648 /* tun.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* tun.c */; }; + 836F703718BDC2190095E648 /* alp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* alp.c */; }; 836F703818BDC2190095E648 /* ubi_ckd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFC18BDC2190095E648 /* ubi_ckd.c */; }; 836F703918BDC2190095E648 /* vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFD18BDC2190095E648 /* vgs.c */; }; 836F703A18BDC2190095E648 /* vs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFE18BDC2190095E648 /* vs.c */; }; @@ -610,6 +610,7 @@ 83AFABBE23795202002F3947 /* isb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABBB23795202002F3947 /* isb.c */; }; 83B46FD12707FB2100847FC9 /* at3plus_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */; }; 83B46FD52707FB9A00847FC9 /* endianness.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FD42707FB9A00847FC9 /* endianness.h */; }; + 83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B69B212845A26600D2435A /* bw_mp3_riff.c */; }; 83B72E3A27904589006007A3 /* libfdk-aac.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B72E342790452C006007A3 /* libfdk-aac.2.dylib */; }; 83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; }; 83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C727FB22BC893800678B4A /* xwb_xsb.h */; }; @@ -1231,7 +1232,7 @@ 836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = ""; }; 836F6EF918BDC2190095E648 /* svs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svs.c; sourceTree = ""; }; 836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = ""; }; - 836F6EFB18BDC2190095E648 /* tun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tun.c; sourceTree = ""; }; + 836F6EFB18BDC2190095E648 /* alp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alp.c; sourceTree = ""; }; 836F6EFC18BDC2190095E648 /* ubi_ckd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_ckd.c; sourceTree = ""; }; 836F6EFD18BDC2190095E648 /* vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgs.c; sourceTree = ""; }; 836F6EFE18BDC2190095E648 /* vs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs.c; sourceTree = ""; }; @@ -1406,6 +1407,7 @@ 83AFABBB23795202002F3947 /* isb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = isb.c; sourceTree = ""; }; 83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at3plus_decoder.h; sourceTree = ""; }; 83B46FD42707FB9A00847FC9 /* endianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = endianness.h; sourceTree = ""; }; + 83B69B212845A26600D2435A /* bw_mp3_riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bw_mp3_riff.c; sourceTree = ""; }; 83B72E342790452C006007A3 /* libfdk-aac.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libfdk-aac.2.dylib"; path = "../../ThirdParty/fdk-aac/lib/libfdk-aac.2.dylib"; sourceTree = ""; }; 83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = ""; }; 83C727FB22BC893800678B4A /* xwb_xsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xwb_xsb.h; sourceTree = ""; }; @@ -1836,6 +1838,7 @@ 8349A8F61FE6257E00E26435 /* aix_streamfile.h */, 836F6E3218BDC2180095E648 /* aix.c */, 836F6E3318BDC2180095E648 /* akb.c */, + 836F6EFB18BDC2190095E648 /* alp.c */, 834FE0C0215C79E5000A5D3D /* ao.c */, 834FE0C7215C79E7000A5D3D /* apc.c */, 836F6E3418BDC2180095E648 /* apple_caff.c */, @@ -1867,6 +1870,7 @@ 836F6E3A18BDC2180095E648 /* brstm.c */, 83AA7F762519C042004C5298 /* bsf.c */, 83EDE5D71A70951A005F5D84 /* btsnd.c */, + 83B69B212845A26600D2435A /* bw_mp3_riff.c */, 835C883122CC17BD001B4B3F /* bwav.c */, 8306B0CF2098458F000302D4 /* caf.c */, 836F6E3B18BDC2180095E648 /* capdsp.c */, @@ -2179,7 +2183,6 @@ 8373342E23F60D4100DE14DC /* tgc.c */, 836F6EFA18BDC2190095E648 /* thp.c */, 836F46AF2820874D005B9B87 /* tt_ad.c */, - 836F6EFB18BDC2190095E648 /* tun.c */, 83C7280122BC893A00678B4A /* txth_streamfile.h */, 830165971F256BD000CA0941 /* txth.c */, 8306B0D22098458F000302D4 /* txtp.c */, @@ -2970,7 +2973,7 @@ 836F703318BDC2190095E648 /* str_snds.c in Sources */, 832BF82221E0514B006F50F1 /* vs_str.c in Sources */, 8349A9191FE6258200E26435 /* afc.c in Sources */, - 836F703718BDC2190095E648 /* tun.c in Sources */, + 836F703718BDC2190095E648 /* alp.c in Sources */, 83031ECD243C50CC00C3F3E0 /* blocked_vid1.c in Sources */, 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, 8349A9161FE6258200E26435 /* flx.c in Sources */, @@ -3066,6 +3069,7 @@ 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */, 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */, 83C7282122BC893D00678B4A /* msf_konami.c in Sources */, + 83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */, 8315958920FEC83F007002F0 /* asf.c in Sources */, 83C7281222BC893D00678B4A /* 9tav.c in Sources */, 836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index bd2c800e0..e55c65727 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -21,7 +21,7 @@ void decode_3ds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci void decode_snds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_otns_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_wv6_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_alp_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_hv_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ffta2_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_blitz_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_mtf_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index 68e6d3f6d..ae136a96c 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -190,8 +190,8 @@ static void wv6_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, if (*step_index > 88) *step_index=88; } -/* Lego Racers (PC) .TUN variation, reverse engineered from the .exe */ -static void alp_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { +/* High Voltage variation, reverse engineered from .exes [Lego Racers (PC), NBA Hangtime (PC)] */ +static void hv_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { int sample_nibble, sample_decoded, step, delta; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; @@ -489,8 +489,8 @@ void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa stream->adpcm_step_index = step_index; } -/* ALT IMA, DVI IMA with custom nibble expand */ -void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { +/* High Voltage's DVI IMA with simplified nibble expand */ +void decode_hv_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { int i, sample_count; int32_t hist1 = stream->adpcm_history1_32; int step_index = stream->adpcm_step_index; @@ -503,7 +503,7 @@ void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa off_t byte_offset = stream->offset + i/2; int nibble_shift = (i&1?0:4); //high nibble first - alp_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + hv_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } diff --git a/Frameworks/vgmstream/vgmstream/src/decode.c b/Frameworks/vgmstream/vgmstream/src/decode.c index 0e82f468d..bdd53ceff 100644 --- a/Frameworks/vgmstream/vgmstream/src/decode.c +++ b/Frameworks/vgmstream/vgmstream/src/decode.c @@ -412,7 +412,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) { case coding_DVI_IMA_int: case coding_3DS_IMA: case coding_WV6_IMA: - case coding_ALP_IMA: + case coding_HV_IMA: case coding_FFTA2_IMA: case coding_BLITZ_IMA: case coding_PCFX: @@ -622,7 +622,7 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) { case coding_DVI_IMA_int: case coding_3DS_IMA: case coding_WV6_IMA: - case coding_ALP_IMA: + case coding_HV_IMA: case coding_FFTA2_IMA: case coding_BLITZ_IMA: case coding_PCFX: @@ -1163,9 +1163,9 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ vgmstream->channels, vgmstream->samples_into_block, samples_to_do); } break; - case coding_ALP_IMA: + case coding_HV_IMA: for (ch = 0; ch < vgmstream->channels; ch++) { - decode_alp_ima(&vgmstream->ch[ch], buffer+ch, + decode_hv_ima(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do); } break; diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index d08c0749f..9cac65d9b 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -79,6 +79,7 @@ static const char* extension_list[] = { "atsl", "atsl3", "atsl4", + "atslx", "atx", "aud", "audio", //txth/reserved [Grimm Echoes (Android)] @@ -118,6 +119,8 @@ static const char* extension_list[] = { "bo2", "brstm", "brstmspm", + "brwav", + "brwsd", //fake extension for RWSD (non-format) "bsnd", "btsnd", "bvg", @@ -776,7 +779,7 @@ static const coding_info coding_info_list[] = { {coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"}, {coding_QD_IMA, "Quantic Dream 4-bit IMA ADPCM"}, {coding_WV6_IMA, "Gorilla Systems WV6 4-bit IMA ADPCM"}, - {coding_ALP_IMA, "High Voltage ALP 4-bit IMA ADPCM"}, + {coding_HV_IMA, "High Voltage 4-bit IMA ADPCM"}, {coding_FFTA2_IMA, "Final Fantasy Tactics A2 4-bit IMA ADPCM"}, {coding_BLITZ_IMA, "Blitz Games 4-bit IMA ADPCM"}, {coding_MTF_IMA, "MT Framework 4-bit IMA ADPCM"}, @@ -1202,7 +1205,7 @@ static const meta_info meta_info_list[] = { {meta_MTAF, "Konami MTAF header"}, {meta_PS2_VAG1, "Konami VAG1 header"}, {meta_PS2_VAG2, "Konami VAG2 header"}, - {meta_TUN, "Lego Racers ALP header"}, + {meta_ALP, "High Voltage ALP header"}, {meta_WPD, "WPD 'DPW' header"}, {meta_MN_STR, "Mini Ninjas 'STR' header"}, {meta_MSS, "Guerilla MCSS header"}, @@ -1223,7 +1226,8 @@ static const meta_info meta_info_list[] = { {meta_HCA, "CRI HCA header"}, {meta_SVAG_SNK, "SNK SVAG header"}, {meta_PS2_VDS_VDM, "Procyon Studio VDS/VDM header"}, - {meta_FFMPEG, "FFmpeg supported file format"}, + {meta_FFMPEG, "FFmpeg supported format"}, + {meta_FFMPEG_faulty, "FFmpeg supported format (check log)"}, {meta_X360_CXS, "tri-Crescendo CXS header"}, {meta_AKB, "Square-Enix AKB header"}, {meta_X360_PASX, "Premium Agency PASX header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aix.c b/Frameworks/vgmstream/vgmstream/src/meta/aix.c index b11d39060..50c974cd1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aix.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aix.c @@ -7,28 +7,35 @@ * as pseudo dynamic/multi-song container [Sega Ages 2500 Vol 28 Tetris Collection (PS2)] */ #define MAX_SEGMENTS 120 -static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, off_t* segment_offsets, size_t* segment_sizes, int32_t* segment_samples, int segment_count, int layer_count); +typedef struct { + uint32_t segment_offsets[MAX_SEGMENTS]; + uint32_t segment_sizes[MAX_SEGMENTS]; + int32_t segment_samples[MAX_SEGMENTS]; + int segment_rates[MAX_SEGMENTS]; + + int segment_count; + int layer_count; + + int force_disable_loop; +} aix_header_t; + +static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, aix_header_t* aix); /* AIX - N segments with M layers (2ch ADX) inside [SoulCalibur IV (PS3), Dragon Ball Z: Burst Limit (PS3)] */ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - - off_t segment_offsets[MAX_SEGMENTS] = {0}; - size_t segment_sizes[MAX_SEGMENTS] = {0}; - int32_t segment_samples[MAX_SEGMENTS] = {0}; - int segment_rates[MAX_SEGMENTS] = {0}; - + aix_header_t aix = {0}; off_t data_offset, subtable_offset; - int segment_count, layer_count; int i; /* checks */ + if (!is_id32be(0x00, sf, "AIXF")) + goto fail; if (!check_extensions(sf, "aix")) goto fail; - if (read_u32be(0x00,sf) != 0x41495846 || /* "AIXF" */ - read_u32be(0x08,sf) != 0x01000014 || /* version? */ - read_u32be(0x0c,sf) != 0x00000800) + if (read_u32be(0x08,sf) != 0x01000014 || /* version? */ + read_u32be(0x0c,sf) != 0x00000800) /* header size? */ goto fail; /* AIX combine layers for multichannel and segments for looping, all very hacky. @@ -42,30 +49,42 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) { const off_t segment_list_offset = 0x20; const size_t segment_list_entry_size = 0x10; - segment_count = read_u16be(0x18,sf); - if (segment_count < 1 || segment_count > MAX_SEGMENTS) goto fail; + aix.segment_count = read_u16be(0x18,sf); + if (aix.segment_count < 1 || aix.segment_count > MAX_SEGMENTS) goto fail; - subtable_offset = segment_list_offset + segment_count*segment_list_entry_size; + subtable_offset = segment_list_offset + aix.segment_count * segment_list_entry_size; if (subtable_offset >= data_offset) goto fail; - for (i = 0; i < segment_count; i++) { - segment_offsets[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x00,sf); - segment_sizes[i] = read_u32be(segment_list_offset + segment_list_entry_size*i + 0x04,sf); - segment_samples[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x08,sf); - segment_rates[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x0c,sf); + for (i = 0; i < aix.segment_count; i++) { + aix.segment_offsets[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x00,sf); + aix.segment_sizes[i] = read_u32be(segment_list_offset + segment_list_entry_size*i + 0x04,sf); + aix.segment_samples[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x08,sf); + aix.segment_rates[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x0c,sf); /* segments > 0 can have 0 sample rate, seems to indicate same as first * [Ryu ga Gotoku: Kenzan! (PS3) tenkei_sng1.aix] */ - if (i > 0 && segment_rates[i] == 0) - segment_rates[i] = segment_rates[0]; + if (i > 0 && aix.segment_rates[i] == 0) + aix.segment_rates[i] = aix.segment_rates[0]; /* all segments must have equal sample rate */ - if (segment_rates[i] != segment_rates[0]) + if (aix.segment_rates[i] != aix.segment_rates[0]) goto fail; } - if (segment_offsets[0] != data_offset) + if (aix.segment_offsets[0] != data_offset) goto fail; + + /* Metroid: Other M (Wii)'s bgm_m_stage_06_02 is truncated on disc, seemingly not an extraction error. + * Playing expected samples aligns to bgm_m_stage_06, but from tests seems the song stops once reaching + * the missing audio (doesn't loop). */ + if (aix.segment_count == 3 && aix.segment_offsets[1] + aix.segment_sizes[1] > get_streamfile_size(sf)) { + aix.segment_count = 2; + + aix.segment_sizes[1] = get_streamfile_size(sf) - aix.segment_offsets[1]; + //aix.segment_samples[1] = 0; + aix.force_disable_loop = 1; /* force */ + vgm_logi("AIX: missing data, parts will be silent\n"); + } } /* between the segment and layer table some kind of 0x10 subtable? */ @@ -80,15 +99,15 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) { layer_list_offset = subtable_offset + 0x10; if (layer_list_offset >= data_offset) goto fail; - layer_count = read_u8(layer_list_offset,sf); - if (layer_count < 1) goto fail; + aix.layer_count = read_u8(layer_list_offset,sf); + if (aix.layer_count < 1) goto fail; - layer_list_end = layer_list_offset + 0x08 + layer_count*layer_list_entry_size; + layer_list_end = layer_list_offset + 0x08 + aix.layer_count * layer_list_entry_size; if (layer_list_end >= data_offset) goto fail; - for (i = 0; i < layer_count; i++) { + for (i = 0; i < aix.layer_count; i++) { /* all layers must have same sample rate as segments */ - if (read_s32be(layer_list_offset + 0x08 + i*layer_list_entry_size + 0x00,sf) != segment_rates[0]) + if (read_s32be(layer_list_offset + 0x08 + i * layer_list_entry_size + 0x00,sf) != aix.segment_rates[0]) goto fail; /* 0x04: layer channels */ } @@ -96,7 +115,7 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) { /* build combo layers + segments VGMSTREAM */ - vgmstream = build_segmented_vgmstream(sf, segment_offsets, segment_sizes, segment_samples, segment_count, layer_count); + vgmstream = build_segmented_vgmstream(sf, &aix); if (!vgmstream) goto fail; vgmstream->meta_type = meta_AIX; @@ -108,7 +127,7 @@ fail: return NULL; } -static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset, size_t segment_size, int layer_count) { +static VGMSTREAM* build_layered_vgmstream(STREAMFILE* sf, aix_header_t* aix, int segment) { VGMSTREAM* vgmstream = NULL; layered_layout_data* data = NULL; int i; @@ -116,12 +135,12 @@ static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset, /* build layers */ - data = init_layout_layered(layer_count); + data = init_layout_layered(aix->layer_count); if (!data) goto fail; - for (i = 0; i < layer_count; i++) { + for (i = 0; i < aix->layer_count; i++) { /* build the layer STREAMFILE */ - temp_sf = setup_aix_streamfile(sf, segment_offset, segment_size, i, "adx"); + temp_sf = setup_aix_streamfile(sf, aix->segment_offsets[segment], aix->segment_sizes[segment], i, "adx"); if (!temp_sf) goto fail; /* build the sub-VGMSTREAM */ @@ -130,6 +149,18 @@ static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset, data->layers[i]->stream_size = get_streamfile_size(temp_sf); +#if 0 + /* for rare truncated AIX */ + if (aix->segment_samples[segment] == 0) { + VGMSTREAM* vl = data->layers[i]; + uint32_t offset = read_u16be(0x02, temp_sf) + 0x04; + uint32_t size = vl->stream_size - offset; + uint32_t frames = size / vl->interleave_block_size / vl->channels; + + vl->num_samples = frames * ((vl->interleave_block_size - 2) * 2) + 0x100; + } +#endif + close_streamfile(temp_sf); temp_sf = NULL; } @@ -151,38 +182,46 @@ fail: return NULL; } -static VGMSTREAM *build_segmented_vgmstream(STREAMFILE* sf, off_t* segment_offsets, size_t* segment_sizes, int32_t* segment_samples, int segment_count, int layer_count) { +static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, aix_header_t* aix) { VGMSTREAM* vgmstream = NULL; segmented_layout_data* data = NULL; int i, loop_flag, loop_start_segment, loop_end_segment; /* build segments */ - data = init_layout_segmented(segment_count); + data = init_layout_segmented(aix->segment_count); if (!data) goto fail; - for (i = 0; i < segment_count; i++) { + for (i = 0; i < aix->segment_count; i++) { /* build the layered sub-VGMSTREAM */ - data->segments[i] = build_layered_vgmstream(sf, segment_offsets[i], segment_sizes[i], layer_count); + data->segments[i] = build_layered_vgmstream(sf, aix, i); if (!data->segments[i]) goto fail; - data->segments[i]->num_samples = segment_samples[i]; /* just in case */ + data->segments[i]->stream_size = aix->segment_sizes[i]; - data->segments[i]->stream_size = segment_sizes[i]; + data->segments[i]->num_samples = aix->segment_samples[i]; +#if 0 + /* should be the same as layer's */ + if (aix->segment_samples[i] != 0) { + data->segments[i]->num_samples = aix->segment_samples[i]; + } +#endif } if (!setup_layout_segmented(data)) goto fail; - /* known loop cases: + /* known loop cases (no info on header, controlled by game?): * - 1 segment: main/no loop [Hatsune Miku: Project Diva (PSP)] * - 2 segments: intro + loop [SoulCalibur IV (PS3)] * - 3 segments: intro + loop + end [Dragon Ball Z: Burst Limit (PS3), Metroid: Other M (Wii)] * - 4/5 segments: intros + loop + ends [Danball Senki (PSP)] * - +39 segments: no loops but multiple segments for dynamic parts? [Tetris Collection (PS2)] */ - loop_flag = (segment_count > 0 && segment_count <= 5); - loop_start_segment = (segment_count > 3) ? 2 : 1; - loop_end_segment = (segment_count > 3) ? (segment_count - 2) : 1; + loop_flag = (aix->segment_count > 0 && aix->segment_count <= 5); + loop_start_segment = (aix->segment_count > 3) ? 2 : 1; + loop_end_segment = (aix->segment_count > 3) ? (aix->segment_count - 2) : 1; + if (aix->force_disable_loop) + loop_flag = 0; /* build the segmented VGMSTREAM */ vgmstream = allocate_segmented_vgmstream(data, loop_flag, loop_start_segment, loop_end_segment); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/alp.c b/Frameworks/vgmstream/vgmstream/src/meta/alp.c new file mode 100644 index 000000000..7a8fd3ec0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/alp.c @@ -0,0 +1,54 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* ALP - from High Voltage games [LEGO Racers (PC), NBA Inside Drive 2000 (PC)] */ +VGMSTREAM* init_vgmstream_alp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels, sample_rate; + + + /* checks */ + if (!is_id32be(0x00,sf, "ALP ")) + goto fail; + /* .tun: stereo + * .pcm: mono */ + if (!check_extensions(sf,"tun,pcm")) + goto fail; + + start_offset = read_u32le(0x04, sf) + 0x08; + if (!is_id32be(0x08,sf, "ADPC")) /* codec, probably */ + goto fail; + /* 0x0c: "M\0\0" */ + channels = read_u8(0x0f, sf); + + /* NBA Inside Drive 2000 (PC) */ + if (start_offset >= 0x14) + sample_rate = read_s32le(0x10, sf); /* still 22050 though */ + else + sample_rate = 22050; + + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_ALP; + vgmstream->channels = channels; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels); + + vgmstream->coding_type = coding_HV_IMA; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/atsl.c b/Frameworks/vgmstream/vgmstream/src/meta/atsl.c index 86869b9a1..6ed299f9e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/atsl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/atsl.c @@ -7,18 +7,22 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; int total_subsongs, target_subsong = sf->stream_index; - int type, big_endian = 0, entries; + int big_endian = 0, entries, version, platform, format; uint32_t subfile_offset = 0, subfile_size = 0, header_size, entry_size; init_vgmstream_t init_vgmstream = NULL; - const char* fake_ext; + const char* fake_ext = NULL; /* checks */ if (!is_id32be(0x00,sf, "ATSL")) goto fail; - /* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */ - if (!check_extensions(sf,"atsl,atsl3,atsl4")) + + /* .atsl: common extension (PC/PS4/etc) + * .atsl3: PS3 games + * .atsl4: some PS4 games + * .atslx: X360 games */ + if (!check_extensions(sf,"atsl,atsl3,atsl4,atslx")) goto fail; /* main header (LE) */ @@ -31,58 +35,44 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) { /* 0x20: subheader size */ /* 0x24/28: null */ - /* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c: + /* 0x08: unknown, varies */ + + /* 0x0c(1): 0/1 (version? seen both in even in the same game) */ + version = read_u8(0x0c, sf); /* <~2017 = v0, both seen in Nioh (PC) */ + platform = read_u8(0x0d, sf); + /* 0x0e: header version? (00~04: size 0x28, 05~06: size 0x30), 03~05 seen in Nioh (PS4) */ + /* 0x0f: always 1? */ + + big_endian = (platform == 0x02 || platform == 0x03); /* PS3/X360 */ + + /* Example flags at 0x08/0x0c for reference: * - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3] - * - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3] + * - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]-bgm007 + * - 01010301 00030201 .atsl3 from Fist of North Star: Ken's Rage 2 (X360)[ATRAC3]-bgm007 * 00000301 00020101 (same) * - 01040301 00060301 .atsl4 from Nobunaga's Ambition: Sphere of Influence (PS4)[ATRAC9] * - 00060301 00040301 .atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9] * - 00060301 00010301 .atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS] * - 000A0301 00010501 .atsl in G1L from Warriors All-Stars (PC)[KOVS] 2017-09 - * - 01000000 01010501 .atsl from Nioh (PC)[KOVS] 2017-11 - * - 01000000 00010501 .atsl from Nioh (PC)[KOVS] 2017-11 * - 000B0301 00080601 .atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS] 2017-09 + * - 01000000 00010501 .atsl from Nioh (PC)[KOVS] 2017-11 + * - 01000000 01010501 .atsl from Nioh (PC)[KOVS] 2017-11 + * - 03070301 01060301 .atsl from Nioh (PS4)[ATRAC9] + * - 00080301 01060401 .atsl from Nioh (PS4)[ATRAC9] + * - 00090301 01060501 .atsl from Nioh (PS4)[ATRAC9] (bigger header) * - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC] * - 010D0301 01010601 .atsl from Dynasty Warriors 9 DLC (PC)[KOVS] */ - type = read_u16le(0x0c, sf); - //version = read_u16le(0x0e, sf); - switch(type) { - case 0x0100: /* KOVS */ - init_vgmstream = init_vgmstream_ogg_vorbis; - fake_ext = "kvs"; + switch(version) { + case 0x00: entry_size = 0x28; break; - case 0x0101: - init_vgmstream = init_vgmstream_ogg_vorbis; - fake_ext = "kvs"; + case 0x01: entry_size = 0x3c; break; - case 0x0200: /* ATRAC3 */ - init_vgmstream = init_vgmstream_riff; - fake_ext = "at3"; - entry_size = 0x28; - big_endian = 1; - break; - case 0x0400: - case 0x0600: /* ATRAC9 */ - init_vgmstream = init_vgmstream_riff; - fake_ext = "at9"; - entry_size = 0x28; - break; - case 0x0601: /* KTAC */ - init_vgmstream = init_vgmstream_ktac; - fake_ext = "ktac"; - entry_size = 0x3c; - break; - case 0x0800: /* KTSS */ - init_vgmstream = init_vgmstream_ktss; - fake_ext = "ktss"; - entry_size = 0x28; - break; default: - vgm_logi("ATSL: unknown type %x (report)\n", type); + vgm_logi("ATSL: unknown version %x (report)\n", version); goto fail; } @@ -99,11 +89,36 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) { int is_unique = 1; uint32_t entry_subfile_offset, entry_subfile_size; - /* 0x00: id */ + /* entry header (values match subfile header) */ + /* 0x00: id (0..N, usually) */ entry_subfile_offset = read_u32(header_size + i*entry_size + 0x04,sf); entry_subfile_size = read_u32(header_size + i*entry_size + 0x08,sf); - /* 0x10+: config, channels/sample rate/num_samples/loop_start/channel layout/etc (matches subfile header) */ + if (version == 0x00) { + format = 0x00; + /* 0x0c: sample rate */ + /* 0x10: samples */ + /* 0x14: loop start */ + /* 0x18: loop end */ + /* 0x1c: null? */ + /* 0x28: offset to unknown extra table (after entries) */ + /* 0x0c: unknown table entries (0x2C each) */ + } + else { + /* 0x0c: null? */ + /* 0x10: offset to unknown extra table (after entries) */ + /* 0x14: unknown table entries (0x2C each) */ + /* 0x18: channels */ + /* 0x1c: some hash/id? (same for all entries) */ + format = read_u32(header_size + i*entry_size + 0x20, sf); + /* 0x24: sample rate */ + /* 0x28: samples */ + /* 0x2c: encoder delay */ + /* 0x30: loop start (includes delay) */ + /* 0x34: channel layout */ + /* 0x38: null? */ + } + //TODO use silence subsong? /* dummy entry, seen in DW9 DLC (has unique config though) */ if (!entry_subfile_offset && !entry_subfile_size) continue; @@ -127,11 +142,64 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) { subfile_size = entry_subfile_size; } } - } - if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail; - if (!subfile_offset || !subfile_size) goto fail; - /* some kind of seek/switch table may follow (optional, found in .atsl3) */ + if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail; + if (!subfile_offset || !subfile_size) goto fail; + + /* some kind of switch table may follow (referenced in entries) */ + } + + /* similar codec values also seen in KTSR */ + switch(platform) { + case 0x01: /* PC */ + if (format == 0x0000 || format == 0x0005) { + init_vgmstream = init_vgmstream_ogg_vorbis; + fake_ext = "kvs"; + } + break; + + case 0x02: /* PS3 */ + if (format == 0x0000) { + init_vgmstream = init_vgmstream_riff; + fake_ext = "at3"; + } + break; + + case 0x03: /* X360 */ + if (format == 0x0000) { + init_vgmstream = init_vgmstream_xma; + fake_ext = "xma"; + } + break; + + case 0x04: /* Vita */ + case 0x06: /* PS4 */ + if (format == 0x0000 || format == 0x1001) { /* Nioh (PS4)-1001 */ + init_vgmstream = init_vgmstream_riff; + fake_ext = "at9"; + } + else if (format == 0x1000) { /* Dynasty Warriors 9 (PS4) patch BGM */ + init_vgmstream = init_vgmstream_ktac; + fake_ext = "ktac"; + } + break; + + case 0x08: /* Switch */ + if (format == 0x0000 || format == 0x0005) {/* Dynasty Warriors 9 (Switch)-0005 w/ Opus */ + init_vgmstream = init_vgmstream_ktss; + fake_ext = "ktss"; + } + break; + + default: + break; + } + + if (init_vgmstream == NULL || fake_ext == NULL) { + vgm_logi("ATSL: unknown platform %x + format %x (report)\n", platform, format); + goto fail; + } + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, fake_ext); if (!temp_sf) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bw_mp3_riff.c b/Frameworks/vgmstream/vgmstream/src/meta/bw_mp3_riff.c new file mode 100644 index 000000000..fcf2799b4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bw_mp3_riff.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* Bioware pseudo-format (for sfx) [Star Wars: Knights of the Old Republic 1/2 (PC/Switch/iOS)] */ +VGMSTREAM* init_vgmstream_bw_mp3_riff(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + uint32_t subfile_offset = 0, subfile_size = 0; + + + /* checks */ + if (read_u32be(0x00, sf) != 0xFFF360C4) + goto fail; + //if ((read_u32be(0x00, sf) & 0xFFF00000) != 0xFFF00000) /* no point to check other mp3s */ + // goto fail; + if (!is_id32be(0x0d, sf, "LAME") && !is_id32be(0x1d6, sf, "RIFF")) + goto fail; + + /* strange mix of micro empty MP3 (LAME3.93, common header) + standard RIFF */ + + subfile_offset = 0x1d6; + subfile_size = read_u32le(subfile_offset + 0x04, sf) + 0x08; + + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "wav"); + if (!temp_sf) goto fail; + + /* init the VGMSTREAM */ + vgmstream = init_vgmstream_riff(temp_sf); + if (!vgmstream) goto fail; + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} + +/* Bioware pseudo-format (for music) [Star Wars: Knights of the Old Republic 1/2 (PC/Switch/iOS)] */ +VGMSTREAM* init_vgmstream_bw_riff_mp3(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + uint32_t subfile_offset = 0, subfile_size = 0; + + + /* checks */ + if (!is_id32be(0x00, sf, "RIFF")) + goto fail; + if (read_u32le(0x04, sf) != 0x32) + goto fail; + if (get_streamfile_size(sf) <= 0x32 + 0x08) /* ? */ + goto fail; + + /* strange mix of micro RIFF (with codec 0x01, "fact" and "data" size 0)) + standard MP3 (sometimes with ID3) */ + + subfile_offset = 0x3A; + subfile_size = get_streamfile_size(sf) - subfile_offset; + + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "mp3"); + if (!temp_sf) goto fail; + + /* init the VGMSTREAM */ + vgmstream = init_vgmstream_mpeg(temp_sf); + if (!vgmstream) goto fail; + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c index 748d1ae3b..c2df0abec 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c @@ -7,7 +7,6 @@ static int read_pos_file(uint8_t* buf, size_t bufsize, STREAMFILE* sf); static int find_meta_loops(ffmpeg_codec_data* data, int32_t* p_loop_start, int32_t* p_loop_end); /* parses any format supported by FFmpeg and not handled elsewhere: - * - MP3 (.mp3, .mus): Marc Ecko's Getting Up (PC) * - MPC (.mpc, mp+): Moonshine Runners (PC), Asphalt 7 (PC) * - FLAC (.flac): Warcraft 3 Reforged (PC), Call of Duty: Ghosts (PC) * - DUCK (.wav): Sonic Jam (SAT), Virtua Fighter 2 (SAT) @@ -26,6 +25,7 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { int loop_flag = 0, channels, sample_rate; int32_t loop_start = 0, loop_end = 0, num_samples = 0, encoder_delay = 0; int total_subsongs, target_subsong = sf->stream_index; + int faulty = 0; /* mark wonky rips in hopes people may fix them */ /* no checks */ //if (!check_extensions(sf, "...")) @@ -102,6 +102,21 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { ffmpeg_set_skip_samples(data, encoder_delay); } + /* detect broken RIFFs */ + if (is_id32be(0x00, sf, "RIFF")) { + uint32_t size = read_u32le(0x04, sf); + /* There is a log in RIFF too but to be extra sure and sometimes FFmpeg don't handle it (this is mainly for wrong AT3). + * Some proper RIFF can be parsed here too (like DUCK). */ + if (size + 0x08 > get_streamfile_size(sf)) { + vgm_logi("RIFF/FFmpeg: incorrect size, file may have missing data\n"); + faulty = 1; + } + else if (size + 0x08 < get_streamfile_size(sf)) { + vgm_logi("RIFF/FFmpeg: incorrect size, file may have padded data\n"); + faulty = 1; + } + } + /* default but often inaccurate when calculated using bitrate (wrong for VBR) */ if (!num_samples) { num_samples = ffmpeg_get_samples(data); /* may be 0 if FFmpeg can't precalculate it */ @@ -115,7 +130,7 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_FFMPEG; + vgmstream->meta_type = faulty ? meta_FFMPEG_faulty : meta_FFMPEG; vgmstream->sample_rate = sample_rate; vgmstream->codec_data = data; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c b/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c index fff43b92b..11312d905 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c @@ -2,7 +2,7 @@ #include "../coding/coding.h" #include "../layout/layout.h" -typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, KVS, /*KNS*/ } ktsr_codec; +typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, RIFF_ATRAC9, KOVS, /*KNS*/ } ktsr_codec; #define MAX_CHANNELS 8 @@ -126,8 +126,28 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) { } #endif + case RIFF_ATRAC9: { + VGMSTREAM* riff_vgmstream = NULL; //TODO: meh + STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "at9"); + if (!temp_sf) goto fail; + + riff_vgmstream = init_vgmstream_riff(temp_sf); + close_streamfile(temp_sf); + if (!riff_vgmstream) goto fail; + + riff_vgmstream->stream_size = vgmstream->stream_size; + riff_vgmstream->num_streams = vgmstream->num_streams; + riff_vgmstream->channel_layout = vgmstream->channel_layout; + + strcpy(riff_vgmstream->stream_name, vgmstream->stream_name); + + close_vgmstream(vgmstream); + if (sf_b != sf) close_streamfile(sf_b); + return riff_vgmstream; + } + #ifdef VGM_USE_VORBIS - case KVS: { + case KOVS: { VGMSTREAM* ogg_vgmstream = NULL; //TODO: meh STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "kvs"); if (!temp_sf) goto fail; @@ -234,18 +254,28 @@ static int parse_codec(ktsr_header* ktsr) { /* platform + format to codec, simplified until more codec combos are found */ switch(ktsr->platform) { case 0x01: /* PC */ - if (ktsr->is_external) - ktsr->codec = KVS; - else if (ktsr->format == 0x00) + if (ktsr->is_external) { + if (ktsr->format == 0x0005) + ktsr->codec = KOVS; + else + goto fail; + } + else if (ktsr->format == 0x0000) { ktsr->codec = MSADPCM; - else + } + else { goto fail; + } break; - case 0x03: /* VITA */ - if (ktsr->is_external) - goto fail; - else if (ktsr->format == 0x01) + case 0x03: /* PS4/VITA */ + if (ktsr->is_external) { + if (ktsr->format == 0x1001) + ktsr->codec = RIFF_ATRAC9; + else + goto fail; + } + else if (ktsr->format == 0x0001) ktsr->codec = ATRAC9; else goto fail; @@ -254,7 +284,7 @@ static int parse_codec(ktsr_header* ktsr) { case 0x04: /* Switch */ if (ktsr->is_external) goto fail; /* KTSS? */ - else if (ktsr->format == 0x00) + else if (ktsr->format == 0x0000) ktsr->codec = DSP; else goto fail; @@ -281,14 +311,14 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, uint32_t offset /* probably could check the flag in sound header, but the format is kinda messy */ switch(type) { - case 0x38D0437D: /* external [Nioh (PC), Atelier Ryza (PC)] */ - case 0x3DEA478D: /* external [Nioh (PC)] */ + case 0x38D0437D: /* external [Nioh (PC/PS4), Atelier Ryza (PC)] */ + case 0x3DEA478D: /* external [Nioh (PC)] (smaller) */ case 0xDF92529F: /* external [Atelier Ryza (PC)] */ case 0x6422007C: /* external [Atelier Ryza (PC)] */ /* 08 subtype? (ex. 0x522B86B9) * 0c channels * 10 ? (always 0x002706B8) - * 14 codec? (05=KVS) + * 14 external codec * 18 sample rate * 1c num samples * 20 null? @@ -317,11 +347,6 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, uint32_t offset } ktsr->is_external = 1; - if (ktsr->format != 0x05) { - VGM_LOG("ktsr: unknown subcodec at %x\n", offset); - goto fail; - } - break; case 0x41FDBD4E: /* internal [Attack on Titan: Wings of Freedom (Vita)] */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 4aff0a009..f423926f9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -541,7 +541,7 @@ VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_mtaf(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_tun(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_alp(STREAMFILE* sf); VGMSTREAM * init_vgmstream_wpd(STREAMFILE* streamFile); @@ -988,4 +988,7 @@ VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf); VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_bw_mp3_riff(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_bw_riff_mp3(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c index 77e49d494..f4a0a248d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c @@ -11,13 +11,13 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) { size_t wave_length; int codec, channels, loop_flag; size_t stream_size; - off_t start_offset, wave_offset = 0; + off_t start_offset, wave_offset = 0, labl_offset; if (!is_id32be(0x00, sf, "RWSD")) goto fail; - if (!check_extensions(sf, "rwsd")) + if (!check_extensions(sf, "brwsd,rwsd")) goto fail; /* check header */ @@ -98,6 +98,11 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) { /* this is just data size and following data may or may not be from this RWSD */ start_offset = read_32bitBE(0x08, sf); + if (is_id32be(start_offset, sf, "LABL")) { + labl_offset = start_offset; + start_offset += read_32bitBE(start_offset + 0x04, sf); + read_string(vgmstream->stream_name, 0x28, labl_offset + 0x18, sf); + } stream_size = read_32bitBE(wave_offset + 0x50,sf); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/tun.c b/Frameworks/vgmstream/vgmstream/src/meta/tun.c deleted file mode 100644 index b49e9ba92..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/tun.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* ALP - from LEGO Racers (PC) */ -VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - /* checks */ - if ( !check_extensions(streamFile,"tun") ) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */ - goto fail; - - channel_count = 2; /* probably at 0x0F */ - loop_flag = 0; - start_offset = 0x10; - /* also "ADPCM" at 0x08 */ - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->channels = channel_count; - vgmstream->sample_rate = 22050; - vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - 0x10, channel_count); - - vgmstream->coding_type = coding_ALP_IMA; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - vgmstream->meta_type = meta_TUN; - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index da3efc697..2a52ad847 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -47,6 +47,7 @@ typedef enum { XA_EA, CP_YM, PCM_FLOAT_LE, + IMA_HV, UNKNOWN = 99, } txth_codec_t; @@ -240,6 +241,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { case PCM_FLOAT_LE: coding = coding_PCMFLOAT; break; case SDX2: coding = coding_SDX2; break; case DVI_IMA: coding = coding_DVI_IMA; break; + case IMA_HV: coding = coding_HV_IMA; break; #ifdef VGM_USE_MPEG case MPEG: coding = coding_MPEG_layer3; break; /* we later find out exactly which */ #endif @@ -316,6 +318,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { case coding_PSX_badflags: case coding_DVI_IMA: case coding_IMA: + case coding_HV_IMA: case coding_AICA: case coding_APPLE_IMA4: case coding_TGC: @@ -968,6 +971,7 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) { else if (is_string(val,"XA_EA")) return XA_EA; else if (is_string(val,"CP_YM")) return CP_YM; else if (is_string(val,"PCM_FLOAT_LE")) return PCM_FLOAT_LE; + else if (is_string(val,"IMA_HV")) return IMA_HV; /* special handling */ else if (is_string(val,"name_value")) return txth->name_values[0]; else if (is_string(val,"name_value1")) return txth->name_values[0]; @@ -2079,6 +2083,7 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) { case IMA: case DVI_IMA: + case IMA_HV: return ima_bytes_to_samples(bytes, txth->channels); case AICA: case CP_YM: diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 012adc5de..dd87b4bd8 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -257,7 +257,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_eb_sfx, init_vgmstream_eb_sf0, init_vgmstream_mtaf, - init_vgmstream_tun, + init_vgmstream_alp, init_vgmstream_wpd, init_vgmstream_mn_str, init_vgmstream_mss, @@ -524,6 +524,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_esf, init_vgmstream_adm3, init_vgmstream_tt_ad, + init_vgmstream_bw_mp3_riff, + init_vgmstream_bw_riff_mp3, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_mpeg, diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 585407108..63cd16fbb 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -118,7 +118,7 @@ typedef enum { coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */ coding_QD_IMA, coding_WV6_IMA, /* Gorilla Systems WV6 4-bit IMA ADPCM */ - coding_ALP_IMA, /* High Voltage ALP 4-bit IMA ADPCM */ + coding_HV_IMA, /* High Voltage 4-bit IMA ADPCM */ coding_FFTA2_IMA, /* Final Fantasy Tactics A2 4-bit IMA ADPCM */ coding_BLITZ_IMA, /* Blitz Games 4-bit IMA ADPCM */ @@ -577,7 +577,7 @@ typedef enum { meta_MTAF, meta_PS2_VAG1, /* Metal Gear Solid 3 VAG1 */ meta_PS2_VAG2, /* Metal Gear Solid 3 VAG2 */ - meta_TUN, /* LEGO Racers (PC) */ + meta_ALP, meta_WPD, /* Shuffle! (PC) */ meta_MN_STR, /* Mini Ninjas (PC/PS3/WII) */ meta_MSS, /* Guerilla: ShellShock Nam '67 (PS2/Xbox), Killzone (PS2) */ @@ -596,7 +596,8 @@ typedef enum { meta_HCA, /* CRI HCA */ meta_SVAG_SNK, meta_PS2_VDS_VDM, /* Graffiti Kingdom */ - meta_FFMPEG, /* any file supported by FFmpeg */ + meta_FFMPEG, + meta_FFMPEG_faulty, meta_X360_CXS, /* Eternal Sonata (Xbox 360) */ meta_AKB, /* SQEX iOS */ meta_X360_PASX, /* Namco PASX (Soul Calibur II HD X360) */ diff --git a/Info.plist b/Info.plist index 260b9dd79..08e8e6dc3 100644 --- a/Info.plist +++ b/Info.plist @@ -155,6 +155,7 @@ atsl atsl3 atsl4 + atslx atx aud audio @@ -192,6 +193,8 @@ bo2 brstm brstmspm + brwav + brwsd bsnd btsnd bvg